blob: 0f26dd35185eef466eea6cbdde3d0395e537c98f [file] [log] [blame]
// Copyright (c) 2015 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 "base/command_line.h"
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/sync/test/integration/autofill_helper.h"
#include "chrome/browser/sync/test/integration/bookmarks_helper.h"
#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
#include "chrome/browser/sync/test/integration/secondary_account_helper.h"
#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
#include "chrome/browser/sync/test/integration/sync_test.h"
#include "chrome/browser/sync/test/integration/wallet_helper.h"
#include "chrome/browser/web_data_service_factory.h"
#include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/data_model/autofill_metadata.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/data_model/credit_card_cloud_token_data.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/payments/payments_customer_data.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/personal_data_manager_observer.h"
#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/browser/webdata/autofill_sync_bridge_util.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/prefs/pref_service.h"
#include "components/sync/base/model_type.h"
#include "components/sync/driver/sync_service.h"
#include "components/sync/protocol/model_type_state.pb.h"
#include "components/sync/test/fake_server/fake_server.h"
#include "components/webdata/common/web_data_service_consumer.h"
#include "content/public/test/browser_test.h"
#include "testing/gmock/include/gmock/gmock.h"
using autofill::AutofillMetadata;
using autofill::AutofillMetrics;
using autofill::AutofillProfile;
using autofill::CreditCard;
using autofill::CreditCardCloudTokenData;
using autofill::data_util::TruncateUTF8;
using base::ASCIIToUTF16;
using testing::Contains;
using wallet_helper::CreateDefaultSyncCreditCardCloudTokenData;
using wallet_helper::CreateDefaultSyncPaymentsCustomerData;
using wallet_helper::CreateDefaultSyncWalletAddress;
using wallet_helper::CreateDefaultSyncWalletCard;
using wallet_helper::CreateSyncCreditCardCloudTokenData;
using wallet_helper::CreateSyncPaymentsCustomerData;
using wallet_helper::CreateSyncWalletAddress;
using wallet_helper::CreateSyncWalletCard;
using wallet_helper::ExpectDefaultCreditCardValues;
using wallet_helper::ExpectDefaultProfileValues;
using wallet_helper::GetAccountWebDataService;
using wallet_helper::GetDefaultCreditCard;
using wallet_helper::GetPersonalDataManager;
using wallet_helper::GetProfileWebDataService;
using wallet_helper::GetServerAddressesMetadata;
using wallet_helper::GetServerCardsMetadata;
using wallet_helper::GetWalletModelTypeState;
using wallet_helper::kDefaultBillingAddressID;
using wallet_helper::kDefaultCardID;
using wallet_helper::kDefaultCreditCardCloudTokenDataID;
using wallet_helper::kDefaultCustomerID;
using wallet_helper::UnmaskServerCard;
namespace {
ACTION_P(QuitMessageLoop, loop) {
loop->Quit();
}
MATCHER(AddressHasConverted, "") {
return arg.specifics().wallet_metadata().address_has_converted();
}
const char kLocalGuidA[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44A";
const char kDifferentBillingAddressId[] = "another address entity ID";
const base::Time kArbitraryDefaultTime = base::Time::FromDoubleT(25);
const syncer::SyncFirstSetupCompleteSource kSetSourceFromTest =
syncer::SyncFirstSetupCompleteSource::BASIC_FLOW;
template <class T>
class AutofillWebDataServiceConsumer : public WebDataServiceConsumer {
public:
AutofillWebDataServiceConsumer() {}
virtual ~AutofillWebDataServiceConsumer() {}
void OnWebDataServiceRequestDone(
WebDataServiceBase::Handle handle,
std::unique_ptr<WDTypedResult> result) override {
result_ = std::move(static_cast<WDResult<T>*>(result.get())->GetValue());
run_loop_.Quit();
}
void Wait() { run_loop_.Run(); }
T& result() { return result_; }
private:
base::RunLoop run_loop_;
T result_;
DISALLOW_COPY_AND_ASSIGN(AutofillWebDataServiceConsumer);
};
std::vector<std::unique_ptr<CreditCard>> GetServerCards(
scoped_refptr<autofill::AutofillWebDataService> service) {
AutofillWebDataServiceConsumer<std::vector<std::unique_ptr<CreditCard>>>
consumer;
service->GetServerCreditCards(&consumer);
consumer.Wait();
return std::move(consumer.result());
}
std::vector<std::unique_ptr<AutofillProfile>> GetServerProfiles(
scoped_refptr<autofill::AutofillWebDataService> service) {
AutofillWebDataServiceConsumer<std::vector<std::unique_ptr<AutofillProfile>>>
consumer;
service->GetServerProfiles(&consumer);
consumer.Wait();
return std::move(consumer.result());
}
#if !BUILDFLAG(IS_CHROMEOS_ASH)
std::unique_ptr<autofill::PaymentsCustomerData> GetPaymentsCustomerData(
scoped_refptr<autofill::AutofillWebDataService> service) {
AutofillWebDataServiceConsumer<
std::unique_ptr<autofill::PaymentsCustomerData>>
consumer;
service->GetPaymentsCustomerData(&consumer);
consumer.Wait();
return std::move(consumer.result());
}
#endif
std::vector<std::unique_ptr<autofill::CreditCardCloudTokenData>>
GetCreditCardCloudTokenData(
scoped_refptr<autofill::AutofillWebDataService> service) {
AutofillWebDataServiceConsumer<
std::vector<std::unique_ptr<CreditCardCloudTokenData>>>
consumer;
service->GetCreditCardCloudTokenData(&consumer);
consumer.Wait();
return std::move(consumer.result());
}
} // namespace
class SingleClientWalletSyncTest : public SyncTest {
public:
SingleClientWalletSyncTest() : SyncTest(SINGLE_CLIENT) {
test_clock_.SetNow(kArbitraryDefaultTime);
}
~SingleClientWalletSyncTest() override {}
protected:
void WaitForOnPersonalDataChanged(autofill::PersonalDataManager* pdm) {
pdm->AddObserver(&personal_data_observer_);
base::RunLoop run_loop;
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillRepeatedly(QuitMessageLoop(&run_loop));
run_loop.Run();
pdm->RemoveObserver(&personal_data_observer_);
}
void WaitForNumberOfCards(size_t expected_count,
autofill::PersonalDataManager* pdm) {
while (pdm->GetCreditCards().size() != expected_count ||
pdm->HasPendingQueriesForTesting()) {
WaitForOnPersonalDataChanged(pdm);
}
}
void WaitForNumberOfServerProfiles(size_t expected_count,
autofill::PersonalDataManager* pdm) {
while (pdm->GetServerProfiles().size() != expected_count ||
pdm->HasPendingQueriesForTesting()) {
WaitForOnPersonalDataChanged(pdm);
}
}
void WaitForPaymentsCustomerData(const std::string& customer_id,
autofill::PersonalDataManager* pdm) {
while (pdm->GetPaymentsCustomerData() == nullptr ||
pdm->GetPaymentsCustomerData()->customer_id != customer_id ||
pdm->HasPendingQueriesForTesting()) {
WaitForOnPersonalDataChanged(pdm);
}
}
void WaitForCreditCardCloudTokenData(size_t expected_count,
autofill::PersonalDataManager* pdm) {
while (pdm->GetCreditCardCloudTokenData().size() != expected_count) {
WaitForOnPersonalDataChanged(pdm);
}
}
bool TriggerGetUpdatesAndWait() {
const base::Time now = base::Time::Now();
// Trigger a sync and wait for the new data to arrive.
TriggerSyncForModelTypes(
0, syncer::ModelTypeSet(syncer::AUTOFILL_WALLET_DATA));
return FullUpdateTypeProgressMarkerChecker(now, GetSyncService(0),
syncer::AUTOFILL_WALLET_DATA)
.Wait();
}
void AdvanceAutofillClockByOneDay() {
test_clock_.Advance(base::TimeDelta::FromDays(1));
}
testing::NiceMock<PersonalDataLoadedObserverMock> personal_data_observer_;
base::HistogramTester histogram_tester_;
autofill::TestAutofillClock test_clock_;
private:
DISALLOW_COPY_AND_ASSIGN(SingleClientWalletSyncTest);
};
class SingleClientWalletSyncTestWithoutAccountStorage
: public SingleClientWalletSyncTest {
public:
SingleClientWalletSyncTestWithoutAccountStorage() {
features_.InitAndDisableFeature(
autofill::features::kAutofillEnableAccountWalletStorage);
}
private:
base::test::ScopedFeatureList features_;
};
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTestWithoutAccountStorage,
DownloadProfileStorage) {
GetFakeServer()->SetWalletData({CreateDefaultSyncWalletAddress(),
CreateDefaultSyncWalletCard(),
CreateDefaultSyncPaymentsCustomerData()});
ASSERT_TRUE(SetupSync());
auto profile_data = GetProfileWebDataService(0);
ASSERT_NE(nullptr, profile_data);
auto account_data = GetAccountWebDataService(0);
ASSERT_EQ(nullptr, account_data);
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
ASSERT_NE(nullptr, pdm);
std::vector<CreditCard*> cards = pdm->GetCreditCards();
ASSERT_EQ(1uL, cards.size());
std::vector<AutofillProfile*> profiles = pdm->GetServerProfiles();
ASSERT_EQ(1uL, profiles.size());
// Check that the data was set correctly.
ExpectDefaultCreditCardValues(*cards[0]);
ExpectDefaultProfileValues(*profiles[0]);
// Check that the data is stored in the profile storage.
EXPECT_EQ(1U, GetServerCards(GetProfileWebDataService(0)).size());
EXPECT_EQ(1U, GetServerProfiles(GetProfileWebDataService(0)).size());
}
class SingleClientWalletWithAccountStorageSyncTest
: public SingleClientWalletSyncTest {
public:
SingleClientWalletWithAccountStorageSyncTest() {
features_.InitAndEnableFeature(
autofill::features::kAutofillEnableAccountWalletStorage);
}
private:
base::test::ScopedFeatureList features_;
};
// ChromeOS does not support late signin after profile creation, so the test
// below does not apply, at least in the current form.
#if !BUILDFLAG(IS_CHROMEOS_ASH)
IN_PROC_BROWSER_TEST_F(SingleClientWalletWithAccountStorageSyncTest,
DownloadAccountStorage_Card) {
ASSERT_TRUE(SetupClients());
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
GetFakeServer()->SetWalletData({CreateDefaultSyncWalletAddress(),
CreateDefaultSyncWalletCard(),
CreateDefaultSyncPaymentsCustomerData()});
ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount());
ASSERT_TRUE(GetClient(0)->AwaitEngineInitialization());
ASSERT_TRUE(AwaitQuiescence());
ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
GetSyncService(0)->GetTransportState());
ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(
syncer::AUTOFILL_WALLET_DATA));
auto profile_data = GetProfileWebDataService(0);
ASSERT_NE(nullptr, profile_data);
auto account_data = GetAccountWebDataService(0);
ASSERT_NE(nullptr, account_data);
// Check that no data is stored in the profile storage.
EXPECT_EQ(0U, GetServerCards(profile_data).size());
EXPECT_EQ(0U, GetServerProfiles(profile_data).size());
// Check that one card is stored in the account storage.
EXPECT_EQ(1U, GetServerCards(account_data).size());
ASSERT_NE(nullptr, pdm);
std::vector<CreditCard*> cards = pdm->GetCreditCards();
ASSERT_EQ(1uL, cards.size());
ExpectDefaultCreditCardValues(*cards[0]);
// Now sign back out.
GetClient(0)->SignOutPrimaryAccount();
// Verify that sync is stopped.
ASSERT_EQ(syncer::SyncService::TransportState::DISABLED,
GetSyncService(0)->GetTransportState());
ASSERT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has(
syncer::AUTOFILL_WALLET_DATA));
// Wait for PDM to receive the data change with no cards.
WaitForNumberOfCards(0, pdm);
// Check directly in the DB that the account storage is now cleared.
EXPECT_EQ(0U, GetServerCards(account_data).size());
}
// Wallet data should get cleared from the database when the user signs out and
// different data should get downstreamed when the user signs in with a
// different account.
IN_PROC_BROWSER_TEST_F(SingleClientWalletWithAccountStorageSyncTest,
ClearOnSignOutAndDownstreamOnSignIn) {
ASSERT_TRUE(SetupClients());
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
ASSERT_NE(nullptr, pdm);
GetFakeServer()->SetWalletData(
{CreateSyncWalletCard(/*name=*/"card-1", /*last_four=*/"0001",
kDefaultBillingAddressID),
CreateSyncWalletAddress(/*name=*/"address-1", /*company=*/"Company-1"),
CreateDefaultSyncPaymentsCustomerData(),
CreateSyncCreditCardCloudTokenData(/*cloud_token_data_id=*/"data-1")});
ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount());
ASSERT_TRUE(GetClient(0)->AwaitEngineInitialization());
ASSERT_TRUE(AwaitQuiescence());
// Make sure the data & metadata is in the DB.
WaitForNumberOfCards(1, pdm);
WaitForNumberOfServerProfiles(1, pdm);
WaitForPaymentsCustomerData(kDefaultCustomerID, pdm);
WaitForCreditCardCloudTokenData(1, pdm);
// Signout, the data & metadata should be gone.
GetClient(0)->SignOutPrimaryAccount();
WaitForNumberOfCards(0, pdm);
EXPECT_EQ(0uL, pdm->GetServerProfiles().size());
EXPECT_EQ(0uL, pdm->GetCreditCards().size());
EXPECT_EQ(nullptr, pdm->GetPaymentsCustomerData());
EXPECT_EQ(0uL, pdm->GetCreditCardCloudTokenData().size());
EXPECT_EQ(0U, GetServerCardsMetadata(0).size());
EXPECT_EQ(0U, GetServerAddressesMetadata(0).size());
// Set a different set of cards on the server, then sign in again (this is a
// good enough approximation of signing in with a different Google account).
GetFakeServer()->SetWalletData(
{CreateSyncWalletCard(/*name=*/"new-card", /*last_four=*/"0002",
kDefaultBillingAddressID),
CreateSyncWalletAddress(/*name=*/"new-address", /*company=*/"Company-2"),
CreateSyncPaymentsCustomerData(/*customer_id=*/"different"),
CreateSyncCreditCardCloudTokenData(/*cloud_token_data_id=*/"data-2")});
GetClient(0)->SignInPrimaryAccount();
WaitForNumberOfCards(1, pdm);
// Make sure the data is in the DB.
EXPECT_EQ(ASCIIToUTF16("0002"), pdm->GetCreditCards()[0]->LastFourDigits());
ASSERT_EQ(1uL, pdm->GetServerProfiles().size());
std::vector<AutofillProfile*> profiles = pdm->GetServerProfiles();
ASSERT_EQ(1uL, profiles.size());
EXPECT_EQ("Company-2", TruncateUTF8(base::UTF16ToUTF8(
profiles[0]->GetRawInfo(autofill::COMPANY_NAME))));
ASSERT_EQ("different", pdm->GetPaymentsCustomerData()->customer_id);
ASSERT_EQ(1uL, pdm->GetCreditCardCloudTokenData().size());
EXPECT_EQ("data-2", pdm->GetCreditCardCloudTokenData()[0]->instrument_token);
}
#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, EnabledByDefault) {
ASSERT_TRUE(SetupSync());
ASSERT_TRUE(GetClient(0)->service()->GetActiveDataTypes().Has(
syncer::AUTOFILL_WALLET_DATA));
// TODO(pvalenzuela): Assert that the local root node for AUTOFILL_WALLET_DATA
// exists.
ASSERT_TRUE(GetClient(0)->service()->GetActiveDataTypes().Has(
syncer::AUTOFILL_WALLET_METADATA));
}
// Wallet data should get cleared from the database when sync is disabled.
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, ClearOnDisableSync) {
GetFakeServer()->SetWalletData({CreateDefaultSyncWalletAddress(),
CreateDefaultSyncWalletCard(),
CreateDefaultSyncPaymentsCustomerData(),
CreateDefaultSyncCreditCardCloudTokenData()});
ASSERT_TRUE(SetupSync());
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
ASSERT_NE(nullptr, pdm);
// Make sure the data & metadata is in the DB.
ASSERT_EQ(1uL, pdm->GetServerProfiles().size());
ASSERT_EQ(1uL, pdm->GetCreditCards().size());
ASSERT_EQ(1uL, pdm->GetCreditCardCloudTokenData().size());
ASSERT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
ASSERT_EQ(1U, GetServerCardsMetadata(0).size());
ASSERT_EQ(1U, GetServerAddressesMetadata(0).size());
// Disable sync, the data & metadata should be gone.
GetSyncService(0)->StopAndClear();
WaitForNumberOfCards(0, pdm);
EXPECT_EQ(0uL, pdm->GetServerProfiles().size());
EXPECT_EQ(0uL, pdm->GetCreditCards().size());
EXPECT_EQ(nullptr, pdm->GetPaymentsCustomerData());
EXPECT_EQ(0uL, pdm->GetCreditCardCloudTokenData().size());
EXPECT_EQ(0U, GetServerCardsMetadata(0).size());
EXPECT_EQ(0U, GetServerAddressesMetadata(0).size());
// Turn sync on again, the data should come back.
GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
// StopAndClear() also clears the "first setup complete" flag, so set it
// again.
GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
kSetSourceFromTest);
// Wait until Sync restores the card and it arrives at PDM.
WaitForNumberOfCards(1, pdm);
EXPECT_EQ(1uL, pdm->GetServerProfiles().size());
EXPECT_EQ(1uL, pdm->GetCreditCards().size());
EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
EXPECT_EQ(1uL, pdm->GetCreditCardCloudTokenData().size());
EXPECT_EQ(1U, GetServerCardsMetadata(0).size());
EXPECT_EQ(1U, GetServerAddressesMetadata(0).size());
}
// Wallet data should get cleared from the database when sync is (temporarily)
// stopped, e.g. due to the Sync feature toggle in Android settings.
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, ClearOnStopSync) {
GetFakeServer()->SetWalletData({CreateDefaultSyncWalletAddress(),
CreateDefaultSyncWalletCard(),
CreateDefaultSyncPaymentsCustomerData(),
CreateDefaultSyncCreditCardCloudTokenData()});
ASSERT_TRUE(SetupSync());
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
ASSERT_NE(nullptr, pdm);
// Make sure the data & metadata is in the DB.
ASSERT_EQ(1uL, pdm->GetServerProfiles().size());
ASSERT_EQ(1uL, pdm->GetCreditCards().size());
ASSERT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
ASSERT_EQ(1uL, pdm->GetCreditCardCloudTokenData().size());
ASSERT_EQ(1U, GetServerCardsMetadata(0).size());
ASSERT_EQ(1U, GetServerAddressesMetadata(0).size());
// Stop sync, the data & metadata should be gone.
GetSyncService(0)->GetUserSettings()->SetSyncRequested(false);
WaitForNumberOfCards(0, pdm);
EXPECT_EQ(0uL, pdm->GetServerProfiles().size());
EXPECT_EQ(0uL, pdm->GetCreditCards().size());
EXPECT_EQ(nullptr, pdm->GetPaymentsCustomerData());
EXPECT_EQ(0uL, pdm->GetCreditCardCloudTokenData().size());
EXPECT_EQ(0U, GetServerCardsMetadata(0).size());
EXPECT_EQ(0U, GetServerAddressesMetadata(0).size());
// Turn sync on again, the data should come back.
GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
// Wait until Sync restores the card and it arrives at PDM.
WaitForNumberOfCards(1, pdm);
EXPECT_EQ(1uL, pdm->GetServerProfiles().size());
EXPECT_EQ(1uL, pdm->GetCreditCards().size());
EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
EXPECT_EQ(1uL, pdm->GetCreditCardCloudTokenData().size());
EXPECT_EQ(1U, GetServerCardsMetadata(0).size());
EXPECT_EQ(1U, GetServerAddressesMetadata(0).size());
}
// ChromeOS does not sign out, so the test below does not apply.
#if !BUILDFLAG(IS_CHROMEOS_ASH)
// Wallet data should get cleared from the database when the user signs out.
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, ClearOnSignOut) {
GetFakeServer()->SetWalletData({CreateDefaultSyncWalletAddress(),
CreateDefaultSyncWalletCard(),
CreateDefaultSyncPaymentsCustomerData(),
CreateDefaultSyncCreditCardCloudTokenData()});
ASSERT_TRUE(SetupSync());
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
ASSERT_NE(nullptr, pdm);
// Make sure the data & metadata is in the DB.
ASSERT_EQ(1uL, pdm->GetServerProfiles().size());
ASSERT_EQ(1uL, pdm->GetCreditCards().size());
ASSERT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
ASSERT_EQ(1uL, pdm->GetCreditCardCloudTokenData().size());
ASSERT_EQ(1U, GetServerCardsMetadata(0).size());
ASSERT_EQ(1U, GetServerAddressesMetadata(0).size());
// Signout, the data & metadata should be gone.
GetClient(0)->SignOutPrimaryAccount();
WaitForNumberOfCards(0, pdm);
EXPECT_EQ(0uL, pdm->GetServerProfiles().size());
EXPECT_EQ(0uL, pdm->GetCreditCards().size());
EXPECT_EQ(nullptr, pdm->GetPaymentsCustomerData());
EXPECT_EQ(0uL, pdm->GetCreditCardCloudTokenData().size());
EXPECT_EQ(0U, GetServerCardsMetadata(0).size());
EXPECT_EQ(0U, GetServerAddressesMetadata(0).size());
}
#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
// Wallet is not using incremental updates. Make sure existing data gets
// replaced when synced down.
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest,
NewSyncDataShouldReplaceExistingData) {
GetFakeServer()->SetWalletData(
{CreateSyncWalletCard(/*name=*/"card-1", /*last_four=*/"0001",
kDefaultBillingAddressID, /*nickname=*/"",
/*instrument_id=*/123),
CreateSyncWalletAddress(/*name=*/"address-1", /*company=*/"Company-1"),
CreateDefaultSyncPaymentsCustomerData(),
CreateSyncCreditCardCloudTokenData(/*cloud_token_data_id=*/"data-1")});
ASSERT_TRUE(SetupSync());
// Make sure the data is in the DB.
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
ASSERT_NE(nullptr, pdm);
std::vector<CreditCard*> cards = pdm->GetCreditCards();
ASSERT_EQ(1uL, cards.size());
EXPECT_EQ(ASCIIToUTF16("0001"), cards[0]->LastFourDigits());
EXPECT_EQ(123, cards[0]->instrument_id());
// When no nickname is returned from Sync server, credit card's nickname is
// empty.
EXPECT_TRUE(cards[0]->nickname().empty());
std::vector<AutofillProfile*> profiles = pdm->GetServerProfiles();
ASSERT_EQ(1uL, profiles.size());
EXPECT_EQ("Company-1", TruncateUTF8(base::UTF16ToUTF8(
profiles[0]->GetRawInfo(autofill::COMPANY_NAME))));
EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
std::vector<CreditCardCloudTokenData*> cloud_token_data =
pdm->GetCreditCardCloudTokenData();
ASSERT_EQ(1uL, cloud_token_data.size());
EXPECT_EQ("data-1", cloud_token_data[0]->instrument_token);
// Put some completely new data in the sync server.
GetFakeServer()->SetWalletData(
{CreateSyncWalletCard(/*name=*/"new-card", /*last_four=*/"0002",
kDefaultBillingAddressID,
/*nickname=*/"Grocery Card", /*instrument_id=*/321),
CreateSyncWalletAddress(/*name=*/"new-address", /*company=*/"Company-2"),
CreateSyncPaymentsCustomerData(/*customer_id=*/"different"),
CreateSyncCreditCardCloudTokenData(/*cloud_token_data_id=*/"data-2")});
WaitForPaymentsCustomerData(/*customer_id=*/"different", pdm);
// Make sure only the new data is present.
cards = pdm->GetCreditCards();
ASSERT_EQ(1uL, cards.size());
EXPECT_EQ(ASCIIToUTF16("0002"), cards[0]->LastFourDigits());
EXPECT_EQ(321, cards[0]->instrument_id());
EXPECT_EQ(ASCIIToUTF16("Grocery Card"), cards[0]->nickname());
profiles = pdm->GetServerProfiles();
ASSERT_EQ(1uL, profiles.size());
EXPECT_EQ("Company-2", TruncateUTF8(base::UTF16ToUTF8(
profiles[0]->GetRawInfo(autofill::COMPANY_NAME))));
cloud_token_data = pdm->GetCreditCardCloudTokenData();
ASSERT_EQ(1uL, cloud_token_data.size());
EXPECT_EQ("data-2", cloud_token_data[0]->instrument_token);
}
// Wallet is not using incremental updates. The server either sends a non-empty
// update with deletion gc directives and with the (possibly empty) full data
// set, or (more often) an empty update.
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, EmptyUpdatesAreIgnored) {
GetFakeServer()->SetWalletData(
{CreateSyncWalletCard(/*name=*/"card-1", /*last_four=*/"0001",
kDefaultBillingAddressID),
CreateSyncWalletAddress(/*name=*/"address-1", /*company=*/"Company-1"),
CreateDefaultSyncPaymentsCustomerData(),
CreateSyncCreditCardCloudTokenData("data-1")});
ASSERT_TRUE(SetupSync());
// Make sure the card is in the DB.
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
ASSERT_NE(nullptr, pdm);
std::vector<CreditCard*> cards = pdm->GetCreditCards();
ASSERT_EQ(1uL, cards.size());
EXPECT_EQ(ASCIIToUTF16("0001"), cards[0]->LastFourDigits());
std::vector<AutofillProfile*> profiles = pdm->GetServerProfiles();
ASSERT_EQ(1uL, profiles.size());
EXPECT_EQ("Company-1", TruncateUTF8(base::UTF16ToUTF8(
profiles[0]->GetRawInfo(autofill::COMPANY_NAME))));
EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
std::vector<CreditCardCloudTokenData*> cloud_token_data =
pdm->GetCreditCardCloudTokenData();
ASSERT_EQ(1uL, cloud_token_data.size());
EXPECT_EQ("data-1", cloud_token_data[0]->instrument_token);
// Trigger a sync and wait for the new data to arrive.
sync_pb::ModelTypeState state_before =
GetWalletModelTypeState(syncer::AUTOFILL_WALLET_DATA, 0);
ASSERT_TRUE(TriggerGetUpdatesAndWait());
// Check that the new progress marker is stored for empty updates. This is a
// regression check for crbug.com/924447.
sync_pb::ModelTypeState state_after =
GetWalletModelTypeState(syncer::AUTOFILL_WALLET_DATA, 0);
EXPECT_NE(state_before.progress_marker().token(),
state_after.progress_marker().token());
// Refresh the pdm to make sure we are checking its state after any potential
// changes from sync in the DB propagate into pdm. As we don't expect anything
// to change, we have no better specific condition to wait for.
pdm->Refresh();
while (pdm->HasPendingQueriesForTesting()) {
WaitForOnPersonalDataChanged(pdm);
}
// Make sure the same data is present on the client.
cards = pdm->GetCreditCards();
ASSERT_EQ(1uL, cards.size());
EXPECT_EQ(ASCIIToUTF16("0001"), cards[0]->LastFourDigits());
profiles = pdm->GetServerProfiles();
ASSERT_EQ(1uL, profiles.size());
EXPECT_EQ("Company-1", TruncateUTF8(base::UTF16ToUTF8(
profiles[0]->GetRawInfo(autofill::COMPANY_NAME))));
EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
cloud_token_data = pdm->GetCreditCardCloudTokenData();
ASSERT_EQ(1uL, cloud_token_data.size());
EXPECT_EQ("data-1", cloud_token_data[0]->instrument_token);
}
// If the server sends the same cards and addresses again, they should not
// change on the client. We should also not overwrite existing metadata.
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, SameUpdatesAreIgnored) {
GetFakeServer()->SetWalletData(
{CreateSyncWalletCard(/*name=*/"card-1", /*last_four=*/"0001",
kDefaultBillingAddressID),
CreateSyncWalletAddress(/*name=*/"address-1", /*company=*/"Company-1"),
CreateDefaultSyncPaymentsCustomerData(),
CreateSyncCreditCardCloudTokenData("data-1")});
ASSERT_TRUE(SetupSync());
// Record use of to get non-default metadata values.
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
std::vector<CreditCard*> cards = pdm->GetCreditCards();
ASSERT_EQ(1uL, cards.size());
pdm->RecordUseOf(cards[0]);
std::vector<AutofillProfile*> profiles = pdm->GetServerProfiles();
ASSERT_EQ(1uL, profiles.size());
// TODO(crbug.com/941498): Server profiles are not recorded.
pdm->RecordUseOf(profiles[0]);
// Keep the same data (only change the customer data and the cloud token to
// force the FakeServer to send the full update).
GetFakeServer()->SetWalletData(
{CreateSyncWalletCard(/*name=*/"card-1", /*last_four=*/"0001",
kDefaultBillingAddressID),
CreateSyncWalletAddress(/*name=*/"address-1", /*company=*/"Company-1"),
CreateSyncPaymentsCustomerData("different"),
CreateSyncCreditCardCloudTokenData("data-2")});
WaitForPaymentsCustomerData(/*customer_id=*/"different", pdm);
// Make sure the data is present on the client.
cards = pdm->GetCreditCards();
ASSERT_EQ(1uL, cards.size());
EXPECT_EQ(ASCIIToUTF16("0001"), cards[0]->LastFourDigits());
profiles = pdm->GetServerProfiles();
ASSERT_EQ(1uL, profiles.size());
EXPECT_EQ("Company-1", TruncateUTF8(base::UTF16ToUTF8(
profiles[0]->GetRawInfo(autofill::COMPANY_NAME))));
std::vector<CreditCardCloudTokenData*> cloud_token_data =
pdm->GetCreditCardCloudTokenData();
ASSERT_EQ(1uL, cloud_token_data.size());
EXPECT_EQ("data-2", cloud_token_data[0]->instrument_token);
// Test that the non-default metadata values stayed around.
std::map<std::string, AutofillMetadata> cards_metadata =
GetServerCardsMetadata(0);
EXPECT_EQ(1U, cards_metadata.size());
EXPECT_EQ(2U, cards_metadata.begin()->second.use_count);
std::map<std::string, AutofillMetadata> addresses_metadata =
GetServerAddressesMetadata(0);
EXPECT_EQ(1U, addresses_metadata.size());
// TODO(crbug.com/941498): Once RecordUseOf() is fixed for server addresses,
// change this expectation back to 2.
EXPECT_EQ(1U, addresses_metadata.begin()->second.use_count);
}
// If the server sends the same cards and addresses with changed data, they
// should change on the client.
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, ChangedEntityGetsUpdated) {
GetFakeServer()->SetWalletData(
{CreateSyncWalletCard(/*name=*/"card-1", /*last_four=*/"0002",
kDefaultBillingAddressID, /*nickname=*/"Outdated"),
CreateSyncWalletAddress(/*name=*/"address-1", /*company=*/"Company-2"),
CreateDefaultSyncPaymentsCustomerData(),
CreateSyncCreditCardCloudTokenData("data-1")});
ASSERT_TRUE(SetupSync());
// Record use of to get non-default metadata values.
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
std::vector<CreditCard*> cards = pdm->GetCreditCards();
ASSERT_EQ(1uL, cards.size());
pdm->RecordUseOf(cards[0]);
std::vector<AutofillProfile*> profiles = pdm->GetServerProfiles();
ASSERT_EQ(1uL, profiles.size());
// TODO(crbug.com/941498): Server profiles are not recorded.
pdm->RecordUseOf(profiles[0]);
// Update the data (also change the customer data to force the full update as
// FakeServer computes the hash for progress markers only based on ids). For
// server card, only the card's nickname is changed, metadata is unchanged.
GetFakeServer()->SetWalletData(
{CreateSyncWalletCard(/*name=*/"card-1", /*last_four=*/"0002",
kDefaultBillingAddressID,
/*nickname=*/"Grocery Card"),
CreateSyncWalletAddress(/*name=*/"address-1", /*company=*/"Company-1"),
CreateSyncPaymentsCustomerData("different"),
CreateSyncCreditCardCloudTokenData("data-2")});
WaitForPaymentsCustomerData(/*customer_id=*/"different", pdm);
// Make sure the data is present on the client.
cards = pdm->GetCreditCards();
ASSERT_EQ(1uL, cards.size());
EXPECT_EQ(ASCIIToUTF16("Grocery Card"), cards[0]->nickname());
profiles = pdm->GetServerProfiles();
ASSERT_EQ(1uL, profiles.size());
EXPECT_EQ("Company-1", TruncateUTF8(base::UTF16ToUTF8(
profiles[0]->GetRawInfo(autofill::COMPANY_NAME))));
std::vector<CreditCardCloudTokenData*> cloud_token_data =
pdm->GetCreditCardCloudTokenData();
ASSERT_EQ(1uL, cloud_token_data.size());
EXPECT_EQ("data-2", cloud_token_data[0]->instrument_token);
// Test that the non-default metadata values stayed around.
std::map<std::string, AutofillMetadata> cards_metadata =
GetServerCardsMetadata(0);
EXPECT_EQ(1U, cards_metadata.size());
EXPECT_EQ(2U, cards_metadata.begin()->second.use_count);
std::map<std::string, AutofillMetadata> addresses_metadata =
GetServerAddressesMetadata(0);
EXPECT_EQ(1U, addresses_metadata.size());
// Metadata for server addresses cannot be preserved because the id changes
// since it is generated on the client as a hash of all the data fields. As a
// result, the metadata entry gets deleted and recreated under a different id
// and has a default use count.
EXPECT_EQ(1U, addresses_metadata.begin()->second.use_count);
}
// If the server sends the same cards again, they should not change on the
// client even if the cards on the client are unmasked.
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest,
SameUpdatesAreIgnoredWhenLocalCardsUnmasked) {
GetFakeServer()->SetWalletData(
{CreateSyncWalletCard(/*name=*/"card-1", /*last_four=*/"0001",
kDefaultBillingAddressID),
CreateDefaultSyncPaymentsCustomerData()});
ASSERT_TRUE(SetupSync());
// Check we have the card locally.
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
ASSERT_NE(nullptr, pdm);
std::vector<CreditCard*> cards = pdm->GetCreditCards();
ASSERT_EQ(1uL, cards.size());
EXPECT_EQ(ASCIIToUTF16("0001"), cards[0]->LastFourDigits());
EXPECT_EQ(CreditCard::MASKED_SERVER_CARD, cards[0]->record_type());
// Unmask the card (the full card number has to start with "34" to match the
// type of the masked card which is by default AMEX in the tests).
UnmaskServerCard(0, *cards[0], base::UTF8ToUTF16("3404000300020001"));
// Keep the same data (only change the customer data to force the FakeServer
// to send the full update).
GetFakeServer()->SetWalletData(
{CreateSyncWalletCard(/*name=*/"card-1", /*last_four=*/"0001",
kDefaultBillingAddressID),
CreateSyncPaymentsCustomerData("different")});
WaitForPaymentsCustomerData(/*customer_id=*/"different", pdm);
// Make sure the data is present on the client.
cards = pdm->GetCreditCards();
ASSERT_EQ(1uL, cards.size());
EXPECT_EQ(ASCIIToUTF16("0001"), cards[0]->LastFourDigits());
EXPECT_EQ(CreditCard::FULL_SERVER_CARD, cards[0]->record_type());
EXPECT_EQ("different", pdm->GetPaymentsCustomerData()->customer_id);
}
// Wallet data should get cleared from the database when the wallet sync type
// flag is disabled.
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, ClearOnDisableWalletSync) {
GetFakeServer()->SetWalletData({CreateDefaultSyncWalletAddress(),
CreateDefaultSyncWalletCard(),
CreateDefaultSyncPaymentsCustomerData(),
CreateDefaultSyncCreditCardCloudTokenData()});
ASSERT_TRUE(SetupSync());
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
ASSERT_NE(nullptr, pdm);
// Make sure the data & metadata is in the DB.
ASSERT_EQ(1uL, pdm->GetServerProfiles().size());
ASSERT_EQ(1uL, pdm->GetCreditCards().size());
ASSERT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
ASSERT_EQ(1uL, pdm->GetCreditCardCloudTokenData().size());
ASSERT_EQ(1U, GetServerCardsMetadata(0).size());
ASSERT_EQ(1U, GetServerAddressesMetadata(0).size());
// Turn off autofill sync, the data & metadata should be gone.
ASSERT_TRUE(
GetClient(0)->DisableSyncForType(syncer::UserSelectableType::kAutofill));
WaitForNumberOfCards(0, pdm);
EXPECT_EQ(0uL, pdm->GetServerProfiles().size());
EXPECT_EQ(0uL, pdm->GetCreditCards().size());
EXPECT_EQ(nullptr, pdm->GetPaymentsCustomerData());
EXPECT_EQ(0uL, pdm->GetCreditCardCloudTokenData().size());
EXPECT_EQ(0U, GetServerCardsMetadata(0).size());
EXPECT_EQ(0U, GetServerAddressesMetadata(0).size());
}
// Wallet data should get cleared from the database when the wallet autofill
// integration flag is disabled.
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest,
ClearOnDisableWalletAutofill) {
GetFakeServer()->SetWalletData({CreateDefaultSyncWalletAddress(),
CreateDefaultSyncWalletCard(),
CreateDefaultSyncPaymentsCustomerData(),
CreateDefaultSyncCreditCardCloudTokenData()});
ASSERT_TRUE(SetupSync());
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
ASSERT_NE(nullptr, pdm);
// Make sure the data & metadata is in the DB.
ASSERT_EQ(1uL, pdm->GetServerProfiles().size());
ASSERT_EQ(1uL, pdm->GetCreditCards().size());
ASSERT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
ASSERT_EQ(1uL, pdm->GetCreditCardCloudTokenData().size());
ASSERT_EQ(1U, GetServerCardsMetadata(0).size());
ASSERT_EQ(1U, GetServerAddressesMetadata(0).size());
// Turn off the wallet autofill pref, the data & metadata should be gone as a
// side effect of the wallet model type controller noticing.
autofill::prefs::SetPaymentsIntegrationEnabled(GetProfile(0)->GetPrefs(),
false);
// It's not sufficient to wait for 0 cards (as in other tests) because
// switching off the pref makes PDM (synchronously) return 0 cards (without
// the other changes in the DB going through).
WaitForNumberOfServerProfiles(0, pdm);
EXPECT_EQ(0uL, pdm->GetCreditCards().size());
EXPECT_EQ(nullptr, pdm->GetPaymentsCustomerData());
EXPECT_EQ(0uL, pdm->GetCreditCardCloudTokenData().size());
EXPECT_EQ(0U, GetServerCardsMetadata(0).size());
EXPECT_EQ(0U, GetServerAddressesMetadata(0).size());
}
// Wallet data present on the client should be cleared in favor of the new data
// synced down form the server.
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest,
NewWalletCardRemovesExistingCardAndProfile) {
ASSERT_TRUE(SetupSync());
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
ASSERT_NE(nullptr, pdm);
// Add a server credit card on the client.
CreditCard credit_card(CreditCard::MASKED_SERVER_CARD, "a123");
std::vector<CreditCard> credit_cards = {credit_card};
wallet_helper::SetServerCreditCards(0, credit_cards);
// Add a server profile on the client.
AutofillProfile profile(AutofillProfile::SERVER_PROFILE, "a123");
profile.SetRawInfo(autofill::COMPANY_NAME, ASCIIToUTF16("JustATest"));
std::vector<AutofillProfile> client_profiles = {profile};
wallet_helper::SetServerProfiles(0, client_profiles);
// Add PaymentsCustomerData on the client.
wallet_helper::SetPaymentsCustomerData(
0, autofill::PaymentsCustomerData(/*customer_id=*/kDefaultCustomerID));
// Add a cloud token data on the client.
CreditCardCloudTokenData data;
data.instrument_token = "data-1";
wallet_helper::SetCreditCardCloudTokenData(0, {data});
// Wait for the pdm to get data from the autofill table (the manual changes
// above don't notify pdm to refresh automatically).
pdm->Refresh();
WaitForNumberOfCards(1, pdm);
// Make sure the card was added correctly.
std::vector<CreditCard*> cards = pdm->GetCreditCards();
ASSERT_EQ(1uL, cards.size());
EXPECT_EQ("a123", cards[0]->server_id());
// Make sure the profile was added correctly.
std::vector<AutofillProfile*> profiles = pdm->GetServerProfiles();
ASSERT_EQ(1uL, profiles.size());
EXPECT_EQ("JustATest", TruncateUTF8(base::UTF16ToUTF8(
profiles[0]->GetRawInfo(autofill::COMPANY_NAME))));
// Make sure the customer data was added correctly.
EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
// Make sure the cloud token data was added correctly.
std::vector<CreditCardCloudTokenData*> cloud_token_data =
pdm->GetCreditCardCloudTokenData();
ASSERT_EQ(1uL, cloud_token_data.size());
EXPECT_EQ("data-1", cloud_token_data[0]->instrument_token);
// Add new data to the server and sync it down.
GetFakeServer()->SetWalletData(
{CreateDefaultSyncWalletCard(),
CreateSyncPaymentsCustomerData("different"),
CreateSyncCreditCardCloudTokenData("data-2")});
WaitForPaymentsCustomerData(/*customer_id=*/"different", pdm);
// The only card present on the client should be the one from the server.
cards = pdm->GetCreditCards();
EXPECT_EQ(1uL, cards.size());
EXPECT_EQ(kDefaultCardID, cards[0]->server_id());
// There should be no profile present.
profiles = pdm->GetServerProfiles();
EXPECT_EQ(0uL, profiles.size());
// The only cloud token present on the client should be the one from the
// server.
cloud_token_data = pdm->GetCreditCardCloudTokenData();
ASSERT_EQ(1uL, cloud_token_data.size());
EXPECT_EQ("data-2", cloud_token_data[0]->instrument_token);
}
// Wallet data present on the client should be cleared in favor of the new data
// synced down form the server.
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest,
NewWalletDataRemovesExistingData) {
ASSERT_TRUE(SetupSync());
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
ASSERT_NE(nullptr, pdm);
// Add a server profile on the client.
AutofillProfile profile(AutofillProfile::SERVER_PROFILE, "a123");
profile.SetRawInfo(autofill::COMPANY_NAME, ASCIIToUTF16("JustATest"));
std::vector<AutofillProfile> client_profiles = {profile};
wallet_helper::SetServerProfiles(0, client_profiles);
// Add a server credit card on the client.
CreditCard credit_card(CreditCard::MASKED_SERVER_CARD, "a123");
std::vector<CreditCard> credit_cards = {credit_card};
wallet_helper::SetServerCreditCards(0, credit_cards);
// Add PaymentsCustomerData on the client.
wallet_helper::SetPaymentsCustomerData(
0, autofill::PaymentsCustomerData(/*customer_id=*/kDefaultCustomerID));
// Add CreditCardCloudTokenData on the client.
CreditCardCloudTokenData data;
data.instrument_token = "data-1";
wallet_helper::SetCreditCardCloudTokenData(0, {data});
// Wait for the pdm to get data from the autofill table (the manual changes
// above don't notify pdm to refresh automatically).
pdm->Refresh();
WaitForNumberOfCards(1, pdm);
// Make sure the profile was added correctly.
std::vector<AutofillProfile*> profiles = pdm->GetServerProfiles();
EXPECT_EQ(1uL, profiles.size());
EXPECT_EQ("JustATest", TruncateUTF8(base::UTF16ToUTF8(
profiles[0]->GetRawInfo(autofill::COMPANY_NAME))));
// Make sure the card was added correctly.
std::vector<CreditCard*> cards = pdm->GetCreditCards();
EXPECT_EQ(1uL, cards.size());
EXPECT_EQ("a123", cards[0]->server_id());
// Make sure the customer data was added correctly.
EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
// Make sure the credit card cloud token data was added correctly.
std::vector<CreditCardCloudTokenData*> cloud_token_data =
pdm->GetCreditCardCloudTokenData();
ASSERT_EQ(1uL, cloud_token_data.size());
EXPECT_EQ("data-1", cloud_token_data[0]->instrument_token);
// Add a new profile and new customer data from the server and sync them down.
GetFakeServer()->SetWalletData(
{CreateDefaultSyncWalletAddress(),
CreateSyncPaymentsCustomerData(/*customer_id=*/"different"),
CreateSyncCreditCardCloudTokenData("data-2")});
WaitForPaymentsCustomerData(/*customer_id=*/"different", pdm);
// The only profile present on the client should be the one from the server.
profiles = pdm->GetServerProfiles();
EXPECT_EQ(1uL, profiles.size());
EXPECT_NE("JustATest", TruncateUTF8(base::UTF16ToUTF8(
profiles[0]->GetRawInfo(autofill::COMPANY_NAME))));
// There should be no cards present.
cards = pdm->GetCreditCards();
EXPECT_EQ(0uL, cards.size());
// Credit card cloud token data should be updated.
cloud_token_data = pdm->GetCreditCardCloudTokenData();
ASSERT_EQ(1uL, cloud_token_data.size());
EXPECT_EQ("data-2", cloud_token_data[0]->instrument_token);
}
// Tests that a local billing address id set on a card on the client should not
// be overwritten when that same card is synced again.
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest,
SameWalletCard_PreservesLocalBillingAddressId) {
ASSERT_TRUE(SetupSync());
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
ASSERT_NE(nullptr, pdm);
// Add a server credit card on the client but with the billing address id of a
// local profile.
CreditCard credit_card = GetDefaultCreditCard();
credit_card.set_billing_address_id(kLocalGuidA);
std::vector<CreditCard> credit_cards = {credit_card};
wallet_helper::SetServerCreditCards(0, credit_cards);
// Wait for the pdm to get data from the autofill table (the manual changes
// above don't notify pdm to refresh automatically).
pdm->Refresh();
WaitForNumberOfCards(1, pdm);
// Make sure the card was added correctly.
std::vector<CreditCard*> cards = pdm->GetCreditCards();
ASSERT_EQ(1uL, cards.size());
EXPECT_EQ(kDefaultCardID, cards[0]->server_id());
// Sync the same card from the server, except with a default billing address
// id.
GetFakeServer()->SetWalletData(
{CreateDefaultSyncWalletCard(),
CreateSyncPaymentsCustomerData(/*customer_id=*/"different")});
WaitForPaymentsCustomerData(/*customer_id=*/"different", pdm);
// The billing address is should still refer to the local profile.
cards = pdm->GetCreditCards();
ASSERT_EQ(1uL, cards.size());
EXPECT_EQ(kDefaultCardID, cards[0]->server_id());
EXPECT_EQ(kLocalGuidA, cards[0]->billing_address_id());
}
// Tests that a server billing address id set on a card on the client is
// overwritten when that same card is synced again.
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest,
SameWalletCard_DiscardsOldServerBillingAddressId) {
ASSERT_TRUE(SetupSync());
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
ASSERT_NE(nullptr, pdm);
// Add a server credit card on the client but with the billing address id of a
// server profile.
CreditCard credit_card = GetDefaultCreditCard();
credit_card.set_billing_address_id(kDifferentBillingAddressId);
std::vector<CreditCard> credit_cards = {credit_card};
wallet_helper::SetServerCreditCards(0, credit_cards);
// Wait for the pdm to get data from the autofill table (the manual changes
// above don't notify pdm to refresh automatically).
pdm->Refresh();
WaitForNumberOfCards(1, pdm);
// Make sure the card was added correctly.
std::vector<CreditCard*> cards = pdm->GetCreditCards();
ASSERT_EQ(1uL, cards.size());
EXPECT_EQ(kDefaultCardID, cards[0]->server_id());
// Sync the same card from the server, except with a default billing address
// id.
GetFakeServer()->SetWalletData(
{CreateDefaultSyncWalletCard(),
CreateSyncPaymentsCustomerData(/*customer_id=*/"different")});
WaitForPaymentsCustomerData(/*customer_id=*/"different", pdm);
// The billing address should be the one from the server card.
cards = pdm->GetCreditCards();
ASSERT_EQ(1uL, cards.size());
EXPECT_EQ(kDefaultCardID, cards[0]->server_id());
EXPECT_EQ(kDefaultBillingAddressID, cards[0]->billing_address_id());
}
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, ConvertServerAddress) {
GetFakeServer()->SetWalletData(
{CreateSyncWalletAddress(/*name=*/"address-1", /*company=*/"Company-1"),
CreateDefaultSyncPaymentsCustomerData()});
ASSERT_TRUE(SetupSync());
// Wait to make sure the address got converted locally.
AutofillWalletConversionChecker(0).Wait();
// Make sure the wallet_metadata is committed to the server, make an
// independent later commit and wait for it to happen.
ASSERT_TRUE(
bookmarks_helper::AddURL(0, "What are you syncing about?",
GURL("https://google.com/synced-bookmark-1")));
ASSERT_TRUE(ServerCountMatchStatusChecker(syncer::BOOKMARKS, 1).Wait());
// Make sure the data is present on the client.
autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
ASSERT_EQ(1uL, pdm->GetServerProfiles().size());
ASSERT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
// Check also the data related to conversion to local profiles.
ASSERT_EQ(1uL, pdm->GetProfiles().size());
std::map<std::string, AutofillMetadata> addresses_metadata =
GetServerAddressesMetadata(0);
EXPECT_EQ(1U, addresses_metadata.size());
EXPECT_TRUE(addresses_metadata.begin()->second.has_converted);
// Check the data is correctly on the server.
EXPECT_THAT(fake_server_->GetSyncEntitiesByModelType(
syncer::AUTOFILL_WALLET_METADATA),
Contains(AddressHasConverted()));
histogram_tester_.ExpectBucketCount(
"Autofill.WalletAddressConversionType",
/*bucket=*/AutofillMetrics::CONVERTED_ADDRESS_ADDED,
/*count=*/1);
}
IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest,
DoNotConvertServerAddressAgain) {
sync_pb::SyncEntity address_entity =
CreateSyncWalletAddress(/*name=*/"address-1", /*company=*/"Company-1");
GetFakeServer()->SetWalletData(
{address_entity, CreateDefaultSyncPaymentsCustomerData()});
// Inject a wallet metadata entity that indicates the address has already been
// converted.
sync_pb::EntitySpecifics specifics;
sync_pb::WalletMetadataSpecifics* wallet_metadata_specifics =
specifics.mutable_wallet_metadata();
wallet_metadata_specifics->set_type(
sync_pb::WalletMetadataSpecifics::ADDRESS);
wallet_metadata_specifics->set_use_count(3);
wallet_metadata_specifics->set_use_date(10);
wallet_metadata_specifics->set_address_has_converted(true);
// The id gets generated on the client based on the data. Simulate the process
// to get the same id. On top of it, we need to base64encode it.
AutofillProfile address = autofill::ProfileFromSpecifics(
address_entity.specifics().autofill_wallet().address());
wallet_metadata_specifics->set_id(
autofill::GetBase64EncodedId(address.server_id()));
GetFakeServer()->InjectEntity(
syncer::PersistentUniqueClientEntity::CreateFromSpecificsForTesting(
"non_unique_name",
/*client_tag_hash=*/"address-" + wallet_metadata_specifics->id(),
specifics,
/*creation_time=*/0,
/*last_modified_time=*/0));
ASSERT_TRUE(SetupSync());
// Wait to make sure we receive the (already converted) metadata entity.
AutofillWalletConversionChecker(0).Wait();
// No conversion happens now.
histogram_tester_.ExpectTotalCount("Autofill.WalletAddressConversionType",
/*count=*/0);
}
class SingleClientWalletSecondaryAccountSyncTest
: public SingleClientWalletSyncTest {
public:
SingleClientWalletSecondaryAccountSyncTest() {
features_.InitAndEnableFeature(
autofill::features::kAutofillEnableAccountWalletStorage);
}
~SingleClientWalletSecondaryAccountSyncTest() override {}
void SetUpInProcessBrowserTestFixture() override {
test_signin_client_subscription_ =
secondary_account_helper::SetUpSigninClient(&test_url_loader_factory_);
}
void SetUpOnMainThread() override {
#if BUILDFLAG(IS_CHROMEOS_ASH)
secondary_account_helper::InitNetwork();
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
SyncTest::SetUpOnMainThread();
}
Profile* profile() { return GetProfile(0); }
private:
base::test::ScopedFeatureList features_;
base::CallbackListSubscription test_signin_client_subscription_;
DISALLOW_COPY_AND_ASSIGN(SingleClientWalletSecondaryAccountSyncTest);
};
// ChromeOS doesn't support changes to the primary account after startup, so
// these secondary-account-related tests don't apply.
#if !BUILDFLAG(IS_CHROMEOS_ASH)
IN_PROC_BROWSER_TEST_F(SingleClientWalletSecondaryAccountSyncTest,
SwitchesFromAccountToProfileStorageOnSyncOptIn) {
ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
GetFakeServer()->SetWalletData({CreateDefaultSyncWalletCard(),
CreateDefaultSyncPaymentsCustomerData(),
CreateDefaultSyncCreditCardCloudTokenData()});
// Set up Sync in transport mode for a non-primary account.
secondary_account_helper::SignInSecondaryAccount(
profile(), &test_url_loader_factory_, "user@email.com");
ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
GetSyncService(0)->GetTransportState());
ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureActive());
ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(
syncer::AUTOFILL_WALLET_DATA));
// PersonalDataManager should use (ephemeral) account storage.
EXPECT_FALSE(GetPersonalDataManager(0)->IsSyncFeatureEnabled());
EXPECT_TRUE(
GetPersonalDataManager(0)->IsUsingAccountStorageForServerDataForTest());
auto account_data = GetAccountWebDataService(0);
ASSERT_NE(nullptr, account_data);
auto profile_data = GetProfileWebDataService(0);
ASSERT_NE(nullptr, profile_data);
// Check that the data is stored in the account storage (ephemeral), but not
// in the profile storage (persisted).
EXPECT_EQ(1U, GetServerCards(account_data).size());
EXPECT_EQ(0U, GetServerCards(profile_data).size());
EXPECT_NE(nullptr, GetPaymentsCustomerData(account_data).get());
EXPECT_EQ(nullptr, GetPaymentsCustomerData(profile_data).get());
EXPECT_EQ(1U, GetCreditCardCloudTokenData(account_data).size());
EXPECT_EQ(0U, GetCreditCardCloudTokenData(profile_data).size());
// Simulate the user opting in to full Sync: Make the account primary, and
// set first-time setup to complete.
secondary_account_helper::MakeAccountPrimary(profile(), "user@email.com");
GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
kSetSourceFromTest);
// Wait for Sync to get reconfigured into feature mode.
ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
GetSyncService(0)->GetTransportState());
ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureEnabled());
ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive());
ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(
syncer::AUTOFILL_WALLET_DATA));
// PersonalDataManager should have switched to persistent storage.
EXPECT_TRUE(GetPersonalDataManager(0)->IsSyncFeatureEnabled());
EXPECT_FALSE(
GetPersonalDataManager(0)->IsUsingAccountStorageForServerDataForTest());
// The data should now be in the profile storage (persisted).
EXPECT_EQ(0U, GetServerCards(account_data).size());
EXPECT_EQ(1U, GetServerCards(profile_data).size());
EXPECT_EQ(nullptr, GetPaymentsCustomerData(account_data).get());
EXPECT_NE(nullptr, GetPaymentsCustomerData(profile_data).get());
EXPECT_EQ(0U, GetCreditCardCloudTokenData(account_data).size());
EXPECT_EQ(1U, GetCreditCardCloudTokenData(profile_data).size());
}
IN_PROC_BROWSER_TEST_F(
SingleClientWalletSecondaryAccountSyncTest,
SwitchesFromAccountToProfileStorageOnSyncOptInWithAdvancedSetup) {
ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
GetFakeServer()->SetWalletData({CreateDefaultSyncWalletCard(),
CreateDefaultSyncCreditCardCloudTokenData()});
// Set up Sync in transport mode for a non-primary account.
secondary_account_helper::SignInSecondaryAccount(
profile(), &test_url_loader_factory_, "user@email.com");
ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
GetSyncService(0)->GetTransportState());
ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureActive());
ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(
syncer::AUTOFILL_WALLET_DATA));
// PersonalDataManager should use (ephemeral) account storage.
EXPECT_FALSE(GetPersonalDataManager(0)->IsSyncFeatureEnabled());
EXPECT_TRUE(
GetPersonalDataManager(0)->IsUsingAccountStorageForServerDataForTest());
auto account_data = GetAccountWebDataService(0);
ASSERT_NE(nullptr, account_data);
auto profile_data = GetProfileWebDataService(0);
ASSERT_NE(nullptr, profile_data);
// Check that the card is stored in the account storage (ephemeral), but not
// in the profile storage (persisted).
EXPECT_EQ(1U, GetServerCards(account_data).size());
EXPECT_EQ(0U, GetServerCards(profile_data).size());
EXPECT_EQ(1U, GetCreditCardCloudTokenData(account_data).size());
EXPECT_EQ(0U, GetCreditCardCloudTokenData(profile_data).size());
// Simulate the user opting in to full Sync: First, make the account primary.
secondary_account_helper::MakeAccountPrimary(profile(), "user@email.com");
// Now start actually configuring Sync.
GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
auto setup_handle = GetSyncService(0)->GetSetupInProgressHandle();
GetSyncService(0)->GetUserSettings()->SetSelectedTypes(
/*sync_everything=*/false, {syncer::UserSelectableType::kAutofill});
// Once the user finishes the setup, the newly selected data types will
// actually get configured.
setup_handle.reset();
ASSERT_EQ(syncer::SyncService::TransportState::CONFIGURING,
GetSyncService(0)->GetTransportState());
GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
kSetSourceFromTest);
// Wait for Sync to get reconfigured into feature mode.
ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
GetSyncService(0)->GetTransportState());
ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureEnabled());
ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive());
ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(
syncer::AUTOFILL_WALLET_DATA));
// PersonalDataManager should have switched to persistent storage.
EXPECT_TRUE(GetPersonalDataManager(0)->IsSyncFeatureEnabled());
EXPECT_FALSE(
GetPersonalDataManager(0)->IsUsingAccountStorageForServerDataForTest());
// The card should now be in the profile storage (persisted).
EXPECT_EQ(0U, GetServerCards(account_data).size());
EXPECT_EQ(1U, GetServerCards(profile_data).size());
EXPECT_EQ(0U, GetCreditCardCloudTokenData(account_data).size());
EXPECT_EQ(1U, GetCreditCardCloudTokenData(profile_data).size());
}
#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
// This tests that switching between Sync-the-feature and
// Sync-standalone-transport properly migrates server credit cards between the
// profile (i.e. persisted) and account (i.e. ephemeral) storage.
// Sync can either be turned off temporarily via
// SyncUserSettings::SetSyncRequested(false), or permanently via
// SyncService::StopAndClear. For full coverage, we test all transitions, and
// each time verify that the card is in the correct storage:
// 1. Start out in Sync-the-feature mode -> profile storage.
// 2. SetSyncRequested(false) -> account storage.
// 3. Enable Sync-the-feature again -> profile storage.
// 4. StopAndClear() -> account storage.
// 5. Enable Sync-the-feature again -> profile storage.
IN_PROC_BROWSER_TEST_F(SingleClientWalletWithAccountStorageSyncTest,
SwitchesBetweenAccountAndProfileStorageOnTogglingSync) {
ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
GetFakeServer()->SetWalletData({CreateDefaultSyncWalletCard(),
CreateDefaultSyncCreditCardCloudTokenData()});
// STEP 1. Set up Sync in full feature mode.
ASSERT_TRUE(GetClient(0)->SetupSync());
ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
GetSyncService(0)->GetTransportState());
ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureEnabled());
ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive());
ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(
syncer::AUTOFILL_WALLET_DATA));
// PersonalDataManager should use the regular persisted (non-account) storage.
EXPECT_TRUE(GetPersonalDataManager(0)->IsSyncFeatureEnabled());
EXPECT_FALSE(
GetPersonalDataManager(0)->IsUsingAccountStorageForServerDataForTest());
auto account_data = GetAccountWebDataService(0);
ASSERT_NE(nullptr, account_data);
auto profile_data = GetProfileWebDataService(0);
ASSERT_NE(nullptr, profile_data);
// Check that the card is stored in the profile storage (persisted), but not
// in the account storage (ephemeral).
EXPECT_EQ(0U, GetServerCards(account_data).size());
EXPECT_EQ(1U, GetServerCards(profile_data).size());
EXPECT_EQ(0U, GetCreditCardCloudTokenData(account_data).size());
EXPECT_EQ(1U, GetCreditCardCloudTokenData(profile_data).size());
// STEP 2. Turn off Sync-the-feature temporarily (e.g. the Sync feature toggle
// on Android), i.e. leave the Sync data around.
GetSyncService(0)->GetUserSettings()->SetSyncRequested(false);
// Wait for Sync to get reconfigured into transport mode.
ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
GetSyncService(0)->GetTransportState());
ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureActive());
ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(
syncer::AUTOFILL_WALLET_DATA));
// PersonalDataManager should have switched to ephemeral storage.
EXPECT_FALSE(GetPersonalDataManager(0)->IsSyncFeatureEnabled());
EXPECT_TRUE(
GetPersonalDataManager(0)->IsUsingAccountStorageForServerDataForTest());
// The card should now be in the account storage (ephemeral). Note that even
// though we specified KEEP_DATA above, the card is *not* in the profile
// storage (persisted) anymore, because AUTOFILL_WALLET_DATA is special-cased
// to always clear its data when Sync is turned off.
EXPECT_EQ(1U, GetServerCards(account_data).size());
EXPECT_EQ(0U, GetServerCards(profile_data).size());
EXPECT_EQ(1U, GetCreditCardCloudTokenData(account_data).size());
EXPECT_EQ(0U, GetCreditCardCloudTokenData(profile_data).size());
// STEP 3. Turn Sync-the-feature on again.
GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
// Wait for Sync to get reconfigured into full feature mode again.
ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
GetSyncService(0)->GetTransportState());
ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureEnabled());
ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive());
ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(
syncer::AUTOFILL_WALLET_DATA));
// PersonalDataManager should have switched back to persistent storage.
EXPECT_TRUE(GetPersonalDataManager(0)->IsSyncFeatureEnabled());
EXPECT_FALSE(
GetPersonalDataManager(0)->IsUsingAccountStorageForServerDataForTest());
// And the card should be in the profile i.e. persistent storage again.
EXPECT_EQ(0U, GetServerCards(account_data).size());
EXPECT_EQ(1U, GetServerCards(profile_data).size());
EXPECT_EQ(0U, GetCreditCardCloudTokenData(account_data).size());
EXPECT_EQ(1U, GetCreditCardCloudTokenData(profile_data).size());
// STEP 4. Turn off Sync-the-feature again, but this time clear data.
GetSyncService(0)->StopAndClear();
// Wait for Sync to get reconfigured into transport mode.
ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
GetSyncService(0)->GetTransportState());
ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled());
ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureActive());
ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(
syncer::AUTOFILL_WALLET_DATA));
// PersonalDataManager should have switched to ephemeral storage.
EXPECT_FALSE(GetPersonalDataManager(0)->IsSyncFeatureEnabled());
EXPECT_TRUE(
GetPersonalDataManager(0)->IsUsingAccountStorageForServerDataForTest());
// The card should now be in the account storage (ephemeral).
EXPECT_EQ(1U, GetServerCards(account_data).size());
EXPECT_EQ(0U, GetServerCards(profile_data).size());
EXPECT_EQ(1U, GetCreditCardCloudTokenData(account_data).size());
EXPECT_EQ(0U, GetCreditCardCloudTokenData(profile_data).size());
// STEP 5. Turn Sync-the-feature on again.
GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
kSetSourceFromTest);
// Wait for Sync to get reconfigured into full feature mode again.
ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
GetSyncService(0)->GetTransportState());
ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureEnabled());
ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive());
ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(
syncer::AUTOFILL_WALLET_DATA));
// PersonalDataManager should have switched back to persistent storage.
EXPECT_TRUE(GetPersonalDataManager(0)->IsSyncFeatureEnabled());
EXPECT_FALSE(
GetPersonalDataManager(0)->IsUsingAccountStorageForServerDataForTest());
// And the card should be in the profile i.e. persistent storage again.
EXPECT_EQ(0U, GetServerCards(account_data).size());
EXPECT_EQ(1U, GetServerCards(profile_data).size());
EXPECT_EQ(0U, GetCreditCardCloudTokenData(account_data).size());
EXPECT_EQ(1U, GetCreditCardCloudTokenData(profile_data).size());
}