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_profile_sync_bridge.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10 #include <utility>
11
12 #include "base/bind.h"
13 #include "base/callback_helpers.h"
14 #include "base/feature_list.h"
15 #include "base/files/scoped_temp_dir.h"
16 #include "base/guid.h"
17 #include "base/location.h"
18 #include "base/memory/ptr_util.h"
19 #include "base/run_loop.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/test/bind.h"
22 #include "base/test/scoped_feature_list.h"
23 #include "base/test/task_environment.h"
24 #include "base/time/time.h"
25 #include "components/autofill/core/browser/autofill_profile_sync_util.h"
26 #include "components/autofill/core/browser/data_model/autofill_profile.h"
27 #include "components/autofill/core/browser/geo/country_names.h"
28 #include "components/autofill/core/browser/test_autofill_clock.h"
29 #include "components/autofill/core/browser/webdata/autofill_change.h"
30 #include "components/autofill/core/browser/webdata/autofill_table.h"
31 #include "components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h"
32 #include "components/autofill/core/common/autofill_constants.h"
33 #include "components/autofill/core/common/autofill_features.h"
34 #include "components/sync/base/client_tag_hash.h"
35 #include "components/sync/model/data_batch.h"
36 #include "components/sync/model/data_type_activation_request.h"
37 #include "components/sync/model/entity_data.h"
38 #include "components/sync/model/sync_data.h"
39 #include "components/sync/model/sync_error_factory.h"
40 #include "components/sync/model_impl/client_tag_based_model_type_processor.h"
41 #include "components/sync/protocol/sync.pb.h"
42 #include "components/sync/test/model/mock_model_type_change_processor.h"
43 #include "components/sync/test/model/sync_error_factory_mock.h"
44 #include "components/webdata/common/web_database.h"
45 #include "testing/gmock/include/gmock/gmock.h"
46 #include "testing/gtest/include/gtest/gtest.h"
47
48 namespace autofill {
49
50 using base::ASCIIToUTF16;
51 using base::ScopedTempDir;
52 using base::UTF16ToUTF8;
53 using base::UTF8ToUTF16;
54 using sync_pb::AutofillProfileSpecifics;
55 using syncer::DataBatch;
56 using syncer::EntityChange;
57 using syncer::EntityChangeList;
58 using syncer::EntityData;
59 using syncer::KeyAndData;
60 using syncer::MockModelTypeChangeProcessor;
61 using syncer::ModelType;
62 using testing::_;
63 using testing::DoAll;
64 using testing::ElementsAre;
65 using testing::Eq;
66 using testing::Property;
67 using testing::Return;
68 using testing::UnorderedElementsAre;
69
70 namespace {
71
72 // Some guids for testing.
73 const char kGuidA[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44A";
74 const char kGuidB[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44B";
75 const char kGuidC[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44C";
76 const char kGuidD[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44D";
77 const char kGuidInvalid[] = "EDC609ED-7EEE-4F27-B00C";
78 const char kHttpOrigin[] = "http://www.example.com/";
79 const char kHttpsOrigin[] = "https://www.example.com/";
80 const int kValidityStateBitfield = 1984;
81 const char kLocaleString[] = "en-US";
82 const base::Time kJune2017 = base::Time::FromDoubleT(1497552271);
83
CreateAutofillProfile(const AutofillProfileSpecifics & specifics)84 AutofillProfile CreateAutofillProfile(
85 const AutofillProfileSpecifics& specifics) {
86 // As more copying does not hurt in tests, we prefer to use AutofillProfile
87 // instead of std::unique_ptr<AutofillProfile> because of code brevity.
88 return *CreateAutofillProfileFromSpecifics(specifics);
89 }
90
CreateAutofillProfileSpecifics(const AutofillProfile & entry)91 AutofillProfileSpecifics CreateAutofillProfileSpecifics(
92 const AutofillProfile& entry) {
93 // Reuse production code. We do not need EntityData, just take out the
94 // specifics.
95 std::unique_ptr<EntityData> entity_data =
96 CreateEntityDataFromAutofillProfile(entry);
97 return entity_data->specifics.autofill_profile();
98 }
99
CreateAutofillProfileSpecifics(const std::string & guid,const std::string & origin)100 AutofillProfileSpecifics CreateAutofillProfileSpecifics(
101 const std::string& guid,
102 const std::string& origin) {
103 AutofillProfileSpecifics specifics;
104 specifics.set_guid(guid);
105 specifics.set_origin(origin);
106 // Make it consistent with the constructor of AutofillProfile constructor (the
107 // clock value is overrided by TestAutofillClock in the test fixture).
108 specifics.set_use_count(1);
109 specifics.set_use_date(kJune2017.ToTimeT());
110 return specifics;
111 }
112
113 MATCHER_P(HasSpecifics, expected, "") {
114 AutofillProfile arg_profile =
115 CreateAutofillProfile(arg->specifics.autofill_profile());
116 AutofillProfile expected_profile = CreateAutofillProfile(expected);
117 if (!arg_profile.EqualsIncludingUsageStatsForTesting(expected_profile)) {
118 *result_listener << "entry\n[" << arg_profile << "]\n"
119 << "did not match expected\n[" << expected_profile << "]";
120 return false;
121 }
122 return true;
123 }
124
125 MATCHER_P(WithUsageStats, expected, "") {
126 if (!arg.EqualsIncludingUsageStatsForTesting(expected)) {
127 *result_listener << "entry\n[" << arg << "]\n"
128 << "did not match expected\n[" << expected << "]";
129 return false;
130 }
131 return true;
132 }
133
ExtractAutofillProfilesFromDataBatch(std::unique_ptr<DataBatch> batch,std::vector<AutofillProfile> * output)134 void ExtractAutofillProfilesFromDataBatch(
135 std::unique_ptr<DataBatch> batch,
136 std::vector<AutofillProfile>* output) {
137 while (batch->HasNext()) {
138 const KeyAndData& data_pair = batch->Next();
139 output->push_back(
140 CreateAutofillProfile(data_pair.second->specifics.autofill_profile()));
141 }
142 }
143
144 // Returns a profile with all fields set. Contains identical data to the data
145 // returned from ConstructCompleteSpecifics().
ConstructCompleteProfile()146 AutofillProfile ConstructCompleteProfile() {
147 AutofillProfile profile(kGuidA, kHttpsOrigin);
148
149 profile.set_use_count(7);
150 profile.set_use_date(base::Time::FromTimeT(1423182152));
151
152 profile.SetRawInfo(NAME_HONORIFIC_PREFIX, ASCIIToUTF16(""));
153 profile.SetRawInfo(NAME_FULL, ASCIIToUTF16("John K. Doe, Jr."));
154 profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
155 profile.SetRawInfo(NAME_MIDDLE, ASCIIToUTF16("K."));
156 profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Doe"));
157 profile.SetRawInfo(NAME_LAST_FIRST, ASCIIToUTF16("D"));
158 profile.SetRawInfo(NAME_LAST_CONJUNCTION, ASCIIToUTF16("o"));
159 profile.SetRawInfo(NAME_LAST_SECOND, ASCIIToUTF16("e"));
160
161 profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16("user@example.com"));
162 profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("1.800.555.1234"));
163
164 profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("123 Fake St.\n"
165 "Apt. 42"));
166 EXPECT_EQ(ASCIIToUTF16("123 Fake St."),
167 profile.GetRawInfo(ADDRESS_HOME_LINE1));
168 EXPECT_EQ(ASCIIToUTF16("Apt. 42"), profile.GetRawInfo(ADDRESS_HOME_LINE2));
169
170 profile.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Google, Inc."));
171 profile.SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("Mountain View"));
172 profile.SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("California"));
173 profile.SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("94043"));
174 profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("US"));
175 profile.SetRawInfo(ADDRESS_HOME_SORTING_CODE, ASCIIToUTF16("CEDEX"));
176 profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
177 ASCIIToUTF16("Santa Clara"));
178 profile.SetRawInfo(ADDRESS_HOME_STREET_NAME, ASCIIToUTF16("Street Name"));
179 profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_STREET_NAME,
180 ASCIIToUTF16("Dependent Street Name"));
181 profile.SetRawInfo(ADDRESS_HOME_HOUSE_NUMBER, ASCIIToUTF16("House Number"));
182 profile.SetRawInfo(ADDRESS_HOME_SUBPREMISE, ASCIIToUTF16("Subpremise"));
183 profile.SetRawInfo(ADDRESS_HOME_PREMISE_NAME, ASCIIToUTF16("Premise"));
184 profile.set_language_code("en");
185 profile.SetClientValidityFromBitfieldValue(kValidityStateBitfield);
186 return profile;
187 }
188
189 // Returns AutofillProfileSpecifics with all Autofill profile fields set.
190 // Contains identical data to the data returned from ConstructCompleteProfile().
ConstructCompleteSpecifics()191 AutofillProfileSpecifics ConstructCompleteSpecifics() {
192 AutofillProfileSpecifics specifics;
193
194 specifics.set_guid(kGuidA);
195 specifics.set_origin(kHttpsOrigin);
196 specifics.set_use_count(7);
197 specifics.set_use_date(1423182152);
198
199 specifics.add_name_honorific("");
200 specifics.add_name_first("John");
201 specifics.add_name_middle("K.");
202 specifics.add_name_last("Doe");
203 specifics.add_name_full("John K. Doe, Jr.");
204 specifics.add_name_last_first("D");
205 specifics.add_name_last_conjunction("o");
206 specifics.add_name_last_second("e");
207
208 specifics.add_name_honorific_status(
209 sync_pb::
210 AutofillProfileSpecifics_VerificationStatus_VERIFICATION_STATUS_UNSPECIFIED);
211 specifics.add_name_first_status(
212 sync_pb::
213 AutofillProfileSpecifics_VerificationStatus_VERIFICATION_STATUS_UNSPECIFIED);
214 specifics.add_name_middle_status(
215 sync_pb::
216 AutofillProfileSpecifics_VerificationStatus_VERIFICATION_STATUS_UNSPECIFIED);
217 specifics.add_name_last_status(
218 sync_pb::
219 AutofillProfileSpecifics_VerificationStatus_VERIFICATION_STATUS_UNSPECIFIED);
220 specifics.add_name_full_status(
221 sync_pb::
222 AutofillProfileSpecifics_VerificationStatus_VERIFICATION_STATUS_UNSPECIFIED);
223 specifics.add_name_last_first_status(
224 sync_pb::
225 AutofillProfileSpecifics_VerificationStatus_VERIFICATION_STATUS_UNSPECIFIED);
226 specifics.add_name_last_conjunction_status(
227 sync_pb::
228 AutofillProfileSpecifics_VerificationStatus_VERIFICATION_STATUS_UNSPECIFIED);
229 specifics.add_name_last_second_status(
230 sync_pb::
231 AutofillProfileSpecifics_VerificationStatus_VERIFICATION_STATUS_UNSPECIFIED);
232
233 specifics.add_email_address("user@example.com");
234
235 specifics.add_phone_home_whole_number("1.800.555.1234");
236
237 specifics.set_address_home_line1("123 Fake St.");
238 specifics.set_address_home_line2("Apt. 42");
239 specifics.set_address_home_street_address(
240 "123 Fake St.\n"
241 "Apt. 42");
242
243 specifics.set_company_name("Google, Inc.");
244 specifics.set_address_home_city("Mountain View");
245 specifics.set_address_home_state("California");
246 specifics.set_address_home_zip("94043");
247 specifics.set_address_home_country("US");
248 specifics.set_address_home_sorting_code("CEDEX");
249 specifics.set_address_home_dependent_locality("Santa Clara");
250 specifics.set_address_home_language_code("en");
251
252 specifics.set_address_home_thoroughfare_name("Street Name");
253 specifics.set_address_home_dependent_thoroughfare_name(
254 "Dependent Street Name");
255 specifics.set_address_home_thoroughfare_number("House Number");
256 specifics.set_address_home_subpremise_name("Subpremise");
257 specifics.set_address_home_premise_name("Premise");
258
259 specifics.set_validity_state_bitfield(kValidityStateBitfield);
260 return specifics;
261 }
262
263 } // namespace
264
265 class AutofillProfileSyncBridgeTestBase : public testing::Test {
266 public:
267 AutofillProfileSyncBridgeTestBase() = default;
268 ~AutofillProfileSyncBridgeTestBase() override = default;
269
SetUp()270 void SetUp() override {
271 // Fix a time for implicitly constructed use_dates in AutofillProfile.
272 test_clock_.SetNow(kJune2017);
273 CountryNames::SetLocaleString(kLocaleString);
274 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
275 db_.AddTable(&table_);
276 db_.Init(temp_dir_.GetPath().AppendASCII("SyncTestWebDatabase"));
277 ON_CALL(*backend(), GetDatabase()).WillByDefault(Return(&db_));
278 ResetProcessor();
279 ResetBridge();
280 }
281
ResetProcessor()282 void ResetProcessor() {
283 real_processor_ =
284 std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
285 syncer::AUTOFILL_PROFILE, /*dump_stack=*/base::DoNothing(),
286 /*commit_only=*/false);
287 mock_processor_.DelegateCallsByDefaultTo(real_processor_.get());
288 }
289
ResetBridge()290 void ResetBridge() {
291 bridge_.reset(new AutofillProfileSyncBridge(
292 mock_processor_.CreateForwardingProcessor(), kLocaleString, &backend_));
293 }
294
StartSyncing(const std::vector<AutofillProfileSpecifics> & remote_data={})295 void StartSyncing(
296 const std::vector<AutofillProfileSpecifics>& remote_data = {}) {
297 base::RunLoop loop;
298 syncer::DataTypeActivationRequest request;
299 request.error_handler = base::DoNothing();
300 real_processor_->OnSyncStarting(
301 request,
302 base::BindLambdaForTesting(
__anon575ee1860202(std::unique_ptr<syncer::DataTypeActivationResponse>) 303 [&loop](std::unique_ptr<syncer::DataTypeActivationResponse>) {
304 loop.Quit();
305 }));
306 loop.Run();
307
308 // Initialize the processor with initial_sync_done.
309 sync_pb::ModelTypeState state;
310 state.set_initial_sync_done(true);
311 syncer::UpdateResponseDataList initial_updates;
312 for (const AutofillProfileSpecifics& specifics : remote_data) {
313 initial_updates.push_back(SpecificsToUpdateResponse(specifics));
314 }
315 real_processor_->OnUpdateReceived(state, std::move(initial_updates));
316 }
317
ApplySyncChanges(EntityChangeList changes)318 void ApplySyncChanges(EntityChangeList changes) {
319 const base::Optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
320 bridge()->CreateMetadataChangeList(), std::move(changes));
321 EXPECT_FALSE(error) << error->ToString();
322 }
323
AddAutofillProfilesToTable(const std::vector<AutofillProfile> & profile_list)324 void AddAutofillProfilesToTable(
325 const std::vector<AutofillProfile>& profile_list) {
326 for (const auto& profile : profile_list) {
327 table_.AddAutofillProfile(profile);
328 }
329 }
330
GetAllLocalData()331 std::vector<AutofillProfile> GetAllLocalData() {
332 std::vector<AutofillProfile> data;
333 // Perform an async call synchronously for testing.
334 base::RunLoop loop;
335 bridge()->GetAllDataForDebugging(base::BindLambdaForTesting(
336 [&loop, &data](std::unique_ptr<DataBatch> batch) {
337 ExtractAutofillProfilesFromDataBatch(std::move(batch), &data);
338 loop.Quit();
339 }));
340 loop.Run();
341 return data;
342 }
343
SpecificsToEntity(const AutofillProfileSpecifics & specifics)344 EntityData SpecificsToEntity(const AutofillProfileSpecifics& specifics) {
345 EntityData data;
346 *data.specifics.mutable_autofill_profile() = specifics;
347 data.client_tag_hash = syncer::ClientTagHash::FromUnhashed(
348 syncer::AUTOFILL_PROFILE, bridge()->GetClientTag(data));
349 return data;
350 }
351
SpecificsToUpdateResponse(const AutofillProfileSpecifics & specifics)352 syncer::UpdateResponseData SpecificsToUpdateResponse(
353 const AutofillProfileSpecifics& specifics) {
354 syncer::UpdateResponseData data;
355 data.entity = SpecificsToEntity(specifics);
356 return data;
357 }
358
bridge()359 AutofillProfileSyncBridge* bridge() { return bridge_.get(); }
360
mock_processor()361 syncer::MockModelTypeChangeProcessor& mock_processor() {
362 return mock_processor_;
363 }
364
table()365 AutofillTable* table() { return &table_; }
366
backend()367 MockAutofillWebDataBackend* backend() { return &backend_; }
368
369 private:
370 autofill::TestAutofillClock test_clock_;
371 ScopedTempDir temp_dir_;
372 base::test::SingleThreadTaskEnvironment task_environment_;
373 testing::NiceMock<MockAutofillWebDataBackend> backend_;
374 AutofillTable table_;
375 WebDatabase db_;
376 testing::NiceMock<MockModelTypeChangeProcessor> mock_processor_;
377 std::unique_ptr<syncer::ClientTagBasedModelTypeProcessor> real_processor_;
378 std::unique_ptr<AutofillProfileSyncBridge> bridge_;
379
380 DISALLOW_COPY_AND_ASSIGN(AutofillProfileSyncBridgeTestBase);
381 };
382
383 // This class performs the sync bridge test with and without structured names
384 // enabled.
385 class AutofillProfileSyncBridgeTest : public AutofillProfileSyncBridgeTestBase,
386 public testing::WithParamInterface<bool> {
387 public:
SetUp()388 void SetUp() override {
389 InitializeFeatures();
390 AutofillProfileSyncBridgeTestBase::SetUp();
391 }
392
InitializeFeatures()393 void InitializeFeatures() {
394 bool structured_names_enabled = GetParam();
395 if (structured_names_enabled) {
396 scoped_features_.InitAndEnableFeature(
397 features::kAutofillEnableSupportForMoreStructureInNames);
398 } else {
399 scoped_features_.InitAndDisableFeature(
400 features::kAutofillEnableSupportForMoreStructureInNames);
401 }
402 }
403
UsingStructuredNames() const404 bool UsingStructuredNames() const {
405 return base::FeatureList::IsEnabled(
406 features::kAutofillEnableSupportForMoreStructureInNames);
407 }
408
409 private:
410 base::test::ScopedFeatureList scoped_features_;
411 };
412
TEST_P(AutofillProfileSyncBridgeTest,AutofillProfileChanged_Added)413 TEST_P(AutofillProfileSyncBridgeTest, AutofillProfileChanged_Added) {
414 StartSyncing({});
415
416 AutofillProfile local(kGuidA, kHttpsOrigin);
417 local.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
418 AutofillProfileChange change(AutofillProfileChange::ADD, kGuidA, &local);
419
420 EXPECT_CALL(
421 mock_processor(),
422 Put(kGuidA, HasSpecifics(CreateAutofillProfileSpecifics(local)), _));
423 // The bridge does not need to commit when reacting to a notification about a
424 // local change.
425 EXPECT_CALL(*backend(), CommitChanges()).Times(0);
426
427 bridge()->AutofillProfileChanged(change);
428 }
429
430 // Language code in autofill profiles should be synced to the server.
TEST_P(AutofillProfileSyncBridgeTest,AutofillProfileChanged_Added_LanguageCodePropagates)431 TEST_P(AutofillProfileSyncBridgeTest,
432 AutofillProfileChanged_Added_LanguageCodePropagates) {
433 StartSyncing({});
434
435 AutofillProfile local(kGuidA, kHttpsOrigin);
436 local.set_language_code("en");
437 AutofillProfileChange change(AutofillProfileChange::ADD, kGuidA, &local);
438
439 EXPECT_CALL(
440 mock_processor(),
441 Put(kGuidA, HasSpecifics(CreateAutofillProfileSpecifics(local)), _));
442 // The bridge does not need to commit when reacting to a notification about a
443 // local change.
444 EXPECT_CALL(*backend(), CommitChanges()).Times(0);
445
446 bridge()->AutofillProfileChanged(change);
447 }
448
449 // Validity state bitfield in autofill profiles should be synced to the server.
TEST_P(AutofillProfileSyncBridgeTest,AutofillProfileChanged_Added_LocalValidityBitfieldPropagates)450 TEST_P(AutofillProfileSyncBridgeTest,
451 AutofillProfileChanged_Added_LocalValidityBitfieldPropagates) {
452 StartSyncing({});
453
454 AutofillProfile local(kGuidA, kHttpsOrigin);
455 local.SetClientValidityFromBitfieldValue(kValidityStateBitfield);
456 AutofillProfileChange change(AutofillProfileChange::ADD, kGuidA, &local);
457
458 EXPECT_CALL(
459 mock_processor(),
460 Put(kGuidA, HasSpecifics(CreateAutofillProfileSpecifics(local)), _));
461 // The bridge does not need to commit when reacting to a notification about a
462 // local change.
463 EXPECT_CALL(*backend(), CommitChanges()).Times(0);
464
465 bridge()->AutofillProfileChanged(change);
466 }
467
468 // Local updates should be properly propagated to the server.
TEST_P(AutofillProfileSyncBridgeTest,AutofillProfileChanged_Updated)469 TEST_P(AutofillProfileSyncBridgeTest, AutofillProfileChanged_Updated) {
470 StartSyncing({});
471
472 AutofillProfile local(kGuidA, kHttpsOrigin);
473 local.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
474 AutofillProfileChange change(AutofillProfileChange::UPDATE, kGuidA, &local);
475
476 EXPECT_CALL(
477 mock_processor(),
478 Put(kGuidA, HasSpecifics(CreateAutofillProfileSpecifics(local)), _));
479 // The bridge does not need to commit when reacting to a notification about a
480 // local change.
481 EXPECT_CALL(*backend(), CommitChanges()).Times(0);
482
483 bridge()->AutofillProfileChanged(change);
484 }
485
486 // Usage stats should be updated by the client.
TEST_P(AutofillProfileSyncBridgeTest,AutofillProfileChanged_Updated_UsageStatsOverwrittenByClient)487 TEST_P(AutofillProfileSyncBridgeTest,
488 AutofillProfileChanged_Updated_UsageStatsOverwrittenByClient) {
489 // Remote data has a profile with usage stats.
490 AutofillProfileSpecifics remote =
491 CreateAutofillProfileSpecifics(kGuidA, kHttpsOrigin);
492 remote.set_address_home_language_code("en");
493 remote.set_use_count(9);
494 remote.set_use_date(25);
495
496 StartSyncing({remote});
497 EXPECT_THAT(GetAllLocalData(),
498 ElementsAre(WithUsageStats(CreateAutofillProfile(remote))));
499
500 // Update to the usage stats for that profile.
501 AutofillProfile local(kGuidA, kHttpsOrigin);
502 local.set_language_code("en");
503 local.set_use_count(10U);
504 local.set_use_date(base::Time::FromTimeT(30));
505 AutofillProfileChange change(AutofillProfileChange::UPDATE, kGuidA, &local);
506
507 EXPECT_CALL(
508 mock_processor(),
509 Put(kGuidA, HasSpecifics(CreateAutofillProfileSpecifics(local)), _));
510 // The bridge does not need to commit when reacting to a notification about a
511 // local change.
512 EXPECT_CALL(*backend(), CommitChanges()).Times(0);
513
514 bridge()->AutofillProfileChanged(change);
515 }
516
517 // Server profile updates should be ignored.
TEST_P(AutofillProfileSyncBridgeTest,AutofillProfileChanged_Updated_IgnoreServerProfiles)518 TEST_P(AutofillProfileSyncBridgeTest,
519 AutofillProfileChanged_Updated_IgnoreServerProfiles) {
520 StartSyncing({});
521
522 AutofillProfile server_profile(AutofillProfile::SERVER_PROFILE, "server-id");
523 AutofillProfileChange change(AutofillProfileChange::UPDATE,
524 server_profile.guid(), &server_profile);
525
526 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
527 // Should not crash.
528 bridge()->AutofillProfileChanged(change);
529 }
530
TEST_P(AutofillProfileSyncBridgeTest,AutofillProfileChanged_Deleted)531 TEST_P(AutofillProfileSyncBridgeTest, AutofillProfileChanged_Deleted) {
532 StartSyncing({});
533
534 AutofillProfile local(kGuidB, kHttpsOrigin);
535 local.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
536 AutofillProfileChange change(AutofillProfileChange::REMOVE, kGuidB, &local);
537 EXPECT_CALL(mock_processor(), Delete(kGuidB, _));
538 // The bridge does not need to commit when reacting to a notification about a
539 // local change.
540 EXPECT_CALL(*backend(), CommitChanges()).Times(0);
541
542 bridge()->AutofillProfileChanged(change);
543 }
544
545 // Server profile updates should be ignored.
TEST_P(AutofillProfileSyncBridgeTest,AutofillProfileChanged_Deleted_IgnoreServerProfiles)546 TEST_P(AutofillProfileSyncBridgeTest,
547 AutofillProfileChanged_Deleted_IgnoreServerProfiles) {
548 StartSyncing({});
549
550 AutofillProfile server_profile(AutofillProfile::SERVER_PROFILE, "server-id");
551 AutofillProfileChange change(AutofillProfileChange::REMOVE,
552 server_profile.guid(), &server_profile);
553
554 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
555 // Should not crash.
556 bridge()->AutofillProfileChanged(change);
557 }
558
TEST_P(AutofillProfileSyncBridgeTest,GetAllDataForDebugging)559 TEST_P(AutofillProfileSyncBridgeTest, GetAllDataForDebugging) {
560 AutofillProfile local1 = AutofillProfile(kGuidA, kHttpsOrigin);
561 local1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
562 local1.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("1 1st st"));
563 AutofillProfile local2 = AutofillProfile(kGuidB, kHttpsOrigin);
564 local2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
565 local2.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("2 2nd st"));
566 AddAutofillProfilesToTable({local1, local2});
567
568 EXPECT_THAT(GetAllLocalData(), UnorderedElementsAre(local1, local2));
569 }
570
TEST_P(AutofillProfileSyncBridgeTest,GetData)571 TEST_P(AutofillProfileSyncBridgeTest, GetData) {
572 AutofillProfile local1 = AutofillProfile(kGuidA, kHttpsOrigin);
573 local1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
574 local1.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("1 1st st"));
575 AutofillProfile local2 = AutofillProfile(kGuidB, kHttpsOrigin);
576 local2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
577 local2.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("2 2nd st"));
578 AddAutofillProfilesToTable({local1, local2});
579
580 std::vector<AutofillProfile> data;
581 base::RunLoop loop;
582 bridge()->GetData({kGuidA},
583 base::BindLambdaForTesting(
584 [&loop, &data](std::unique_ptr<DataBatch> batch) {
585 ExtractAutofillProfilesFromDataBatch(std::move(batch),
586 &data);
587 loop.Quit();
588 }));
589 loop.Run();
590
591 EXPECT_THAT(data, ElementsAre(local1));
592 }
593
TEST_P(AutofillProfileSyncBridgeTest,MergeSyncData)594 TEST_P(AutofillProfileSyncBridgeTest, MergeSyncData) {
595 AutofillProfile local1 = AutofillProfile(kGuidA, kHttpOrigin);
596 local1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
597 local1.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("1 1st st"));
598
599 AutofillProfile local2 = AutofillProfile(kGuidB, std::string());
600 local2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
601 local2.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("2 2nd st"));
602
603 AddAutofillProfilesToTable({local1, local2});
604
605 AutofillProfile remote1 = AutofillProfile(kGuidC, kHttpOrigin);
606 remote1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
607 remote1.FinalizeAfterImport();
608
609 AutofillProfile remote2 = AutofillProfile(kGuidD, kSettingsOrigin);
610 remote2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Harry"));
611 remote2.FinalizeAfterImport();
612
613 AutofillProfile remote3 = AutofillProfile(kGuidB, kSettingsOrigin);
614 remote3.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom Doe"));
615 remote3.FinalizeAfterImport();
616
617 AutofillProfileSpecifics remote1_specifics =
618 CreateAutofillProfileSpecifics(remote1);
619 AutofillProfileSpecifics remote2_specifics =
620 CreateAutofillProfileSpecifics(remote2);
621 AutofillProfileSpecifics remote3_specifics =
622 CreateAutofillProfileSpecifics(remote3);
623
624 EXPECT_CALL(
625 mock_processor(),
626 Put(kGuidA, HasSpecifics(CreateAutofillProfileSpecifics(local1)), _));
627 EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0);
628 EXPECT_CALL(*backend(), CommitChanges());
629
630 StartSyncing({remote1_specifics, remote2_specifics, remote3_specifics});
631
632 // Since |local2| and |remote3| have the same GUID, data from |remote3| is
633 // incorporated into the local profile which is mostly a replace operation.
634 EXPECT_THAT(
635 GetAllLocalData(),
636 UnorderedElementsAre(local1, CreateAutofillProfile(remote1_specifics),
637 CreateAutofillProfile(remote2_specifics),
638 CreateAutofillProfile(remote3_specifics)));
639 }
640
641 // Tests the profile migration that is performed after specifics are converted
642 // to profiles.
TEST_P(AutofillProfileSyncBridgeTest,ProfileMigration)643 TEST_P(AutofillProfileSyncBridgeTest, ProfileMigration) {
644 // This test is only applicable when structured names are enabled.
645 if (!UsingStructuredNames())
646 return;
647
648 AutofillProfile remote1 = AutofillProfile(kGuidC, kHttpOrigin);
649 remote1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Thomas"));
650 remote1.SetRawInfo(NAME_MIDDLE, ASCIIToUTF16("Neo"));
651 remote1.SetRawInfo(NAME_LAST, ASCIIToUTF16("Anderson"));
652
653 AutofillProfileSpecifics remote1_specifics =
654 CreateAutofillProfileSpecifics(remote1);
655
656 EXPECT_CALL(*backend(), CommitChanges());
657
658 StartSyncing({remote1_specifics});
659
660 // Create the expected profile after migration.
661 AutofillProfile finalized_profile = AutofillProfile(kGuidC, kHttpOrigin);
662 finalized_profile.SetRawInfoWithVerificationStatus(
663 NAME_FULL, ASCIIToUTF16("Thomas Neo Anderson"),
664 structured_address::VerificationStatus::kFormatted);
665 finalized_profile.SetRawInfoWithVerificationStatus(
666 NAME_FIRST, ASCIIToUTF16("Thomas"),
667 structured_address::VerificationStatus::kObserved);
668 finalized_profile.SetRawInfoWithVerificationStatus(
669 NAME_MIDDLE, ASCIIToUTF16("Neo"),
670 structured_address::VerificationStatus::kObserved);
671 finalized_profile.SetRawInfoWithVerificationStatus(
672 NAME_LAST, ASCIIToUTF16("Anderson"),
673 structured_address::VerificationStatus::kObserved);
674 finalized_profile.SetRawInfoWithVerificationStatus(
675 NAME_LAST_SECOND, ASCIIToUTF16("Anderson"),
676 structured_address::VerificationStatus::kParsed);
677 finalized_profile.SetRawInfoWithVerificationStatus(
678 NAME_LAST_FIRST, ASCIIToUTF16(""),
679 structured_address::VerificationStatus::kParsed);
680 finalized_profile.SetRawInfoWithVerificationStatus(
681 NAME_LAST_CONJUNCTION, ASCIIToUTF16(""),
682 structured_address::VerificationStatus::kParsed);
683
684 EXPECT_THAT(GetAllLocalData(), UnorderedElementsAre(finalized_profile));
685 }
686
687 // Ensure that all profile fields are able to be synced up from the client to
688 // the server.
TEST_P(AutofillProfileSyncBridgeTest,MergeSyncData_SyncAllFieldsToServer)689 TEST_P(AutofillProfileSyncBridgeTest, MergeSyncData_SyncAllFieldsToServer) {
690 AutofillProfile local = ConstructCompleteProfile();
691 AddAutofillProfilesToTable({local});
692
693 // This complete profile is fully uploaded to sync.
694 EXPECT_CALL(mock_processor(),
695 Put(_, HasSpecifics(ConstructCompleteSpecifics()), _));
696 EXPECT_CALL(*backend(), CommitChanges());
697
698 StartSyncing({});
699
700 // No changes locally.
701 EXPECT_THAT(GetAllLocalData(), ElementsAre(WithUsageStats(local)));
702 }
703
704 // Ensure that all profile fields are able to be synced down from the server to
705 // the client (and nothing gets uploaded back).
TEST_P(AutofillProfileSyncBridgeTest,MergeSyncData_SyncAllFieldsToClient)706 TEST_P(AutofillProfileSyncBridgeTest, MergeSyncData_SyncAllFieldsToClient) {
707 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
708 EXPECT_CALL(*backend(), CommitChanges());
709 StartSyncing({ConstructCompleteSpecifics()});
710
711 EXPECT_THAT(GetAllLocalData(),
712 ElementsAre(WithUsageStats(ConstructCompleteProfile())));
713 }
714
TEST_P(AutofillProfileSyncBridgeTest,MergeSyncData_IdenticalProfiles)715 TEST_P(AutofillProfileSyncBridgeTest, MergeSyncData_IdenticalProfiles) {
716 AutofillProfile local1 = AutofillProfile(kGuidA, kHttpOrigin);
717 local1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
718 local1.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("1 1st st"));
719
720 AutofillProfile local2 = AutofillProfile(kGuidB, kSettingsOrigin);
721 local2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
722 local2.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("2 2nd st"));
723
724 AddAutofillProfilesToTable({local1, local2});
725
726 // The synced profiles are identical to the local ones, except that the guids
727 // are different.
728
729 AutofillProfile remote1 = AutofillProfile(kGuidC, kHttpsOrigin);
730 remote1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
731 remote1.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("1 1st st"));
732 remote1.FinalizeAfterImport();
733
734 AutofillProfile remote2 = AutofillProfile(kGuidD, kHttpsOrigin);
735 remote2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
736 remote2.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("2 2nd st"));
737 remote2.FinalizeAfterImport();
738
739 AutofillProfileSpecifics remote1_specifics =
740 CreateAutofillProfileSpecifics(remote1);
741 AutofillProfileSpecifics remote2_specifics =
742 CreateAutofillProfileSpecifics(remote2);
743
744 // Both remote profiles win, only the verified origin is taken over for the
745 // second profile.
746 AutofillProfileSpecifics merged2(remote2_specifics);
747 merged2.set_origin(kSettingsOrigin);
748 EXPECT_CALL(mock_processor(), Put(kGuidD, HasSpecifics(merged2), _));
749 EXPECT_CALL(*backend(), CommitChanges());
750
751 StartSyncing({remote1_specifics, remote2_specifics});
752
753 EXPECT_THAT(GetAllLocalData(),
754 UnorderedElementsAre(CreateAutofillProfile(remote1_specifics),
755 CreateAutofillProfile(merged2)));
756 }
757
TEST_P(AutofillProfileSyncBridgeTest,MergeSyncData_NonSimilarProfiles)758 TEST_P(AutofillProfileSyncBridgeTest, MergeSyncData_NonSimilarProfiles) {
759 AutofillProfile local = ConstructCompleteProfile();
760 local.set_guid(kGuidA);
761 local.SetRawInfo(NAME_FULL, ASCIIToUTF16("John K. Doe, Jr."));
762 local.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
763 local.SetRawInfo(NAME_MIDDLE, ASCIIToUTF16("K."));
764 local.SetRawInfo(NAME_LAST, ASCIIToUTF16("Doe"));
765 AddAutofillProfilesToTable({local});
766
767 // The remote profile are not similar as the names are different (all other
768 // fields except for guids are identical).
769 AutofillProfileSpecifics remote = ConstructCompleteSpecifics();
770 remote.set_guid(kGuidB);
771 remote.set_name_full(0, "Jane T. Roe, Sr.");
772 remote.set_name_first(0, "Jane");
773 remote.set_name_middle(0, "T.");
774 remote.set_name_last(0, "Roe");
775
776 // The profiles are not similar enough and thus do not get merged.
777 // Expect the local one being synced up and the remote one being added to the
778 // local database.
779 EXPECT_CALL(
780 mock_processor(),
781 Put(kGuidA, HasSpecifics(CreateAutofillProfileSpecifics(local)), _));
782 EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0);
783 EXPECT_CALL(*backend(), CommitChanges());
784
785 StartSyncing({remote});
786
787 EXPECT_THAT(GetAllLocalData(),
788 UnorderedElementsAre(local, CreateAutofillProfile(remote)));
789 }
790
TEST_P(AutofillProfileSyncBridgeTest,MergeSyncData_SimilarProfiles)791 TEST_P(AutofillProfileSyncBridgeTest, MergeSyncData_SimilarProfiles) {
792 AutofillProfile local1 = AutofillProfile(kGuidA, kHttpOrigin);
793 local1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
794 local1.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("1 1st st"));
795 local1.FinalizeAfterImport();
796 local1.set_use_count(27);
797
798 AutofillProfile local2 = AutofillProfile(kGuidB, kSettingsOrigin);
799 local2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
800 local2.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("2 2nd st"));
801 local2.FinalizeAfterImport();
802 AddAutofillProfilesToTable({local1, local2});
803
804 // The synced profiles are identical to the local ones, except that the guids
805 // and use_count values are different. Remote ones have additional company
806 // name which makes them not be identical.
807 AutofillProfile remote1 = AutofillProfile(kGuidC, kHttpOrigin);
808 remote1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
809 remote1.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("1 1st st"));
810 remote1.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Frobbers, Inc."));
811 // Note, this populates the full name for structured profiles.
812 remote1.FinalizeAfterImport();
813 remote1.set_use_count(13);
814
815 AutofillProfile remote2 = AutofillProfile(kGuidD, kHttpOrigin);
816 remote2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
817 remote2.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("2 2nd st"));
818 remote2.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Fizzbang, LLC."));
819 remote2.FinalizeAfterImport();
820 remote2.set_use_count(4);
821
822 AutofillProfileSpecifics remote1_specifics =
823 CreateAutofillProfileSpecifics(remote1);
824 AutofillProfileSpecifics remote2_specifics =
825 CreateAutofillProfileSpecifics(remote2);
826
827 // The first profile should have its origin updated.
828 // The second profile should remain as-is, because an unverified profile
829 // should never overwrite a verified one.
830 AutofillProfileSpecifics merged1(remote1_specifics);
831 merged1.set_origin(kHttpOrigin);
832 // For the legacy implementation, the full name field gets popluated by the
833 // merging operation and must be added to the expectation.
834 // For structured names, the full name is already populated by calling
835 // |FinalizeAfterImport()|.
836 if (UsingStructuredNames()) {
837 ASSERT_GT(merged1.name_full_size(), 0);
838 ASSERT_EQ(merged1.name_full(0), "John");
839 } else {
840 merged1.set_name_full(0, "John");
841 }
842 // Merging two profile takes their max use count.
843 merged1.set_use_count(27);
844
845 // Expect updating the first (merged) profile and adding the second local one.
846 EXPECT_CALL(mock_processor(), Put(kGuidC, HasSpecifics(merged1), _));
847 EXPECT_CALL(
848 mock_processor(),
849 Put(kGuidB, HasSpecifics(CreateAutofillProfileSpecifics(local2)), _));
850 EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0);
851 EXPECT_CALL(*backend(), CommitChanges());
852
853 StartSyncing({remote1_specifics, remote2_specifics});
854
855 EXPECT_THAT(GetAllLocalData(),
856 UnorderedElementsAre(
857 WithUsageStats(CreateAutofillProfile(merged1)), local2,
858 WithUsageStats(CreateAutofillProfile(remote2_specifics))));
859 }
860
861 // Tests that MergeSimilarProfiles keeps the most recent use date of the two
862 // profiles being merged.
TEST_P(AutofillProfileSyncBridgeTest,MergeSyncData_SimilarProfiles_OlderUseDate)863 TEST_P(AutofillProfileSyncBridgeTest,
864 MergeSyncData_SimilarProfiles_OlderUseDate) {
865 // Different guids, same origin, difference in the phone number.
866 AutofillProfile local(kGuidA, kHttpOrigin);
867 local.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("650234567"));
868 local.set_use_date(base::Time::FromTimeT(30));
869 AddAutofillProfilesToTable({local});
870
871 AutofillProfileSpecifics remote =
872 CreateAutofillProfileSpecifics(kGuidB, kHttpOrigin);
873 // |local| has a more recent use date.
874 remote.set_use_date(25);
875
876 // The use date of |local| should replace the use date of |remote|.
877 AutofillProfileSpecifics merged(remote);
878 merged.set_use_date(30);
879 merged.add_phone_home_whole_number("650234567");
880 EXPECT_CALL(mock_processor(), Put(kGuidB, HasSpecifics(merged), _));
881 EXPECT_CALL(*backend(), CommitChanges());
882
883 StartSyncing({remote});
884 }
885
886 // Tests that MergeSimilarProfiles keeps the most recent use date of the two
887 // profiles being merged.
TEST_P(AutofillProfileSyncBridgeTest,MergeSyncData_SimilarProfiles_NewerUseDate)888 TEST_P(AutofillProfileSyncBridgeTest,
889 MergeSyncData_SimilarProfiles_NewerUseDate) {
890 // Different guids, same origin, difference in the phone number.
891 AutofillProfile local(kGuidA, kHttpOrigin);
892 local.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("650234567"));
893 local.set_use_date(base::Time::FromTimeT(30));
894 AddAutofillProfilesToTable({local});
895
896 AutofillProfileSpecifics remote =
897 CreateAutofillProfileSpecifics(kGuidB, kHttpOrigin);
898 // |remote| has a more recent use date.
899 remote.set_use_date(35);
900
901 // The use date of |local| should _not_ replace the use date of |remote|.
902 AutofillProfileSpecifics merged(remote);
903 merged.add_phone_home_whole_number("650234567");
904 EXPECT_CALL(mock_processor(), Put(kGuidB, HasSpecifics(merged), _));
905 EXPECT_CALL(*backend(), CommitChanges());
906
907 StartSyncing({remote});
908 }
909
910 // Tests that MergeSimilarProfiles saves the max of the use counts of the two
911 // profiles in |remote|.
TEST_P(AutofillProfileSyncBridgeTest,MergeSyncData_SimilarProfiles_NonZeroUseCounts)912 TEST_P(AutofillProfileSyncBridgeTest,
913 MergeSyncData_SimilarProfiles_NonZeroUseCounts) {
914 // Different guids, same origin, difference in the phone number.
915 AutofillProfile local(kGuidA, kHttpOrigin);
916 local.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("650234567"));
917 local.set_use_count(12);
918 AddAutofillProfilesToTable({local});
919
920 AutofillProfileSpecifics remote =
921 CreateAutofillProfileSpecifics(kGuidB, kHttpOrigin);
922 remote.set_use_count(5);
923
924 // The use count of |local| should replace the use count of |remote|.
925 AutofillProfileSpecifics merged(remote);
926 merged.set_use_count(12);
927 merged.add_phone_home_whole_number("650234567");
928 EXPECT_CALL(mock_processor(), Put(kGuidB, HasSpecifics(merged), _));
929 EXPECT_CALL(*backend(), CommitChanges());
930
931 StartSyncing({remote});
932 }
933
934 // Tests that when merging similar profiles for initial sync, we add the
935 // additional information of |local| into |remote|.
TEST_P(AutofillProfileSyncBridgeTest,MergeSyncData_SimilarProfiles_LocalOriginPreserved)936 TEST_P(AutofillProfileSyncBridgeTest,
937 MergeSyncData_SimilarProfiles_LocalOriginPreserved) {
938 AutofillProfile local(kGuidA, kHttpsOrigin);
939 local.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("650234567"));
940 AddAutofillProfilesToTable({local});
941
942 AutofillProfile remote_profile = AutofillProfile(kGuidB, kHttpOrigin);
943 remote_profile.FinalizeAfterImport();
944 AutofillProfileSpecifics remote =
945 CreateAutofillProfileSpecifics(remote_profile);
946 remote.set_address_home_language_code("en");
947
948 // Expect that the resulting merged profile is written back to sync and that
949 // it has the phone number and origin from |local|.
950 AutofillProfileSpecifics merged(remote);
951 merged.set_origin(kHttpsOrigin);
952 merged.set_phone_home_whole_number(0, "650234567");
953 // TODO(jkrcal): Is this expected that language code gets deleted? Not
954 // explicitly covered by previous tests but happens.
955 merged.set_address_home_language_code("");
956 EXPECT_CALL(mock_processor(), Put(kGuidB, HasSpecifics(merged), _));
957 EXPECT_CALL(*backend(), CommitChanges());
958
959 StartSyncing({remote});
960 }
961
962 // Sync data without origin should not overwrite existing origin in local
963 // autofill profile.
TEST_P(AutofillProfileSyncBridgeTest,MergeSyncData_SimilarProfiles_LocalExistingOriginPreserved)964 TEST_P(AutofillProfileSyncBridgeTest,
965 MergeSyncData_SimilarProfiles_LocalExistingOriginPreserved) {
966 AutofillProfile local(kGuidA, kHttpsOrigin);
967 AddAutofillProfilesToTable({local});
968
969 // Remote data does not have an origin value.
970 AutofillProfileSpecifics remote = CreateAutofillProfileSpecifics(kGuidA, "");
971 remote.clear_origin();
972 remote.add_name_first("John");
973 ASSERT_FALSE(remote.has_origin());
974
975 // Expect no sync events to add origin to the remote data.
976 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
977 EXPECT_CALL(*backend(), CommitChanges());
978 StartSyncing({remote});
979
980 // Expect the local autofill profile to still have an origin after sync.
981 AutofillProfile merged(local);
982 merged.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
983
984 EXPECT_THAT(GetAllLocalData(), ElementsAre(merged));
985 }
986
987 // Ensure that no Sync events are generated to fill in missing origins from Sync
988 // with explicitly present empty ones. This ensures that the migration to add
989 // origins to profiles does not generate lots of needless Sync updates.
TEST_P(AutofillProfileSyncBridgeTest,MergeSyncData_SimilarProfiles_LocalMissingOriginPreserved)990 TEST_P(AutofillProfileSyncBridgeTest,
991 MergeSyncData_SimilarProfiles_LocalMissingOriginPreserved) {
992 AutofillProfile local = AutofillProfile(kGuidA, std::string());
993 local.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
994 AddAutofillProfilesToTable({local});
995
996 // Create a Sync profile identical to |local|, except with no origin set.
997 AutofillProfile remote_profile = AutofillProfile(kGuidA, "");
998 remote_profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
999 remote_profile.FinalizeAfterImport();
1000 AutofillProfileSpecifics remote =
1001 CreateAutofillProfileSpecifics(remote_profile);
1002 remote.clear_origin();
1003 ASSERT_FALSE(remote.has_origin());
1004
1005 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
1006 EXPECT_CALL(*backend(), CommitChanges());
1007 StartSyncing({remote});
1008 EXPECT_THAT(GetAllLocalData(), ElementsAre(local));
1009 }
1010
TEST_P(AutofillProfileSyncBridgeTest,ApplySyncChanges)1011 TEST_P(AutofillProfileSyncBridgeTest, ApplySyncChanges) {
1012 AutofillProfile local = AutofillProfile(kGuidA, kHttpsOrigin);
1013 AddAutofillProfilesToTable({local});
1014
1015 StartSyncing({});
1016
1017 AutofillProfile remote_profile = AutofillProfile(kGuidB, kHttpOrigin);
1018 remote_profile.SetRawInfo(NAME_FIRST, base::ASCIIToUTF16("Jane"));
1019 remote_profile.FinalizeAfterImport();
1020 AutofillProfileSpecifics remote =
1021 CreateAutofillProfileSpecifics(remote_profile);
1022
1023 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
1024 EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0);
1025 EXPECT_CALL(*backend(), CommitChanges());
1026
1027 syncer::EntityChangeList entity_change_list;
1028 entity_change_list.push_back(EntityChange::CreateDelete(kGuidA));
1029 entity_change_list.push_back(
1030 EntityChange::CreateAdd(kGuidB, SpecificsToEntity(remote)));
1031 ApplySyncChanges(std::move(entity_change_list));
1032
1033 EXPECT_THAT(GetAllLocalData(), ElementsAre(CreateAutofillProfile(remote)));
1034 }
1035
1036 // Ensure that entries with invalid specifics are ignored.
TEST_P(AutofillProfileSyncBridgeTest,ApplySyncChanges_OmitsInvalidSpecifics)1037 TEST_P(AutofillProfileSyncBridgeTest, ApplySyncChanges_OmitsInvalidSpecifics) {
1038 StartSyncing({});
1039
1040 AutofillProfileSpecifics remote_valid =
1041 CreateAutofillProfileSpecifics(kGuidA, std::string());
1042 AutofillProfileSpecifics remote_invalid =
1043 CreateAutofillProfileSpecifics(kGuidInvalid, std::string());
1044
1045 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
1046 EXPECT_CALL(*backend(), CommitChanges());
1047
1048 syncer::EntityChangeList entity_change_list;
1049 entity_change_list.push_back(
1050 EntityChange::CreateAdd(kGuidA, SpecificsToEntity(remote_valid)));
1051 entity_change_list.push_back(
1052 EntityChange::CreateAdd(kGuidInvalid, SpecificsToEntity(remote_invalid)));
1053 ApplySyncChanges(std::move(entity_change_list));
1054
1055 EXPECT_THAT(GetAllLocalData(),
1056 ElementsAre(CreateAutofillProfile(remote_valid)));
1057 }
1058
1059 // Verifies that setting the street address field also sets the (deprecated)
1060 // address line 1 and line 2 fields.
TEST_P(AutofillProfileSyncBridgeTest,StreetAddress_SplitAutomatically)1061 TEST_P(AutofillProfileSyncBridgeTest, StreetAddress_SplitAutomatically) {
1062 AutofillProfile local;
1063 local.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("123 Example St.\n"
1064 "Apt. 42"));
1065 EXPECT_EQ(ASCIIToUTF16("123 Example St."),
1066 local.GetRawInfo(ADDRESS_HOME_LINE1));
1067 EXPECT_EQ(ASCIIToUTF16("Apt. 42"), local.GetRawInfo(ADDRESS_HOME_LINE2));
1068
1069 // The same does _not_ work for profile specifics.
1070 AutofillProfileSpecifics remote;
1071 remote.set_address_home_street_address(
1072 "123 Example St.\n"
1073 "Apt. 42");
1074 EXPECT_FALSE(remote.has_address_home_line1());
1075 EXPECT_FALSE(remote.has_address_home_line2());
1076 }
1077
1078 // Verifies that setting the (deprecated) address line 1 and line 2 fields also
1079 // sets the street address.
TEST_P(AutofillProfileSyncBridgeTest,StreetAddress_JointAutomatically)1080 TEST_P(AutofillProfileSyncBridgeTest, StreetAddress_JointAutomatically) {
1081 AutofillProfile local;
1082 local.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("123 Example St."));
1083 local.SetRawInfo(ADDRESS_HOME_LINE2, ASCIIToUTF16("Apt. 42"));
1084 EXPECT_EQ(ASCIIToUTF16("123 Example St.\n"
1085 "Apt. 42"),
1086 local.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
1087
1088 // The same does _not_ work for profile specifics.
1089 AutofillProfileSpecifics remote;
1090 remote.set_address_home_line1("123 Example St.");
1091 remote.set_address_home_line2("Apt. 42");
1092 EXPECT_FALSE(remote.has_address_home_street_address());
1093 }
1094
1095 // Ensure that the street address field takes precedence over the (deprecated)
1096 // address line 1 and line 2 fields, even though these are expected to always be
1097 // in sync in practice.
TEST_P(AutofillProfileSyncBridgeTest,RemoteWithSameGuid_StreetAddress_TakesPrecedenceOverAddressLines)1098 TEST_P(AutofillProfileSyncBridgeTest,
1099 RemoteWithSameGuid_StreetAddress_TakesPrecedenceOverAddressLines) {
1100 // Create remote entry with conflicting address data in the street address
1101 // field vs. the address line 1 and address line 2 fields.
1102 AutofillProfileSpecifics remote =
1103 CreateAutofillProfileSpecifics(kGuidA, kHttpsOrigin);
1104 remote.set_address_home_line1("123 Example St.");
1105 remote.set_address_home_line2("Apt. 42");
1106 remote.set_address_home_street_address(
1107 "456 El Camino Real\n"
1108 "Suite #1337");
1109 EXPECT_CALL(*backend(), CommitChanges());
1110
1111 StartSyncing({remote});
1112
1113 // Verify that full street address takes precedence over address lines.
1114 AutofillProfile local(kGuidA, kHttpsOrigin);
1115 local.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS,
1116 ASCIIToUTF16("456 El Camino Real\n"
1117 "Suite #1337"));
1118 local.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("456 El Camino Real"));
1119 local.SetRawInfo(ADDRESS_HOME_LINE2, ASCIIToUTF16("Suite #1337"));
1120 EXPECT_THAT(GetAllLocalData(), ElementsAre(local));
1121 }
1122
1123 // Ensure that no Sync events are generated to fill in missing street address
1124 // fields from Sync with explicitly present ones identical to the data stored in
1125 // the line1 and line2 fields. This ensures that the migration to add the
1126 // street address field to profiles does not generate lots of needless Sync
1127 // updates.
TEST_P(AutofillProfileSyncBridgeTest,RemoteWithSameGuid_StreetAddress_NoUpdateToEmptyStreetAddressSyncedUp)1128 TEST_P(AutofillProfileSyncBridgeTest,
1129 RemoteWithSameGuid_StreetAddress_NoUpdateToEmptyStreetAddressSyncedUp) {
1130 AutofillProfile local(kGuidA, kHttpsOrigin);
1131 local.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("123 Example St.\n"
1132 "Apt. 42"));
1133 AddAutofillProfilesToTable({local});
1134
1135 // Create a Sync profile identical to |profile|, except without street address
1136 // explicitly set.
1137 AutofillProfileSpecifics remote =
1138 CreateAutofillProfileSpecifics(kGuidA, kHttpsOrigin);
1139 remote.set_address_home_line1("123 Example St.");
1140 remote.set_address_home_line2("Apt. 42");
1141
1142 // No update to sync, no change in local data.
1143 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
1144 EXPECT_CALL(*backend(), CommitChanges());
1145 StartSyncing({remote});
1146 EXPECT_THAT(GetAllLocalData(), ElementsAre(local));
1147 }
1148
1149 // Missing language code field should not generate sync events.
TEST_P(AutofillProfileSyncBridgeTest,RemoteWithSameGuid_LanguageCode_MissingCodesNoSync)1150 TEST_P(AutofillProfileSyncBridgeTest,
1151 RemoteWithSameGuid_LanguageCode_MissingCodesNoSync) {
1152 AutofillProfile local(kGuidA, kHttpsOrigin);
1153 ASSERT_TRUE(local.language_code().empty());
1154 AddAutofillProfilesToTable({local});
1155
1156 // Remote data does not have a language code value.
1157 AutofillProfileSpecifics remote =
1158 CreateAutofillProfileSpecifics(kGuidA, kHttpsOrigin);
1159 ASSERT_FALSE(remote.has_address_home_language_code());
1160
1161 // No update to sync, no change in local data.
1162 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
1163 EXPECT_CALL(*backend(), CommitChanges());
1164 StartSyncing({remote});
1165 EXPECT_THAT(GetAllLocalData(), ElementsAre(local));
1166 }
1167
1168 // Empty language code should be overwritten by sync.
TEST_P(AutofillProfileSyncBridgeTest,RemoteWithSameGuid_LanguageCode_ExistingRemoteWinsOverMissingLocal)1169 TEST_P(AutofillProfileSyncBridgeTest,
1170 RemoteWithSameGuid_LanguageCode_ExistingRemoteWinsOverMissingLocal) {
1171 AutofillProfile local(kGuidA, kHttpsOrigin);
1172 ASSERT_TRUE(local.language_code().empty());
1173 AddAutofillProfilesToTable({local});
1174
1175 // Remote data has "en" language code.
1176 AutofillProfileSpecifics remote =
1177 CreateAutofillProfileSpecifics(kGuidA, kHttpsOrigin);
1178 remote.set_address_home_language_code("en");
1179
1180 // No update to sync, remote language code overwrites the empty local one.
1181 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
1182 EXPECT_CALL(*backend(), CommitChanges());
1183 StartSyncing({remote});
1184 EXPECT_THAT(GetAllLocalData(), ElementsAre(CreateAutofillProfile(remote)));
1185 }
1186
1187 // Local language code should be overwritten by remote one.
TEST_P(AutofillProfileSyncBridgeTest,RemoteWithSameGuid_LanguageCode_ExistingRemoteWinsOverExistingLocal)1188 TEST_P(AutofillProfileSyncBridgeTest,
1189 RemoteWithSameGuid_LanguageCode_ExistingRemoteWinsOverExistingLocal) {
1190 AutofillProfile local(kGuidA, kHttpsOrigin);
1191 local.set_language_code("de");
1192 AddAutofillProfilesToTable({local});
1193
1194 // Remote data has "en" language code.
1195 AutofillProfileSpecifics remote =
1196 CreateAutofillProfileSpecifics(kGuidA, kHttpsOrigin);
1197 remote.set_address_home_language_code("en");
1198
1199 // No update to sync, remote language code overwrites the local one.
1200 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
1201 EXPECT_CALL(*backend(), CommitChanges());
1202 StartSyncing({remote});
1203 EXPECT_THAT(GetAllLocalData(), ElementsAre(CreateAutofillProfile(remote)));
1204 }
1205
1206 // Sync data without language code should not overwrite existing language code
1207 // in local autofill profile.
TEST_P(AutofillProfileSyncBridgeTest,RemoteWithSameGuid_LanguageCode_ExistingLocalWinsOverMissingRemote)1208 TEST_P(AutofillProfileSyncBridgeTest,
1209 RemoteWithSameGuid_LanguageCode_ExistingLocalWinsOverMissingRemote) {
1210 // Local autofill profile has "en" language code.
1211 AutofillProfile local(kGuidA, kHttpsOrigin);
1212 local.set_language_code("en");
1213 AddAutofillProfilesToTable({local});
1214
1215 // Remote data does not have a language code value.
1216 AutofillProfile remote_profile = AutofillProfile(kGuidA, kHttpsOrigin);
1217 remote_profile.SetRawInfo(NAME_FIRST, base::ASCIIToUTF16("John"));
1218 remote_profile.FinalizeAfterImport();
1219 AutofillProfileSpecifics remote =
1220 CreateAutofillProfileSpecifics(remote_profile);
1221 ASSERT_TRUE(remote.address_home_language_code().empty());
1222
1223 // Expect local autofill profile to still have "en" language code after
1224 AutofillProfile merged(local);
1225 merged.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
1226 merged.FinalizeAfterImport();
1227
1228 // No update to sync, remote language code overwrites the local one.
1229 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
1230 EXPECT_CALL(*backend(), CommitChanges());
1231 StartSyncing({remote});
1232 EXPECT_THAT(GetAllLocalData(), ElementsAre(merged));
1233 }
1234
1235 // Missing validity state bitifield should not generate sync events.
TEST_P(AutofillProfileSyncBridgeTest,RemoteWithSameGuid_ValidityState_DefaultValueNoSync)1236 TEST_P(AutofillProfileSyncBridgeTest,
1237 RemoteWithSameGuid_ValidityState_DefaultValueNoSync) {
1238 AutofillProfile local(kGuidA, kHttpsOrigin);
1239 ASSERT_EQ(0, local.GetClientValidityBitfieldValue());
1240 ASSERT_FALSE(local.is_client_validity_states_updated());
1241 AddAutofillProfilesToTable({local});
1242
1243 // Remote data does not have a validity state bitfield value.
1244 AutofillProfileSpecifics remote =
1245 CreateAutofillProfileSpecifics(kGuidA, kHttpsOrigin);
1246 ASSERT_FALSE(remote.has_validity_state_bitfield());
1247 ASSERT_FALSE(remote.is_client_validity_states_updated());
1248
1249 // No update to sync, no change in local data.
1250 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
1251 EXPECT_CALL(*backend(), CommitChanges());
1252 StartSyncing({remote});
1253 EXPECT_THAT(GetAllLocalData(), ElementsAre(local));
1254 }
1255
1256 // Default validity state bitfield should be overwritten by sync.
TEST_P(AutofillProfileSyncBridgeTest,RemoteWithSameGuid_ValidityState_ExistingRemoteWinsOverMissingLocal)1257 TEST_P(AutofillProfileSyncBridgeTest,
1258 RemoteWithSameGuid_ValidityState_ExistingRemoteWinsOverMissingLocal) {
1259 AutofillProfile local(kGuidA, kHttpsOrigin);
1260 ASSERT_EQ(0, local.GetClientValidityBitfieldValue());
1261 AddAutofillProfilesToTable({local});
1262
1263 // Remote data has a non default validity state bitfield value.
1264 AutofillProfileSpecifics remote =
1265 CreateAutofillProfileSpecifics(kGuidA, kHttpsOrigin);
1266 remote.set_validity_state_bitfield(kValidityStateBitfield);
1267 ASSERT_TRUE(remote.has_validity_state_bitfield());
1268
1269 // No update to sync, the validity bitfield should be stored to local.
1270 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
1271 EXPECT_CALL(*backend(), CommitChanges());
1272 StartSyncing({remote});
1273 EXPECT_THAT(GetAllLocalData(), ElementsAre(CreateAutofillProfile(remote)));
1274 }
1275
1276 // Local validity state bitfield should be overwritten by sync.
TEST_P(AutofillProfileSyncBridgeTest,RemoteWithSameGuid_ValidityState_ExistingRemoteWinsOverExistingLocal)1277 TEST_P(AutofillProfileSyncBridgeTest,
1278 RemoteWithSameGuid_ValidityState_ExistingRemoteWinsOverExistingLocal) {
1279 AutofillProfile local(kGuidA, kHttpsOrigin);
1280 local.SetClientValidityFromBitfieldValue(kValidityStateBitfield + 1);
1281 AddAutofillProfilesToTable({local});
1282
1283 // Remote data has a non default validity state bitfield value.
1284 AutofillProfileSpecifics remote =
1285 CreateAutofillProfileSpecifics(kGuidA, kHttpsOrigin);
1286 remote.set_validity_state_bitfield(kValidityStateBitfield);
1287 ASSERT_TRUE(remote.has_validity_state_bitfield());
1288
1289 // No update to sync, the remote validity bitfield should overwrite local.
1290 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
1291 EXPECT_CALL(*backend(), CommitChanges());
1292 StartSyncing({remote});
1293 EXPECT_THAT(GetAllLocalData(), ElementsAre(CreateAutofillProfile(remote)));
1294 }
1295
1296 // Sync data without a default validity state bitfield should not overwrite
1297 // an existing validity state bitfield in local autofill profile.
TEST_P(AutofillProfileSyncBridgeTest,RemoteWithSameGuid_ValidityState_ExistingLocalWinsOverMissingRemote)1298 TEST_P(AutofillProfileSyncBridgeTest,
1299 RemoteWithSameGuid_ValidityState_ExistingLocalWinsOverMissingRemote) {
1300 AutofillProfile local(kGuidA, kHttpsOrigin);
1301 local.SetClientValidityFromBitfieldValue(kValidityStateBitfield);
1302 AddAutofillProfilesToTable({local});
1303
1304 // Remote data has a non default validity state bitfield value.
1305 AutofillProfileSpecifics remote =
1306 CreateAutofillProfileSpecifics(kGuidA, kHttpsOrigin);
1307 remote.add_name_first("John");
1308 ASSERT_FALSE(remote.has_validity_state_bitfield());
1309
1310 // Expect local autofill profile to still have the validity state after.
1311 AutofillProfile merged(local);
1312 merged.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
1313
1314 // No update to sync, the local validity bitfield should stay untouched.
1315 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
1316 EXPECT_CALL(*backend(), CommitChanges());
1317 StartSyncing({remote});
1318 EXPECT_THAT(GetAllLocalData(), ElementsAre(merged));
1319 }
1320
1321 // Missing full name field should not generate sync events.
TEST_P(AutofillProfileSyncBridgeTest,RemoteWithSameGuid_FullName_MissingValueNoSync)1322 TEST_P(AutofillProfileSyncBridgeTest,
1323 RemoteWithSameGuid_FullName_MissingValueNoSync) {
1324 // Local autofill profile has an empty full name.
1325 AutofillProfile local(kGuidA, kHttpsOrigin);
1326 local.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
1327 AddAutofillProfilesToTable({local});
1328
1329 // Remote data does not have a full name value.
1330 AutofillProfileSpecifics remote =
1331 CreateAutofillProfileSpecifics(kGuidA, kHttpsOrigin);
1332 remote.add_name_first(std::string("John"));
1333
1334 // No update to sync, no change in local data.
1335 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
1336 EXPECT_CALL(*backend(), CommitChanges());
1337 StartSyncing({remote});
1338 EXPECT_THAT(GetAllLocalData(), ElementsAre(local));
1339 }
1340
1341 // This test verifies that for the legacy implementation of names, the full name
1342 // is maintained from the local profile.
1343 // However, this is not a valid use case for structured names as name structures
1344 // must be either merged or fully maintained. For structured names, this test
1345 // verifies that the names are merged.
TEST_P(AutofillProfileSyncBridgeTest,RemoteWithSameGuid_FullName_ExistingLocalWinsOverMissingRemote)1346 TEST_P(AutofillProfileSyncBridgeTest,
1347 RemoteWithSameGuid_FullName_ExistingLocalWinsOverMissingRemote) {
1348 // Local autofill profile has a full name.
1349 AutofillProfile local(kGuidA, kHttpsOrigin);
1350 local.SetRawInfoWithVerificationStatus(
1351 NAME_FULL, ASCIIToUTF16("John Jacob Smith"),
1352 structured_address::VerificationStatus::kObserved);
1353 local.FinalizeAfterImport();
1354 AddAutofillProfilesToTable({local});
1355
1356 if (UsingStructuredNames()) {
1357 // After finalization, the first, middle and last name should have the
1358 // status |kParsed|.
1359 ASSERT_EQ(local.GetVerificationStatus(NAME_FIRST),
1360 structured_address::VerificationStatus::kParsed);
1361 ASSERT_EQ(local.GetVerificationStatus(NAME_MIDDLE),
1362 structured_address::VerificationStatus::kParsed);
1363 ASSERT_EQ(local.GetVerificationStatus(NAME_LAST),
1364 structured_address::VerificationStatus::kParsed);
1365 }
1366
1367 // Remote data does not have a full name value.
1368 AutofillProfile remote_profile = AutofillProfile(kGuidA, kHttpsOrigin);
1369 remote_profile.SetRawInfoWithVerificationStatus(
1370 NAME_FIRST, base::ASCIIToUTF16("John"),
1371 structured_address::VerificationStatus::kObserved);
1372 remote_profile.SetRawInfoWithVerificationStatus(
1373 NAME_MIDDLE, base::ASCIIToUTF16("Jacob"),
1374 structured_address::VerificationStatus::kObserved);
1375 remote_profile.SetRawInfoWithVerificationStatus(
1376 NAME_LAST, base::ASCIIToUTF16("Smith"),
1377 structured_address::VerificationStatus::kObserved);
1378 remote_profile.FinalizeAfterImport();
1379 AutofillProfileSpecifics remote =
1380 CreateAutofillProfileSpecifics(remote_profile);
1381
1382 // Expect local autofill profile to still have the same full name after.
1383 AutofillProfile merged(local);
1384
1385 // Note, for structured names, the verification status of those tokens is
1386 // |kParsed| for local and becomes |kObserved| when merged with the remote
1387 // profile.
1388 merged.SetRawInfoWithVerificationStatus(
1389 NAME_FIRST, base::ASCIIToUTF16("John"),
1390 structured_address::VerificationStatus::kObserved);
1391 merged.SetRawInfoWithVerificationStatus(
1392 NAME_MIDDLE, base::ASCIIToUTF16("Jacob"),
1393 structured_address::VerificationStatus::kObserved);
1394 merged.SetRawInfoWithVerificationStatus(
1395 NAME_LAST, base::ASCIIToUTF16("Smith"),
1396 structured_address::VerificationStatus::kObserved);
1397
1398 // No update to sync, merged changes in local data.
1399 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
1400 EXPECT_CALL(*backend(), CommitChanges());
1401 StartSyncing({remote});
1402 EXPECT_THAT(GetAllLocalData(), ElementsAre(merged));
1403 }
1404
1405 // Missing use_count/use_date fields should not generate sync events.
TEST_P(AutofillProfileSyncBridgeTest,RemoteWithSameGuid_UsageStats_MissingValueNoSync)1406 TEST_P(AutofillProfileSyncBridgeTest,
1407 RemoteWithSameGuid_UsageStats_MissingValueNoSync) {
1408 // Local autofill profile has 0 for use_count/use_date.
1409 AutofillProfile local(kGuidA, kHttpsOrigin);
1410 local.set_language_code("en");
1411 local.set_use_count(0);
1412 local.set_use_date(base::Time());
1413 AddAutofillProfilesToTable({local});
1414
1415 // Remote data does not have use_count/use_date.
1416 AutofillProfileSpecifics remote =
1417 CreateAutofillProfileSpecifics(kGuidA, kHttpsOrigin);
1418 remote.clear_use_count();
1419 remote.clear_use_date();
1420 remote.set_address_home_language_code("en");
1421
1422 // No update to sync, no change in local data.
1423 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
1424 EXPECT_CALL(*backend(), CommitChanges());
1425 StartSyncing({remote});
1426 EXPECT_THAT(GetAllLocalData(), ElementsAre(WithUsageStats(local)));
1427 }
1428
1429 struct UpdatesUsageStatsTestCase {
1430 size_t local_use_count;
1431 base::Time local_use_date;
1432 size_t remote_use_count;
1433 int remote_use_date;
1434 size_t merged_use_count;
1435 base::Time merged_use_date;
1436 };
1437
1438 class AutofillProfileSyncBridgeUpdatesUsageStatsTest
1439 : public AutofillProfileSyncBridgeTestBase,
1440 public testing::WithParamInterface<UpdatesUsageStatsTestCase> {
1441 public:
AutofillProfileSyncBridgeUpdatesUsageStatsTest()1442 AutofillProfileSyncBridgeUpdatesUsageStatsTest() {}
~AutofillProfileSyncBridgeUpdatesUsageStatsTest()1443 ~AutofillProfileSyncBridgeUpdatesUsageStatsTest() override {}
1444
1445 private:
1446 DISALLOW_COPY_AND_ASSIGN(AutofillProfileSyncBridgeUpdatesUsageStatsTest);
1447 };
1448
TEST_P(AutofillProfileSyncBridgeUpdatesUsageStatsTest,UpdatesUsageStats)1449 TEST_P(AutofillProfileSyncBridgeUpdatesUsageStatsTest, UpdatesUsageStats) {
1450 auto test_case = GetParam();
1451
1452 // Local data has usage stats.
1453 AutofillProfile local(kGuidA, kHttpsOrigin);
1454 local.set_language_code("en");
1455 local.set_use_count(test_case.local_use_count);
1456 local.set_use_date(test_case.local_use_date);
1457 ASSERT_EQ(test_case.local_use_count, local.use_count());
1458 ASSERT_EQ(test_case.local_use_date, local.use_date());
1459 AddAutofillProfilesToTable({local});
1460
1461 // Remote data has usage stats.
1462 AutofillProfileSpecifics remote =
1463 CreateAutofillProfileSpecifics(kGuidA, kHttpsOrigin);
1464 remote.set_address_home_language_code("en");
1465 remote.set_use_count(test_case.remote_use_count);
1466 remote.set_use_date(test_case.remote_use_date);
1467 ASSERT_TRUE(remote.has_use_count());
1468 ASSERT_TRUE(remote.has_use_date());
1469
1470 // Expect the local autofill profile to have usage stats after sync.
1471 AutofillProfile merged(local);
1472 merged.set_use_count(test_case.merged_use_count);
1473 merged.set_use_date(test_case.merged_use_date);
1474
1475 // Expect no changes to remote data.
1476 EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
1477 EXPECT_CALL(*backend(), CommitChanges());
1478
1479 StartSyncing({remote});
1480 EXPECT_THAT(GetAllLocalData(), ElementsAre(WithUsageStats(merged)));
1481 }
1482
1483 // Test the sync bridge with and without structured names.
1484 INSTANTIATE_TEST_SUITE_P(, AutofillProfileSyncBridgeTest, testing::Bool());
1485
1486 INSTANTIATE_TEST_SUITE_P(
1487 AutofillProfileSyncBridgeTest,
1488 AutofillProfileSyncBridgeUpdatesUsageStatsTest,
1489 testing::Values(
1490 // Local profile with default stats.
1491 UpdatesUsageStatsTestCase{
1492 /*local_use_count=*/0U,
1493 /*local_use_date=*/base::Time(),
1494 /*remote_use_count=*/9U,
1495 /*remote_use_date=*/4321,
1496 /*merged_use_count=*/9U,
1497 /*merged_use_date=*/base::Time::FromTimeT(4321)},
1498 // Local profile has older stats than the server.
1499 UpdatesUsageStatsTestCase{
1500 /*local_use_count=*/3U,
1501 /*local_use_date=*/base::Time::FromTimeT(1234),
1502 /*remote_use_count=*/9U, /*remote_use_date=*/4321,
1503 /*merged_use_count=*/9U,
1504 /*merged_use_date=*/base::Time::FromTimeT(4321)},
1505 // Local profile has newer stats than the server
1506 UpdatesUsageStatsTestCase{
1507 /*local_use_count=*/10U,
1508 /*local_use_date=*/base::Time::FromTimeT(9999),
1509 /*remote_use_count=*/9U, /*remote_use_date=*/4321,
1510 /*merged_use_count=*/9U,
1511 /*merged_use_date=*/base::Time::FromTimeT(4321)}));
1512
1513 } // namespace autofill
1514