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