autofill_profile_syncable_service_unittest.cc revision 6d86b77056ed63eb6871182f42a9fd5f07550f90
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 17namespace autofill { 18 19using ::testing::_; 20using ::testing::DoAll; 21using ::testing::Eq; 22using ::testing::Return; 23using ::testing::Property; 24using base::ASCIIToUTF16; 25 26namespace { 27 28// Some guids for testing. 29const char kGuid1[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44B"; 30const char kGuid2[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44C"; 31const char kGuid3[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44D"; 32const char kGuid4[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44E"; 33const char kHttpOrigin[] = "http://www.example.com/"; 34const char kHttpsOrigin[] = "https://www.example.com/"; 35const char kSettingsOrigin[] = "Chrome settings"; 36 37class 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 52ACTION_P(CopyData, data) { 53 arg0->resize(data->size()); 54 std::copy(data->begin(), data->end(), arg0->begin()); 55} 56 57MATCHER_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 75MATCHER_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 95class 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 107class 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(). 132scoped_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(). 172syncer::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 215class AutofillProfileSyncableServiceTest : public testing::Test { 216 public: 217 AutofillProfileSyncableServiceTest() {} 218 219 virtual void SetUp() OVERRIDE { 220 sync_processor_.reset(new MockSyncChangeProcessor); 221 } 222 223 // Wrapper around AutofillProfileSyncableService::MergeDataAndStartSyncing() 224 // that also verifies expectations. 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 262TEST_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 313TEST_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 367TEST_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. 433TEST_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 469TEST_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 510TEST_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 546TEST_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 568TEST_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 585TEST_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 601TEST_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 634TEST_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. 741TEST_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. 765TEST_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. 787TEST_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. 836TEST_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. 881TEST_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. 921TEST_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. 958TEST_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. 1001TEST_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. 1045TEST_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. 1088TEST_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. 1109TEST_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 1143TEST_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