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.
4
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"
16
17 namespace autofill {
18
19 using ::testing::_;
20 using ::testing::DoAll;
21 using ::testing::Eq;
22 using ::testing::Return;
23 using ::testing::Property;
24 using base::ASCIIToUTF16;
25
26 namespace {
27
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";
36
37 class MockAutofillProfileSyncableService
38 : public AutofillProfileSyncableService {
39 public:
MockAutofillProfileSyncableService()40 MockAutofillProfileSyncableService() {}
~MockAutofillProfileSyncableService()41 virtual ~MockAutofillProfileSyncableService() {}
42
43 using AutofillProfileSyncableService::DataBundle;
44 using AutofillProfileSyncableService::set_sync_processor;
45 using AutofillProfileSyncableService::CreateData;
46
47 MOCK_METHOD1(LoadAutofillData, bool(std::vector<AutofillProfile*>*));
48 MOCK_METHOD1(SaveChangesToWebData,
49 bool(const AutofillProfileSyncableService::DataBundle&));
50 };
51
ACTION_P(CopyData,data)52 ACTION_P(CopyData, data) {
53 arg0->resize(data->size());
54 std::copy(data->begin(), data->end(), arg0->begin());
55 }
56
57 MATCHER_P(CheckSyncChanges, n_sync_changes_list, "") {
58 if (arg.size() != n_sync_changes_list.size())
59 return false;
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())
66 return false;
67 if (passed->sync_data().GetSpecifics().SerializeAsString() !=
68 expected->sync_data().GetSpecifics().SerializeAsString()) {
69 return false;
70 }
71 }
72 return true;
73 }
74
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()))
79 return false;
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])
82 return false;
83 }
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])
86 return false;
87 }
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])
90 return false;
91 }
92 return true;
93 }
94
95 class MockSyncChangeProcessor : public syncer::SyncChangeProcessor {
96 public:
MockSyncChangeProcessor()97 MockSyncChangeProcessor() {}
~MockSyncChangeProcessor()98 virtual ~MockSyncChangeProcessor() {}
99
100 MOCK_METHOD2(ProcessSyncChanges,
101 syncer::SyncError(const tracked_objects::Location&,
102 const syncer::SyncChangeList&));
GetAllSyncData(syncer::ModelType type) const103 virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type)
104 const OVERRIDE { return syncer::SyncDataList(); }
105 };
106
107 class TestSyncChangeProcessor : public syncer::SyncChangeProcessor {
108 public:
TestSyncChangeProcessor()109 TestSyncChangeProcessor() {}
~TestSyncChangeProcessor()110 virtual ~TestSyncChangeProcessor() {}
111
ProcessSyncChanges(const tracked_objects::Location & location,const syncer::SyncChangeList & changes)112 virtual syncer::SyncError ProcessSyncChanges(
113 const tracked_objects::Location& location,
114 const syncer::SyncChangeList& changes) OVERRIDE {
115 changes_ = changes;
116 return syncer::SyncError();
117 }
118
GetAllSyncData(syncer::ModelType type) const119 virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const
120 OVERRIDE {
121 return syncer::SyncDataList();
122 }
123
changes()124 const syncer::SyncChangeList& changes() { return changes_; }
125
126 private:
127 syncer::SyncChangeList changes_;
128 };
129
130 // Returns a profile with all fields set. Contains identical data to the data
131 // returned from ConstructCompleteSyncData().
ConstructCompleteProfile()132 scoped_ptr<AutofillProfile> ConstructCompleteProfile() {
133 scoped_ptr<AutofillProfile> profile(
134 new AutofillProfile(kGuid1, kHttpsOrigin));
135
136 std::vector<base::string16> names;
137 names.push_back(ASCIIToUTF16("John K. Doe, Jr."));
138 names.push_back(ASCIIToUTF16("Jane Luise Smith MD"));
139 profile->SetRawMultiInfo(NAME_FULL, names);
140
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);
145
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);
150
151 profile->SetRawInfo(ADDRESS_HOME_STREET_ADDRESS,
152 ASCIIToUTF16("123 Fake St.\n"
153 "Apt. 42"));
154 EXPECT_EQ(ASCIIToUTF16("123 Fake St."),
155 profile->GetRawInfo(ADDRESS_HOME_LINE1));
156 EXPECT_EQ(ASCIIToUTF16("Apt. 42"), profile->GetRawInfo(ADDRESS_HOME_LINE2));
157
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();
168 }
169
170 // Returns SyncData with all Autofill profile fields set. Contains identical
171 // data to the data returned from ConstructCompleteProfile().
ConstructCompleteSyncData()172 syncer::SyncData ConstructCompleteSyncData() {
173 sync_pb::EntitySpecifics entity_specifics;
174 sync_pb::AutofillProfileSpecifics* specifics =
175 entity_specifics.mutable_autofill_profile();
176
177 specifics->set_guid(kGuid1);
178 specifics->set_origin(kHttpsOrigin);
179
180 specifics->add_name_first("John");
181 specifics->add_name_middle("K.");
182 specifics->add_name_last("Doe");
183 specifics->add_name_full("John K. Doe, Jr.");
184
185 specifics->add_name_first("Jane");
186 specifics->add_name_middle("Luise");
187 specifics->add_name_last("Smith");
188 specifics->add_name_full("Jane Luise Smith MD");
189
190 specifics->add_email_address("user@example.com");
191 specifics->add_email_address("superuser@example.org");
192
193 specifics->add_phone_home_whole_number("1.800.555.1234");
194 specifics->add_phone_home_whole_number("1.866.650.0000");
195
196 specifics->set_address_home_line1("123 Fake St.");
197 specifics->set_address_home_line2("Apt. 42");
198 specifics->set_address_home_street_address("123 Fake St.\n"
199 "Apt. 42");
200
201 specifics->set_company_name("Google, Inc.");
202 specifics->set_address_home_city("Mountain View");
203 specifics->set_address_home_state("California");
204 specifics->set_address_home_zip("94043");
205 specifics->set_address_home_country("US");
206 specifics->set_address_home_sorting_code("CEDEX");
207 specifics->set_address_home_dependent_locality("Santa Clara");
208 specifics->set_address_home_language_code("en");
209
210 return syncer::SyncData::CreateLocalData(kGuid1, kGuid1, entity_specifics);
211 }
212
213 } // namespace
214
215 class AutofillProfileSyncableServiceTest : public testing::Test {
216 public:
AutofillProfileSyncableServiceTest()217 AutofillProfileSyncableServiceTest() {}
218
SetUp()219 virtual void SetUp() OVERRIDE {
220 sync_processor_.reset(new MockSyncChangeProcessor);
221 }
222
223 // Wrapper around AutofillProfileSyncableService::MergeDataAndStartSyncing()
224 // that also verifies expectations.
MergeDataAndStartSyncing(const std::vector<AutofillProfile * > & profiles_from_web_db,const syncer::SyncDataList & data_list,const MockAutofillProfileSyncableService::DataBundle & expected_bundle,const syncer::SyncChangeList & expected_change_list)225 void MergeDataAndStartSyncing(
226 const std::vector<AutofillProfile*>& profiles_from_web_db,
227 const syncer::SyncDataList& data_list,
228 const MockAutofillProfileSyncableService::DataBundle& expected_bundle,
229 const syncer::SyncChangeList& expected_change_list) {
230 EXPECT_CALL(autofill_syncable_service_, LoadAutofillData(_))
231 .Times(1)
232 .WillOnce(DoAll(CopyData(&profiles_from_web_db), Return(true)));
233 EXPECT_CALL(autofill_syncable_service_,
234 SaveChangesToWebData(DataBundleCheck(expected_bundle)))
235 .Times(1)
236 .WillOnce(Return(true));
237 if (expected_change_list.empty()) {
238 EXPECT_CALL(*sync_processor_, ProcessSyncChanges(_, _)).Times(0);
239 } else {
240 ON_CALL(*sync_processor_, ProcessSyncChanges(_, _))
241 .WillByDefault(Return(syncer::SyncError()));
242 EXPECT_CALL(*sync_processor_,
243 ProcessSyncChanges(_, CheckSyncChanges(expected_change_list)))
244 .Times(1)
245 .WillOnce(Return(syncer::SyncError()));
246 }
247
248 // Takes ownership of sync_processor_.
249 autofill_syncable_service_.MergeDataAndStartSyncing(
250 syncer::AUTOFILL_PROFILE, data_list,
251 sync_processor_.PassAs<syncer::SyncChangeProcessor>(),
252 scoped_ptr<syncer::SyncErrorFactory>(
253 new syncer::SyncErrorFactoryMock()));
254 }
255
256 protected:
257 base::MessageLoop message_loop_;
258 MockAutofillProfileSyncableService autofill_syncable_service_;
259 scoped_ptr<MockSyncChangeProcessor> sync_processor_;
260 };
261
TEST_F(AutofillProfileSyncableServiceTest,MergeDataAndStartSyncing)262 TEST_F(AutofillProfileSyncableServiceTest, MergeDataAndStartSyncing) {
263 std::vector<AutofillProfile*> profiles_from_web_db;
264 std::string guid_present1 = kGuid1;
265 std::string guid_present2 = kGuid2;
266 std::string guid_synced1 = kGuid3;
267 std::string guid_synced2 = kGuid4;
268 std::string origin_present1 = kHttpOrigin;
269 std::string origin_present2 = std::string();
270 std::string origin_synced1 = kHttpsOrigin;
271 std::string origin_synced2 = kSettingsOrigin;
272
273 profiles_from_web_db.push_back(
274 new AutofillProfile(guid_present1, origin_present1));
275 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
276 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
277 ASCIIToUTF16("1 1st st"));
278 profiles_from_web_db.push_back(
279 new AutofillProfile(guid_present2, origin_present2));
280 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
281 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
282 ASCIIToUTF16("2 2nd st"));
283
284 syncer::SyncDataList data_list;
285 AutofillProfile profile1(guid_synced1, origin_synced1);
286 profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
287 data_list.push_back(autofill_syncable_service_.CreateData(profile1));
288 AutofillProfile profile2(guid_synced2, origin_synced2);
289 profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Harry"));
290 data_list.push_back(autofill_syncable_service_.CreateData(profile2));
291 // This one will have the name and origin updated.
292 AutofillProfile profile3(guid_present2, origin_synced2);
293 profile3.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom Doe"));
294 data_list.push_back(autofill_syncable_service_.CreateData(profile3));
295
296 syncer::SyncChangeList expected_change_list;
297 expected_change_list.push_back(
298 syncer::SyncChange(FROM_HERE,
299 syncer::SyncChange::ACTION_ADD,
300 MockAutofillProfileSyncableService::CreateData(
301 *profiles_from_web_db.front())));
302
303 MockAutofillProfileSyncableService::DataBundle expected_bundle;
304 expected_bundle.profiles_to_add.push_back(&profile1);
305 expected_bundle.profiles_to_add.push_back(&profile2);
306 expected_bundle.profiles_to_update.push_back(&profile3);
307
308 MergeDataAndStartSyncing(
309 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
310 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
311 }
312
TEST_F(AutofillProfileSyncableServiceTest,MergeIdenticalProfiles)313 TEST_F(AutofillProfileSyncableServiceTest, MergeIdenticalProfiles) {
314 std::vector<AutofillProfile*> profiles_from_web_db;
315 std::string guid_present1 = kGuid1;
316 std::string guid_present2 = kGuid2;
317 std::string guid_synced1 = kGuid3;
318 std::string guid_synced2 = kGuid4;
319 std::string origin_present1 = kHttpOrigin;
320 std::string origin_present2 = kSettingsOrigin;
321 std::string origin_synced1 = kHttpsOrigin;
322 std::string origin_synced2 = kHttpsOrigin;
323
324 profiles_from_web_db.push_back(
325 new AutofillProfile(guid_present1, origin_present1));
326 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
327 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
328 ASCIIToUTF16("1 1st st"));
329 profiles_from_web_db.push_back(
330 new AutofillProfile(guid_present2, origin_present2));
331 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
332 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
333 ASCIIToUTF16("2 2nd st"));
334
335 // The synced profiles are identical to the local ones, except that the guids
336 // are different.
337 syncer::SyncDataList data_list;
338 AutofillProfile profile1(guid_synced1, origin_synced1);
339 profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
340 profile1.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1 1st st"));
341 data_list.push_back(autofill_syncable_service_.CreateData(profile1));
342 AutofillProfile profile2(guid_synced2, origin_synced2);
343 profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
344 profile2.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("2 2nd st"));
345 data_list.push_back(autofill_syncable_service_.CreateData(profile2));
346
347 AutofillProfile expected_profile(profile2);
348 expected_profile.set_origin(kSettingsOrigin);
349 syncer::SyncChangeList expected_change_list;
350 expected_change_list.push_back(
351 syncer::SyncChange(FROM_HERE,
352 syncer::SyncChange::ACTION_UPDATE,
353 MockAutofillProfileSyncableService::CreateData(
354 expected_profile)));
355
356 MockAutofillProfileSyncableService::DataBundle expected_bundle;
357 expected_bundle.profiles_to_delete.push_back(guid_present1);
358 expected_bundle.profiles_to_delete.push_back(guid_present2);
359 expected_bundle.profiles_to_add.push_back(&profile1);
360 expected_bundle.profiles_to_add.push_back(&expected_profile);
361
362 MergeDataAndStartSyncing(
363 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
364 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
365 }
366
TEST_F(AutofillProfileSyncableServiceTest,MergeSimilarProfiles)367 TEST_F(AutofillProfileSyncableServiceTest, MergeSimilarProfiles) {
368 std::vector<AutofillProfile*> profiles_from_web_db;
369 std::string guid_present1 = kGuid1;
370 std::string guid_present2 = kGuid2;
371 std::string guid_synced1 = kGuid3;
372 std::string guid_synced2 = kGuid4;
373 std::string origin_present1 = kHttpOrigin;
374 std::string origin_present2 = kSettingsOrigin;
375 std::string origin_synced1 = kHttpsOrigin;
376 std::string origin_synced2 = kHttpsOrigin;
377
378 profiles_from_web_db.push_back(
379 new AutofillProfile(guid_present1, origin_present1));
380 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
381 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
382 ASCIIToUTF16("1 1st st"));
383 profiles_from_web_db.push_back(
384 new AutofillProfile(guid_present2, origin_present2));
385 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
386 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
387 ASCIIToUTF16("2 2nd st"));
388
389 // The synced profiles are identical to the local ones, except that the guids
390 // are different.
391 syncer::SyncDataList data_list;
392 AutofillProfile profile1(guid_synced1, origin_synced1);
393 profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
394 profile1.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1 1st st"));
395 profile1.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Frobbers, Inc."));
396 data_list.push_back(autofill_syncable_service_.CreateData(profile1));
397 AutofillProfile profile2(guid_synced2, origin_synced2);
398 profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
399 profile2.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("2 2nd st"));
400 profile2.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Fizzbang, LLC."));
401 data_list.push_back(autofill_syncable_service_.CreateData(profile2));
402
403 // The first profile should have its origin updated.
404 // The second profile should remain as-is, because an unverified profile
405 // should never overwrite a verified one.
406 AutofillProfile expected_profile(profile1);
407 expected_profile.set_origin(origin_present1);
408 syncer::SyncChangeList expected_change_list;
409 expected_change_list.push_back(
410 syncer::SyncChange(FROM_HERE,
411 syncer::SyncChange::ACTION_ADD,
412 MockAutofillProfileSyncableService::CreateData(
413 *profiles_from_web_db.back())));
414 expected_change_list.push_back(
415 syncer::SyncChange(FROM_HERE,
416 syncer::SyncChange::ACTION_UPDATE,
417 MockAutofillProfileSyncableService::CreateData(
418 expected_profile)));
419
420 MockAutofillProfileSyncableService::DataBundle expected_bundle;
421 expected_bundle.profiles_to_delete.push_back(guid_present1);
422 expected_bundle.profiles_to_add.push_back(&expected_profile);
423 expected_bundle.profiles_to_add.push_back(&profile2);
424
425 MergeDataAndStartSyncing(
426 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
427 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
428 }
429
430 // Ensure that no Sync events are generated to fill in missing origins from Sync
431 // with explicitly present empty ones. This ensures that the migration to add
432 // origins to profiles does not generate lots of needless Sync updates.
TEST_F(AutofillProfileSyncableServiceTest,MergeDataEmptyOrigins)433 TEST_F(AutofillProfileSyncableServiceTest, MergeDataEmptyOrigins) {
434 std::vector<AutofillProfile*> profiles_from_web_db;
435
436 // Create a profile with an empty origin.
437 AutofillProfile profile(kGuid1, std::string());
438 profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
439 profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1 1st st"));
440
441 profiles_from_web_db.push_back(new AutofillProfile(profile));
442
443 // Create a Sync profile identical to |profile|, except with no origin set.
444 sync_pb::EntitySpecifics specifics;
445 sync_pb::AutofillProfileSpecifics* autofill_specifics =
446 specifics.mutable_autofill_profile();
447 autofill_specifics->set_guid(profile.guid());
448 autofill_specifics->add_name_first("John");
449 autofill_specifics->add_name_middle(std::string());
450 autofill_specifics->add_name_last(std::string());
451 autofill_specifics->add_name_full("John");
452 autofill_specifics->add_email_address(std::string());
453 autofill_specifics->add_phone_home_whole_number(std::string());
454 autofill_specifics->set_address_home_line1("1 1st st");
455 EXPECT_FALSE(autofill_specifics->has_origin());
456
457 syncer::SyncDataList data_list;
458 data_list.push_back(
459 syncer::SyncData::CreateLocalData(
460 profile.guid(), profile.guid(), specifics));
461
462 MockAutofillProfileSyncableService::DataBundle expected_bundle;
463 syncer::SyncChangeList expected_change_list;
464 MergeDataAndStartSyncing(
465 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
466 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
467 }
468
TEST_F(AutofillProfileSyncableServiceTest,GetAllSyncData)469 TEST_F(AutofillProfileSyncableServiceTest, GetAllSyncData) {
470 std::vector<AutofillProfile*> profiles_from_web_db;
471 std::string guid_present1 = kGuid1;
472 std::string guid_present2 = kGuid2;
473
474 profiles_from_web_db.push_back(
475 new AutofillProfile(guid_present1, kHttpOrigin));
476 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
477 profiles_from_web_db.push_back(
478 new AutofillProfile(guid_present2, kHttpsOrigin));
479 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
480
481 syncer::SyncChangeList expected_change_list;
482 expected_change_list.push_back(
483 syncer::SyncChange(FROM_HERE,
484 syncer::SyncChange::ACTION_ADD,
485 MockAutofillProfileSyncableService::CreateData(
486 *profiles_from_web_db.front())));
487 expected_change_list.push_back(
488 syncer::SyncChange(FROM_HERE,
489 syncer::SyncChange::ACTION_ADD,
490 MockAutofillProfileSyncableService::CreateData(
491 *profiles_from_web_db.back())));
492
493 MockAutofillProfileSyncableService::DataBundle expected_bundle;
494 syncer::SyncDataList data_list;
495 MergeDataAndStartSyncing(
496 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
497
498 syncer::SyncDataList data =
499 autofill_syncable_service_.GetAllSyncData(syncer::AUTOFILL_PROFILE);
500
501 ASSERT_EQ(2U, data.size());
502 EXPECT_EQ(guid_present1, data[0].GetSpecifics().autofill_profile().guid());
503 EXPECT_EQ(guid_present2, data[1].GetSpecifics().autofill_profile().guid());
504 EXPECT_EQ(kHttpOrigin, data[0].GetSpecifics().autofill_profile().origin());
505 EXPECT_EQ(kHttpsOrigin, data[1].GetSpecifics().autofill_profile().origin());
506
507 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
508 }
509
TEST_F(AutofillProfileSyncableServiceTest,ProcessSyncChanges)510 TEST_F(AutofillProfileSyncableServiceTest, ProcessSyncChanges) {
511 std::vector<AutofillProfile *> profiles_from_web_db;
512 std::string guid_present = kGuid1;
513 std::string guid_synced = kGuid2;
514
515 syncer::SyncChangeList change_list;
516 AutofillProfile profile(guid_synced, kHttpOrigin);
517 profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
518 change_list.push_back(
519 syncer::SyncChange(
520 FROM_HERE,
521 syncer::SyncChange::ACTION_ADD,
522 MockAutofillProfileSyncableService::CreateData(profile)));
523 AutofillProfile empty_profile(guid_present, kHttpsOrigin);
524 change_list.push_back(
525 syncer::SyncChange(
526 FROM_HERE,
527 syncer::SyncChange::ACTION_DELETE,
528 MockAutofillProfileSyncableService::CreateData(empty_profile)));
529
530 MockAutofillProfileSyncableService::DataBundle expected_bundle;
531 expected_bundle.profiles_to_delete.push_back(guid_present);
532 expected_bundle.profiles_to_add.push_back(&profile);
533
534 EXPECT_CALL(autofill_syncable_service_, SaveChangesToWebData(
535 DataBundleCheck(expected_bundle)))
536 .Times(1)
537 .WillOnce(Return(true));
538
539 autofill_syncable_service_.set_sync_processor(sync_processor_.release());
540 syncer::SyncError error = autofill_syncable_service_.ProcessSyncChanges(
541 FROM_HERE, change_list);
542
543 EXPECT_FALSE(error.IsSet());
544 }
545
TEST_F(AutofillProfileSyncableServiceTest,AutofillProfileAdded)546 TEST_F(AutofillProfileSyncableServiceTest, AutofillProfileAdded) {
547 // Will be owned by the syncable service. Keep a reference available here for
548 // verifying test expectations.
549 TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;
550 autofill_syncable_service_.set_sync_processor(sync_change_processor);
551
552 AutofillProfile profile(kGuid1, kHttpsOrigin);
553 profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
554 AutofillProfileChange change(AutofillProfileChange::ADD, kGuid1, &profile);
555 autofill_syncable_service_.AutofillProfileChanged(change);
556
557 ASSERT_EQ(1U, sync_change_processor->changes().size());
558 syncer::SyncChange result = sync_change_processor->changes()[0];
559 EXPECT_EQ(syncer::SyncChange::ACTION_ADD, result.change_type());
560
561 sync_pb::AutofillProfileSpecifics specifics =
562 result.sync_data().GetSpecifics().autofill_profile();
563 EXPECT_EQ(kGuid1, specifics.guid());
564 EXPECT_EQ(kHttpsOrigin, specifics.origin());
565 EXPECT_THAT(specifics.name_first(), testing::ElementsAre("Jane"));
566 }
567
TEST_F(AutofillProfileSyncableServiceTest,AutofillProfileDeleted)568 TEST_F(AutofillProfileSyncableServiceTest, AutofillProfileDeleted) {
569 // Will be owned by the syncable service. Keep a reference available here for
570 // verifying test expectations.
571 TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;
572 autofill_syncable_service_.set_sync_processor(sync_change_processor);
573
574 AutofillProfileChange change(AutofillProfileChange::REMOVE, kGuid2, NULL);
575 autofill_syncable_service_.AutofillProfileChanged(change);
576
577 ASSERT_EQ(1U, sync_change_processor->changes().size());
578 syncer::SyncChange result = sync_change_processor->changes()[0];
579 EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, result.change_type());
580 sync_pb::AutofillProfileSpecifics specifics =
581 result.sync_data().GetSpecifics().autofill_profile();
582 EXPECT_EQ(kGuid2, specifics.guid());
583 }
584
TEST_F(AutofillProfileSyncableServiceTest,UpdateField)585 TEST_F(AutofillProfileSyncableServiceTest, UpdateField) {
586 AutofillProfile profile(kGuid1, kSettingsOrigin);
587 std::string company1 = "A Company";
588 std::string company2 = "Another Company";
589 profile.SetRawInfo(COMPANY_NAME, ASCIIToUTF16(company1));
590 EXPECT_FALSE(AutofillProfileSyncableService::UpdateField(
591 COMPANY_NAME, company1, &profile));
592 EXPECT_EQ(profile.GetRawInfo(COMPANY_NAME), ASCIIToUTF16(company1));
593 EXPECT_TRUE(AutofillProfileSyncableService::UpdateField(
594 COMPANY_NAME, company2, &profile));
595 EXPECT_EQ(profile.GetRawInfo(COMPANY_NAME), ASCIIToUTF16(company2));
596 EXPECT_FALSE(AutofillProfileSyncableService::UpdateField(
597 COMPANY_NAME, company2, &profile));
598 EXPECT_EQ(profile.GetRawInfo(COMPANY_NAME), ASCIIToUTF16(company2));
599 }
600
TEST_F(AutofillProfileSyncableServiceTest,UpdateMultivaluedField)601 TEST_F(AutofillProfileSyncableServiceTest, UpdateMultivaluedField) {
602 AutofillProfile profile(kGuid1, kHttpsOrigin);
603
604 std::vector<base::string16> values;
605 values.push_back(ASCIIToUTF16("1@1.com"));
606 values.push_back(ASCIIToUTF16("2@1.com"));
607 profile.SetRawMultiInfo(EMAIL_ADDRESS, values);
608
609 ::google::protobuf::RepeatedPtrField<std::string> specifics_fields;
610 specifics_fields.AddAllocated(new std::string("2@1.com"));
611 specifics_fields.AddAllocated(new std::string("3@1.com"));
612
613 EXPECT_TRUE(AutofillProfileSyncableService::UpdateMultivaluedField(
614 EMAIL_ADDRESS, specifics_fields, &profile));
615 profile.GetRawMultiInfo(EMAIL_ADDRESS, &values);
616 ASSERT_TRUE(values.size() == 2);
617 EXPECT_EQ(values[0], ASCIIToUTF16("2@1.com"));
618 EXPECT_EQ(values[1], ASCIIToUTF16("3@1.com"));
619
620 EXPECT_FALSE(AutofillProfileSyncableService::UpdateMultivaluedField(
621 EMAIL_ADDRESS, specifics_fields, &profile));
622 profile.GetRawMultiInfo(EMAIL_ADDRESS, &values);
623 ASSERT_EQ(values.size(), 2U);
624 EXPECT_EQ(values[0], ASCIIToUTF16("2@1.com"));
625 EXPECT_EQ(values[1], ASCIIToUTF16("3@1.com"));
626 EXPECT_TRUE(AutofillProfileSyncableService::UpdateMultivaluedField(
627 EMAIL_ADDRESS, ::google::protobuf::RepeatedPtrField<std::string>(),
628 &profile));
629 profile.GetRawMultiInfo(EMAIL_ADDRESS, &values);
630 ASSERT_EQ(values.size(), 1U); // Always have at least an empty string.
631 EXPECT_EQ(values[0], ASCIIToUTF16(""));
632 }
633
TEST_F(AutofillProfileSyncableServiceTest,MergeProfile)634 TEST_F(AutofillProfileSyncableServiceTest, MergeProfile) {
635 AutofillProfile profile1(kGuid1, kHttpOrigin);
636 profile1.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("111 First St."));
637
638 std::vector<base::string16> values;
639 values.push_back(ASCIIToUTF16("1@1.com"));
640 values.push_back(ASCIIToUTF16("2@1.com"));
641 profile1.SetRawMultiInfo(EMAIL_ADDRESS, values);
642
643 AutofillProfile profile2(kGuid2, kHttpsOrigin);
644 profile2.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("111 First St."));
645
646 // |values| now is [ "1@1.com", "2@1.com", "3@1.com" ].
647 values.push_back(ASCIIToUTF16("3@1.com"));
648 profile2.SetRawMultiInfo(EMAIL_ADDRESS, values);
649
650 values.clear();
651 values.push_back(ASCIIToUTF16("John"));
652 profile1.SetRawMultiInfo(NAME_FIRST, values);
653 values.push_back(ASCIIToUTF16("Jane"));
654 profile2.SetRawMultiInfo(NAME_FIRST, values);
655
656 values.clear();
657 values.push_back(ASCIIToUTF16("Doe"));
658 profile1.SetRawMultiInfo(NAME_LAST, values);
659 values.push_back(ASCIIToUTF16("Other"));
660 profile2.SetRawMultiInfo(NAME_LAST, values);
661
662 values.clear();
663 values.push_back(ASCIIToUTF16("650234567"));
664 profile2.SetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, values);
665
666 profile1.set_language_code("en");
667
668 EXPECT_FALSE(AutofillProfileSyncableService::MergeProfile(profile2,
669 &profile1,
670 "en-US"));
671
672 profile1.GetRawMultiInfo(NAME_FIRST, &values);
673 ASSERT_EQ(values.size(), 2U);
674 EXPECT_EQ(values[0], ASCIIToUTF16("John"));
675 EXPECT_EQ(values[1], ASCIIToUTF16("Jane"));
676
677 profile1.GetRawMultiInfo(NAME_LAST, &values);
678 ASSERT_EQ(values.size(), 2U);
679 EXPECT_EQ(values[0], ASCIIToUTF16("Doe"));
680 EXPECT_EQ(values[1], ASCIIToUTF16("Other"));
681
682 profile1.GetRawMultiInfo(EMAIL_ADDRESS, &values);
683 ASSERT_EQ(values.size(), 3U);
684 EXPECT_EQ(values[0], ASCIIToUTF16("1@1.com"));
685 EXPECT_EQ(values[1], ASCIIToUTF16("2@1.com"));
686 EXPECT_EQ(values[2], ASCIIToUTF16("3@1.com"));
687
688 profile1.GetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, &values);
689 ASSERT_EQ(values.size(), 1U);
690 EXPECT_EQ(values[0], ASCIIToUTF16("650234567"));
691
692 EXPECT_EQ(profile2.origin(), profile1.origin());
693
694 AutofillProfile profile3(kGuid3, kHttpOrigin);
695 profile3.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("111 First St."));
696
697 values.clear();
698 values.push_back(ASCIIToUTF16("Jane"));
699 profile3.SetRawMultiInfo(NAME_FIRST, values);
700
701 values.clear();
702 values.push_back(ASCIIToUTF16("Doe"));
703 profile3.SetRawMultiInfo(NAME_LAST, values);
704
705 EXPECT_TRUE(AutofillProfileSyncableService::MergeProfile(profile3,
706 &profile1,
707 "en-US"));
708
709 profile1.GetRawMultiInfo(NAME_FIRST, &values);
710 ASSERT_EQ(values.size(), 3U);
711 EXPECT_EQ(values[0], ASCIIToUTF16("John"));
712 EXPECT_EQ(values[1], ASCIIToUTF16("Jane"));
713 EXPECT_EQ(values[2], ASCIIToUTF16("Jane"));
714
715 profile1.GetRawMultiInfo(NAME_LAST, &values);
716 ASSERT_EQ(values.size(), 3U);
717 EXPECT_EQ(values[0], ASCIIToUTF16("Doe"));
718 EXPECT_EQ(values[1], ASCIIToUTF16("Other"));
719 EXPECT_EQ(values[2], ASCIIToUTF16("Doe"));
720
721 // Middle name should have three entries as well.
722 profile1.GetRawMultiInfo(NAME_MIDDLE, &values);
723 ASSERT_EQ(values.size(), 3U);
724 EXPECT_TRUE(values[0].empty());
725 EXPECT_TRUE(values[1].empty());
726 EXPECT_TRUE(values[2].empty());
727
728 profile1.GetRawMultiInfo(EMAIL_ADDRESS, &values);
729 ASSERT_EQ(values.size(), 3U);
730 EXPECT_EQ(values[0], ASCIIToUTF16("1@1.com"));
731 EXPECT_EQ(values[1], ASCIIToUTF16("2@1.com"));
732 EXPECT_EQ(values[2], ASCIIToUTF16("3@1.com"));
733
734 profile1.GetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, &values);
735 ASSERT_EQ(values.size(), 1U);
736 EXPECT_EQ(values[0], ASCIIToUTF16("650234567"));
737 }
738
739 // Ensure that all profile fields are able to be synced up from the client to
740 // the server.
TEST_F(AutofillProfileSyncableServiceTest,SyncAllFieldsToServer)741 TEST_F(AutofillProfileSyncableServiceTest, SyncAllFieldsToServer) {
742 std::vector<AutofillProfile*> profiles_from_web_db;
743
744 // Create a profile with all fields set.
745 profiles_from_web_db.push_back(ConstructCompleteProfile().release());
746
747 // Set up expectations: No changes to the WebDB, and all fields correctly
748 // copied to Sync.
749 MockAutofillProfileSyncableService::DataBundle expected_bundle;
750 syncer::SyncChangeList expected_change_list;
751 expected_change_list.push_back(
752 syncer::SyncChange(FROM_HERE,
753 syncer::SyncChange::ACTION_ADD,
754 ConstructCompleteSyncData()));
755
756 // Verify the expectations.
757 syncer::SyncDataList data_list;
758 MergeDataAndStartSyncing(
759 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
760 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
761 }
762
763 // Ensure that all profile fields are able to be synced down from the server to
764 // the client.
TEST_F(AutofillProfileSyncableServiceTest,SyncAllFieldsToClient)765 TEST_F(AutofillProfileSyncableServiceTest, SyncAllFieldsToClient) {
766 // Create a profile with all fields set.
767 syncer::SyncDataList data_list;
768 data_list.push_back(ConstructCompleteSyncData());
769
770 // Set up expectations: All fields correctly copied to the WebDB, and no
771 // changes propagated to Sync.
772 syncer::SyncChangeList expected_change_list;
773 scoped_ptr<AutofillProfile> expected_profile = ConstructCompleteProfile();
774 MockAutofillProfileSyncableService::DataBundle expected_bundle;
775 expected_bundle.profiles_to_add.push_back(expected_profile.get());
776
777 // Verify the expectations.
778 std::vector<AutofillProfile*> profiles_from_web_db;
779 MergeDataAndStartSyncing(
780 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
781 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
782 }
783
784 // Ensure that the street address field takes precedence over the address line 1
785 // and line 2 fields, even though these are expected to always be in sync in
786 // practice.
TEST_F(AutofillProfileSyncableServiceTest,StreetAddressTakesPrecedenceOverAddressLines)787 TEST_F(AutofillProfileSyncableServiceTest,
788 StreetAddressTakesPrecedenceOverAddressLines) {
789 // Create a Sync profile with conflicting address data in the street address
790 // field vs. the address line 1 and address line 2 fields.
791 sync_pb::EntitySpecifics specifics;
792 sync_pb::AutofillProfileSpecifics* autofill_specifics =
793 specifics.mutable_autofill_profile();
794 autofill_specifics->set_guid(kGuid1);
795 autofill_specifics->set_origin(kHttpsOrigin);
796 autofill_specifics->add_name_first(std::string());
797 autofill_specifics->add_name_middle(std::string());
798 autofill_specifics->add_name_last(std::string());
799 autofill_specifics->add_email_address(std::string());
800 autofill_specifics->add_phone_home_whole_number(std::string());
801 autofill_specifics->set_address_home_line1("123 Example St.");
802 autofill_specifics->set_address_home_line2("Apt. 42");
803 autofill_specifics->set_address_home_street_address("456 El Camino Real\n"
804 "Suite #1337");
805
806 syncer::SyncDataList data_list;
807 data_list.push_back(
808 syncer::SyncData::CreateLocalData(kGuid1, kGuid1, specifics));
809
810 // Set up expectations: Full street address takes precedence over address
811 // lines.
812 syncer::SyncChangeList expected_change_list;
813 AutofillProfile expected_profile(kGuid1, kHttpsOrigin);
814 expected_profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS,
815 ASCIIToUTF16("456 El Camino Real\n"
816 "Suite #1337"));
817 EXPECT_EQ(ASCIIToUTF16("456 El Camino Real"),
818 expected_profile.GetRawInfo(ADDRESS_HOME_LINE1));
819 EXPECT_EQ(ASCIIToUTF16("Suite #1337"),
820 expected_profile.GetRawInfo(ADDRESS_HOME_LINE2));
821 MockAutofillProfileSyncableService::DataBundle expected_bundle;
822 expected_bundle.profiles_to_add.push_back(&expected_profile);
823
824 // Verify the expectations.
825 std::vector<AutofillProfile*> profiles_from_web_db;
826 MergeDataAndStartSyncing(
827 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
828 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
829 }
830
831 // Ensure that no Sync events are generated to fill in missing street address
832 // fields from Sync with explicitly present ones identical to the data stored in
833 // the line1 and line2 fields. This ensures that the migration to add the
834 // street address field to profiles does not generate lots of needless Sync
835 // updates.
TEST_F(AutofillProfileSyncableServiceTest,MergeDataEmptyStreetAddress)836 TEST_F(AutofillProfileSyncableServiceTest, MergeDataEmptyStreetAddress) {
837 std::vector<AutofillProfile*> profiles_from_web_db;
838
839 // Create a profile with the street address set.
840 AutofillProfile profile(kGuid1, kHttpsOrigin);
841 profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS,
842 ASCIIToUTF16("123 Example St.\n"
843 "Apt. 42"));
844 EXPECT_EQ(ASCIIToUTF16("123 Example St."),
845 profile.GetRawInfo(ADDRESS_HOME_LINE1));
846 EXPECT_EQ(ASCIIToUTF16("Apt. 42"), profile.GetRawInfo(ADDRESS_HOME_LINE2));
847
848 profiles_from_web_db.push_back(new AutofillProfile(profile));
849
850 // Create a Sync profile identical to |profile|, except without street address
851 // explicitly set.
852 sync_pb::EntitySpecifics specifics;
853 sync_pb::AutofillProfileSpecifics* autofill_specifics =
854 specifics.mutable_autofill_profile();
855 autofill_specifics->set_guid(profile.guid());
856 autofill_specifics->set_origin(profile.origin());
857 autofill_specifics->add_name_first(std::string());
858 autofill_specifics->add_name_middle(std::string());
859 autofill_specifics->add_name_last(std::string());
860 autofill_specifics->add_name_full(std::string());
861 autofill_specifics->add_email_address(std::string());
862 autofill_specifics->add_phone_home_whole_number(std::string());
863 autofill_specifics->set_address_home_line1("123 Example St.");
864 autofill_specifics->set_address_home_line2("Apt. 42");
865 EXPECT_FALSE(autofill_specifics->has_address_home_street_address());
866
867 syncer::SyncDataList data_list;
868 data_list.push_back(
869 syncer::SyncData::CreateLocalData(
870 profile.guid(), profile.guid(), specifics));
871
872 MockAutofillProfileSyncableService::DataBundle expected_bundle;
873 syncer::SyncChangeList expected_change_list;
874 MergeDataAndStartSyncing(
875 profiles_from_web_db, data_list, expected_bundle, expected_change_list);
876 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
877 }
878
879 // Sync data without origin should not overwrite existing origin in local
880 // autofill profile.
TEST_F(AutofillProfileSyncableServiceTest,EmptySyncPreservesOrigin)881 TEST_F(AutofillProfileSyncableServiceTest, EmptySyncPreservesOrigin) {
882 std::vector<AutofillProfile*> profiles_from_web_db;
883
884 // Local autofill profile has an origin.
885 AutofillProfile profile(kGuid1, kHttpsOrigin);
886 profiles_from_web_db.push_back(new AutofillProfile(profile));
887
888 // Remote data does not have an origin value.
889 sync_pb::EntitySpecifics specifics;
890 sync_pb::AutofillProfileSpecifics* autofill_specifics =
891 specifics.mutable_autofill_profile();
892 autofill_specifics->set_guid(profile.guid());
893 autofill_specifics->add_name_first("John");
894 autofill_specifics->add_name_middle(std::string());
895 autofill_specifics->add_name_last(std::string());
896 autofill_specifics->add_name_full("John");
897 autofill_specifics->add_email_address(std::string());
898 autofill_specifics->add_phone_home_whole_number(std::string());
899 EXPECT_FALSE(autofill_specifics->has_origin());
900
901 syncer::SyncDataList data_list;
902 data_list.push_back(
903 syncer::SyncData::CreateLocalData(
904 profile.guid(), profile.guid(), specifics));
905
906 // Expect the local autofill profile to still have an origin after sync.
907 MockAutofillProfileSyncableService::DataBundle expected_bundle;
908 AutofillProfile expected_profile(profile.guid(), profile.origin());
909 expected_profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
910 expected_bundle.profiles_to_update.push_back(&expected_profile);
911
912 // Expect no sync events to add origin to the remote data.
913 syncer::SyncChangeList expected_empty_change_list;
914
915 MergeDataAndStartSyncing(profiles_from_web_db, data_list,
916 expected_bundle, expected_empty_change_list);
917 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
918 }
919
920 // Missing language code field should not generate sync events.
TEST_F(AutofillProfileSyncableServiceTest,NoLanguageCodeNoSync)921 TEST_F(AutofillProfileSyncableServiceTest, NoLanguageCodeNoSync) {
922 std::vector<AutofillProfile*> profiles_from_web_db;
923
924 // Local autofill profile has an empty language code.
925 AutofillProfile profile(kGuid1, kHttpsOrigin);
926 EXPECT_TRUE(profile.language_code().empty());
927 profiles_from_web_db.push_back(new AutofillProfile(profile));
928
929 // Remote data does not have a language code value.
930 sync_pb::EntitySpecifics specifics;
931 sync_pb::AutofillProfileSpecifics* autofill_specifics =
932 specifics.mutable_autofill_profile();
933 autofill_specifics->set_guid(profile.guid());
934 autofill_specifics->set_origin(profile.origin());
935 autofill_specifics->add_name_first(std::string());
936 autofill_specifics->add_name_middle(std::string());
937 autofill_specifics->add_name_last(std::string());
938 autofill_specifics->add_name_full(std::string());
939 autofill_specifics->add_email_address(std::string());
940 autofill_specifics->add_phone_home_whole_number(std::string());
941 EXPECT_FALSE(autofill_specifics->has_address_home_language_code());
942
943 syncer::SyncDataList data_list;
944 data_list.push_back(
945 syncer::SyncData::CreateLocalData(
946 profile.guid(), profile.guid(), specifics));
947
948 // Expect no changes to local and remote data.
949 MockAutofillProfileSyncableService::DataBundle expected_empty_bundle;
950 syncer::SyncChangeList expected_empty_change_list;
951
952 MergeDataAndStartSyncing(profiles_from_web_db, data_list,
953 expected_empty_bundle, expected_empty_change_list);
954 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
955 }
956
957 // Empty language code should be overwritten by sync.
TEST_F(AutofillProfileSyncableServiceTest,SyncUpdatesEmptyLanguageCode)958 TEST_F(AutofillProfileSyncableServiceTest, SyncUpdatesEmptyLanguageCode) {
959 std::vector<AutofillProfile*> profiles_from_web_db;
960
961 // Local autofill profile has an empty language code.
962 AutofillProfile profile(kGuid1, kHttpsOrigin);
963 EXPECT_TRUE(profile.language_code().empty());
964 profiles_from_web_db.push_back(new AutofillProfile(profile));
965
966 // Remote data has "en" language code.
967 sync_pb::EntitySpecifics specifics;
968 sync_pb::AutofillProfileSpecifics* autofill_specifics =
969 specifics.mutable_autofill_profile();
970 autofill_specifics->set_guid(profile.guid());
971 autofill_specifics->set_origin(profile.origin());
972 autofill_specifics->add_name_first(std::string());
973 autofill_specifics->add_name_middle(std::string());
974 autofill_specifics->add_name_last(std::string());
975 autofill_specifics->add_name_full(std::string());
976 autofill_specifics->add_email_address(std::string());
977 autofill_specifics->add_phone_home_whole_number(std::string());
978 autofill_specifics->set_address_home_language_code("en");
979 EXPECT_TRUE(autofill_specifics->has_address_home_language_code());
980
981 syncer::SyncDataList data_list;
982 data_list.push_back(
983 syncer::SyncData::CreateLocalData(
984 profile.guid(), profile.guid(), specifics));
985
986 // Expect the local autofill profile to have "en" language code after sync.
987 MockAutofillProfileSyncableService::DataBundle expected_bundle;
988 AutofillProfile expected_profile(kGuid1, kHttpsOrigin);
989 expected_profile.set_language_code("en");
990 expected_bundle.profiles_to_update.push_back(&expected_profile);
991
992 // Expect not changes to remote data.
993 syncer::SyncChangeList expected_empty_change_list;
994
995 MergeDataAndStartSyncing(profiles_from_web_db, data_list,
996 expected_bundle, expected_empty_change_list);
997 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
998 }
999
1000 // Incorrect language code should be overwritten by sync.
TEST_F(AutofillProfileSyncableServiceTest,SyncUpdatesIncorrectLanguageCode)1001 TEST_F(AutofillProfileSyncableServiceTest, SyncUpdatesIncorrectLanguageCode) {
1002 std::vector<AutofillProfile*> profiles_from_web_db;
1003
1004 // Local autofill profile has "de" language code.
1005 AutofillProfile profile(kGuid1, kHttpsOrigin);
1006 profile.set_language_code("de");
1007 profiles_from_web_db.push_back(new AutofillProfile(profile));
1008
1009 // Remote data has "en" language code.
1010 sync_pb::EntitySpecifics specifics;
1011 sync_pb::AutofillProfileSpecifics* autofill_specifics =
1012 specifics.mutable_autofill_profile();
1013 autofill_specifics->set_guid(profile.guid());
1014 autofill_specifics->set_origin(profile.origin());
1015 autofill_specifics->add_name_first(std::string());
1016 autofill_specifics->add_name_middle(std::string());
1017 autofill_specifics->add_name_last(std::string());
1018 autofill_specifics->add_name_full(std::string());
1019 autofill_specifics->add_email_address(std::string());
1020 autofill_specifics->add_phone_home_whole_number(std::string());
1021 autofill_specifics->set_address_home_language_code("en");
1022 EXPECT_TRUE(autofill_specifics->has_address_home_language_code());
1023
1024 syncer::SyncDataList data_list;
1025 data_list.push_back(
1026 syncer::SyncData::CreateLocalData(
1027 profile.guid(), profile.guid(), specifics));
1028
1029 // Expect the local autofill profile to have "en" language code after sync.
1030 MockAutofillProfileSyncableService::DataBundle expected_bundle;
1031 AutofillProfile expected_profile(kGuid1, kHttpsOrigin);
1032 expected_profile.set_language_code("en");
1033 expected_bundle.profiles_to_update.push_back(&expected_profile);
1034
1035 // Expect no changes to remote data.
1036 syncer::SyncChangeList expected_empty_change_list;
1037
1038 MergeDataAndStartSyncing(profiles_from_web_db, data_list,
1039 expected_bundle, expected_empty_change_list);
1040 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
1041 }
1042
1043 // Sync data without language code should not overwrite existing language code
1044 // in local autofill profile.
TEST_F(AutofillProfileSyncableServiceTest,EmptySyncPreservesLanguageCode)1045 TEST_F(AutofillProfileSyncableServiceTest, EmptySyncPreservesLanguageCode) {
1046 std::vector<AutofillProfile*> profiles_from_web_db;
1047
1048 // Local autofill profile has "en" language code.
1049 AutofillProfile profile(kGuid1, kHttpsOrigin);
1050 profile.set_language_code("en");
1051 profiles_from_web_db.push_back(new AutofillProfile(profile));
1052
1053 // Remote data does not have a language code value.
1054 sync_pb::EntitySpecifics specifics;
1055 sync_pb::AutofillProfileSpecifics* autofill_specifics =
1056 specifics.mutable_autofill_profile();
1057 autofill_specifics->set_guid(profile.guid());
1058 autofill_specifics->set_origin(profile.origin());
1059 autofill_specifics->add_name_first("John");
1060 autofill_specifics->add_name_middle(std::string());
1061 autofill_specifics->add_name_last(std::string());
1062 autofill_specifics->add_name_full("John");
1063 autofill_specifics->add_email_address(std::string());
1064 autofill_specifics->add_phone_home_whole_number(std::string());
1065 EXPECT_FALSE(autofill_specifics->has_address_home_language_code());
1066
1067 syncer::SyncDataList data_list;
1068 data_list.push_back(
1069 syncer::SyncData::CreateLocalData(
1070 profile.guid(), profile.guid(), specifics));
1071
1072 // Expect local autofill profile to still have "en" language code after sync.
1073 MockAutofillProfileSyncableService::DataBundle expected_bundle;
1074 AutofillProfile expected_profile(profile.guid(), profile.origin());
1075 expected_profile.set_language_code("en");
1076 expected_profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
1077 expected_bundle.profiles_to_update.push_back(&expected_profile);
1078
1079 // Expect no changes to remote data.
1080 syncer::SyncChangeList expected_empty_change_list;
1081
1082 MergeDataAndStartSyncing(profiles_from_web_db, data_list,
1083 expected_bundle, expected_empty_change_list);
1084 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
1085 }
1086
1087 // Language code in autofill profiles should be synced to the server.
TEST_F(AutofillProfileSyncableServiceTest,LanguageCodePropagates)1088 TEST_F(AutofillProfileSyncableServiceTest, LanguageCodePropagates) {
1089 TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;
1090 autofill_syncable_service_.set_sync_processor(sync_change_processor);
1091
1092 AutofillProfile profile(kGuid1, kHttpsOrigin);
1093 profile.set_language_code("en");
1094 AutofillProfileChange change(AutofillProfileChange::ADD, kGuid1, &profile);
1095 autofill_syncable_service_.AutofillProfileChanged(change);
1096
1097 ASSERT_EQ(1U, sync_change_processor->changes().size());
1098 syncer::SyncChange result = sync_change_processor->changes()[0];
1099 EXPECT_EQ(syncer::SyncChange::ACTION_ADD, result.change_type());
1100
1101 sync_pb::AutofillProfileSpecifics specifics =
1102 result.sync_data().GetSpecifics().autofill_profile();
1103 EXPECT_EQ(kGuid1, specifics.guid());
1104 EXPECT_EQ(kHttpsOrigin, specifics.origin());
1105 EXPECT_EQ("en", specifics.address_home_language_code());
1106 }
1107
1108 // Missing full name field should not generate sync events.
TEST_F(AutofillProfileSyncableServiceTest,NoFullNameNoSync)1109 TEST_F(AutofillProfileSyncableServiceTest, NoFullNameNoSync) {
1110 std::vector<AutofillProfile*> profiles_from_web_db;
1111
1112 // Local autofill profile has an empty full name.
1113 AutofillProfile profile(kGuid1, kHttpsOrigin);
1114 profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
1115 profiles_from_web_db.push_back(new AutofillProfile(profile));
1116
1117 // Remote data does not have a full name.
1118 sync_pb::EntitySpecifics specifics;
1119 sync_pb::AutofillProfileSpecifics* autofill_specifics =
1120 specifics.mutable_autofill_profile();
1121 autofill_specifics->set_guid(profile.guid());
1122 autofill_specifics->set_origin(profile.origin());
1123 autofill_specifics->add_name_first(std::string("John"));
1124 autofill_specifics->add_name_middle(std::string());
1125 autofill_specifics->add_name_last(std::string());
1126 autofill_specifics->add_email_address(std::string());
1127 autofill_specifics->add_phone_home_whole_number(std::string());
1128
1129 syncer::SyncDataList data_list;
1130 data_list.push_back(
1131 syncer::SyncData::CreateLocalData(
1132 profile.guid(), profile.guid(), specifics));
1133
1134 // Expect no changes to local and remote data.
1135 MockAutofillProfileSyncableService::DataBundle expected_empty_bundle;
1136 syncer::SyncChangeList expected_empty_change_list;
1137
1138 MergeDataAndStartSyncing(profiles_from_web_db, data_list,
1139 expected_empty_bundle, expected_empty_change_list);
1140 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
1141 }
1142
TEST_F(AutofillProfileSyncableServiceTest,EmptySyncPreservesFullName)1143 TEST_F(AutofillProfileSyncableServiceTest, EmptySyncPreservesFullName) {
1144 std::vector<AutofillProfile*> profiles_from_web_db;
1145
1146 // Local autofill profile has a full name.
1147 AutofillProfile profile(kGuid1, kHttpsOrigin);
1148 profile.SetRawInfo(NAME_FULL, ASCIIToUTF16("John Jacob Smith, Jr"));
1149 profiles_from_web_db.push_back(new AutofillProfile(profile));
1150
1151 // Remote data does not have a full name value.
1152 sync_pb::EntitySpecifics specifics;
1153 sync_pb::AutofillProfileSpecifics* autofill_specifics =
1154 specifics.mutable_autofill_profile();
1155 autofill_specifics->set_guid(profile.guid());
1156 autofill_specifics->set_origin(profile.origin());
1157 autofill_specifics->add_name_first(std::string("John"));
1158 autofill_specifics->add_name_middle(std::string("Jacob"));
1159 autofill_specifics->add_name_last(std::string("Smith"));
1160
1161 syncer::SyncDataList data_list;
1162 data_list.push_back(
1163 syncer::SyncData::CreateLocalData(
1164 profile.guid(), profile.guid(), specifics));
1165
1166 // Expect local autofill profile to still have the same full name after sync.
1167 MockAutofillProfileSyncableService::DataBundle expected_bundle;
1168 AutofillProfile expected_profile(profile.guid(), profile.origin());
1169 expected_profile.SetRawInfo(NAME_FULL, ASCIIToUTF16("John Jacob Smith, Jr"));
1170 expected_bundle.profiles_to_update.push_back(&expected_profile);
1171
1172 // Expect no changes to remote data.
1173 syncer::SyncChangeList expected_empty_change_list;
1174
1175 MergeDataAndStartSyncing(profiles_from_web_db, data_list,
1176 expected_bundle, expected_empty_change_list);
1177 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
1178 }
1179
1180 } // namespace autofill
1181