1 // Copyright 2014 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.
5 #include "base/location.h"
6 #include "base/message_loop/message_loop.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "components/autofill/core/browser/autofill_profile.h"
9 #include "components/autofill/core/browser/webdata/autofill_change.h"
10 #include "components/autofill/core/browser/webdata/autofill_profile_syncable_service.h"
11 #include "sync/api/sync_error_factory.h"
12 #include "sync/api/sync_error_factory_mock.h"
13 #include "sync/protocol/sync.pb.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
20 using ::testing::DoAll;
22 using ::testing::Return;
23 using ::testing::Property;
24 using base::ASCIIToUTF16;
28 // Some guids for testing.
29 const char kGuid1[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44B";
30 const char kGuid2[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44C";
31 const char kGuid3[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44D";
32 const char kGuid4[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44E";
33 const char kHttpOrigin[] = "http://www.example.com/";
34 const char kHttpsOrigin[] = "https://www.example.com/";
35 const char kSettingsOrigin[] = "Chrome settings";
37 class MockAutofillProfileSyncableService
38 : public AutofillProfileSyncableService {
40 MockAutofillProfileSyncableService() {}
41 virtual ~MockAutofillProfileSyncableService() {}
43 using AutofillProfileSyncableService::DataBundle;
44 using AutofillProfileSyncableService::set_sync_processor;
45 using AutofillProfileSyncableService::CreateData;
47 MOCK_METHOD1(LoadAutofillData, bool(std::vector<AutofillProfile*>*));
48 MOCK_METHOD1(SaveChangesToWebData,
49 bool(const AutofillProfileSyncableService::DataBundle&));
52 ACTION_P(CopyData, data) {
53 arg0->resize(data->size());
54 std::copy(data->begin(), data->end(), arg0->begin());
57 MATCHER_P(CheckSyncChanges, n_sync_changes_list, "") {
58 if (arg.size() != n_sync_changes_list.size())
60 syncer::SyncChangeList::const_iterator passed, expected;
61 for (passed = arg.begin(), expected = n_sync_changes_list.begin();
62 passed != arg.end() && expected != n_sync_changes_list.end();
63 ++passed, ++expected) {
64 DCHECK(passed->IsValid());
65 if (passed->change_type() != expected->change_type())
67 if (passed->sync_data().GetSpecifics().SerializeAsString() !=
68 expected->sync_data().GetSpecifics().SerializeAsString()) {
75 MATCHER_P(DataBundleCheck, n_bundle, "") {
76 if ((arg.profiles_to_delete.size() != n_bundle.profiles_to_delete.size()) ||
77 (arg.profiles_to_update.size() != n_bundle.profiles_to_update.size()) ||
78 (arg.profiles_to_add.size() != n_bundle.profiles_to_add.size()))
80 for (size_t i = 0; i < arg.profiles_to_delete.size(); ++i) {
81 if (arg.profiles_to_delete[i] != n_bundle.profiles_to_delete[i])
84 for (size_t i = 0; i < arg.profiles_to_update.size(); ++i) {
85 if (*arg.profiles_to_update[i] != *n_bundle.profiles_to_update[i])
88 for (size_t i = 0; i < arg.profiles_to_add.size(); ++i) {
89 if (*arg.profiles_to_add[i] != *n_bundle.profiles_to_add[i])
95 class MockSyncChangeProcessor : public syncer::SyncChangeProcessor {
97 MockSyncChangeProcessor() {}
98 virtual ~MockSyncChangeProcessor() {}
100 MOCK_METHOD2(ProcessSyncChanges,
101 syncer::SyncError(const tracked_objects::Location&,
102 const syncer::SyncChangeList&));
103 virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type)
104 const OVERRIDE { return syncer::SyncDataList(); }
107 class TestSyncChangeProcessor : public syncer::SyncChangeProcessor {
109 TestSyncChangeProcessor() {}
110 virtual ~TestSyncChangeProcessor() {}
112 virtual syncer::SyncError ProcessSyncChanges(
113 const tracked_objects::Location& location,
114 const syncer::SyncChangeList& changes) OVERRIDE {
116 return syncer::SyncError();
119 virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const
121 return syncer::SyncDataList();
124 const syncer::SyncChangeList& changes() { return changes_; }
127 syncer::SyncChangeList changes_;
130 // Returns a profile with all fields set. Contains identical data to the data
131 // returned from ConstructCompleteSyncData().
132 scoped_ptr<AutofillProfile> ConstructCompleteProfile() {
133 scoped_ptr<AutofillProfile> profile(
134 new AutofillProfile(kGuid1, kHttpsOrigin));
136 std::vector<base::string16> names;
137 names.push_back(ASCIIToUTF16("John K. Doe"));
138 names.push_back(ASCIIToUTF16("Jane Luise Smith"));
139 profile->SetRawMultiInfo(NAME_FULL, names);
141 std::vector<base::string16> emails;
142 emails.push_back(ASCIIToUTF16("user@example.com"));
143 emails.push_back(ASCIIToUTF16("superuser@example.org"));
144 profile->SetRawMultiInfo(EMAIL_ADDRESS, emails);
146 std::vector<base::string16> phones;
147 phones.push_back(ASCIIToUTF16("1.800.555.1234"));
148 phones.push_back(ASCIIToUTF16("1.866.650.0000"));
149 profile->SetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, phones);
151 profile->SetRawInfo(ADDRESS_HOME_STREET_ADDRESS,
152 ASCIIToUTF16("123 Fake St.\n"
154 EXPECT_EQ(ASCIIToUTF16("123 Fake St."),
155 profile->GetRawInfo(ADDRESS_HOME_LINE1));
156 EXPECT_EQ(ASCIIToUTF16("Apt. 42"), profile->GetRawInfo(ADDRESS_HOME_LINE2));
158 profile->SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Google, Inc."));
159 profile->SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("Mountain View"));
160 profile->SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("California"));
161 profile->SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("94043"));
162 profile->SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("US"));
163 profile->SetRawInfo(ADDRESS_HOME_SORTING_CODE, ASCIIToUTF16("CEDEX"));
164 profile->SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
165 ASCIIToUTF16("Santa Clara"));
166 profile->set_language_code("en");
167 return profile.Pass();
170 // Returns SyncData with all Autofill profile fields set. Contains identical
171 // data to the data returned from ConstructCompleteProfile().
172 syncer::SyncData ConstructCompleteSyncData() {
173 sync_pb::EntitySpecifics entity_specifics;
174 sync_pb::AutofillProfileSpecifics* specifics =
175 entity_specifics.mutable_autofill_profile();
177 specifics->set_guid(kGuid1);
178 specifics->set_origin(kHttpsOrigin);
180 specifics->add_name_first("John");
181 specifics->add_name_middle("K.");
182 specifics->add_name_last("Doe");
184 specifics->add_name_first("Jane");
185 specifics->add_name_middle("Luise");
186 specifics->add_name_last("Smith");
188 specifics->add_email_address("user@example.com");
189 specifics->add_email_address("superuser@example.org");
191 specifics->add_phone_home_whole_number("1.800.555.1234");
192 specifics->add_phone_home_whole_number("1.866.650.0000");
194 specifics->set_address_home_line1("123 Fake St.");
195 specifics->set_address_home_line2("Apt. 42");
196 specifics->set_address_home_street_address("123 Fake St.\n"
199 specifics->set_company_name("Google, Inc.");
200 specifics->set_address_home_city("Mountain View");
201 specifics->set_address_home_state("California");
202 specifics->set_address_home_zip("94043");
203 specifics->set_address_home_country("US");
204 specifics->set_address_home_sorting_code("CEDEX");
205 specifics->set_address_home_dependent_locality("Santa Clara");
206 specifics->set_address_home_language_code("en");
208 return syncer::SyncData::CreateLocalData(kGuid1, kGuid1, entity_specifics);
213 class AutofillProfileSyncableServiceTest : public testing::Test {
215 AutofillProfileSyncableServiceTest() {}
217 virtual void SetUp() OVERRIDE {
218 sync_processor_.reset(new MockSyncChangeProcessor);
221 // Wrapper around AutofillProfileSyncableService::MergeDataAndStartSyncing()
222 // that also verifies expectations.
223 void MergeDataAndStartSyncing(
224 const std::vector<AutofillProfile*>& profiles_from_web_db,
225 const syncer::SyncDataList& data_list,
226 const MockAutofillProfileSyncableService::DataBundle& expected_bundle,
227 const syncer::SyncChangeList& expected_change_list) {
228 EXPECT_CALL(autofill_syncable_service_, LoadAutofillData(_))
230 .WillOnce(DoAll(CopyData(&profiles_from_web_db), Return(true)));
231 EXPECT_CALL(autofill_syncable_service_,
232 SaveChangesToWebData(DataBundleCheck(expected_bundle)))
234 .WillOnce(Return(true));
235 if (expected_change_list.empty()) {
236 EXPECT_CALL(*sync_processor_, ProcessSyncChanges(_, _)).Times(0);
238 ON_CALL(*sync_processor_, ProcessSyncChanges(_, _))
239 .WillByDefault(Return(syncer::SyncError()));
240 EXPECT_CALL(*sync_processor_,
241 ProcessSyncChanges(_, CheckSyncChanges(expected_change_list)))
243 .WillOnce(Return(syncer::SyncError()));
246 // Takes ownership of sync_processor_.
247 autofill_syncable_service_.MergeDataAndStartSyncing(
248 syncer::AUTOFILL_PROFILE, data_list,
249 sync_processor_.PassAs<syncer::SyncChangeProcessor>(),
250 scoped_ptr<syncer::SyncErrorFactory>(
251 new syncer::SyncErrorFactoryMock()));
255 base::MessageLoop message_loop_;
256 MockAutofillProfileSyncableService autofill_syncable_service_;
257 scoped_ptr<MockSyncChangeProcessor> sync_processor_;
260 TEST_F(AutofillProfileSyncableServiceTest, MergeDataAndStartSyncing) {
261 std::vector<AutofillProfile*> profiles_from_web_db;
262 std::string guid_present1 = kGuid1;
263 std::string guid_present2 = kGuid2;
264 std::string guid_synced1 = kGuid3;
265 std::string guid_synced2 = kGuid4;
266 std::string origin_present1 = kHttpOrigin;
267 std::string origin_present2 = std::string();
268 std::string origin_synced1 = kHttpsOrigin;
269 std::string origin_synced2 = kSettingsOrigin;
271 profiles_from_web_db.push_back(
272 new AutofillProfile(guid_present1, origin_present1));
273 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
274 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
275 ASCIIToUTF16("1 1st st"));
276 profiles_from_web_db.push_back(
277 new AutofillProfile(guid_present2, origin_present2));
278 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
279 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
280 ASCIIToUTF16("2 2nd st"));
282 syncer::SyncDataList data_list;
283 AutofillProfile profile1(guid_synced1, origin_synced1);
284 profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
285 data_list.push_back(autofill_syncable_service_.CreateData(profile1));
286 AutofillProfile profile2(guid_synced2, origin_synced2);
287 profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Harry"));
288 data_list.push_back(autofill_syncable_service_.CreateData(profile2));
289 // This one will have the name and origin updated.
290 AutofillProfile profile3(guid_present2, origin_synced2);
291 profile3.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom Doe"));
292 data_list.push_back(autofill_syncable_service_.CreateData(profile3));
294 syncer::SyncChangeList expected_change_list;
295 expected_change_list.push_back(
296 syncer::SyncChange(FROM_HERE,
297 syncer::SyncChange::ACTION_ADD,
298 MockAutofillProfileSyncableService::CreateData(
299 *profiles_from_web_db.front())));
301 MockAutofillProfileSyncableService::DataBundle expected_bundle;
302 expected_bundle.profiles_to_add.push_back(&profile1);
303 expected_bundle.profiles_to_add.push_back(&profile2);
304 expected_bundle.profiles_to_update.push_back(&profile3);
306 MergeDataAndStartSyncing(
307 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
308 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
311 TEST_F(AutofillProfileSyncableServiceTest, MergeIdenticalProfiles) {
312 std::vector<AutofillProfile*> profiles_from_web_db;
313 std::string guid_present1 = kGuid1;
314 std::string guid_present2 = kGuid2;
315 std::string guid_synced1 = kGuid3;
316 std::string guid_synced2 = kGuid4;
317 std::string origin_present1 = kHttpOrigin;
318 std::string origin_present2 = kSettingsOrigin;
319 std::string origin_synced1 = kHttpsOrigin;
320 std::string origin_synced2 = kHttpsOrigin;
322 profiles_from_web_db.push_back(
323 new AutofillProfile(guid_present1, origin_present1));
324 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
325 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
326 ASCIIToUTF16("1 1st st"));
327 profiles_from_web_db.push_back(
328 new AutofillProfile(guid_present2, origin_present2));
329 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
330 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
331 ASCIIToUTF16("2 2nd st"));
333 // The synced profiles are identical to the local ones, except that the guids
335 syncer::SyncDataList data_list;
336 AutofillProfile profile1(guid_synced1, origin_synced1);
337 profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
338 profile1.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1 1st st"));
339 data_list.push_back(autofill_syncable_service_.CreateData(profile1));
340 AutofillProfile profile2(guid_synced2, origin_synced2);
341 profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
342 profile2.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("2 2nd st"));
343 data_list.push_back(autofill_syncable_service_.CreateData(profile2));
345 AutofillProfile expected_profile(profile2);
346 expected_profile.set_origin(kSettingsOrigin);
347 syncer::SyncChangeList expected_change_list;
348 expected_change_list.push_back(
349 syncer::SyncChange(FROM_HERE,
350 syncer::SyncChange::ACTION_UPDATE,
351 MockAutofillProfileSyncableService::CreateData(
354 MockAutofillProfileSyncableService::DataBundle expected_bundle;
355 expected_bundle.profiles_to_delete.push_back(guid_present1);
356 expected_bundle.profiles_to_delete.push_back(guid_present2);
357 expected_bundle.profiles_to_add.push_back(&profile1);
358 expected_bundle.profiles_to_add.push_back(&expected_profile);
360 MergeDataAndStartSyncing(
361 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
362 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
365 TEST_F(AutofillProfileSyncableServiceTest, MergeSimilarProfiles) {
366 std::vector<AutofillProfile*> profiles_from_web_db;
367 std::string guid_present1 = kGuid1;
368 std::string guid_present2 = kGuid2;
369 std::string guid_synced1 = kGuid3;
370 std::string guid_synced2 = kGuid4;
371 std::string origin_present1 = kHttpOrigin;
372 std::string origin_present2 = kSettingsOrigin;
373 std::string origin_synced1 = kHttpsOrigin;
374 std::string origin_synced2 = kHttpsOrigin;
376 profiles_from_web_db.push_back(
377 new AutofillProfile(guid_present1, origin_present1));
378 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
379 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
380 ASCIIToUTF16("1 1st st"));
381 profiles_from_web_db.push_back(
382 new AutofillProfile(guid_present2, origin_present2));
383 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
384 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
385 ASCIIToUTF16("2 2nd st"));
387 // The synced profiles are identical to the local ones, except that the guids
389 syncer::SyncDataList data_list;
390 AutofillProfile profile1(guid_synced1, origin_synced1);
391 profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
392 profile1.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1 1st st"));
393 profile1.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Frobbers, Inc."));
394 data_list.push_back(autofill_syncable_service_.CreateData(profile1));
395 AutofillProfile profile2(guid_synced2, origin_synced2);
396 profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
397 profile2.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("2 2nd st"));
398 profile2.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Fizzbang, LLC."));
399 data_list.push_back(autofill_syncable_service_.CreateData(profile2));
401 // The first profile should have its origin updated.
402 // The second profile should remain as-is, because an unverified profile
403 // should never overwrite a verified one.
404 AutofillProfile expected_profile(profile1);
405 expected_profile.set_origin(origin_present1);
406 syncer::SyncChangeList expected_change_list;
407 expected_change_list.push_back(
408 syncer::SyncChange(FROM_HERE,
409 syncer::SyncChange::ACTION_ADD,
410 MockAutofillProfileSyncableService::CreateData(
411 *profiles_from_web_db.back())));
412 expected_change_list.push_back(
413 syncer::SyncChange(FROM_HERE,
414 syncer::SyncChange::ACTION_UPDATE,
415 MockAutofillProfileSyncableService::CreateData(
418 MockAutofillProfileSyncableService::DataBundle expected_bundle;
419 expected_bundle.profiles_to_delete.push_back(guid_present1);
420 expected_bundle.profiles_to_add.push_back(&expected_profile);
421 expected_bundle.profiles_to_add.push_back(&profile2);
423 MergeDataAndStartSyncing(
424 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
425 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
428 // Ensure that no Sync events are generated to fill in missing origins from Sync
429 // with explicitly present empty ones. This ensures that the migration to add
430 // origins to profiles does not generate lots of needless Sync updates.
431 TEST_F(AutofillProfileSyncableServiceTest, MergeDataEmptyOrigins) {
432 std::vector<AutofillProfile*> profiles_from_web_db;
434 // Create a profile with an empty origin.
435 AutofillProfile profile(kGuid1, std::string());
436 profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
437 profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1 1st st"));
439 profiles_from_web_db.push_back(new AutofillProfile(profile));
441 // Create a Sync profile identical to |profile|, except with no origin set.
442 sync_pb::EntitySpecifics specifics;
443 sync_pb::AutofillProfileSpecifics* autofill_specifics =
444 specifics.mutable_autofill_profile();
445 autofill_specifics->set_guid(profile.guid());
446 autofill_specifics->add_name_first("John");
447 autofill_specifics->add_name_middle(std::string());
448 autofill_specifics->add_name_last(std::string());
449 autofill_specifics->add_email_address(std::string());
450 autofill_specifics->add_phone_home_whole_number(std::string());
451 autofill_specifics->set_address_home_line1("1 1st st");
452 EXPECT_FALSE(autofill_specifics->has_origin());
454 syncer::SyncDataList data_list;
456 syncer::SyncData::CreateLocalData(
457 profile.guid(), profile.guid(), specifics));
459 MockAutofillProfileSyncableService::DataBundle expected_bundle;
460 syncer::SyncChangeList expected_change_list;
461 MergeDataAndStartSyncing(
462 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
463 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
466 TEST_F(AutofillProfileSyncableServiceTest, GetAllSyncData) {
467 std::vector<AutofillProfile*> profiles_from_web_db;
468 std::string guid_present1 = kGuid1;
469 std::string guid_present2 = kGuid2;
471 profiles_from_web_db.push_back(
472 new AutofillProfile(guid_present1, kHttpOrigin));
473 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
474 profiles_from_web_db.push_back(
475 new AutofillProfile(guid_present2, kHttpsOrigin));
476 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
478 syncer::SyncChangeList expected_change_list;
479 expected_change_list.push_back(
480 syncer::SyncChange(FROM_HERE,
481 syncer::SyncChange::ACTION_ADD,
482 MockAutofillProfileSyncableService::CreateData(
483 *profiles_from_web_db.front())));
484 expected_change_list.push_back(
485 syncer::SyncChange(FROM_HERE,
486 syncer::SyncChange::ACTION_ADD,
487 MockAutofillProfileSyncableService::CreateData(
488 *profiles_from_web_db.back())));
490 MockAutofillProfileSyncableService::DataBundle expected_bundle;
491 syncer::SyncDataList data_list;
492 MergeDataAndStartSyncing(
493 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
495 syncer::SyncDataList data =
496 autofill_syncable_service_.GetAllSyncData(syncer::AUTOFILL_PROFILE);
498 ASSERT_EQ(2U, data.size());
499 EXPECT_EQ(guid_present1, data[0].GetSpecifics().autofill_profile().guid());
500 EXPECT_EQ(guid_present2, data[1].GetSpecifics().autofill_profile().guid());
501 EXPECT_EQ(kHttpOrigin, data[0].GetSpecifics().autofill_profile().origin());
502 EXPECT_EQ(kHttpsOrigin, data[1].GetSpecifics().autofill_profile().origin());
504 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
507 TEST_F(AutofillProfileSyncableServiceTest, ProcessSyncChanges) {
508 std::vector<AutofillProfile *> profiles_from_web_db;
509 std::string guid_present = kGuid1;
510 std::string guid_synced = kGuid2;
512 syncer::SyncChangeList change_list;
513 AutofillProfile profile(guid_synced, kHttpOrigin);
514 profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
515 change_list.push_back(
518 syncer::SyncChange::ACTION_ADD,
519 MockAutofillProfileSyncableService::CreateData(profile)));
520 AutofillProfile empty_profile(guid_present, kHttpsOrigin);
521 change_list.push_back(
524 syncer::SyncChange::ACTION_DELETE,
525 MockAutofillProfileSyncableService::CreateData(empty_profile)));
527 MockAutofillProfileSyncableService::DataBundle expected_bundle;
528 expected_bundle.profiles_to_delete.push_back(guid_present);
529 expected_bundle.profiles_to_add.push_back(&profile);
531 EXPECT_CALL(autofill_syncable_service_, SaveChangesToWebData(
532 DataBundleCheck(expected_bundle)))
534 .WillOnce(Return(true));
536 autofill_syncable_service_.set_sync_processor(sync_processor_.release());
537 syncer::SyncError error = autofill_syncable_service_.ProcessSyncChanges(
538 FROM_HERE, change_list);
540 EXPECT_FALSE(error.IsSet());
543 TEST_F(AutofillProfileSyncableServiceTest, AutofillProfileAdded) {
544 // Will be owned by the syncable service. Keep a reference available here for
545 // verifying test expectations.
546 TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;
547 autofill_syncable_service_.set_sync_processor(sync_change_processor);
549 AutofillProfile profile(kGuid1, kHttpsOrigin);
550 profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
551 AutofillProfileChange change(AutofillProfileChange::ADD, kGuid1, &profile);
552 autofill_syncable_service_.AutofillProfileChanged(change);
554 ASSERT_EQ(1U, sync_change_processor->changes().size());
555 syncer::SyncChange result = sync_change_processor->changes()[0];
556 EXPECT_EQ(syncer::SyncChange::ACTION_ADD, result.change_type());
558 sync_pb::AutofillProfileSpecifics specifics =
559 result.sync_data().GetSpecifics().autofill_profile();
560 EXPECT_EQ(kGuid1, specifics.guid());
561 EXPECT_EQ(kHttpsOrigin, specifics.origin());
562 EXPECT_THAT(specifics.name_first(), testing::ElementsAre("Jane"));
565 TEST_F(AutofillProfileSyncableServiceTest, AutofillProfileDeleted) {
566 // Will be owned by the syncable service. Keep a reference available here for
567 // verifying test expectations.
568 TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;
569 autofill_syncable_service_.set_sync_processor(sync_change_processor);
571 AutofillProfileChange change(AutofillProfileChange::REMOVE, kGuid2, NULL);
572 autofill_syncable_service_.AutofillProfileChanged(change);
574 ASSERT_EQ(1U, sync_change_processor->changes().size());
575 syncer::SyncChange result = sync_change_processor->changes()[0];
576 EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, result.change_type());
577 sync_pb::AutofillProfileSpecifics specifics =
578 result.sync_data().GetSpecifics().autofill_profile();
579 EXPECT_EQ(kGuid2, specifics.guid());
582 TEST_F(AutofillProfileSyncableServiceTest, UpdateField) {
583 AutofillProfile profile(kGuid1, kSettingsOrigin);
584 std::string company1 = "A Company";
585 std::string company2 = "Another Company";
586 profile.SetRawInfo(COMPANY_NAME, ASCIIToUTF16(company1));
587 EXPECT_FALSE(AutofillProfileSyncableService::UpdateField(
588 COMPANY_NAME, company1, &profile));
589 EXPECT_EQ(profile.GetRawInfo(COMPANY_NAME), ASCIIToUTF16(company1));
590 EXPECT_TRUE(AutofillProfileSyncableService::UpdateField(
591 COMPANY_NAME, company2, &profile));
592 EXPECT_EQ(profile.GetRawInfo(COMPANY_NAME), ASCIIToUTF16(company2));
593 EXPECT_FALSE(AutofillProfileSyncableService::UpdateField(
594 COMPANY_NAME, company2, &profile));
595 EXPECT_EQ(profile.GetRawInfo(COMPANY_NAME), ASCIIToUTF16(company2));
598 TEST_F(AutofillProfileSyncableServiceTest, UpdateMultivaluedField) {
599 AutofillProfile profile(kGuid1, kHttpsOrigin);
601 std::vector<base::string16> values;
602 values.push_back(ASCIIToUTF16("1@1.com"));
603 values.push_back(ASCIIToUTF16("2@1.com"));
604 profile.SetRawMultiInfo(EMAIL_ADDRESS, values);
606 ::google::protobuf::RepeatedPtrField<std::string> specifics_fields;
607 specifics_fields.AddAllocated(new std::string("2@1.com"));
608 specifics_fields.AddAllocated(new std::string("3@1.com"));
610 EXPECT_TRUE(AutofillProfileSyncableService::UpdateMultivaluedField(
611 EMAIL_ADDRESS, specifics_fields, &profile));
612 profile.GetRawMultiInfo(EMAIL_ADDRESS, &values);
613 ASSERT_TRUE(values.size() == 2);
614 EXPECT_EQ(values[0], ASCIIToUTF16("2@1.com"));
615 EXPECT_EQ(values[1], ASCIIToUTF16("3@1.com"));
617 EXPECT_FALSE(AutofillProfileSyncableService::UpdateMultivaluedField(
618 EMAIL_ADDRESS, specifics_fields, &profile));
619 profile.GetRawMultiInfo(EMAIL_ADDRESS, &values);
620 ASSERT_EQ(values.size(), 2U);
621 EXPECT_EQ(values[0], ASCIIToUTF16("2@1.com"));
622 EXPECT_EQ(values[1], ASCIIToUTF16("3@1.com"));
623 EXPECT_TRUE(AutofillProfileSyncableService::UpdateMultivaluedField(
624 EMAIL_ADDRESS, ::google::protobuf::RepeatedPtrField<std::string>(),
626 profile.GetRawMultiInfo(EMAIL_ADDRESS, &values);
627 ASSERT_EQ(values.size(), 1U); // Always have at least an empty string.
628 EXPECT_EQ(values[0], ASCIIToUTF16(""));
631 TEST_F(AutofillProfileSyncableServiceTest, MergeProfile) {
632 AutofillProfile profile1(kGuid1, kHttpOrigin);
633 profile1.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("111 First St."));
635 std::vector<base::string16> values;
636 values.push_back(ASCIIToUTF16("1@1.com"));
637 values.push_back(ASCIIToUTF16("2@1.com"));
638 profile1.SetRawMultiInfo(EMAIL_ADDRESS, values);
640 AutofillProfile profile2(kGuid2, kHttpsOrigin);
641 profile2.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("111 First St."));
643 // |values| now is [ "1@1.com", "2@1.com", "3@1.com" ].
644 values.push_back(ASCIIToUTF16("3@1.com"));
645 profile2.SetRawMultiInfo(EMAIL_ADDRESS, values);
648 values.push_back(ASCIIToUTF16("John"));
649 profile1.SetRawMultiInfo(NAME_FIRST, values);
650 values.push_back(ASCIIToUTF16("Jane"));
651 profile2.SetRawMultiInfo(NAME_FIRST, values);
654 values.push_back(ASCIIToUTF16("Doe"));
655 profile1.SetRawMultiInfo(NAME_LAST, values);
656 values.push_back(ASCIIToUTF16("Other"));
657 profile2.SetRawMultiInfo(NAME_LAST, values);
660 values.push_back(ASCIIToUTF16("650234567"));
661 profile2.SetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, values);
663 profile1.set_language_code("en");
665 EXPECT_FALSE(AutofillProfileSyncableService::MergeProfile(profile2,
669 profile1.GetRawMultiInfo(NAME_FIRST, &values);
670 ASSERT_EQ(values.size(), 2U);
671 EXPECT_EQ(values[0], ASCIIToUTF16("John"));
672 EXPECT_EQ(values[1], ASCIIToUTF16("Jane"));
674 profile1.GetRawMultiInfo(NAME_LAST, &values);
675 ASSERT_EQ(values.size(), 2U);
676 EXPECT_EQ(values[0], ASCIIToUTF16("Doe"));
677 EXPECT_EQ(values[1], ASCIIToUTF16("Other"));
679 profile1.GetRawMultiInfo(EMAIL_ADDRESS, &values);
680 ASSERT_EQ(values.size(), 3U);
681 EXPECT_EQ(values[0], ASCIIToUTF16("1@1.com"));
682 EXPECT_EQ(values[1], ASCIIToUTF16("2@1.com"));
683 EXPECT_EQ(values[2], ASCIIToUTF16("3@1.com"));
685 profile1.GetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, &values);
686 ASSERT_EQ(values.size(), 1U);
687 EXPECT_EQ(values[0], ASCIIToUTF16("650234567"));
689 EXPECT_EQ(profile2.origin(), profile1.origin());
691 AutofillProfile profile3(kGuid3, kHttpOrigin);
692 profile3.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("111 First St."));
695 values.push_back(ASCIIToUTF16("Jane"));
696 profile3.SetRawMultiInfo(NAME_FIRST, values);
699 values.push_back(ASCIIToUTF16("Doe"));
700 profile3.SetRawMultiInfo(NAME_LAST, values);
702 EXPECT_TRUE(AutofillProfileSyncableService::MergeProfile(profile3,
706 profile1.GetRawMultiInfo(NAME_FIRST, &values);
707 ASSERT_EQ(values.size(), 3U);
708 EXPECT_EQ(values[0], ASCIIToUTF16("John"));
709 EXPECT_EQ(values[1], ASCIIToUTF16("Jane"));
710 EXPECT_EQ(values[2], ASCIIToUTF16("Jane"));
712 profile1.GetRawMultiInfo(NAME_LAST, &values);
713 ASSERT_EQ(values.size(), 3U);
714 EXPECT_EQ(values[0], ASCIIToUTF16("Doe"));
715 EXPECT_EQ(values[1], ASCIIToUTF16("Other"));
716 EXPECT_EQ(values[2], ASCIIToUTF16("Doe"));
718 // Middle name should have three entries as well.
719 profile1.GetRawMultiInfo(NAME_MIDDLE, &values);
720 ASSERT_EQ(values.size(), 3U);
721 EXPECT_TRUE(values[0].empty());
722 EXPECT_TRUE(values[1].empty());
723 EXPECT_TRUE(values[2].empty());
725 profile1.GetRawMultiInfo(EMAIL_ADDRESS, &values);
726 ASSERT_EQ(values.size(), 3U);
727 EXPECT_EQ(values[0], ASCIIToUTF16("1@1.com"));
728 EXPECT_EQ(values[1], ASCIIToUTF16("2@1.com"));
729 EXPECT_EQ(values[2], ASCIIToUTF16("3@1.com"));
731 profile1.GetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, &values);
732 ASSERT_EQ(values.size(), 1U);
733 EXPECT_EQ(values[0], ASCIIToUTF16("650234567"));
736 // Ensure that all profile fields are able to be synced up from the client to
738 TEST_F(AutofillProfileSyncableServiceTest, SyncAllFieldsToServer) {
739 std::vector<AutofillProfile*> profiles_from_web_db;
741 // Create a profile with all fields set.
742 profiles_from_web_db.push_back(ConstructCompleteProfile().release());
744 // Set up expectations: No changes to the WebDB, and all fields correctly
746 MockAutofillProfileSyncableService::DataBundle expected_bundle;
747 syncer::SyncChangeList expected_change_list;
748 expected_change_list.push_back(
749 syncer::SyncChange(FROM_HERE,
750 syncer::SyncChange::ACTION_ADD,
751 ConstructCompleteSyncData()));
753 // Verify the expectations.
754 syncer::SyncDataList data_list;
755 MergeDataAndStartSyncing(
756 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
757 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
760 // Ensure that all profile fields are able to be synced down from the server to
762 TEST_F(AutofillProfileSyncableServiceTest, SyncAllFieldsToClient) {
763 // Create a profile with all fields set.
764 syncer::SyncDataList data_list;
765 data_list.push_back(ConstructCompleteSyncData());
767 // Set up expectations: All fields correctly copied to the WebDB, and no
768 // changes propagated to Sync.
769 syncer::SyncChangeList expected_change_list;
770 scoped_ptr<AutofillProfile> expected_profile = ConstructCompleteProfile();
771 MockAutofillProfileSyncableService::DataBundle expected_bundle;
772 expected_bundle.profiles_to_add.push_back(expected_profile.get());
774 // Verify the expectations.
775 std::vector<AutofillProfile*> profiles_from_web_db;
776 MergeDataAndStartSyncing(
777 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
778 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
781 // Ensure that the street address field takes precedence over the address line 1
782 // and line 2 fields, even though these are expected to always be in sync in
784 TEST_F(AutofillProfileSyncableServiceTest,
785 StreetAddressTakesPrecedenceOverAddressLines) {
786 // Create a Sync profile with conflicting address data in the street address
787 // field vs. the address line 1 and address line 2 fields.
788 sync_pb::EntitySpecifics specifics;
789 sync_pb::AutofillProfileSpecifics* autofill_specifics =
790 specifics.mutable_autofill_profile();
791 autofill_specifics->set_guid(kGuid1);
792 autofill_specifics->set_origin(kHttpsOrigin);
793 autofill_specifics->add_name_first(std::string());
794 autofill_specifics->add_name_middle(std::string());
795 autofill_specifics->add_name_last(std::string());
796 autofill_specifics->add_email_address(std::string());
797 autofill_specifics->add_phone_home_whole_number(std::string());
798 autofill_specifics->set_address_home_line1("123 Example St.");
799 autofill_specifics->set_address_home_line2("Apt. 42");
800 autofill_specifics->set_address_home_street_address("456 El Camino Real\n"
803 syncer::SyncDataList data_list;
805 syncer::SyncData::CreateLocalData(kGuid1, kGuid1, specifics));
807 // Set up expectations: Full street address takes precedence over address
809 syncer::SyncChangeList expected_change_list;
810 AutofillProfile expected_profile(kGuid1, kHttpsOrigin);
811 expected_profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS,
812 ASCIIToUTF16("456 El Camino Real\n"
814 EXPECT_EQ(ASCIIToUTF16("456 El Camino Real"),
815 expected_profile.GetRawInfo(ADDRESS_HOME_LINE1));
816 EXPECT_EQ(ASCIIToUTF16("Suite #1337"),
817 expected_profile.GetRawInfo(ADDRESS_HOME_LINE2));
818 MockAutofillProfileSyncableService::DataBundle expected_bundle;
819 expected_bundle.profiles_to_add.push_back(&expected_profile);
821 // Verify the expectations.
822 std::vector<AutofillProfile*> profiles_from_web_db;
823 MergeDataAndStartSyncing(
824 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
825 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
828 // Ensure that no Sync events are generated to fill in missing street address
829 // fields from Sync with explicitly present ones identical to the data stored in
830 // the line1 and line2 fields. This ensures that the migration to add the
831 // street address field to profiles does not generate lots of needless Sync
833 TEST_F(AutofillProfileSyncableServiceTest, MergeDataEmptyStreetAddress) {
834 std::vector<AutofillProfile*> profiles_from_web_db;
836 // Create a profile with the street address set.
837 AutofillProfile profile(kGuid1, kHttpsOrigin);
838 profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS,
839 ASCIIToUTF16("123 Example St.\n"
841 EXPECT_EQ(ASCIIToUTF16("123 Example St."),
842 profile.GetRawInfo(ADDRESS_HOME_LINE1));
843 EXPECT_EQ(ASCIIToUTF16("Apt. 42"), profile.GetRawInfo(ADDRESS_HOME_LINE2));
845 profiles_from_web_db.push_back(new AutofillProfile(profile));
847 // Create a Sync profile identical to |profile|, except without street address
849 sync_pb::EntitySpecifics specifics;
850 sync_pb::AutofillProfileSpecifics* autofill_specifics =
851 specifics.mutable_autofill_profile();
852 autofill_specifics->set_guid(profile.guid());
853 autofill_specifics->set_origin(profile.origin());
854 autofill_specifics->add_name_first(std::string());
855 autofill_specifics->add_name_middle(std::string());
856 autofill_specifics->add_name_last(std::string());
857 autofill_specifics->add_email_address(std::string());
858 autofill_specifics->add_phone_home_whole_number(std::string());
859 autofill_specifics->set_address_home_line1("123 Example St.");
860 autofill_specifics->set_address_home_line2("Apt. 42");
861 EXPECT_FALSE(autofill_specifics->has_address_home_street_address());
863 syncer::SyncDataList data_list;
865 syncer::SyncData::CreateLocalData(
866 profile.guid(), profile.guid(), specifics));
868 MockAutofillProfileSyncableService::DataBundle expected_bundle;
869 syncer::SyncChangeList expected_change_list;
870 MergeDataAndStartSyncing(
871 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
872 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
875 // Sync data without origin should not overwrite existing origin in local
877 TEST_F(AutofillProfileSyncableServiceTest, EmptySyncPreservesOrigin) {
878 std::vector<AutofillProfile*> profiles_from_web_db;
880 // Local autofill profile has an origin.
881 AutofillProfile profile(kGuid1, kHttpsOrigin);
882 profiles_from_web_db.push_back(new AutofillProfile(profile));
884 // Remote data does not have an origin value.
885 sync_pb::EntitySpecifics specifics;
886 sync_pb::AutofillProfileSpecifics* autofill_specifics =
887 specifics.mutable_autofill_profile();
888 autofill_specifics->set_guid(profile.guid());
889 autofill_specifics->add_name_first("John");
890 autofill_specifics->add_name_middle(std::string());
891 autofill_specifics->add_name_last(std::string());
892 autofill_specifics->add_email_address(std::string());
893 autofill_specifics->add_phone_home_whole_number(std::string());
894 EXPECT_FALSE(autofill_specifics->has_origin());
896 syncer::SyncDataList data_list;
898 syncer::SyncData::CreateLocalData(
899 profile.guid(), profile.guid(), specifics));
901 // Expect the local autofill profile to still have an origin after sync.
902 MockAutofillProfileSyncableService::DataBundle expected_bundle;
903 AutofillProfile expected_profile(profile.guid(), profile.origin());
904 expected_profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
905 expected_bundle.profiles_to_update.push_back(&expected_profile);
907 // Expect no sync events to add origin to the remote data.
908 syncer::SyncChangeList expected_empty_change_list;
910 MergeDataAndStartSyncing(profiles_from_web_db, data_list,
911 expected_bundle, expected_empty_change_list);
912 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
915 // Missing language code field should not generate sync events.
916 TEST_F(AutofillProfileSyncableServiceTest, NoLanguageCodeNoSync) {
917 std::vector<AutofillProfile*> profiles_from_web_db;
919 // Local autofill profile has an empty language code.
920 AutofillProfile profile(kGuid1, kHttpsOrigin);
921 EXPECT_TRUE(profile.language_code().empty());
922 profiles_from_web_db.push_back(new AutofillProfile(profile));
924 // Remote data does not have a language code value.
925 sync_pb::EntitySpecifics specifics;
926 sync_pb::AutofillProfileSpecifics* autofill_specifics =
927 specifics.mutable_autofill_profile();
928 autofill_specifics->set_guid(profile.guid());
929 autofill_specifics->set_origin(profile.origin());
930 autofill_specifics->add_name_first(std::string());
931 autofill_specifics->add_name_middle(std::string());
932 autofill_specifics->add_name_last(std::string());
933 autofill_specifics->add_email_address(std::string());
934 autofill_specifics->add_phone_home_whole_number(std::string());
935 EXPECT_FALSE(autofill_specifics->has_address_home_language_code());
937 syncer::SyncDataList data_list;
939 syncer::SyncData::CreateLocalData(
940 profile.guid(), profile.guid(), specifics));
942 // Expect no changes to local and remote data.
943 MockAutofillProfileSyncableService::DataBundle expected_empty_bundle;
944 syncer::SyncChangeList expected_empty_change_list;
946 MergeDataAndStartSyncing(profiles_from_web_db, data_list,
947 expected_empty_bundle, expected_empty_change_list);
948 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
951 // Empty language code should be overwritten by sync.
952 TEST_F(AutofillProfileSyncableServiceTest, SyncUpdatesEmptyLanguageCode) {
953 std::vector<AutofillProfile*> profiles_from_web_db;
955 // Local autofill profile has an empty language code.
956 AutofillProfile profile(kGuid1, kHttpsOrigin);
957 EXPECT_TRUE(profile.language_code().empty());
958 profiles_from_web_db.push_back(new AutofillProfile(profile));
960 // Remote data has "en" language code.
961 sync_pb::EntitySpecifics specifics;
962 sync_pb::AutofillProfileSpecifics* autofill_specifics =
963 specifics.mutable_autofill_profile();
964 autofill_specifics->set_guid(profile.guid());
965 autofill_specifics->set_origin(profile.origin());
966 autofill_specifics->add_name_first(std::string());
967 autofill_specifics->add_name_middle(std::string());
968 autofill_specifics->add_name_last(std::string());
969 autofill_specifics->add_email_address(std::string());
970 autofill_specifics->add_phone_home_whole_number(std::string());
971 autofill_specifics->set_address_home_language_code("en");
972 EXPECT_TRUE(autofill_specifics->has_address_home_language_code());
974 syncer::SyncDataList data_list;
976 syncer::SyncData::CreateLocalData(
977 profile.guid(), profile.guid(), specifics));
979 // Expect the local autofill profile to have "en" language code after sync.
980 MockAutofillProfileSyncableService::DataBundle expected_bundle;
981 AutofillProfile expected_profile(kGuid1, kHttpsOrigin);
982 expected_profile.set_language_code("en");
983 expected_bundle.profiles_to_update.push_back(&expected_profile);
985 // Expect not changes to remote data.
986 syncer::SyncChangeList expected_empty_change_list;
988 MergeDataAndStartSyncing(profiles_from_web_db, data_list,
989 expected_bundle, expected_empty_change_list);
990 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
993 // Incorrect language code should be overwritten by sync.
994 TEST_F(AutofillProfileSyncableServiceTest, SyncUpdatesIncorrectLanguageCode) {
995 std::vector<AutofillProfile*> profiles_from_web_db;
997 // Local autofill profile has "de" language code.
998 AutofillProfile profile(kGuid1, kHttpsOrigin);
999 profile.set_language_code("de");
1000 profiles_from_web_db.push_back(new AutofillProfile(profile));
1002 // Remote data has "en" language code.
1003 sync_pb::EntitySpecifics specifics;
1004 sync_pb::AutofillProfileSpecifics* autofill_specifics =
1005 specifics.mutable_autofill_profile();
1006 autofill_specifics->set_guid(profile.guid());
1007 autofill_specifics->set_origin(profile.origin());
1008 autofill_specifics->add_name_first(std::string());
1009 autofill_specifics->add_name_middle(std::string());
1010 autofill_specifics->add_name_last(std::string());
1011 autofill_specifics->add_email_address(std::string());
1012 autofill_specifics->add_phone_home_whole_number(std::string());
1013 autofill_specifics->set_address_home_language_code("en");
1014 EXPECT_TRUE(autofill_specifics->has_address_home_language_code());
1016 syncer::SyncDataList data_list;
1017 data_list.push_back(
1018 syncer::SyncData::CreateLocalData(
1019 profile.guid(), profile.guid(), specifics));
1021 // Expect the local autofill profile to have "en" language code after sync.
1022 MockAutofillProfileSyncableService::DataBundle expected_bundle;
1023 AutofillProfile expected_profile(kGuid1, kHttpsOrigin);
1024 expected_profile.set_language_code("en");
1025 expected_bundle.profiles_to_update.push_back(&expected_profile);
1027 // Expect no changes to remote data.
1028 syncer::SyncChangeList expected_empty_change_list;
1030 MergeDataAndStartSyncing(profiles_from_web_db, data_list,
1031 expected_bundle, expected_empty_change_list);
1032 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
1035 // Sync data without language code should not overwrite existing language code
1036 // in local autofill profile.
1037 TEST_F(AutofillProfileSyncableServiceTest, EmptySyncPreservesLanguageCode) {
1038 std::vector<AutofillProfile*> profiles_from_web_db;
1040 // Local autofill profile has "en" language code.
1041 AutofillProfile profile(kGuid1, kHttpsOrigin);
1042 profile.set_language_code("en");
1043 profiles_from_web_db.push_back(new AutofillProfile(profile));
1045 // Remote data does not have a language code value.
1046 sync_pb::EntitySpecifics specifics;
1047 sync_pb::AutofillProfileSpecifics* autofill_specifics =
1048 specifics.mutable_autofill_profile();
1049 autofill_specifics->set_guid(profile.guid());
1050 autofill_specifics->set_origin(profile.origin());
1051 autofill_specifics->add_name_first("John");
1052 autofill_specifics->add_name_middle(std::string());
1053 autofill_specifics->add_name_last(std::string());
1054 autofill_specifics->add_email_address(std::string());
1055 autofill_specifics->add_phone_home_whole_number(std::string());
1056 EXPECT_FALSE(autofill_specifics->has_address_home_language_code());
1058 syncer::SyncDataList data_list;
1059 data_list.push_back(
1060 syncer::SyncData::CreateLocalData(
1061 profile.guid(), profile.guid(), specifics));
1063 // Expect local autofill profile to still have "en" language code after sync.
1064 MockAutofillProfileSyncableService::DataBundle expected_bundle;
1065 AutofillProfile expected_profile(profile.guid(), profile.origin());
1066 expected_profile.set_language_code("en");
1067 expected_profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
1068 expected_bundle.profiles_to_update.push_back(&expected_profile);
1070 // Expect no changes to remote data.
1071 syncer::SyncChangeList expected_empty_change_list;
1073 MergeDataAndStartSyncing(profiles_from_web_db, data_list,
1074 expected_bundle, expected_empty_change_list);
1075 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
1078 // Language code in autofill profiles should be synced to the server.
1079 TEST_F(AutofillProfileSyncableServiceTest, LanguageCodePropagates) {
1080 TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;
1081 autofill_syncable_service_.set_sync_processor(sync_change_processor);
1083 AutofillProfile profile(kGuid1, kHttpsOrigin);
1084 profile.set_language_code("en");
1085 AutofillProfileChange change(AutofillProfileChange::ADD, kGuid1, &profile);
1086 autofill_syncable_service_.AutofillProfileChanged(change);
1088 ASSERT_EQ(1U, sync_change_processor->changes().size());
1089 syncer::SyncChange result = sync_change_processor->changes()[0];
1090 EXPECT_EQ(syncer::SyncChange::ACTION_ADD, result.change_type());
1092 sync_pb::AutofillProfileSpecifics specifics =
1093 result.sync_data().GetSpecifics().autofill_profile();
1094 EXPECT_EQ(kGuid1, specifics.guid());
1095 EXPECT_EQ(kHttpsOrigin, specifics.origin());
1096 EXPECT_EQ("en", specifics.address_home_language_code());
1099 } // namespace autofill