1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/autofill/core/browser/webdata/autofill_sync_bridge_util.h"
6
7 #include <vector>
8
9 #include "base/strings/utf_string_conversions.h"
10 #include "components/autofill/core/browser/data_model/autofill_profile.h"
11 #include "components/autofill/core/browser/data_model/credit_card.h"
12 #include "components/autofill/core/browser/data_model/credit_card_cloud_token_data.h"
13 #include "components/autofill/core/browser/payments/payments_customer_data.h"
14 #include "components/autofill/core/browser/test_autofill_clock.h"
15 #include "components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.h"
16 #include "components/autofill/core/browser/webdata/autofill_table.h"
17 #include "components/autofill/core/common/autofill_constants.h"
18 #include "components/sync/base/client_tag_hash.h"
19 #include "components/sync/model/entity_data.h"
20 #include "components/sync/protocol/sync.pb.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 namespace autofill {
24 namespace {
25
26 using syncer::EntityChange;
27 using syncer::EntityData;
28
29 class TestAutofillTable : public AutofillTable {
30 public:
TestAutofillTable(std::vector<CreditCard> cards_on_disk)31 explicit TestAutofillTable(std::vector<CreditCard> cards_on_disk)
32 : cards_on_disk_(cards_on_disk) {}
33
~TestAutofillTable()34 ~TestAutofillTable() override {}
35
GetServerCreditCards(std::vector<std::unique_ptr<CreditCard>> * cards) const36 bool GetServerCreditCards(
37 std::vector<std::unique_ptr<CreditCard>>* cards) const override {
38 for (const auto& card_on_disk : cards_on_disk_)
39 cards->push_back(std::make_unique<CreditCard>(card_on_disk));
40 return true;
41 }
42
43 private:
44 std::vector<CreditCard> cards_on_disk_;
45
46 DISALLOW_COPY_AND_ASSIGN(TestAutofillTable);
47 };
48
SpecificsToEntity(const sync_pb::AutofillWalletSpecifics & specifics,const std::string & client_tag)49 EntityData SpecificsToEntity(const sync_pb::AutofillWalletSpecifics& specifics,
50 const std::string& client_tag) {
51 syncer::EntityData data;
52 *data.specifics.mutable_autofill_wallet() = specifics;
53 data.client_tag_hash = syncer::ClientTagHash::FromUnhashed(
54 syncer::AUTOFILL_WALLET_DATA, client_tag);
55 return data;
56 }
57
58 class AutofillSyncBridgeUtilTest : public testing::Test {
59 public:
AutofillSyncBridgeUtilTest()60 AutofillSyncBridgeUtilTest() {}
~AutofillSyncBridgeUtilTest()61 ~AutofillSyncBridgeUtilTest() override {}
62
63 private:
64 DISALLOW_COPY_AND_ASSIGN(AutofillSyncBridgeUtilTest);
65 };
66
67 // Tests that PopulateWalletTypesFromSyncData behaves as expected.
TEST_F(AutofillSyncBridgeUtilTest,PopulateWalletTypesFromSyncData)68 TEST_F(AutofillSyncBridgeUtilTest, PopulateWalletTypesFromSyncData) {
69 // Add an address first.
70 syncer::EntityChangeList entity_data;
71 std::string address_id("address1");
72 entity_data.push_back(EntityChange::CreateAdd(
73 address_id,
74 SpecificsToEntity(CreateAutofillWalletSpecificsForAddress(address_id),
75 /*client_tag=*/"address-address1")));
76 // Add the first card that has its billing address id set to the address's id.
77 // No nickname is set.
78 entity_data.push_back(EntityChange::CreateAdd(
79 "card_with_billing_address_id",
80 SpecificsToEntity(CreateAutofillWalletSpecificsForCard(
81 /*id=*/"card_with_billing_address_id",
82 /*billing_address_id=*/address_id),
83 /*client_tag=*/"card-card1")));
84 // Add the second card that has nickname.
85 std::string nickname("Grocery card");
86 entity_data.push_back(EntityChange::CreateAdd(
87 "card_with_nickname",
88 SpecificsToEntity(CreateAutofillWalletSpecificsForCard(
89 /*id=*/"card_with_nickname",
90 /*billing_address_id=*/"", /*nickname=*/nickname),
91 /*client_tag=*/"card-card2")));
92 entity_data.push_back(EntityChange::CreateAdd(
93 "deadbeef",
94 SpecificsToEntity(CreateAutofillWalletSpecificsForPaymentsCustomerData(
95 /*specifics_id=*/"deadbeef"),
96 /*client_tag=*/"customer-deadbeef")));
97 entity_data.push_back(EntityChange::CreateAdd(
98 "data1", SpecificsToEntity(
99 CreateAutofillWalletSpecificsForCreditCardCloudTokenData(
100 /*specifics_id=*/"data1"),
101 /*client_tag=*/"token-data1")));
102
103 std::vector<CreditCard> wallet_cards;
104 std::vector<AutofillProfile> wallet_addresses;
105 std::vector<PaymentsCustomerData> customer_data;
106 std::vector<CreditCardCloudTokenData> cloud_token_data;
107 PopulateWalletTypesFromSyncData(entity_data, &wallet_cards, &wallet_addresses,
108 &customer_data, &cloud_token_data);
109
110 ASSERT_EQ(2U, wallet_cards.size());
111 ASSERT_EQ(1U, wallet_addresses.size());
112
113 EXPECT_EQ("deadbeef", customer_data.back().customer_id);
114
115 EXPECT_EQ("data1", cloud_token_data.back().instrument_token);
116
117 // Make sure the first card's billing address id is equal to the address'
118 // server id.
119 EXPECT_EQ(wallet_addresses.back().server_id(),
120 wallet_cards.front().billing_address_id());
121 // The first card's nickname is empty.
122 EXPECT_TRUE(wallet_cards.front().nickname().empty());
123
124 // Make sure the second card's nickname is correctly populated from sync data.
125 EXPECT_EQ(base::UTF8ToUTF16(nickname), wallet_cards.back().nickname());
126 }
127
128 // Verify that the billing address id from the card saved on disk is kept if it
129 // is a local profile guid.
TEST_F(AutofillSyncBridgeUtilTest,CopyRelevantWalletMetadataFromDisk_KeepLocalAddresses)130 TEST_F(AutofillSyncBridgeUtilTest,
131 CopyRelevantWalletMetadataFromDisk_KeepLocalAddresses) {
132 std::vector<CreditCard> cards_on_disk;
133 std::vector<CreditCard> wallet_cards;
134
135 // Create a local profile to be used as a billing address.
136 AutofillProfile billing_address;
137
138 // Create a card on disk that refers to that local profile as its billing
139 // address.
140 cards_on_disk.push_back(CreditCard());
141 cards_on_disk.back().set_billing_address_id(billing_address.guid());
142
143 // Create a card pulled from wallet with the same id, but a different billing
144 // address id.
145 wallet_cards.push_back(CreditCard(cards_on_disk.back()));
146 wallet_cards.back().set_billing_address_id("1234");
147
148 // Setup the TestAutofillTable with the cards_on_disk.
149 TestAutofillTable table(cards_on_disk);
150
151 CopyRelevantWalletMetadataFromDisk(table, &wallet_cards);
152
153 ASSERT_EQ(1U, wallet_cards.size());
154
155 // Make sure the wallet card replace its billing address id for the one that
156 // was saved on disk.
157 EXPECT_EQ(cards_on_disk.back().billing_address_id(),
158 wallet_cards.back().billing_address_id());
159 }
160
161 // Verify that the billing address id from the card saved on disk is overwritten
162 // if it does not refer to a local profile.
TEST_F(AutofillSyncBridgeUtilTest,CopyRelevantWalletMetadataFromDisk_OverwriteOtherAddresses)163 TEST_F(AutofillSyncBridgeUtilTest,
164 CopyRelevantWalletMetadataFromDisk_OverwriteOtherAddresses) {
165 std::string old_billing_id = "1234";
166 std::string new_billing_id = "9876";
167 std::vector<CreditCard> cards_on_disk;
168 std::vector<CreditCard> wallet_cards;
169
170 // Create a card on disk that does not refer to a local profile (which have 36
171 // chars ids).
172 cards_on_disk.push_back(CreditCard());
173 cards_on_disk.back().set_billing_address_id(old_billing_id);
174
175 // Create a card pulled from wallet with the same id, but a different billing
176 // address id.
177 wallet_cards.push_back(CreditCard(cards_on_disk.back()));
178 wallet_cards.back().set_billing_address_id(new_billing_id);
179
180 // Setup the TestAutofillTable with the cards_on_disk.
181 TestAutofillTable table(cards_on_disk);
182
183 CopyRelevantWalletMetadataFromDisk(table, &wallet_cards);
184
185 ASSERT_EQ(1U, wallet_cards.size());
186
187 // Make sure the local address billing id that was saved on disk did not
188 // replace the new one.
189 EXPECT_EQ(new_billing_id, wallet_cards.back().billing_address_id());
190 }
191
192 // Verify that the use stats on disk are kept when server cards are synced.
TEST_F(AutofillSyncBridgeUtilTest,CopyRelevantWalletMetadataFromDisk_KeepUseStats)193 TEST_F(AutofillSyncBridgeUtilTest,
194 CopyRelevantWalletMetadataFromDisk_KeepUseStats) {
195 TestAutofillClock test_clock;
196 base::Time arbitrary_time = base::Time::FromDoubleT(25);
197 base::Time disk_time = base::Time::FromDoubleT(10);
198 test_clock.SetNow(arbitrary_time);
199
200 std::vector<CreditCard> cards_on_disk;
201 std::vector<CreditCard> wallet_cards;
202
203 // Create a card on disk with specific use stats.
204 cards_on_disk.push_back(CreditCard());
205 cards_on_disk.back().set_use_count(3U);
206 cards_on_disk.back().set_use_date(disk_time);
207
208 // Create a card pulled from wallet with the same id, but a different billing
209 // address id.
210 wallet_cards.push_back(CreditCard());
211 wallet_cards.back().set_use_count(10U);
212
213 // Setup the TestAutofillTable with the cards_on_disk.
214 TestAutofillTable table(cards_on_disk);
215
216 CopyRelevantWalletMetadataFromDisk(table, &wallet_cards);
217
218 ASSERT_EQ(1U, wallet_cards.size());
219
220 // Make sure the use stats from disk were kept
221 EXPECT_EQ(3U, wallet_cards.back().use_count());
222 EXPECT_EQ(disk_time, wallet_cards.back().use_date());
223 }
224
225 } // namespace
226 } // namespace autofill
227