blob: 2a6ecfaae304aaf13b715d4ea4f1f8c7f0441448 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/autofill/core/browser/personal_data_manager.h"
#include <stddef.h>
#include <algorithm>
#include <list>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/command_line.h"
#include "base/files/scoped_temp_dir.h"
#include "base/guid.h"
#include "base/metrics/field_trial.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/personal_data_manager_observer.h"
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_pref_names.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/form_data.h"
#include "components/os_crypt/os_crypt_mocker.h"
#include "components/prefs/pref_service.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/fake_signin_manager.h"
#include "components/signin/core/browser/test_signin_client.h"
#include "components/signin/core/common/signin_pref_names.h"
#include "components/variations/entropy_provider.h"
#include "components/variations/variations_associated_data.h"
#include "components/webdata/common/web_data_service_base.h"
#include "components/webdata/common/web_database_service.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::ASCIIToUTF16;
using base::UTF8ToUTF16;
namespace autofill {
namespace {
enum UserMode { USER_MODE_NORMAL, USER_MODE_INCOGNITO };
ACTION(QuitMainMessageLoop) {
base::MessageLoop::current()->QuitWhenIdle();
}
class PersonalDataLoadedObserverMock : public PersonalDataManagerObserver {
public:
PersonalDataLoadedObserverMock() {}
virtual ~PersonalDataLoadedObserverMock() {}
MOCK_METHOD0(OnPersonalDataChanged, void());
};
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(std::mismatch(results_copy.begin(),
results_copy.end(),
expectations_copy.begin(),
ElementsEqual<T>).first,
results_copy.end());
}
} // anonymous namespace
class PersonalDataManagerTest : public testing::Test {
protected:
PersonalDataManagerTest() : autofill_table_(nullptr) {}
void SetUp() override {
OSCryptMocker::SetUpWithSingleton();
prefs_ = test::PrefServiceForTesting();
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
base::FilePath path = temp_dir_.path().AppendASCII("TestWebDB");
web_database_ =
new WebDatabaseService(path, base::ThreadTaskRunnerHandle::Get(),
base::ThreadTaskRunnerHandle::Get());
// Setup account tracker.
signin_client_.reset(new TestSigninClient(prefs_.get()));
account_tracker_.reset(new AccountTrackerService());
account_tracker_->Initialize(signin_client_.get());
signin_manager_.reset(new FakeSigninManagerBase(signin_client_.get(),
account_tracker_.get()));
signin_manager_->Initialize(prefs_.get());
// Hacky: hold onto a pointer but pass ownership.
autofill_table_ = new AutofillTable;
web_database_->AddTable(std::unique_ptr<WebDatabaseTable>(autofill_table_));
web_database_->LoadDatabase();
autofill_database_service_ = new AutofillWebDataService(
web_database_, base::ThreadTaskRunnerHandle::Get(),
base::ThreadTaskRunnerHandle::Get(),
WebDataServiceBase::ProfileErrorCallback());
autofill_database_service_->Init();
test::DisableSystemServices(prefs_.get());
ResetPersonalDataManager(USER_MODE_NORMAL);
// There are no field trials enabled by default.
field_trial_list_.reset();
}
void TearDown() override {
// Order of destruction is important as AutofillManager relies on
// PersonalDataManager to be around when it gets destroyed.
signin_manager_->Shutdown();
signin_manager_.reset();
account_tracker_->Shutdown();
account_tracker_.reset();
signin_client_.reset();
test::DisableSystemServices(prefs_.get());
OSCryptMocker::TearDown();
}
void ResetPersonalDataManager(UserMode user_mode) {
bool is_incognito = (user_mode == USER_MODE_INCOGNITO);
personal_data_.reset(new PersonalDataManager("en"));
personal_data_->Init(
scoped_refptr<AutofillWebDataService>(autofill_database_service_),
prefs_.get(),
account_tracker_.get(),
signin_manager_.get(),
is_incognito);
personal_data_->AddObserver(&personal_data_observer_);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
}
void ResetProfiles() {
std::vector<AutofillProfile> empty_profiles;
personal_data_->SetProfiles(&empty_profiles);
}
void EnableWalletCardImport() {
signin_manager_->SetAuthenticatedAccountInfo("12345",
"syncuser@example.com");
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableOfferStoreUnmaskedWalletCards);
}
void SetupReferenceProfile() {
ASSERT_EQ(0U, personal_data_->GetProfiles().size());
AutofillProfile profile(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
personal_data_->AddProfile(profile);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
ASSERT_EQ(1U, personal_data_->GetProfiles().size());
}
// Helper method that will add credit card fields in |form|, according to the
// specified values. If a value is nullptr, the corresponding field won't get
// added (empty string will add a field with an empty string as the value).
void AddFullCreditCardForm(FormData* form,
const char* name,
const char* number,
const char* month,
const char* year) {
FormFieldData field;
if (name) {
test::CreateTestFormField("Name on card:", "name_on_card", name, "text",
&field);
form->fields.push_back(field);
}
if (number) {
test::CreateTestFormField("Card Number:", "card_number", number, "text",
&field);
form->fields.push_back(field);
}
if (month) {
test::CreateTestFormField("Exp Month:", "exp_month", month, "text",
&field);
form->fields.push_back(field);
}
if (year) {
test::CreateTestFormField("Exp Year:", "exp_year", year, "text", &field);
form->fields.push_back(field);
}
}
// 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",
"https://www.example.com");
test::SetCreditCardInfo(&credit_card0, "Clyde Barrow",
"347666888555" /* American Express */, "04",
"3999");
credit_card0.set_use_count(3);
credit_card0.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
personal_data_->AddCreditCard(credit_card0);
CreditCard credit_card1("1141084B-72D7-4B73-90CF-3D6AC154673B",
"https://www.example.com");
credit_card1.set_use_count(300);
credit_card1.set_use_date(base::Time::Now() -
base::TimeDelta::FromDays(10));
test::SetCreditCardInfo(&credit_card1, "John Dillinger",
"423456789012" /* Visa */, "01", "2999");
personal_data_->AddCreditCard(credit_card1);
CreditCard credit_card2("002149C1-EE28-4213-A3B9-DA243FFF021B",
"https://www.example.com");
credit_card2.set_use_count(1);
credit_card2.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
test::SetCreditCardInfo(&credit_card2, "Bonnie Parker",
"518765432109" /* Mastercard */, "12", "3999");
personal_data_->AddCreditCard(credit_card2);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
}
// Helper methods that simply forward the call to the private member (to avoid
// having to friend every test that needs to access the private
// PersonalDataManager::ImportAddressProfile or ImportCreditCard).
bool ImportAddressProfiles(const FormStructure& form) {
return personal_data_->ImportAddressProfiles(form);
}
bool ImportCreditCard(const FormStructure& form,
bool should_return_local_card,
std::unique_ptr<CreditCard>* imported_credit_card) {
return personal_data_->ImportCreditCard(form, should_return_local_card,
imported_credit_card);
}
// Sets up the profile order field trial group and parameter. Sets up the
// suggestions limit parameter to |limit_param|.
void EnableAutofillProfileLimitFieldTrial(const std::string& limit_param) {
DCHECK(!limit_param.empty());
// Clear the existing |field_trial_list_| and variation parameters.
field_trial_list_.reset(NULL);
field_trial_list_.reset(
new base::FieldTrialList(new metrics::SHA1EntropyProvider("foo")));
variations::testing::ClearAllVariationParams();
std::map<std::string, std::string> params;
params[kFrecencyFieldTrialLimitParam] = limit_param;
variations::AssociateVariationParams(kFrecencyFieldTrialName, "LimitToN",
params);
field_trial_ = base::FieldTrialList::CreateFieldTrial(
kFrecencyFieldTrialName, "LimitToN");
field_trial_->group();
}
// The temporary directory should be deleted at the end to ensure that
// files are not used anymore and deletion succeeds.
base::ScopedTempDir temp_dir_;
base::MessageLoopForUI message_loop_;
std::unique_ptr<PrefService> prefs_;
std::unique_ptr<AccountTrackerService> account_tracker_;
std::unique_ptr<FakeSigninManagerBase> signin_manager_;
std::unique_ptr<TestSigninClient> signin_client_;
scoped_refptr<AutofillWebDataService> autofill_database_service_;
scoped_refptr<WebDatabaseService> web_database_;
AutofillTable* autofill_table_; // weak ref
PersonalDataLoadedObserverMock personal_data_observer_;
std::unique_ptr<PersonalDataManager> personal_data_;
std::unique_ptr<base::FieldTrialList> field_trial_list_;
scoped_refptr<base::FieldTrial> field_trial_;
};
TEST_F(PersonalDataManagerTest, AddProfile) {
// Add profile0 to the database.
AutofillProfile profile0(test::GetFullProfile());
profile0.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16("j@s.com"));
personal_data_->AddProfile(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::GenerateGUID());
personal_data_->AddProfile(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::GenerateGUID());
profile1.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16("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.
personal_data_->AddProfile(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());
}
// Test that a new profile has its basic information set.
TEST_F(PersonalDataManagerTest, AddProfile_BasicInformation) {
// Add a profile to the database.
AutofillProfile profile(test::GetFullProfile());
profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16("j@s.com"));
personal_data_->AddProfile(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_NE(base::Time(), results[0]->use_date());
EXPECT_NE(base::Time(), results[0]->modification_date());
}
TEST_F(PersonalDataManagerTest, DontDuplicateServerProfile) {
EnableWalletCardImport();
std::vector<AutofillProfile> server_profiles;
server_profiles.push_back(
AutofillProfile(AutofillProfile::SERVER_PROFILE, "a123"));
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, ASCIIToUTF16("John Doe"));
autofill_table_->SetServerProfiles(server_profiles);
personal_data_->Refresh();
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
// Add profile with identical values. Duplicates should not get saved.
AutofillProfile scraped_profile(base::GenerateGUID(),
"https://www.example.com");
test::SetProfileInfo(&scraped_profile, "John", "", "Doe", "", "ACME Corp",
"500 Oak View", "Apt 8", "Houston", "TX", "77401", "US",
"");
EXPECT_TRUE(scraped_profile.IsSubsetOf(server_profiles.back(), "en-US"));
std::string saved_guid = personal_data_->SaveImportedProfile(scraped_profile);
EXPECT_NE(scraped_profile.guid(), saved_guid);
personal_data_->Refresh();
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// Verify the non-addition.
EXPECT_EQ(0U, personal_data_->web_profiles().size());
ASSERT_EQ(1U, personal_data_->GetProfiles().size());
// Verify that the server profile's use date was updated.
const AutofillProfile* server_profile = personal_data_->GetProfiles()[0];
EXPECT_GT(base::TimeDelta::FromMilliseconds(500),
base::Time::Now() - server_profile->use_date());
}
// 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());
personal_data_->SaveImportedProfile(profile);
const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
ASSERT_EQ(1U, profiles.size());
EXPECT_GT(base::TimeDelta::FromMilliseconds(500),
base::Time::Now() - profiles[0]->modification_date());
}
TEST_F(PersonalDataManagerTest, AddUpdateRemoveProfiles) {
AutofillProfile profile0(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile0,
"Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
"91601", "US", "12345678910");
AutofillProfile profile1(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile1,
"Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "903 Apple Ct.", NULL, "Orlando", "FL", "32801",
"US", "19482937549");
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
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.
personal_data_->AddProfile(profile0);
personal_data_->AddProfile(profile1);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
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, ASCIIToUTF16("John"));
personal_data_->UpdateProfile(profile0);
personal_data_->RemoveByGUID(profile1.guid());
personal_data_->AddProfile(profile2);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
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());
}
TEST_F(PersonalDataManagerTest, AddUpdateRemoveCreditCards) {
CreditCard credit_card0(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&credit_card0,
"John Dillinger", "423456789012" /* Visa */, "01", "2999");
CreditCard credit_card1(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&credit_card1,
"Bonnie Parker", "518765432109" /* Mastercard */, "12", "3999");
CreditCard credit_card2(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&credit_card2,
"Clyde Barrow", "347666888555" /* American Express */, "04", "3999");
// Add two test credit cards to the database.
personal_data_->AddCreditCard(credit_card0);
personal_data_->AddCreditCard(credit_card1);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
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, ASCIIToUTF16("Joe"));
personal_data_->UpdateCreditCard(credit_card0);
personal_data_->RemoveByGUID(credit_card1.guid());
personal_data_->AddCreditCard(credit_card2);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
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());
}
// Test that a new credit card has its basic information set.
TEST_F(PersonalDataManagerTest, AddCreditCard_BasicInformation) {
// Add a credit to the database.
CreditCard credit_card(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&credit_card, "John Dillinger",
"423456789012" /* Visa */, "01", "2999");
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_NE(base::Time(), results[0]->use_date());
EXPECT_NE(base::Time(), results[0]->modification_date());
}
TEST_F(PersonalDataManagerTest, UpdateUnverifiedProfilesAndCreditCards) {
// Start with unverified data.
AutofillProfile profile(base::GenerateGUID(), "https://www.example.com/");
test::SetProfileInfo(&profile,
"Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
"91601", "US", "12345678910");
EXPECT_FALSE(profile.IsVerified());
CreditCard credit_card(base::GenerateGUID(), "https://www.example.com/");
test::SetCreditCardInfo(&credit_card,
"John Dillinger", "423456789012" /* Visa */, "01", "2999");
EXPECT_FALSE(credit_card.IsVerified());
// Add the data to the database.
personal_data_->AddProfile(profile);
personal_data_->AddCreditCard(credit_card);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
const std::vector<AutofillProfile*>& profiles1 =
personal_data_->GetProfiles();
const std::vector<CreditCard*>& cards1 = personal_data_->GetCreditCards();
ASSERT_EQ(1U, profiles1.size());
ASSERT_EQ(1U, cards1.size());
EXPECT_EQ(0, profile.Compare(*profiles1[0]));
EXPECT_EQ(0, credit_card.Compare(*cards1[0]));
// Try to update with just the origin changed.
AutofillProfile original_profile(profile);
CreditCard original_credit_card(credit_card);
profile.set_origin(kSettingsOrigin);
credit_card.set_origin(kSettingsOrigin);
EXPECT_TRUE(profile.IsVerified());
EXPECT_TRUE(credit_card.IsVerified());
personal_data_->UpdateProfile(profile);
personal_data_->UpdateCreditCard(credit_card);
// Note: No refresh, as no update is expected.
const std::vector<AutofillProfile*>& profiles2 =
personal_data_->GetProfiles();
const std::vector<CreditCard*>& cards2 = personal_data_->GetCreditCards();
ASSERT_EQ(1U, profiles2.size());
ASSERT_EQ(1U, cards2.size());
EXPECT_NE(profile.origin(), profiles2[0]->origin());
EXPECT_NE(credit_card.origin(), cards2[0]->origin());
EXPECT_EQ(original_profile.origin(), profiles2[0]->origin());
EXPECT_EQ(original_credit_card.origin(), cards2[0]->origin());
// Try to update with data changed as well.
profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
credit_card.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("Joe"));
personal_data_->UpdateProfile(profile);
personal_data_->UpdateCreditCard(credit_card);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
const std::vector<AutofillProfile*>& profiles3 =
personal_data_->GetProfiles();
const std::vector<CreditCard*>& cards3 = personal_data_->GetCreditCards();
ASSERT_EQ(1U, profiles3.size());
ASSERT_EQ(1U, cards3.size());
EXPECT_EQ(0, profile.Compare(*profiles3[0]));
EXPECT_EQ(0, credit_card.Compare(*cards3[0]));
EXPECT_EQ(profile.origin(), profiles3[0]->origin());
EXPECT_EQ(credit_card.origin(), cards3[0]->origin());
}
// Makes sure that full cards are re-masked when full PAN storage is off.
TEST_F(PersonalDataManagerTest, RefuseToStoreFullCard) {
// On Linux this should be disabled automatically. Elsewhere, only if the
// flag is passed.
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
EXPECT_FALSE(base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableOfferStoreUnmaskedWalletCards));
#else
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kDisableOfferStoreUnmaskedWalletCards);
#endif
std::vector<CreditCard> server_cards;
server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "c789"));
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"347666888555" /* American Express */, "04", "3999");
test::SetServerCreditCards(autofill_table_, server_cards);
personal_data_->Refresh();
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
ASSERT_EQ(1U, personal_data_->GetCreditCards().size());
EXPECT_EQ(CreditCard::MASKED_SERVER_CARD,
personal_data_->GetCreditCards()[0]->record_type());
}
TEST_F(PersonalDataManagerTest, OfferStoreUnmaskedCards) {
#if defined(OS_CHROMEOS) || defined(OS_WIN) || defined(OS_MACOSX) || \
defined(OS_IOS) || defined(OS_ANDROID)
bool should_offer = true;
#elif defined(OS_LINUX)
bool should_offer = false;
#endif
EXPECT_EQ(should_offer, OfferStoreUnmaskedCards());
}
// Tests that UpdateServerCreditCard can be used to mask or unmask server cards.
TEST_F(PersonalDataManagerTest, UpdateServerCreditCards) {
EnableWalletCardImport();
std::vector<CreditCard> server_cards;
server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "a123"));
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"9012" /* Visa */, "01", "2999");
server_cards.back().SetTypeForMaskedCard(kVisaCard);
server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b456"));
test::SetCreditCardInfo(&server_cards.back(), "Bonnie Parker",
"2109" /* Mastercard */, "12", "3999");
server_cards.back().SetTypeForMaskedCard(kMasterCard);
server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "c789"));
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"347666888555" /* American Express */, "04", "3999");
test::SetServerCreditCards(autofill_table_, server_cards);
personal_data_->Refresh();
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
if (!OfferStoreUnmaskedCards()) {
for (CreditCard* card : personal_data_->GetCreditCards()) {
EXPECT_EQ(CreditCard::MASKED_SERVER_CARD, card->record_type());
}
// The rest of this test doesn't work if we're force-masking all unmasked
// cards.
return;
}
// The GUIDs will be different, so just compare the data.
for (size_t i = 0; i < 3; ++i)
EXPECT_EQ(0, server_cards[i].Compare(*personal_data_->GetCreditCards()[i]));
CreditCard* unmasked_card = &server_cards.front();
unmasked_card->set_record_type(CreditCard::FULL_SERVER_CARD);
unmasked_card->SetNumber(ASCIIToUTF16("423456789012"));
EXPECT_NE(0, server_cards.front().Compare(
*personal_data_->GetCreditCards().front()));
personal_data_->UpdateServerCreditCard(*unmasked_card);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
for (size_t i = 0; i < 3; ++i)
EXPECT_EQ(0, server_cards[i].Compare(*personal_data_->GetCreditCards()[i]));
CreditCard* remasked_card = &server_cards.back();
remasked_card->set_record_type(CreditCard::MASKED_SERVER_CARD);
remasked_card->SetNumber(ASCIIToUTF16("8555"));
EXPECT_NE(
0, server_cards.back().Compare(*personal_data_->GetCreditCards().back()));
personal_data_->UpdateServerCreditCard(*remasked_card);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
for (size_t i = 0; i < 3; ++i)
EXPECT_EQ(0, server_cards[i].Compare(*personal_data_->GetCreditCards()[i]));
}
TEST_F(PersonalDataManagerTest, AddProfilesAndCreditCards) {
AutofillProfile profile0(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile0,
"Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
"91601", "US", "12345678910");
AutofillProfile profile1(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile1,
"Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "903 Apple Ct.", NULL, "Orlando", "FL", "32801",
"US", "19482937549");
CreditCard credit_card0(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&credit_card0,
"John Dillinger", "423456789012" /* Visa */, "01", "2999");
CreditCard credit_card1(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&credit_card1,
"Bonnie Parker", "518765432109" /* Mastercard */, "12", "3999");
// Add two test profiles to the database.
personal_data_->AddProfile(profile0);
personal_data_->AddProfile(profile1);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
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);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
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(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile0,
"y", "", "", "", "", "", "", "", "", "", "", "");
// Add the profile0 to the db.
personal_data_->AddProfile(profile0);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// 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(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile1,
"z", "", "", "", "", "", "", "", "", "", "", "");
personal_data_->AddProfile(profile1);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// 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::IsValidGUID(results3[0]->guid()));
EXPECT_TRUE(base::IsValidGUID(results3[1]->guid()));
}
TEST_F(PersonalDataManagerTest, SetUniqueCreditCardLabels) {
CreditCard credit_card0(base::GenerateGUID(), "https://www.example.com");
credit_card0.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("John"));
CreditCard credit_card1(base::GenerateGUID(), "https://www.example.com");
credit_card1.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("Paul"));
CreditCard credit_card2(base::GenerateGUID(), "https://www.example.com");
credit_card2.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("Ringo"));
CreditCard credit_card3(base::GenerateGUID(), "https://www.example.com");
credit_card3.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("Other"));
CreditCard credit_card4(base::GenerateGUID(), "https://www.example.com");
credit_card4.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("Ozzy"));
CreditCard credit_card5(base::GenerateGUID(), "https://www.example.com");
credit_card5.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("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(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile0,
"", "", "", "", "", "", "", "", "", "", "", "");
// Add the empty profile to the database.
personal_data_->AddProfile(profile0);
// 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 profiles from the web
// database.
ResetPersonalDataManager(USER_MODE_NORMAL);
// Verify that we've loaded the profiles from the web database.
const std::vector<AutofillProfile*>& results2 = personal_data_->GetProfiles();
ASSERT_EQ(0U, results2.size());
}
TEST_F(PersonalDataManagerTest, SetEmptyCreditCard) {
CreditCard credit_card0(base::GenerateGUID(), "https://www.example.com");
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.
const std::vector<CreditCard*>& results2 = personal_data_->GetCreditCards();
ASSERT_EQ(0U, results2.size());
}
TEST_F(PersonalDataManagerTest, Refresh) {
AutofillProfile profile0(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile0,
"Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
"91601", "US", "12345678910");
AutofillProfile profile1(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile1,
"Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "903 Apple Ct.", NULL, "Orlando", "FL", "32801",
"US", "19482937549");
// Add the test profiles to the database.
personal_data_->AddProfile(profile0);
personal_data_->AddProfile(profile1);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
std::vector<AutofillProfile*> profiles;
profiles.push_back(&profile0);
profiles.push_back(&profile1);
ExpectSameElements(profiles, personal_data_->GetProfiles());
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile2,
"Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL",
"32801", "US", "19482937549");
autofill_database_service_->AddAutofillProfile(profile2);
personal_data_->Refresh();
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
profiles.clear();
profiles.push_back(&profile0);
profiles.push_back(&profile1);
profiles.push_back(&profile2);
ExpectSameElements(profiles, personal_data_->GetProfiles());
autofill_database_service_->RemoveAutofillProfile(profile1.guid());
autofill_database_service_->RemoveAutofillProfile(profile2.guid());
// Before telling the PDM to refresh, simulate an edit to one of the deleted
// profiles via a SetProfile update (this would happen if the Autofill window
// was open with a previous snapshot of the profiles, and something
// [e.g. sync] removed a profile from the browser. In this edge case, we will
// end up in a consistent state by dropping the write).
profile0.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Mar"));
profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jo"));
personal_data_->UpdateProfile(profile0);
personal_data_->AddProfile(profile1);
personal_data_->AddProfile(profile2);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(profile0, *results[0]);
}
// ImportAddressProfiles tests.
TEST_F(PersonalDataManagerTest, ImportAddressProfiles) {
FormData form;
FormFieldData field;
test::CreateTestFormField(
"First name:", "first_name", "George", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Last name:", "last_name", "Washington", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Email:", "email", "theprez@gmail.com", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Address:", "address1", "21 Laussat St", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("State:", "state", "California", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
AutofillProfile expected(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&expected, "George", NULL,
"Washington", "theprez@gmail.com", NULL, "21 Laussat St", NULL,
"San Francisco", "California", "94102", NULL, NULL);
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, expected.Compare(*results[0]));
}
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_BadEmail) {
FormData form;
FormFieldData field;
test::CreateTestFormField(
"First name:", "first_name", "George", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Last name:", "last_name", "Washington", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Email:", "email", "bogus", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Address:", "address1", "21 Laussat St", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("State:", "state", "California", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
EXPECT_FALSE(ImportAddressProfiles(form_structure));
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(0U, results.size());
}
// Tests that a 'confirm email' field does not block profile import.
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_TwoEmails) {
FormData form;
FormFieldData field;
test::CreateTestFormField(
"Name:", "name", "George Washington", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Address:", "address1", "21 Laussat St", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("State:", "state", "California", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Email:", "email", "example@example.com", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Confirm email:", "confirm_email", "example@example.com", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
}
// Tests two email fields containing different values blocks profile import.
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_TwoDifferentEmails) {
FormData form;
FormFieldData field;
test::CreateTestFormField(
"Name:", "name", "George Washington", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Address:", "address1", "21 Laussat St", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("State:", "state", "California", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Email:", "email", "example@example.com", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Email:", "email2", "example2@example.com", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
EXPECT_FALSE(ImportAddressProfiles(form_structure));
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(0U, results.size());
}
// Tests that not enough filled fields will result in not importing an address.
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_NotEnoughFilledFields) {
FormData form;
FormFieldData field;
test::CreateTestFormField(
"First name:", "first_name", "George", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Last name:", "last_name", "Washington", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Card number:", "card_number", "4111 1111 1111 1111", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
EXPECT_FALSE(ImportAddressProfiles(form_structure));
const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
ASSERT_EQ(0U, profiles.size());
const std::vector<CreditCard*>& cards = personal_data_->GetCreditCards();
ASSERT_EQ(0U, cards.size());
}
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MinimumAddressUSA) {
// United States addresses must specifiy one address line, a city, state and
// zip code.
FormData form;
FormFieldData field;
test::CreateTestFormField("Name:", "name", "Barack Obama", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Address:", "address", "1600 Pennsylvania Avenue", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "Washington", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("State:", "state", "DC", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "20500", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Country:", "country", "USA", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
ASSERT_EQ(1U, profiles.size());
}
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MinimumAddressGB) {
// British addresses do not require a state/province as the county is usually
// not requested on forms.
FormData form;
FormFieldData field;
test::CreateTestFormField("Name:", "name", "David Cameron", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Address:", "address", "10 Downing Street", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "London", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Postcode:", "postcode", "SW1A 2AA", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Country:", "country", "United Kingdom", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
ASSERT_EQ(1U, profiles.size());
}
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MinimumAddressGI) {
// Gibraltar has the most minimal set of requirements for a valid address.
// There are no cities or provinces and no postal/zip code system.
FormData form;
FormFieldData field;
test::CreateTestFormField(
"Name:", "name", "Sir Adrian Johns", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Address:", "address", "The Convent, Main Street", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Country:", "country", "Gibraltar", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
ASSERT_EQ(1U, profiles.size());
}
TEST_F(PersonalDataManagerTest,
ImportAddressProfiles_PhoneNumberSplitAcrossMultipleFields) {
FormData form;
FormFieldData field;
test::CreateTestFormField(
"First name:", "first_name", "George", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Last name:", "last_name", "Washington", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Phone #:", "home_phone_area_code", "650", "text", &field);
field.max_length = 3;
form.fields.push_back(field);
test::CreateTestFormField(
"Phone #:", "home_phone_prefix", "555", "text", &field);
field.max_length = 3;
form.fields.push_back(field);
test::CreateTestFormField(
"Phone #:", "home_phone_suffix", "0000", "text", &field);
field.max_length = 4;
form.fields.push_back(field);
test::CreateTestFormField(
"Address:", "address1", "21 Laussat St", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("State:", "state", "California", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
AutofillProfile expected(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&expected, "George", NULL,
"Washington", NULL, NULL, "21 Laussat St", NULL,
"San Francisco", "California", "94102", NULL, "(650) 555-0000");
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, expected.Compare(*results[0]));
}
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MultilineAddress) {
FormData form;
FormFieldData field;
test::CreateTestFormField(
"First name:", "first_name", "George", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Last name:", "last_name", "Washington", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Email:", "email", "theprez@gmail.com", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField(
"Address:",
"street_address",
"21 Laussat St\n"
"Apt. #42",
"textarea",
&field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("State:", "state", "California", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
AutofillProfile expected(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&expected, "George", NULL,
"Washington", "theprez@gmail.com", NULL, "21 Laussat St", "Apt. #42",
"San Francisco", "California", "94102", NULL, NULL);
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, expected.Compare(*results[0]));
}
TEST_F(PersonalDataManagerTest,
ImportAddressProfiles_TwoValidProfilesDifferentForms) {
FormData form1;
FormFieldData field;
test::CreateTestFormField(
"First name:", "first_name", "George", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField(
"Last name:", "last_name", "Washington", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField(
"Email:", "email", "theprez@gmail.com", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField(
"Address:", "address1", "21 Laussat St", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("State:", "state", "California", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form1.fields.push_back(field);
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure1));
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
AutofillProfile expected(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&expected, "George", NULL,
"Washington", "theprez@gmail.com", NULL, "21 Laussat St", NULL,
"San Francisco", "California", "94102", NULL, NULL);
const std::vector<AutofillProfile*>& results1 = personal_data_->GetProfiles();
ASSERT_EQ(1U, results1.size());
EXPECT_EQ(0, expected.Compare(*results1[0]));
// Now create a completely different profile.
FormData form2;
test::CreateTestFormField(
"First name:", "first_name", "John", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField(
"Last name:", "last_name", "Adams", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField(
"Email:", "email", "second@gmail.com", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField(
"Address:", "address1", "22 Laussat St", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("State:", "state", "California", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form2.fields.push_back(field);
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure2));
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
AutofillProfile expected2(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&expected2, "John", NULL,
"Adams", "second@gmail.com", NULL, "22 Laussat St", NULL,
"San Francisco", "California", "94102", NULL, NULL);
std::vector<AutofillProfile*> profiles;
profiles.push_back(&expected);
profiles.push_back(&expected2);
ExpectSameElements(profiles, personal_data_->GetProfiles());
}
TEST_F(PersonalDataManagerTest,
ImportAddressProfiles_TwoValidProfilesSameForm) {
FormData form;
FormFieldData field;
test::CreateTestFormField("First name:", "first_name", "George", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Address:", "address1", "21 Laussat St", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("State:", "state", "California", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
// Different address.
test::CreateTestFormField("First name:", "first_name", "John", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Last name:", "last_name", "Adams", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Email:", "email", "second@gmail.com", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Address:", "address1", "22 Laussat St", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("State:", "state", "California", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
AutofillProfile expected(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&expected, "George", NULL, "Washington",
"theprez@gmail.com", NULL, "21 Laussat St", NULL,
"San Francisco", "California", "94102", NULL, NULL);
AutofillProfile expected2(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&expected2, "John", NULL, "Adams", "second@gmail.com",
NULL, "22 Laussat St", NULL, "San Francisco",
"California", "94102", NULL, NULL);
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(2U, results.size());
std::vector<AutofillProfile*> profiles;
profiles.push_back(&expected);
profiles.push_back(&expected2);
ExpectSameElements(profiles, personal_data_->GetProfiles());
}
TEST_F(PersonalDataManagerTest,
ImportAddressProfiles_OneValidProfileSameForm_PartsHidden) {
FormData form;
FormFieldData field;
test::CreateTestFormField("First name:", "first_name", "George", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Address:", "address1", "21 Laussat St", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("State:", "state", "California", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
// There is an empty but hidden form section (this has been observed on sites
// where users can choose which form section they choose by unhiding it).
test::CreateTestFormField("First name:", "first_name", "", "text",
&field);
field.is_focusable = false;
form.fields.push_back(field);
test::CreateTestFormField("Last name:", "last_name", "", "text", &field);
field.is_focusable = false;
form.fields.push_back(field);
test::CreateTestFormField("Email:", "email", "", "text",
&field);
field.is_focusable = false;
form.fields.push_back(field);
test::CreateTestFormField("Address:", "address1", "", "text",
&field);
field.is_focusable = false;
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "", "text", &field);
field.is_focusable = false;
form.fields.push_back(field);
test::CreateTestFormField("State:", "state", "", "text", &field);
field.is_focusable = false;
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "", "text", &field);
field.is_focusable = false;
form.fields.push_back(field);
// Still able to do the import.
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
AutofillProfile expected(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&expected, "George", NULL, "Washington",
"theprez@gmail.com", NULL, "21 Laussat St", NULL,
"San Francisco", "California", "94102", NULL, NULL);
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
std::vector<AutofillProfile*> profiles;
profiles.push_back(&expected);
ExpectSameElements(profiles, personal_data_->GetProfiles());
}
// A maximum of two address profiles are imported per form.
TEST_F(PersonalDataManagerTest,
ImportAddressProfiles_ThreeValidProfilesSameForm) {
FormData form;
FormFieldData field;
test::CreateTestFormField("First name:", "first_name", "George", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Address:", "address1", "21 Laussat St", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("State:", "state", "California", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
// Different address within the same form.
test::CreateTestFormField("First name:", "first_name", "John", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Last name:", "last_name", "Adams", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Email:", "email", "second@gmail.com", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Address:", "address1", "22 Laussat St", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("State:", "state", "California", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
// Yet another different address.
test::CreateTestFormField("First name:", "first_name", "David", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Last name:", "last_name", "Cameron", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Address:", "address", "10 Downing Street", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "London", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Postcode:", "postcode", "SW1A 2AA", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Country:", "country", "United Kingdom", "text",
&field);
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// Only two are saved.
AutofillProfile expected(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&expected, "George", NULL, "Washington",
"theprez@gmail.com", NULL, "21 Laussat St", NULL,
"San Francisco", "California", "94102", NULL, NULL);
AutofillProfile expected2(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&expected2, "John", NULL, "Adams", "second@gmail.com",
NULL, "22 Laussat St", NULL, "San Francisco",
"California", "94102", NULL, NULL);
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(2U, results.size());
std::vector<AutofillProfile*> profiles;
profiles.push_back(&expected);
profiles.push_back(&expected2);
ExpectSameElements(profiles, personal_data_->GetProfiles());
}
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_SameProfileWithConflict) {
FormData form1;
FormFieldData field;
test::CreateTestFormField(
"First name:", "first_name", "George", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField(
"Last name:", "last_name", "Washington", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField(
"Address:", "address", "1600 Pennsylvania Avenue", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField(
"Address Line 2:", "address2", "Suite A", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("State:", "state", "California", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField(
"Email:", "email", "theprez@gmail.com", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("Phone:", "phone", "6505556666", "text", &field);
form1.fields.push_back(field);
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure1));
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
AutofillProfile expected(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&expected, "George", nullptr, "Washington",
"theprez@gmail.com", nullptr, "1600 Pennsylvania Avenue",
"Suite A", "San Francisco", "California", "94102",
nullptr, "(650) 555-6666");
const std::vector<AutofillProfile*>& results1 = personal_data_->GetProfiles();
ASSERT_EQ(1U, results1.size());
EXPECT_EQ(0, expected.Compare(*results1[0]));
// Now create an updated profile.
FormData form2;
test::CreateTestFormField(
"First name:", "first_name", "George", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField(
"Last name:", "last_name", "Washington", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField(
"Address:", "address", "1600 Pennsylvania Avenue", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField(
"Address Line 2:", "address2", "Suite A", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("State:", "state", "California", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField(
"Email:", "email", "theprez@gmail.com", "text", &field);
form2.fields.push_back(field);
// Country gets added.
test::CreateTestFormField("Country:", "country", "USA", "text", &field);
form2.fields.push_back(field);
// Same phone number with different formatting doesn't create a new profile.
test::CreateTestFormField("Phone:", "phone", "650-555-6666", "text", &field);
form2.fields.push_back(field);
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure2));
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
const std::vector<AutofillProfile*>& results2 = personal_data_->GetProfiles();
// Phone formatting is updated. Also, country gets added.
expected.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("650-555-6666"));
expected.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("US"));
ASSERT_EQ(1U, results2.size());
EXPECT_EQ(0, expected.Compare(*results2[0]));
}
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MissingInfoInOld) {
FormData form1;
FormFieldData field;
test::CreateTestFormField(
"First name:", "first_name", "George", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField(
"Last name:", "last_name", "Washington", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField(
"Address Line 1:", "address", "190 High Street", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("City:", "city", "Philadelphia", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("State:", "state", "Pennsylvania", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("Zip:", "zipcode", "19106", "text", &field);
form1.fields.push_back(field);
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure1));
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
AutofillProfile expected(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&expected, "George", NULL,
"Washington", NULL, NULL, "190 High Street", NULL,
"Philadelphia", "Pennsylvania", "19106", NULL, NULL);
const std::vector<AutofillProfile*>& results1 = personal_data_->GetProfiles();
ASSERT_EQ(1U, results1.size());
EXPECT_EQ(0, expected.Compare(*results1[0]));
// Submit a form with new data for the first profile.
FormData form2;
test::CreateTestFormField(
"First name:", "first_name", "George", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField(
"Last name:", "last_name", "Washington", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField(
"Email:", "email", "theprez@gmail.com", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField(
"Address Line 1:", "address", "190 High Street", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("City:", "city", "Philadelphia", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("State:", "state", "Pennsylvania", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("Zip:", "zipcode", "19106", "text", &field);
form2.fields.push_back(field);
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure2));
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
const std::vector<AutofillProfile*>& results2 = personal_data_->GetProfiles();
AutofillProfile expected2(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&expected2, "George", NULL,
"Washington", "theprez@gmail.com", NULL, "190 High Street", NULL,
"Philadelphia", "Pennsylvania", "19106", NULL, NULL);
ASSERT_EQ(1U, results2.size());
EXPECT_EQ(0, expected2.Compare(*results2[0]));
}
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MissingInfoInNew) {
FormData form1;
FormFieldData field;
test::CreateTestFormField(
"First name:", "first_name", "George", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField(
"Last name:", "last_name", "Washington", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField(
"Company:", "company", "Government", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField(
"Email:", "email", "theprez@gmail.com", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField(
"Address Line 1:", "address", "190 High Street", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("City:", "city", "Philadelphia", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("State:", "state", "Pennsylvania", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("Zip:", "zipcode", "19106", "text", &field);
form1.fields.push_back(field);
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure1));
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
AutofillProfile expected(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&expected, "George", NULL,
"Washington", "theprez@gmail.com", "Government", "190 High Street", NULL,
"Philadelphia", "Pennsylvania", "19106", NULL, NULL);
const std::vector<AutofillProfile*>& results1 = personal_data_->GetProfiles();
ASSERT_EQ(1U, results1.size());
EXPECT_EQ(0, expected.Compare(*results1[0]));
// Submit a form with new data for the first profile.
FormData form2;
test::CreateTestFormField(
"First name:", "first_name", "George", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField(
"Last name:", "last_name", "Washington", "text", &field);
form2.fields.push_back(field);
// Note missing Company field.
test::CreateTestFormField(
"Email:", "email", "theprez@gmail.com", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField(
"Address Line 1:", "address", "190 High Street", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("City:", "city", "Philadelphia", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("State:", "state", "Pennsylvania", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("Zip:", "zipcode", "19106", "text", &field);
form2.fields.push_back(field);
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure2));
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
const std::vector<AutofillProfile*>& results2 = personal_data_->GetProfiles();
// Expect no change.
ASSERT_EQ(1U, results2.size());
EXPECT_EQ(0, expected.Compare(*results2[0]));
}
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_InsufficientAddress) {
FormData form1;
FormFieldData field;
test::CreateTestFormField(
"First name:", "first_name", "George", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField(
"Last name:", "last_name", "Washington", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField(
"Company:", "company", "Government", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField(
"Email:", "email", "theprez@gmail.com", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField(
"Address Line 1:", "address", "190 High Street", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("City:", "city", "Philadelphia", "text", &field);
form1.fields.push_back(field);
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes();
EXPECT_FALSE(ImportAddressProfiles(form_structure1));
// Since no refresh is expected, reload the data from the database to make
// sure no changes were written out.
ResetPersonalDataManager(USER_MODE_NORMAL);
const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
ASSERT_EQ(0U, profiles.size());
const std::vector<CreditCard*>& cards = personal_data_->GetCreditCards();
ASSERT_EQ(0U, cards.size());
}
// Ensure that if a verified profile already exists, aggregated profiles cannot
// modify it in any way. This also checks the profile merging/matching algorithm
// works: if either the full name OR all the non-empty name pieces match, the
// profile is a match.
TEST_F(PersonalDataManagerTest,
ImportAddressProfiles_ExistingVerifiedProfileWithConflict) {
// Start with a verified profile.
AutofillProfile profile(base::GenerateGUID(), kSettingsOrigin);
test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
EXPECT_TRUE(profile.IsVerified());
// Add the profile to the database.
personal_data_->AddProfile(profile);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// Simulate a form submission with conflicting info.
FormData form;
FormFieldData field;
test::CreateTestFormField("First name:", "first_name", "Marion Mitchell",
"text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Last name:", "last_name", "Morrison", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Email:", "email", "johnwayne@me.xyz", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Address:", "address1", "123 Zoo St.", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "Hollywood", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("State:", "state", "CA", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "91601", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
// Wait for the refresh, which in this case is a no-op.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// Expect that no new profile is saved.
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, profile.Compare(*results[0]));
// Try the same thing, but without "Mitchell". The profiles should still match
// because the non empty name pieces (first and last) match that stored in the
// profile.
test::CreateTestFormField("First name:", "first_name", "Marion", "text",
&field);
form.fields[0] = field;
FormStructure form_structure2(form);
form_structure2.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure2));
// Wait for the refresh, which in this case is a no-op.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// Expect that no new profile is saved.
const std::vector<AutofillProfile*>& results2 = personal_data_->GetProfiles();
ASSERT_EQ(1U, results2.size());
EXPECT_EQ(0, profile.Compare(*results2[0]));
}
// ImportCreditCard tests.
// Tests that a valid credit card is extracted.
TEST_F(PersonalDataManagerTest, ImportCreditCard_Valid) {
// Add a single valid credit card form.
FormData form;
AddFullCreditCardForm(&form, "Biggie Smalls", "4111-1111-1111-1111", "01",
"2999");
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
personal_data_->SaveImportedCreditCard(*imported_credit_card);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
CreditCard expected(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&expected, "Biggie Smalls", "4111111111111111", "01",
"2999");
const std::vector<CreditCard*>& results = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, expected.Compare(*results[0]));
}
// Tests that an invalid credit card is not extracted.
TEST_F(PersonalDataManagerTest, ImportCreditCard_Invalid) {
FormData form;
AddFullCreditCardForm(&form, "Jim Johansen", "1000000000000000", "02",
"3999");
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_FALSE(ImportCreditCard(form_structure, false, &imported_credit_card));
ASSERT_FALSE(imported_credit_card);
// Since no refresh is expected, reload the data from the database to make
// sure no changes were written out.
ResetPersonalDataManager(USER_MODE_NORMAL);
const std::vector<CreditCard*>& results = personal_data_->GetCreditCards();
ASSERT_EQ(0U, results.size());
}
// Tests that a valid credit card is extracted when the option text for month
// select can't be parsed but its value can.
TEST_F(PersonalDataManagerTest, ImportCreditCard_MonthSelectInvalidText) {
// Add a single valid credit card form with an invalid option value.
FormData form;
AddFullCreditCardForm(&form, "Biggie Smalls", "4111-1111-1111-1111",
"Feb (2)", "2999");
// Add option values and contents to the expiration month field.
ASSERT_EQ(ASCIIToUTF16("exp_month"), form.fields[2].name);
std::vector<base::string16> values;
values.push_back(ASCIIToUTF16("1"));
values.push_back(ASCIIToUTF16("2"));
values.push_back(ASCIIToUTF16("3"));
std::vector<base::string16> contents;
contents.push_back(ASCIIToUTF16("Jan (1)"));
contents.push_back(ASCIIToUTF16("Feb (2)"));
contents.push_back(ASCIIToUTF16("Mar (3)"));
form.fields[2].option_values = values;
form.fields[2].option_contents = contents;
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
personal_data_->SaveImportedCreditCard(*imported_credit_card);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// See that the invalid option text was converted to the right value.
CreditCard expected(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&expected, "Biggie Smalls", "4111111111111111", "02",
"2999");
const std::vector<CreditCard*>& results = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, expected.Compare(*results[0]));
}
TEST_F(PersonalDataManagerTest, ImportCreditCard_TwoValidCards) {
// Start with a single valid credit card form.
FormData form1;
AddFullCreditCardForm(&form1, "Biggie Smalls", "4111-1111-1111-1111", "01",
"2999");
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure1, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
personal_data_->SaveImportedCreditCard(*imported_credit_card);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
CreditCard expected(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&expected, "Biggie Smalls", "4111111111111111", "01",
"2999");
const std::vector<CreditCard*>& results = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, expected.Compare(*results[0]));
// Add a second different valid credit card.
FormData form2;
AddFullCreditCardForm(&form2, "", "5500 0000 0000 0004", "02", "3999");
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card2;
EXPECT_TRUE(ImportCreditCard(form_structure2, false, &imported_credit_card2));
ASSERT_TRUE(imported_credit_card2);
personal_data_->SaveImportedCreditCard(*imported_credit_card2);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
CreditCard expected2(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&expected2, "", "5500000000000004", "02", "3999");
std::vector<CreditCard*> cards;
cards.push_back(&expected);
cards.push_back(&expected2);
ExpectSameElements(cards, personal_data_->GetCreditCards());
}
// Tests that a credit card is extracted because it only matches a masked server
// card.
TEST_F(PersonalDataManagerTest,
ImportCreditCard_DuplicateServerCards_MaskedCard) {
// Add a masked server card.
std::vector<CreditCard> server_cards;
server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "a123"));
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"1111" /* Visa */, "01", "2999");
server_cards.back().SetTypeForMaskedCard(kVisaCard);
test::SetServerCreditCards(autofill_table_, server_cards);
// Type the same data as the masked card into a form.
FormData form;
AddFullCreditCardForm(&form, "John Dillinger", "4111111111111111", "01",
"2999");
// The card should be offered to be saved locally because it only matches the
// masked server card.
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
personal_data_->SaveImportedCreditCard(*imported_credit_card);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
}
// Tests that a credit card is not extracted because it matches a full server
// card.
TEST_F(PersonalDataManagerTest,
ImportCreditCard_DuplicateServerCards_FullCard) {
// Add a full server card.
std::vector<CreditCard> server_cards;
server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "c789"));
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"347666888555" /* American Express */, "04", "3999");
test::SetServerCreditCards(autofill_table_, server_cards);
// Type the same data as the unmasked card into a form.
FormData form;
AddFullCreditCardForm(&form, "Clyde Barrow", "347666888555", "04", "3999");
// The card should not be offered to be saved locally because it only matches
// the full server card.
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_FALSE(ImportCreditCard(form_structure, false, &imported_credit_card));
ASSERT_FALSE(imported_credit_card);
}
TEST_F(PersonalDataManagerTest, ImportCreditCard_SameCreditCardWithConflict) {
// Start with a single valid credit card form.
FormData form1;
AddFullCreditCardForm(&form1, "Biggie Smalls", "4111-1111-1111-1111", "01",
"2999");
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure1, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
personal_data_->SaveImportedCreditCard(*imported_credit_card);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
CreditCard expected(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&expected,
"Biggie Smalls", "4111111111111111", "01", "2999");
const std::vector<CreditCard*>& results = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, expected.Compare(*results[0]));
// Add a second different valid credit card where the year is different but
// the credit card number matches.
FormData form2;
AddFullCreditCardForm(&form2, "Biggie Smalls", "4111 1111 1111 1111", "01",
/* different year */ "3999");
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card2;
EXPECT_TRUE(ImportCreditCard(form_structure2, false, &imported_credit_card2));
EXPECT_FALSE(imported_credit_card2);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// Expect that the newer information is saved. In this case the year is
// updated to "3999".
CreditCard expected2(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&expected2, "Biggie Smalls", "4111111111111111", "01",
"3999");
const std::vector<CreditCard*>& results2 = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results2.size());
EXPECT_EQ(0, expected2.Compare(*results2[0]));
}
TEST_F(PersonalDataManagerTest, ImportCreditCard_ShouldReturnLocalCard) {
// Start with a single valid credit card form.
FormData form1;
AddFullCreditCardForm(&form1, "Biggie Smalls", "4111-1111-1111-1111", "01",
"2999");
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure1, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
personal_data_->SaveImportedCreditCard(*imported_credit_card);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
CreditCard expected(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&expected,
"Biggie Smalls", "4111111111111111", "01", "2999");
const std::vector<CreditCard*>& results = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, expected.Compare(*results[0]));
// Add a second different valid credit card where the year is different but
// the credit card number matches.
FormData form2;
AddFullCreditCardForm(&form2, "Biggie Smalls", "4111 1111 1111 1111", "01",
/* different year */ "3999");
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card2;
EXPECT_TRUE(ImportCreditCard(form_structure2,
/* should_return_local_card= */ true,
&imported_credit_card2));
// The local card is returned after an update.
EXPECT_TRUE(imported_credit_card2);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// Expect that the newer information is saved. In this case the year is
// updated to "3999".
CreditCard expected2(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&expected2,
"Biggie Smalls", "4111111111111111", "01", "3999");
const std::vector<CreditCard*>& results2 = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results2.size());
EXPECT_EQ(0, expected2.Compare(*results2[0]));
}
TEST_F(PersonalDataManagerTest, ImportCreditCard_EmptyCardWithConflict) {
// Start with a single valid credit card form.
FormData form1;
AddFullCreditCardForm(&form1, "Biggie Smalls", "4111-1111-1111-1111", "01",
"2999");
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure1, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
personal_data_->SaveImportedCreditCard(*imported_credit_card);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
CreditCard expected(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&expected,
"Biggie Smalls", "4111111111111111", "01", "2999");
const std::vector<CreditCard*>& results = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, expected.Compare(*results[0]));
// Add a second credit card with no number.
FormData form2;
AddFullCreditCardForm(&form2, "Biggie Smalls", /* no number */ nullptr, "01",
"3999");
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card2;
EXPECT_FALSE(
ImportCreditCard(form_structure2, false, &imported_credit_card2));
EXPECT_FALSE(imported_credit_card2);
// Since no refresh is expected, reload the data from the database to make
// sure no changes were written out.
ResetPersonalDataManager(USER_MODE_NORMAL);
// No change is expected.
CreditCard expected2(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&expected2,
"Biggie Smalls", "4111111111111111", "01", "2999");
const std::vector<CreditCard*>& results2 = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results2.size());
EXPECT_EQ(0, expected2.Compare(*results2[0]));
}
TEST_F(PersonalDataManagerTest, ImportCreditCard_MissingInfoInNew) {
// Start with a single valid credit card form.
FormData form1;
AddFullCreditCardForm(&form1, "Biggie Smalls", "4111-1111-1111-1111", "01",
"2999");
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure1, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
personal_data_->SaveImportedCreditCard(*imported_credit_card);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
CreditCard expected(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&expected,
"Biggie Smalls", "4111111111111111", "01", "2999");
const std::vector<CreditCard*>& results = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, expected.Compare(*results[0]));
// Add a second different valid credit card where the name is missing but
// the credit card number matches.
FormData form2;
AddFullCreditCardForm(&form2, /* missing name */ nullptr,
"4111-1111-1111-1111", "01", "2999");
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card2;
EXPECT_TRUE(ImportCreditCard(form_structure2, false, &imported_credit_card2));
EXPECT_FALSE(imported_credit_card2);
// Since no refresh is expected, reload the data from the database to make
// sure no changes were written out.
ResetPersonalDataManager(USER_MODE_NORMAL);
// No change is expected.
CreditCard expected2(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&expected2,
"Biggie Smalls", "4111111111111111", "01", "2999");
const std::vector<CreditCard*>& results2 = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results2.size());
EXPECT_EQ(0, expected2.Compare(*results2[0]));
// Add a third credit card where the expiration date is missing.
FormData form3;
AddFullCreditCardForm(&form3, "Johnny McEnroe", "5555555555554444",
/* no month */ nullptr,
/* no year */ nullptr);
FormStructure form_structure3(form3);
form_structure3.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card3;
EXPECT_FALSE(
ImportCreditCard(form_structure3, false, &imported_credit_card3));
ASSERT_FALSE(imported_credit_card3);
// Since no refresh is expected, reload the data from the database to make
// sure no changes were written out.
ResetPersonalDataManager(USER_MODE_NORMAL);
// No change is expected.
CreditCard expected3(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&expected3,
"Biggie Smalls", "4111111111111111", "01", "2999");
const std::vector<CreditCard*>& results3 = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results3.size());
EXPECT_EQ(0, expected3.Compare(*results3[0]));
}
TEST_F(PersonalDataManagerTest, ImportCreditCard_MissingInfoInOld) {
// Start with a single valid credit card stored via the preferences.
// Note the empty name.
CreditCard saved_credit_card(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&saved_credit_card,
"", "4111111111111111" /* Visa */, "01", "2999");
personal_data_->AddCreditCard(saved_credit_card);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
const std::vector<CreditCard*>& results1 = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results1.size());
EXPECT_EQ(saved_credit_card, *results1[0]);
// Add a second different valid credit card where the year is different but
// the credit card number matches.
FormData form;
AddFullCreditCardForm(&form, "Biggie Smalls", "4111-1111-1111-1111", "01",
/* different year */ "3999");
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
EXPECT_FALSE(imported_credit_card);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// Expect that the newer information is saved. In this case the year is
// added to the existing credit card.
CreditCard expected2(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&expected2,
"Biggie Smalls", "4111111111111111", "01", "3999");
const std::vector<CreditCard*>& results2 = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results2.size());
EXPECT_EQ(0, expected2.Compare(*results2[0]));
}
// We allow the user to store a credit card number with separators via the UI.
// We should not try to re-aggregate the same card with the separators stripped.
TEST_F(PersonalDataManagerTest, ImportCreditCard_SameCardWithSeparators) {
// Start with a single valid credit card stored via the preferences.
// Note the separators in the credit card number.
CreditCard saved_credit_card(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&saved_credit_card,
"Biggie Smalls", "4111 1111 1111 1111" /* Visa */, "01", "2999");
personal_data_->AddCreditCard(saved_credit_card);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
const std::vector<CreditCard*>& results1 = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results1.size());
EXPECT_EQ(0, saved_credit_card.Compare(*results1[0]));
// Import the same card info, but with different separators in the number.
FormData form;
AddFullCreditCardForm(&form, "Biggie Smalls", "4111-1111-1111-1111", "01",
"2999");
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
EXPECT_FALSE(imported_credit_card);
// Since no refresh is expected, reload the data from the database to make
// sure no changes were written out.
ResetPersonalDataManager(USER_MODE_NORMAL);
// Expect that no new card is saved.
const std::vector<CreditCard*>& results2 = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results2.size());
EXPECT_EQ(0, saved_credit_card.Compare(*results2[0]));
}
// Ensure that if a verified credit card already exists, aggregated credit cards
// cannot modify it in any way.
TEST_F(PersonalDataManagerTest,
ImportCreditCard_ExistingVerifiedCardWithConflict) {
// Start with a verified credit card.
CreditCard credit_card(base::GenerateGUID(), 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);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// Simulate a form submission with conflicting expiration year.
FormData form;
AddFullCreditCardForm(&form, "Biggie Smalls", "4111 1111 1111 1111", "01",
/* different year */ "3999");
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
ASSERT_FALSE(imported_credit_card);
// Since no refresh is expected, reload the data from the database to make
// sure no changes were written out.
ResetPersonalDataManager(USER_MODE_NORMAL);
// Expect that the saved credit card is not modified.
const std::vector<CreditCard*>& results = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, credit_card.Compare(*results[0]));
}
// ImportFormData tests (both addresses and credit cards).
// Test that a form with both address and credit card sections imports the
// address and the credit card.
TEST_F(PersonalDataManagerTest, ImportFormData_OneAddressOneCreditCard) {
FormData form;
FormFieldData field;
// Address section.
test::CreateTestFormField("First name:", "first_name", "George", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Address:", "address1", "21 Laussat St", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("State:", "state", "California", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
// Credit card section.
AddFullCreditCardForm(&form, "Biggie Smalls", "4111-1111-1111-1111", "01",
"2999");
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(personal_data_->ImportFormData(form_structure, false,
&imported_credit_card));
ASSERT_TRUE(imported_credit_card);
personal_data_->SaveImportedCreditCard(*imported_credit_card);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// Test that the address has been saved.
AutofillProfile expected_address(base::GenerateGUID(),
"https://www.example.com");
test::SetProfileInfo(&expected_address, "George", NULL, "Washington",
"theprez@gmail.com", NULL, "21 Laussat St", NULL,
"San Francisco", "California", "94102", NULL, NULL);
const std::vector<AutofillProfile*>& results_addr =
personal_data_->GetProfiles();
ASSERT_EQ(1U, results_addr.size());
EXPECT_EQ(0, expected_address.Compare(*results_addr[0]));
// Test that the credit card has also been saved.
CreditCard expected_card(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&expected_card, "Biggie Smalls", "4111111111111111",
"01", "2999");
const std::vector<CreditCard*>& results_cards =
personal_data_->GetCreditCards();
ASSERT_EQ(1U, results_cards.size());
EXPECT_EQ(0, expected_card.Compare(*results_cards[0]));
}
// Test that a form with two address sections and a credit card section does not
// import the address but does import the credit card.
TEST_F(PersonalDataManagerTest, ImportFormData_TwoAddressesOneCreditCard) {
FormData form;
FormFieldData field;
// Address section 1.
test::CreateTestFormField("First name:", "first_name", "George", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("Address:", "address1", "21 Laussat St", "text",
&field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("State:", "state", "California", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
// Address section 2.
test::CreateTestFormField("Name:", "name", "Barack Obama", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Address:", "address", "1600 Pennsylvania Avenue",
"text", &field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "Washington", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("State:", "state", "DC", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "20500", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Country:", "country", "USA", "text", &field);
form.fields.push_back(field);
// Credit card section.
AddFullCreditCardForm(&form, "Biggie Smalls", "4111-1111-1111-1111", "01",
"2999");
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
// Still returns true because the credit card import was successful.
EXPECT_TRUE(personal_data_->ImportFormData(form_structure, false,
&imported_credit_card));
ASSERT_TRUE(imported_credit_card);
personal_data_->SaveImportedCreditCard(*imported_credit_card);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// Test that both addresses have been saved.
EXPECT_EQ(2U, personal_data_->GetProfiles().size());
// Test that the credit card has been saved.
CreditCard expected_card(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&expected_card, "Biggie Smalls", "4111111111111111",
"01", "2999");
const std::vector<CreditCard*>& results = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, expected_card.Compare(*results[0]));
}
// Ensure that verified profiles can be saved via SaveImportedProfile,
// overwriting existing unverified profiles.
TEST_F(PersonalDataManagerTest, SaveImportedProfileWithVerifiedData) {
// Start with an unverified profile.
AutofillProfile profile(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile,
"Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
"91601", "US", "12345678910");
EXPECT_FALSE(profile.IsVerified());
// Add the profile to the database.
personal_data_->AddProfile(profile);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
AutofillProfile new_verified_profile = profile;
new_verified_profile.set_guid(base::GenerateGUID());
new_verified_profile.set_origin(kSettingsOrigin);
new_verified_profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
ASCIIToUTF16("1 234 567-8910"));
EXPECT_TRUE(new_verified_profile.IsVerified());
personal_data_->SaveImportedProfile(new_verified_profile);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// The new profile should be merged into the existing one.
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, new_verified_profile.Compare(*results[0]));
}
// Ensure that verified profiles can be saved via SaveImportedProfile,
// overwriting existing verified profiles as well.
TEST_F(PersonalDataManagerTest, SaveImportedProfileWithExistingVerifiedData) {
// Start with a verified profile.
AutofillProfile profile(base::GenerateGUID(), kSettingsOrigin);
test::SetProfileInfo(&profile,
"Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
"91601", "US", "12345678910");
EXPECT_TRUE(profile.IsVerified());
// Add the profile to the database.
personal_data_->AddProfile(profile);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
AutofillProfile new_verified_profile = profile;
new_verified_profile.set_guid(base::GenerateGUID());
new_verified_profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
ASCIIToUTF16("1 234 567-8910"));
EXPECT_TRUE(new_verified_profile.IsVerified());
personal_data_->SaveImportedProfile(new_verified_profile);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// The new profile should be merged into the existing one.
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, new_verified_profile.Compare(*results[0]));
}
// Ensure that verified credit cards can be saved via SaveImportedCreditCard.
TEST_F(PersonalDataManagerTest, SaveImportedCreditCardWithVerifiedData) {
// Start with a verified credit card.
CreditCard credit_card(base::GenerateGUID(), 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);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
CreditCard new_verified_card = credit_card;
new_verified_card.set_guid(base::GenerateGUID());
new_verified_card.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("B. Small"));
EXPECT_TRUE(new_verified_card.IsVerified());
personal_data_->SaveImportedCreditCard(new_verified_card);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// Expect that the saved credit card is updated.
const std::vector<CreditCard*>& results = personal_data_->GetCreditCards();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(ASCIIToUTF16("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(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile0,
"Marion", NULL, "Morrison",
"johnwayne@me.xyz", NULL, "123 Zoo St.", NULL, "Hollywood", "CA",
"91601", "US", "14155678910");
personal_data_->AddProfile(profile0);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
personal_data_->GetNonEmptyTypes(&non_empty_types);
EXPECT_EQ(15U, non_empty_types.size());
EXPECT_TRUE(non_empty_types.count(NAME_FIRST));
EXPECT_TRUE(non_empty_types.count(NAME_LAST));
EXPECT_TRUE(non_empty_types.count(NAME_FULL));
EXPECT_TRUE(non_empty_types.count(EMAIL_ADDRESS));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_LINE1));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STREET_ADDRESS));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_CITY));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STATE));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_ZIP));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_COUNTRY));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_NUMBER));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_COUNTRY_CODE));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_CODE));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_AND_NUMBER));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_WHOLE_NUMBER));
// Test with multiple profiles stored.
AutofillProfile profile1(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile1,
"Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "903 Apple Ct.", NULL, "Orlando", "FL", "32801",
"US", "16502937549");
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile2,
"Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL",
"32801", "US", "16502937549");
personal_data_->AddProfile(profile1);
personal_data_->AddProfile(profile2);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
personal_data_->GetNonEmptyTypes(&non_empty_types);
EXPECT_EQ(19U, non_empty_types.size());
EXPECT_TRUE(non_empty_types.count(NAME_FIRST));
EXPECT_TRUE(non_empty_types.count(NAME_MIDDLE));
EXPECT_TRUE(non_empty_types.count(NAME_MIDDLE_INITIAL));
EXPECT_TRUE(non_empty_types.count(NAME_LAST));
EXPECT_TRUE(non_empty_types.count(NAME_FULL));
EXPECT_TRUE(non_empty_types.count(EMAIL_ADDRESS));
EXPECT_TRUE(non_empty_types.count(COMPANY_NAME));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_LINE1));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_LINE2));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STREET_ADDRESS));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_CITY));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STATE));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_ZIP));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_COUNTRY));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_NUMBER));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_CODE));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_COUNTRY_CODE));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_AND_NUMBER));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_WHOLE_NUMBER));
// Test with credit card information also stored.
CreditCard credit_card(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&credit_card,
"John Dillinger", "423456789012" /* Visa */,
"01", "2999");
personal_data_->AddCreditCard(credit_card);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
personal_data_->GetNonEmptyTypes(&non_empty_types);
EXPECT_EQ(29U, non_empty_types.size());
EXPECT_TRUE(non_empty_types.count(NAME_FIRST));
EXPECT_TRUE(non_empty_types.count(NAME_MIDDLE));
EXPECT_TRUE(non_empty_types.count(NAME_MIDDLE_INITIAL));
EXPECT_TRUE(non_empty_types.count(NAME_LAST));
EXPECT_TRUE(non_empty_types.count(NAME_FULL));
EXPECT_TRUE(non_empty_types.count(EMAIL_ADDRESS));
EXPECT_TRUE(non_empty_types.count(COMPANY_NAME));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_LINE1));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_LINE2));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STREET_ADDRESS));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_CITY));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STATE));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_ZIP));
EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_COUNTRY));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_NUMBER));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_CODE));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_COUNTRY_CODE));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_CITY_AND_NUMBER));
EXPECT_TRUE(non_empty_types.count(PHONE_HOME_WHOLE_NUMBER));
EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_NAME_FULL));
EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_NAME_FIRST));
EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_NAME_LAST));
EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_NUMBER));
EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_TYPE));
EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_EXP_MONTH));
EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_EXP_2_DIGIT_YEAR));
EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_EXP_4_DIGIT_YEAR));
EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR));
EXPECT_TRUE(non_empty_types.count(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR));
}
TEST_F(PersonalDataManagerTest, IncognitoReadOnly) {
ASSERT_TRUE(personal_data_->GetProfiles().empty());
ASSERT_TRUE(personal_data_->GetCreditCards().empty());
AutofillProfile steve_jobs(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&steve_jobs, "Steven", "Paul", "Jobs", "sjobs@apple.com",
"Apple Computer, Inc.", "1 Infinite Loop", "", "Cupertino", "CA", "95014",
"US", "(800) 275-2273");
personal_data_->AddProfile(steve_jobs);
CreditCard bill_gates(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(
&bill_gates, "William H. Gates", "5555555555554444", "1", "2020");
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::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(
&larry_page, "Lawrence Page", "4111111111111111", "10", "2025");
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, ASCIIToUTF16("Steve"));
personal_data_->SaveImportedProfile(steve_jobs);
bill_gates.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("Bill Gates"));
personal_data_->SaveImportedCreditCard(bill_gates);
ResetPersonalDataManager(USER_MODE_INCOGNITO);
EXPECT_EQ(ASCIIToUTF16("Steven"),
personal_data_->GetProfiles()[0]->GetRawInfo(NAME_FIRST));
EXPECT_EQ(
ASCIIToUTF16("William H. Gates"),
personal_data_->GetCreditCards()[0]->GetRawInfo(CREDIT_CARD_NAME_FULL));
// Updating existing profiles shouldn't work.
steve_jobs.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Steve"));
personal_data_->UpdateProfile(steve_jobs);
bill_gates.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("Bill Gates"));
personal_data_->UpdateCreditCard(bill_gates);
ResetPersonalDataManager(USER_MODE_INCOGNITO);
EXPECT_EQ(ASCIIToUTF16("Steven"),
personal_data_->GetProfiles()[0]->GetRawInfo(NAME_FIRST));
EXPECT_EQ(
ASCIIToUTF16("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());
}
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 moose(base::GenerateGUID(), kSettingsOrigin);
test::SetProfileInfo(&moose, "Moose", "P", "McMahon", "mpm@example.com",
"", "1 Taiga TKTR", "", "Calgary", "AB", "T2B 2K2",
"CA", "(800) 555-9000");
personal_data_->AddProfile(moose);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// The value is cached and doesn't change even after adding an address.
EXPECT_EQ(default_country,
personal_data_->GetDefaultCountryCodeForNewAddress());
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(2);
// Disabling Autofill blows away this cache and shouldn't account for Autofill
// profiles.
prefs_->SetBoolean(prefs::kAutofillEnabled, false);
EXPECT_EQ(default_country,
personal_data_->GetDefaultCountryCodeForNewAddress());
// Enabling Autofill blows away the cached value and should reflect the new
// value (accounting for profiles).
prefs_->SetBoolean(prefs::kAutofillEnabled, true);
EXPECT_EQ(base::UTF16ToUTF8(moose.GetRawInfo(ADDRESS_HOME_COUNTRY)),
personal_data_->GetDefaultCountryCodeForNewAddress());
}
TEST_F(PersonalDataManagerTest, DefaultCountryCodeComesFromProfiles) {
AutofillProfile moose(base::GenerateGUID(), kSettingsOrigin);
test::SetProfileInfo(&moose, "Moose", "P", "McMahon", "mpm@example.com",
"", "1 Taiga TKTR", "", "Calgary", "AB", "T2B 2K2",
"CA", "(800) 555-9000");
personal_data_->AddProfile(moose);
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_EQ("CA", personal_data_->GetDefaultCountryCodeForNewAddress());
// Multiple profiles cast votes.
AutofillProfile armadillo(base::GenerateGUID(), kSettingsOrigin);
test::SetProfileInfo(&armadillo, "Armin", "Dill", "Oh", "ado@example.com",
"", "1 Speed Bump", "", "Lubbock", "TX", "77500",
"MX", "(800) 555-9000");
AutofillProfile armadillo2(base::GenerateGUID(), kSettingsOrigin);
test::SetProfileInfo(&armadillo2, "Armin", "Dill", "Oh", "ado@example.com",
"", "2 Speed Bump", "", "Lubbock", "TX", "77500",
"MX", "(800) 555-9000");
personal_data_->AddProfile(armadillo);
personal_data_->AddProfile(armadillo2);
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_EQ("MX", personal_data_->GetDefaultCountryCodeForNewAddress());
personal_data_->RemoveByGUID(armadillo.guid());
personal_data_->RemoveByGUID(armadillo2.guid());
ResetPersonalDataManager(USER_MODE_NORMAL);
// Verified profiles count more.
armadillo.set_origin("http://randomwebsite.com");
armadillo2.set_origin("http://randomwebsite.com");
personal_data_->AddProfile(armadillo);
personal_data_->AddProfile(armadillo2);
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_EQ("CA", personal_data_->GetDefaultCountryCodeForNewAddress());
personal_data_->RemoveByGUID(armadillo.guid());
ResetPersonalDataManager(USER_MODE_NORMAL);
// But unverified profiles can be a tie breaker.
armadillo.set_origin(kSettingsOrigin);
personal_data_->AddProfile(armadillo);
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_EQ("MX", personal_data_->GetDefaultCountryCodeForNewAddress());
// Invalid country codes are ignored.
personal_data_->RemoveByGUID(armadillo.guid());
personal_data_->RemoveByGUID(moose.guid());
AutofillProfile space_invader(base::GenerateGUID(), kSettingsOrigin);
test::SetProfileInfo(&space_invader, "Marty", "", "Martian",
"mm@example.com", "", "1 Flying Object", "", "Valles Marineris", "",
"", "XX", "");
personal_data_->AddProfile(moose);
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_EQ("MX", personal_data_->GetDefaultCountryCodeForNewAddress());
}
TEST_F(PersonalDataManagerTest, UpdateLanguageCodeInProfile) {
AutofillProfile profile(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile,
"Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
"91601", "US", "12345678910");
personal_data_->AddProfile(profile);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
profile.set_language_code("en");
personal_data_->UpdateProfile(profile);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
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(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile,
"Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5", "Hollywood", "CA",
"91601", "US", "12345678910");
personal_data_->AddProfile(profile);
ResetPersonalDataManager(USER_MODE_NORMAL);
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(ADDRESS_HOME_STREET_ADDRESS), base::ASCIIToUTF16("123"),
false, std::vector<ServerFieldType>());
ASSERT_FALSE(suggestions.empty());
EXPECT_EQ(base::ASCIIToUTF16("123 Zoo St., Second Line, Third line, unit 5"),
suggestions[0].value);
}
TEST_F(PersonalDataManagerTest, GetProfileSuggestions_PhoneSubstring) {
AutofillProfile profile(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
personal_data_->AddProfile(profile);
ResetPersonalDataManager(USER_MODE_NORMAL);
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(PHONE_HOME_WHOLE_NUMBER), base::ASCIIToUTF16("234"), false,
std::vector<ServerFieldType>());
ASSERT_FALSE(suggestions.empty());
EXPECT_EQ(base::ASCIIToUTF16("12345678910"), suggestions[0].value);
}
TEST_F(PersonalDataManagerTest, GetProfileSuggestions_HideSubsets) {
AutofillProfile profile(base::GenerateGUID(), "https://www.example.com");
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::GenerateGUID());
profile1.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("spam_me@example.com"));
// Dupe profile, except different in address state.
AutofillProfile profile2 = profile;
profile2.set_guid(base::GenerateGUID());
profile2.SetRawInfo(ADDRESS_HOME_STATE, base::ASCIIToUTF16("TX"));
// Subset profile.
AutofillProfile profile3 = profile;
profile3.set_guid(base::GenerateGUID());
profile3.SetRawInfo(ADDRESS_HOME_STATE, base::string16());
// For easier results verification, make sure |profile| is suggested first.
profile.set_use_count(5);
personal_data_->AddProfile(profile);
personal_data_->AddProfile(profile1);
personal_data_->AddProfile(profile2);
personal_data_->AddProfile(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), base::ASCIIToUTF16("123"),
false, types);
ASSERT_EQ(2U, suggestions.size());
EXPECT_EQ(base::ASCIIToUTF16("Hollywood, CA"), suggestions[0].label);
EXPECT_EQ(base::ASCIIToUTF16("Hollywood, TX"), suggestions[1].label);
}
// Tests that GetProfileSuggestions orders its suggestions based on the frecency
// 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 frecency.
AutofillProfile profile3(base::GenerateGUID(), "https://www.example.com");
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(base::Time::Now() - base::TimeDelta::FromDays(1));
profile3.set_use_count(5);
personal_data_->AddProfile(profile3);
AutofillProfile profile1(base::GenerateGUID(), "https://www.example.com");
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(base::Time::Now() - base::TimeDelta::FromDays(1));
profile1.set_use_count(10);
personal_data_->AddProfile(profile1);
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
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(base::Time::Now() - base::TimeDelta::FromDays(15));
profile2.set_use_count(300);
personal_data_->AddProfile(profile2);
ResetPersonalDataManager(USER_MODE_NORMAL);
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(NAME_FIRST), base::ASCIIToUTF16("Ma"), false,
std::vector<ServerFieldType>());
ASSERT_EQ(3U, suggestions.size());
EXPECT_EQ(suggestions[0].value, base::ASCIIToUTF16("Marion1"));
EXPECT_EQ(suggestions[1].value, base::ASCIIToUTF16("Marion2"));
EXPECT_EQ(suggestions[2].value, base::ASCIIToUTF16("Marion3"));
}
// Tests that GetProfileSuggestions returns all profiles suggestions by default
// and only two if the appropriate field trial is set.
TEST_F(PersonalDataManagerTest, GetProfileSuggestions_NumberOfSuggestions) {
// Set up 3 different profiles.
AutofillProfile profile1(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile1, "Marion1", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
personal_data_->AddProfile(profile1);
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile2, "Marion2", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
personal_data_->AddProfile(profile2);
AutofillProfile profile3(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile3, "Marion3", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
personal_data_->AddProfile(profile3);
ResetPersonalDataManager(USER_MODE_NORMAL);
// Verify that all the profiles are suggested.
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(NAME_FIRST), base::string16(), false,
std::vector<ServerFieldType>());
EXPECT_EQ(3U, suggestions.size());
// Verify that only two profiles are suggested.
EnableAutofillProfileLimitFieldTrial("2");
suggestions = personal_data_->GetProfileSuggestions(
AutofillType(NAME_FIRST), base::string16(), false,
std::vector<ServerFieldType>());
EXPECT_EQ(2U, suggestions.size());
}
// Tests that GetProfileSuggestions returns the right number of profile
// suggestions when the limit to three field trial is set and there are less
// than three profiles.
TEST_F(PersonalDataManagerTest,
GetProfileSuggestions_LimitIsMoreThanProfileSuggestions) {
EnableAutofillProfileLimitFieldTrial("3");
// Set up 2 different profiles.
AutofillProfile profile1(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile1, "Marion1", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
personal_data_->AddProfile(profile1);
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile2, "Marion2", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
personal_data_->AddProfile(profile2);
ResetPersonalDataManager(USER_MODE_NORMAL);
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(NAME_FIRST), base::string16(), false,
std::vector<ServerFieldType>());
EXPECT_EQ(2U, suggestions.size());
}
// Test that a masked server card is not suggested if more that six numbers have
// been typed in the field.
TEST_F(PersonalDataManagerTest,
GetCreditCardSuggestions_MaskedCardWithMoreThan6Numbers) {
EnableWalletCardImport();
// Add a masked server card.
std::vector<CreditCard> server_cards;
server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b459"));
test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton", "2110", "12",
"3999");
server_cards.back().SetTypeForMaskedCard(kVisaCard);
test::SetServerCreditCards(autofill_table_, server_cards);
personal_data_->Refresh();
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
std::vector<Suggestion> suggestions =
personal_data_->GetCreditCardSuggestions(AutofillType(CREDIT_CARD_NUMBER),
ASCIIToUTF16("12345678"));
// There should be no suggestions.
ASSERT_EQ(0U, suggestions.size());
}
// Test that local credit cards are ordered as expected.
TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_LocalCardsRanking) {
SetupReferenceLocalCreditCards();
// Sublabel is card number when filling name (exact format depends on
// the platform, but the last 4 digits should appear).
std::vector<Suggestion> suggestions =
personal_data_->GetCreditCardSuggestions(
AutofillType(CREDIT_CARD_NAME_FULL),
/* field_contents= */ base::string16());
ASSERT_EQ(3U, suggestions.size());
// Ordered as expected.
EXPECT_EQ(ASCIIToUTF16("John Dillinger"), suggestions[0].value);
EXPECT_TRUE(suggestions[0].label.find(ASCIIToUTF16("9012")) !=
base::string16::npos);
EXPECT_EQ(ASCIIToUTF16("Clyde Barrow"), suggestions[1].value);
EXPECT_TRUE(suggestions[1].label.find(ASCIIToUTF16("8555")) !=
base::string16::npos);
EXPECT_EQ(ASCIIToUTF16("Bonnie Parker"), suggestions[2].value);
EXPECT_TRUE(suggestions[2].label.find(ASCIIToUTF16("2109")) !=
base::string16::npos);
}
// Test that local and server cards are ordered as expected.
TEST_F(PersonalDataManagerTest,
GetCreditCardSuggestions_LocalAndServerCardsRanking) {
EnableWalletCardImport();
SetupReferenceLocalCreditCards();
// Add some server cards.
std::vector<CreditCard> server_cards;
server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b459"));
test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton", "2110", "12",
"3999");
server_cards.back().set_use_count(2);
server_cards.back().set_use_date(base::Time::Now() -
base::TimeDelta::FromDays(1));
server_cards.back().SetTypeForMaskedCard(kVisaCard);
server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "b460"));
test::SetCreditCardInfo(&server_cards.back(), "Jesse James", "2109", "12",
"3999");
server_cards.back().set_use_count(6);
server_cards.back().set_use_date(base::Time::Now() -
base::TimeDelta::FromDays(1));
test::SetServerCreditCards(autofill_table_, server_cards);
personal_data_->Refresh();
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
std::vector<Suggestion> suggestions =
personal_data_->GetCreditCardSuggestions(
AutofillType(CREDIT_CARD_NAME_FULL),
/* field_contents= */ base::string16());
ASSERT_EQ(5U, suggestions.size());
// All cards should be ordered as expected.
EXPECT_EQ(ASCIIToUTF16("Jesse James"), suggestions[0].value);
EXPECT_EQ(ASCIIToUTF16("John Dillinger"), suggestions[1].value);
EXPECT_EQ(ASCIIToUTF16("Clyde Barrow"), suggestions[2].value);
EXPECT_EQ(ASCIIToUTF16("Emmet Dalton"), suggestions[3].value);
EXPECT_EQ(ASCIIToUTF16("Bonnie Parker"), suggestions[4].value);
}
// Test that expired cards are ordered by frecency and are always suggested
// after non expired cards even if they have a higher frecency score.
TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_ExpiredCards) {
ASSERT_EQ(0U, personal_data_->GetCreditCards().size());
// Add a never used non expired credit card.
CreditCard credit_card0("002149C1-EE28-4213-A3B9-DA243FFF021B",
"https://www.example.com");
test::SetCreditCardInfo(&credit_card0, "Bonnie Parker",
"518765432109" /* Mastercard */, "04", "2999");
personal_data_->AddCreditCard(credit_card0);
// Add an expired card with a higher frecency score.
CreditCard credit_card1("287151C8-6AB1-487C-9095-28E80BE5DA15",
"https://www.example.com");
test::SetCreditCardInfo(&credit_card1, "Clyde Barrow",
"347666888555" /* American Express */, "04", "1999");
credit_card1.set_use_count(300);
credit_card1.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(10));
personal_data_->AddCreditCard(credit_card1);
// Add an expired card with a lower frecency score.
CreditCard credit_card2("1141084B-72D7-4B73-90CF-3D6AC154673B",
"https://www.example.com");
credit_card2.set_use_count(3);
credit_card2.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
test::SetCreditCardInfo(&credit_card2, "John Dillinger",
"423456789012" /* Visa */, "01", "1998");
personal_data_->AddCreditCard(credit_card2);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
std::vector<Suggestion> suggestions =
personal_data_->GetCreditCardSuggestions(
AutofillType(CREDIT_CARD_NAME_FULL),
/* field_contents= */ base::string16());
ASSERT_EQ(3U, suggestions.size());
// The never used non expired card should be suggested first.
EXPECT_EQ(ASCIIToUTF16("Bonnie Parker"), suggestions[0].value);
// The expired cards should be sorted by frecency
EXPECT_EQ(ASCIIToUTF16("Clyde Barrow"), suggestions[1].value);
EXPECT_EQ(ASCIIToUTF16("John Dillinger"), suggestions[2].value);
}
// Test that a card that doesn't have a number is not shown in the suggestions
// when querying credit cards by their number.
TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_NumberMissing) {
// Create one normal credit card and one credit card with the number missing.
ASSERT_EQ(0U, personal_data_->GetCreditCards().size());
CreditCard credit_card0("287151C8-6AB1-487C-9095-28E80BE5DA15",
"https://www.example.com");
test::SetCreditCardInfo(&credit_card0, "Clyde Barrow",
"347666888555" /* American Express */, "04", "3999");
credit_card0.set_use_count(3);
credit_card0.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
personal_data_->AddCreditCard(credit_card0);
CreditCard credit_card1("1141084B-72D7-4B73-90CF-3D6AC154673B",
"https://www.example.com");
credit_card1.set_use_count(300);
credit_card1.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(10));
test::SetCreditCardInfo(&credit_card1, "John Dillinger", "", "01", "2999");
personal_data_->AddCreditCard(credit_card1);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
ASSERT_EQ(2U, personal_data_->GetCreditCards().size());
// Sublabel is expiration date when filling card number. The second card
// doesn't have a number so it should not be included in the suggestions.
std::vector<Suggestion> suggestions =
personal_data_->GetCreditCardSuggestions(
AutofillType(CREDIT_CARD_NUMBER),
/* field_contents= */ base::string16());
ASSERT_EQ(1U, suggestions.size());
EXPECT_EQ(UTF8ToUTF16("Amex\xC2\xA0\xE2\x8B\xAF"
"8555"),
suggestions[0].value);
EXPECT_EQ(ASCIIToUTF16("04/99"), suggestions[0].label);
}
// Tests the suggestions of duplicate local and server credit cards.
TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_ServerDuplicates) {
EnableWalletCardImport();
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.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "a123"));
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"9012" /* Visa */, "01", "2999");
server_cards.back().set_use_count(2);
server_cards.back().set_use_date(base::Time::Now() -
base::TimeDelta::FromDays(15));
server_cards.back().SetTypeForMaskedCard(kVisaCard);
// This server card is identical to a local card, but has a different
// card type. Not a dupe and therefore both should appear in the suggestions.
server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b456"));
test::SetCreditCardInfo(&server_cards.back(), "Bonnie Parker", "2109", "12",
"3999");
server_cards.back().set_use_count(3);
server_cards.back().set_use_date(base::Time::Now() -
base::TimeDelta::FromDays(15));
server_cards.back().SetTypeForMaskedCard(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.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "c789"));
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"347666888555" /* American Express */, "04", "3999");
server_cards.back().set_use_count(1);
server_cards.back().set_use_date(base::Time::Now() -
base::TimeDelta::FromDays(15));
test::SetServerCreditCards(autofill_table_, server_cards);
personal_data_->Refresh();
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
std::vector<Suggestion> suggestions =
personal_data_->GetCreditCardSuggestions(
AutofillType(CREDIT_CARD_NAME_FULL),
/* field_contents= */ base::string16());
ASSERT_EQ(4U, suggestions.size());
EXPECT_EQ(ASCIIToUTF16("John Dillinger"), suggestions[0].value);
EXPECT_EQ(ASCIIToUTF16("Clyde Barrow"), suggestions[1].value);
EXPECT_EQ(ASCIIToUTF16("Bonnie Parker"), suggestions[2].value);
EXPECT_EQ(ASCIIToUTF16("Bonnie Parker"), suggestions[3].value);
suggestions = personal_data_->GetCreditCardSuggestions(
AutofillType(CREDIT_CARD_NUMBER), /* field_contents= */ base::string16());
ASSERT_EQ(4U, suggestions.size());
EXPECT_EQ(UTF8ToUTF16("Visa\xC2\xA0\xE2\x8B\xAF"
"9012"),
suggestions[0].value);
EXPECT_EQ(UTF8ToUTF16("Amex\xC2\xA0\xE2\x8B\xAF"
"8555"),
suggestions[1].value);
EXPECT_EQ(UTF8ToUTF16("MasterCard\xC2\xA0\xE2\x8B\xAF"
"2109"),
suggestions[2].value);
EXPECT_EQ(UTF8ToUTF16("Visa\xC2\xA0\xE2\x8B\xAF"
"2109"),
suggestions[3].value);
}
// Tests that a full server card can be a dupe of more than one local card.
TEST_F(PersonalDataManagerTest,
GetCreditCardSuggestions_ServerCardDuplicateOfMultipleLocalCards) {
EnableWalletCardImport();
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.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "c789"));
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"347666888555" /* American Express */, "04", "3999");
test::SetServerCreditCards(autofill_table_, server_cards);
personal_data_->Refresh();
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
std::vector<Suggestion> suggestions =
personal_data_->GetCreditCardSuggestions(
AutofillType(CREDIT_CARD_NAME_FULL),
/* field_contents= */ base::string16());
ASSERT_EQ(3U, suggestions.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",
"https://www.example.com");
test::SetCreditCardInfo(&credit_card3, "Clyde Barrow", "", "04", "");
personal_data_->AddCreditCard(credit_card3);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
suggestions = personal_data_->GetCreditCardSuggestions(
AutofillType(CREDIT_CARD_NAME_FULL),
/* field_contents= */ base::string16());
ASSERT_EQ(3U, suggestions.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<const CreditCard*> credit_cards;
// Create 3 different local credit cards.
CreditCard local_card("287151C8-6AB1-487C-9095-28E80BE5DA15",
"https://www.example.com");
test::SetCreditCardInfo(&local_card, "Homer Simpson",
"423456789012" /* Visa */, "01", "2999");
local_card.set_use_count(3);
local_card.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(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",
"423456789012" /* Visa */, "01", "2999");
full_server_card.set_use_count(1);
full_server_card.set_use_date(base::Time::Now() -
base::TimeDelta::FromDays(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.
TEST_F(PersonalDataManagerTest, DedupeCreditCardToSuggest_LocalShadowsMasked) {
std::list<const CreditCard*> credit_cards;
CreditCard local_card("1141084B-72D7-4B73-90CF-3D6AC154673B",
"https://www.example.com");
local_card.set_use_count(300);
local_card.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(10));
test::SetCreditCardInfo(&local_card, "Homer Simpson",
"423456789012" /* Visa */, "01", "2999");
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", "9012" /* Visa */,
"01", "2999");
masked_card.set_use_count(2);
masked_card.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(15));
masked_card.SetTypeForMaskedCard(kVisaCard);
credit_cards.push_back(&masked_card);
PersonalDataManager::DedupeCreditCardToSuggest(&credit_cards);
ASSERT_EQ(1U, credit_cards.size());
const CreditCard* deduped_card(credit_cards.front());
EXPECT_TRUE(*deduped_card == local_card);
}
// Tests that identical full server and masked credit cards are not deduped.
TEST_F(PersonalDataManagerTest, DedupeCreditCardToSuggest_FullServerAndMasked) {
std::list<const 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",
"423456789012" /* Visa */, "01", "2999");
full_server_card.set_use_count(1);
full_server_card.set_use_date(base::Time::Now() -
base::TimeDelta::FromDays(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", "9012" /* Visa */,
"01", "2999");
masked_card.set_use_count(2);
masked_card.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(15));
masked_card.SetTypeForMaskedCard(kVisaCard);
credit_cards.push_back(&masked_card);
PersonalDataManager::DedupeCreditCardToSuggest(&credit_cards);
EXPECT_EQ(2U, credit_cards.size());
}
// Tests that slightly different local, full server, and masked credit cards are
// not deduped.
TEST_F(PersonalDataManagerTest, DedupeCreditCardToSuggest_DifferentCards) {
std::list<const CreditCard*> credit_cards;
CreditCard credit_card2("002149C1-EE28-4213-A3B9-DA243FFF021B",
"https://www.example.com");
credit_card2.set_use_count(1);
credit_card2.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
test::SetCreditCardInfo(&credit_card2, "Homer Simpson",
"518765432109" /* Mastercard */, "", "");
credit_cards.push_back(&credit_card2);
// Create a masked server card that is slightly different of the local card.
CreditCard credit_card4(CreditCard::MASKED_SERVER_CARD, "b456");
test::SetCreditCardInfo(&credit_card4, "Homer Simpson", "2109", "12", "3999");
credit_card4.set_use_count(3);
credit_card4.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(15));
credit_card4.SetTypeForMaskedCard(kVisaCard);
credit_cards.push_back(&credit_card4);
// Create a full server card that is slightly different of the two other
// cards.
CreditCard credit_card5(CreditCard::FULL_SERVER_CARD, "c789");
test::SetCreditCardInfo(&credit_card5, "Homer Simpson",
"347666888555" /* American Express */, "04", "3999");
credit_card5.set_use_count(1);
credit_card5.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(15));
credit_cards.push_back(&credit_card5);
PersonalDataManager::DedupeCreditCardToSuggest(&credit_cards);
EXPECT_EQ(3U, credit_cards.size());
}
TEST_F(PersonalDataManagerTest, RecordUseOf) {
base::Time creation_time = base::Time::FromTimeT(12345);
AutofillProfile profile(test::GetFullProfile());
profile.set_use_date(creation_time);
profile.set_modification_date(creation_time);
EXPECT_EQ(1U, profile.use_count());
EXPECT_EQ(creation_time, profile.use_date());
EXPECT_EQ(creation_time, profile.modification_date());
personal_data_->AddProfile(profile);
CreditCard credit_card(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&credit_card, "John Dillinger",
"423456789012" /* Visa */, "01", "2999");
credit_card.set_use_date(creation_time);
credit_card.set_modification_date(creation_time);
EXPECT_EQ(1U, credit_card.use_count());
EXPECT_EQ(creation_time, credit_card.use_date());
EXPECT_EQ(creation_time, credit_card.modification_date());
personal_data_->AddCreditCard(credit_card);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// 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);
EXPECT_EQ(1U, added_profile->use_count());
EXPECT_EQ(creation_time, added_profile->use_date());
EXPECT_NE(creation_time, added_profile->modification_date());
personal_data_->RecordUseOf(profile);
CreditCard* added_card =
personal_data_->GetCreditCardByGUID(credit_card.guid());
ASSERT_TRUE(added_card);
EXPECT_EQ(*added_card, credit_card);
EXPECT_EQ(1U, added_card->use_count());
EXPECT_EQ(creation_time, added_card->use_date());
EXPECT_NE(creation_time, added_card->modification_date());
personal_data_->RecordUseOf(credit_card);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// Verify usage stats are updated.
added_profile = personal_data_->GetProfileByGUID(profile.guid());
ASSERT_TRUE(added_profile);
EXPECT_EQ(2U, added_profile->use_count());
EXPECT_NE(creation_time, added_profile->use_date());
EXPECT_NE(creation_time, added_profile->modification_date());
added_card = personal_data_->GetCreditCardByGUID(credit_card.guid());
ASSERT_TRUE(added_card);
EXPECT_EQ(2U, added_card->use_count());
EXPECT_NE(creation_time, added_card->use_date());
EXPECT_NE(creation_time, added_card->modification_date());
}
TEST_F(PersonalDataManagerTest, UpdateServerCreditCardUsageStats) {
EnableWalletCardImport();
std::vector<CreditCard> server_cards;
server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "a123"));
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"9012" /* Visa */, "01", "2999");
server_cards.back().SetTypeForMaskedCard(kVisaCard);
server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b456"));
test::SetCreditCardInfo(&server_cards.back(), "Bonnie Parker",
"4444" /* Mastercard */, "12", "3999");
server_cards.back().SetTypeForMaskedCard(kMasterCard);
server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "c789"));
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"347666888555" /* American Express */, "04", "3999");
test::SetServerCreditCards(autofill_table_, server_cards);
personal_data_->Refresh();
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
if (!OfferStoreUnmaskedCards()) {
for (CreditCard* card : personal_data_->GetCreditCards()) {
EXPECT_EQ(CreditCard::MASKED_SERVER_CARD, card->record_type());
}
// The rest of this test doesn't work if we're force-masking all unmasked
// cards.
return;
}
// The GUIDs will be different, so just compare the data.
for (size_t i = 0; i < 3; ++i)
EXPECT_EQ(0, server_cards[i].Compare(*personal_data_->GetCreditCards()[i]));
CreditCard* unmasked_card = &server_cards.front();
unmasked_card->set_record_type(CreditCard::FULL_SERVER_CARD);
unmasked_card->SetNumber(ASCIIToUTF16("423456789012"));
EXPECT_NE(0, unmasked_card->Compare(
*personal_data_->GetCreditCards().front()));
personal_data_->UpdateServerCreditCard(*unmasked_card);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
for (size_t i = 0; i < 3; ++i)
EXPECT_EQ(0, server_cards[i].Compare(*personal_data_->GetCreditCards()[i]));
// For an unmasked card, usage data starts out as 2 because of the unmasking
// which is considered a use.
EXPECT_EQ(2U, personal_data_->GetCreditCards()[0]->use_count());
EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[0]->use_date());
EXPECT_EQ(1U, personal_data_->GetCreditCards()[1]->use_count());
EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[1]->use_date());
// Having unmasked this card, usage stats should be 2 and Now().
EXPECT_EQ(2U, personal_data_->GetCreditCards()[2]->use_count());
EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[2]->use_date());
base::Time initial_use_date = personal_data_->GetCreditCards()[2]->use_date();
server_cards.back().set_guid(personal_data_->GetCreditCards()[2]->guid());
personal_data_->RecordUseOf(server_cards.back());
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
EXPECT_EQ(2U, personal_data_->GetCreditCards()[0]->use_count());
EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[0]->use_date());
EXPECT_EQ(1U, personal_data_->GetCreditCards()[1]->use_count());
EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[1]->use_date());
EXPECT_EQ(3U, personal_data_->GetCreditCards()[2]->use_count());
EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[2]->use_date());
// Time may or may not have elapsed between unmasking and RecordUseOf.
EXPECT_LE(initial_use_date, personal_data_->GetCreditCards()[2]->use_date());
// Can record usage stats on masked cards.
server_cards[1].set_guid(personal_data_->GetCreditCards()[1]->guid());
personal_data_->RecordUseOf(server_cards[1]);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
EXPECT_EQ(2U, personal_data_->GetCreditCards()[1]->use_count());
EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[1]->use_date());
// Upgrading to unmasked retains the usage stats (and increments them).
CreditCard* unmasked_card2 = &server_cards[1];
unmasked_card2->set_record_type(CreditCard::FULL_SERVER_CARD);
unmasked_card2->SetNumber(ASCIIToUTF16("5555555555554444"));
personal_data_->UpdateServerCreditCard(*unmasked_card2);
server_cards[1].set_guid(personal_data_->GetCreditCards()[1]->guid());
personal_data_->RecordUseOf(server_cards[1]);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
EXPECT_EQ(3U, personal_data_->GetCreditCards()[1]->use_count());
EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[1]->use_date());
}
TEST_F(PersonalDataManagerTest, ClearAllServerData) {
// Add a server card.
std::vector<CreditCard> server_cards;
server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "a123"));
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"9012" /* Visa */, "01", "2999");
server_cards.back().SetTypeForMaskedCard(kVisaCard);
test::SetServerCreditCards(autofill_table_, server_cards);
personal_data_->Refresh();
// Need to set the google services username
EnableWalletCardImport();
// Add a server profile.
std::vector<AutofillProfile> server_profiles;
server_profiles.push_back(
AutofillProfile(AutofillProfile::SERVER_PROFILE, "a123"));
test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe", "",
"ACME Corp", "500 Oak View", "Apt 8", "Houston", "TX",
"77401", "US", "");
autofill_table_->SetServerProfiles(server_profiles);
// 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_->ClearAllServerData();
// Reload the database, everything should be gone.
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_TRUE(personal_data_->GetCreditCards().empty());
EXPECT_TRUE(personal_data_->GetProfiles().empty());
}
TEST_F(PersonalDataManagerTest, DontDuplicateServerCard) {
EnableWalletCardImport();
std::vector<CreditCard> server_cards;
server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "a123"));
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"1881" /* Visa */, "01", "4999");
server_cards.back().SetTypeForMaskedCard(kVisaCard);
server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "c789"));
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"347666888555" /* American Express */, "04", "3999");
test::SetServerCreditCards(autofill_table_, server_cards);
personal_data_->Refresh();
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
// A valid credit card form. A user re-enters one of their masked cards.
// We shouldn't offer to save. It's possible this is actually a different card
// but it's very unlikely. And these circumstances will also arise if the user
// has the same card available locally and synced from payments.
FormData form1;
FormFieldData field;
test::CreateTestFormField("Name on card:", "name_on_card", "John Dillinger",
"text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("Card Number:", "card_number", "4012888888881881",
"text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("Exp Month:", "exp_month", "01", "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("Exp Year:", "exp_year", "4999", "text", &field);
form1.fields.push_back(field);
FormStructure form_structure1(form1);
form_structure1.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_FALSE(personal_data_->ImportFormData(form_structure1, false,
&imported_credit_card));
EXPECT_FALSE(imported_credit_card);
// A user re-types (or fills with) an unmasked card. Don't offer to save
// here, either. Since it's unmasked, we know for certain that it's the same
// card.
FormData form2;
test::CreateTestFormField("Name on card:", "name_on_card", "Clyde Barrow",
"text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("Card Number:", "card_number", "347666888555",
"text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("Exp Month:", "exp_month", "04", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("Exp Year:", "exp_year", "3999", "text", &field);
form2.fields.push_back(field);
FormStructure form_structure2(form2);
form_structure2.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card2;
EXPECT_FALSE(personal_data_->ImportFormData(form_structure2, false,
&imported_credit_card2));
EXPECT_FALSE(imported_credit_card2);
}
// Tests the SaveImportedProfile method with different profiles to make sure the
// merge logic works correctly.
TEST_F(PersonalDataManagerTest, SaveImportedProfile) {
typedef struct {
autofill::ServerFieldType field_type;
std::string 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;
} TestCase;
TestCase test_cases[] = {
// Test that saving an identical profile except for the name results in
// two profiles being saved.
{ProfileFields(), {{NAME_FIRST, "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.
{ProfileFields(), {{NAME_MIDDLE, "M"}}, {{NAME_MIDDLE, "Mitchell"}}},
// 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.
{{{NAME_MIDDLE, "M"}},
{{NAME_MIDDLE, "Mitchell"}},
{{NAME_MIDDLE, "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.
{ProfileFields(), {{NAME_MIDDLE, ""}}, {{NAME_MIDDLE, "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.
{{{NAME_MIDDLE, ""}}, {{NAME_MIDDLE, "M"}}, {{NAME_MIDDLE, "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.
{{{NAME_MIDDLE, ""}},
{{NAME_MIDDLE, "Mitchell"}},
{{NAME_MIDDLE, "Mitchell"}}},
// Test that saving a 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.
{
{
{NAME_FIRST, "Marion"},
{NAME_MIDDLE, "Mitchell"},
{NAME_LAST, "Morrison"},
{NAME_FULL, ""},
},
{
{NAME_FIRST, ""},
{NAME_MIDDLE, ""},
{NAME_LAST, ""},
{NAME_FULL, "Marion Mitchell Morrison"},
},
{
{NAME_FIRST, "Marion"},
{NAME_MIDDLE, "Mitchell"},
{NAME_LAST, "Morrison"},
{NAME_FULL, "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.
{
{
{NAME_FIRST, ""},
{NAME_MIDDLE, ""},
{NAME_LAST, ""},
{NAME_FULL, "Marion Mitchell Morrison"},
},
{
{NAME_FIRST, "Marion"},
{NAME_MIDDLE, "Mitchell"},
{NAME_LAST, "Morrison"},
{NAME_FULL, ""},
},
{
{NAME_FIRST, "Marion"},
{NAME_MIDDLE, "Mitchell"},
{NAME_LAST, "Morrison"},
{NAME_FULL, "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.
{
{
{NAME_FIRST, "Marion"},
{NAME_MIDDLE, "Mitchell"},
{NAME_LAST, "Morrison"},
{NAME_FULL, ""},
},
{
{NAME_FIRST, ""},
{NAME_MIDDLE, ""},
{NAME_LAST, ""},
{NAME_FULL, "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.
{
{
{NAME_FIRST, ""},
{NAME_MIDDLE, ""},
{NAME_LAST, ""},
{NAME_FULL, "John Thompson Smith"},
},
{
{NAME_FIRST, "Marion"},
{NAME_MIDDLE, "Mitchell"},
{NAME_LAST, "Morrison"},
{NAME_FULL, ""},
},
},
// Test that saving an identical profile except for the first address line
// results in two profiles being saved.
{ProfileFields(), {{ADDRESS_HOME_LINE1, "123 Aquarium St."}}},
// Test that saving an identical profile except for the second address
// line results in two profiles being saved.
{ProfileFields(), {{ADDRESS_HOME_LINE2, "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.
{{{COMPANY_NAME, ""}}, ProfileFields(), {{COMPANY_NAME, "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).
{ProfileFields(), {{COMPANY_NAME, ""}}, {{COMPANY_NAME, "Fox"}}},
// Tests that saving an identical profile except a slightly different
// postal code results in a merge with the new value kept.
{{{ADDRESS_HOME_ZIP, "R2C 0A1"}},
{{ADDRESS_HOME_ZIP, "R2C0A1"}},
{{ADDRESS_HOME_ZIP, "R2C0A1"}}},
{{{ADDRESS_HOME_ZIP, "R2C0A1"}},
{{ADDRESS_HOME_ZIP, "R2C 0A1"}},
{{ADDRESS_HOME_ZIP, "R2C 0A1"}}},
{{{ADDRESS_HOME_ZIP, "r2c 0a1"}},
{{ADDRESS_HOME_ZIP, "R2C0A1"}},
{{ADDRESS_HOME_ZIP, "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.
{{{ADDRESS_HOME_LINE2, ""}},
ProfileFields(),
{{ADDRESS_HOME_LINE2, "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).
{ProfileFields(),
{{ADDRESS_HOME_LINE2, ""}},
{{ADDRESS_HOME_LINE2, "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.
{{{ADDRESS_HOME_LINE2, ""}},
{{ADDRESS_HOME_LINE2, ""}, {ADDRESS_HOME_LINE1, "123, Zoo St."}},
{{ADDRESS_HOME_LINE1, "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 original address gets overwritten.
{{{ADDRESS_HOME_LINE2, ""}, {ADDRESS_HOME_LINE1, "123, Zoo St."}},
{{ADDRESS_HOME_LINE2, ""}},
{{ADDRESS_HOME_LINE1, "123 Zoo St"}}},
// Tests that saving an identical profile except additional punctuation in
// the two address lines results in a merge and that the original address
// gets overwritten.
{ProfileFields(),
{{ADDRESS_HOME_LINE1, "123, Zoo St."}, {ADDRESS_HOME_LINE2, "unit. 5"}},
{{ADDRESS_HOME_LINE1, "123, Zoo St."}, {ADDRESS_HOME_LINE2, "unit. 5"}}},
// Tests that saving an identical profile except less punctuation in the
// two address lines results in a merge and that the original address gets
// overwritten.
{{{ADDRESS_HOME_LINE1, "123, Zoo St."}, {ADDRESS_HOME_LINE2, "unit. 5"}},
ProfileFields(),
{{ADDRESS_HOME_LINE1, "123 Zoo St"}, {ADDRESS_HOME_LINE2, "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 original
// address lines do not get overwritten.
{ProfileFields(),
{{ADDRESS_HOME_LINE1, "123 Zoo St, unit 5"}, {ADDRESS_HOME_LINE2, ""}},
{{ADDRESS_HOME_LINE1, "123 Zoo St"}, {ADDRESS_HOME_LINE2, "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.
{{{ADDRESS_HOME_LINE1, "123 Zoo St, unit 5"}, {ADDRESS_HOME_LINE2, ""}},
ProfileFields(),
{{ADDRESS_HOME_LINE1, "123 Zoo St"}, {ADDRESS_HOME_LINE2, "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.
{{{ADDRESS_HOME_STATE, "California"}},
ProfileFields(),
{{ADDRESS_HOME_STATE, "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
// original state gets overwritten.
{ProfileFields(),
{{ADDRESS_HOME_STATE, "California"}},
{{ADDRESS_HOME_STATE, "California"}}},
// 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.
{{{COMPANY_NAME, "Stark inc"}},
{{COMPANY_NAME, "Stark Inc."}},
{{COMPANY_NAME, "Stark Inc."}}},
};
for (TestCase test_case : test_cases) {
SetupReferenceProfile();
const std::vector<AutofillProfile*>& initial_profiles =
personal_data_->GetProfiles();
// Apply changes to the original profile (if applicable).
for (ProfileField change : test_case.changes_to_original) {
initial_profiles.front()->SetRawInfo(
change.field_type, base::UTF8ToUTF16(change.field_value));
}
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile2, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
// Apply changes to the second profile (if applicable).
for (ProfileField change : test_case.changes_to_new) {
profile2.SetRawInfo(change.field_type,
base::UTF8ToUTF16(change.field_value));
}
personal_data_->SaveImportedProfile(profile2);
const std::vector<AutofillProfile*>& saved_profiles =
personal_data_->GetProfiles();
// 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(base::UTF8ToUTF16(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 updated.
EXPECT_EQ(2U, saved_profiles.front()->use_count());
EXPECT_GT(base::TimeDelta::FromMilliseconds(500),
base::Time::Now() - saved_profiles.front()->use_date());
EXPECT_GT(
base::TimeDelta::FromMilliseconds(500),
base::Time::Now() - saved_profiles.front()->modification_date());
}
// Erase the profiles for the next test.
ResetProfiles();
}
}
// Tests that MergeProfile tries to merge the imported profile into the
// existing profile in decreasing order of frecency.
TEST_F(PersonalDataManagerTest, MergeProfile_Frecency) {
// Create two very similar profiles except with different company names.
AutofillProfile profile1(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile1, "Homer", "Jay", "Simpson",
"homer.simpson@abc.com", "SNP", "742 Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "12345678910");
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile2, "Homer", "Jay", "Simpson",
"homer.simpson@abc.com", "Fox", "742 Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "12345678910");
// Give the "Fox" profile a bigger frecency score.
profile2.set_use_count(15);
// Create the |existing_profiles| vector.
std::vector<AutofillProfile*> existing_profiles;
existing_profiles.push_back(&profile1);
existing_profiles.push_back(&profile2);
// Create a new imported profile with no company name.
AutofillProfile imported_profile(base::GenerateGUID(),
"https://www.example.com");
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 = personal_data_->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.
TEST_F(PersonalDataManagerTest, MergeProfile_UsageStats) {
// 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(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile, "Homer", "Jay", "Simpson",
"homer.simpson@abc.com", "SNP", "742 Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "12345678910");
profile.set_use_count(4U);
profile.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(4));
profile.set_modification_date(base::Time::Now() -
base::TimeDelta::FromDays(4));
// Create the |existing_profiles| vector.
std::vector<AutofillProfile*> existing_profiles;
existing_profiles.push_back(&profile);
// Create a new imported profile that will get merged with the existing one.
AutofillProfile imported_profile(base::GenerateGUID(),
"https://www.example.com");
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 = personal_data_->MergeProfile(
imported_profile, existing_profiles, "US-EN", &profiles);
// The new profile should be merged into the existing profile.
EXPECT_EQ(profile.guid(), guid);
// The use count should have been incremented by one.
EXPECT_EQ(5U, profile.use_count());
// The use date and modification dates should have been set to less than 500
// milliseconds ago.
EXPECT_GT(base::TimeDelta::FromMilliseconds(500),
base::Time::Now() - profile.use_date());
EXPECT_GT(base::TimeDelta::FromMilliseconds(500),
base::Time::Now() - profile.modification_date());
}
} // namespace autofill