autofill_profile_syncable_service_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 "content/public/test/test_browser_thread.h" 12#include "sync/api/sync_error_factory.h" 13#include "sync/api/sync_error_factory_mock.h" 14#include "sync/protocol/sync.pb.h" 15#include "testing/gmock/include/gmock/gmock.h" 16#include "testing/gtest/include/gtest/gtest.h" 17 18namespace autofill { 19 20using ::testing::_; 21using ::testing::DoAll; 22using ::testing::Eq; 23using ::testing::Return; 24using ::testing::Property; 25using base::ASCIIToUTF16; 26using content::BrowserThread; 27 28namespace { 29 30// Some guids for testing. 31const char kGuid1[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44B"; 32const char kGuid2[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44C"; 33const char kGuid3[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44D"; 34const char kGuid4[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44E"; 35const char kHttpOrigin[] = "http://www.example.com/"; 36const char kHttpsOrigin[] = "https://www.example.com/"; 37const char kSettingsOrigin[] = "Chrome settings"; 38 39class MockAutofillProfileSyncableService 40 : public AutofillProfileSyncableService { 41 public: 42 MockAutofillProfileSyncableService() {} 43 virtual ~MockAutofillProfileSyncableService() {} 44 45 using AutofillProfileSyncableService::DataBundle; 46 using AutofillProfileSyncableService::set_sync_processor; 47 using AutofillProfileSyncableService::CreateData; 48 49 MOCK_METHOD1(LoadAutofillData, bool(std::vector<AutofillProfile*>*)); 50 MOCK_METHOD1(SaveChangesToWebData, 51 bool(const AutofillProfileSyncableService::DataBundle&)); 52}; 53 54ACTION_P(CopyData, data) { 55 arg0->resize(data->size()); 56 std::copy(data->begin(), data->end(), arg0->begin()); 57} 58 59MATCHER_P(CheckSyncChanges, n_sync_changes_list, "") { 60 if (arg.size() != n_sync_changes_list.size()) 61 return false; 62 syncer::SyncChangeList::const_iterator passed, expected; 63 for (passed = arg.begin(), expected = n_sync_changes_list.begin(); 64 passed != arg.end() && expected != n_sync_changes_list.end(); 65 ++passed, ++expected) { 66 DCHECK(passed->IsValid()); 67 if (passed->change_type() != expected->change_type()) 68 return false; 69 if (passed->sync_data().GetSpecifics().SerializeAsString() != 70 expected->sync_data().GetSpecifics().SerializeAsString()) { 71 return false; 72 } 73 } 74 return true; 75} 76 77MATCHER_P(DataBundleCheck, n_bundle, "") { 78 if ((arg.profiles_to_delete.size() != n_bundle.profiles_to_delete.size()) || 79 (arg.profiles_to_update.size() != n_bundle.profiles_to_update.size()) || 80 (arg.profiles_to_add.size() != n_bundle.profiles_to_add.size())) 81 return false; 82 for (size_t i = 0; i < arg.profiles_to_delete.size(); ++i) { 83 if (arg.profiles_to_delete[i] != n_bundle.profiles_to_delete[i]) 84 return false; 85 } 86 for (size_t i = 0; i < arg.profiles_to_update.size(); ++i) { 87 if (*arg.profiles_to_update[i] != *n_bundle.profiles_to_update[i]) 88 return false; 89 } 90 for (size_t i = 0; i < arg.profiles_to_add.size(); ++i) { 91 if (*arg.profiles_to_add[i] != *n_bundle.profiles_to_add[i]) 92 return false; 93 } 94 return true; 95} 96 97class MockSyncChangeProcessor : public syncer::SyncChangeProcessor { 98 public: 99 MockSyncChangeProcessor() {} 100 virtual ~MockSyncChangeProcessor() {} 101 102 MOCK_METHOD2(ProcessSyncChanges, 103 syncer::SyncError(const tracked_objects::Location&, 104 const syncer::SyncChangeList&)); 105 virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) 106 const OVERRIDE { return syncer::SyncDataList(); } 107}; 108 109class TestSyncChangeProcessor : public syncer::SyncChangeProcessor { 110 public: 111 TestSyncChangeProcessor() {} 112 virtual ~TestSyncChangeProcessor() {} 113 114 virtual syncer::SyncError ProcessSyncChanges( 115 const tracked_objects::Location& location, 116 const syncer::SyncChangeList& changes) OVERRIDE { 117 changes_ = changes; 118 return syncer::SyncError(); 119 } 120 121 virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const 122 OVERRIDE { 123 return syncer::SyncDataList(); 124 } 125 126 const syncer::SyncChangeList& changes() { return changes_; } 127 128 private: 129 syncer::SyncChangeList changes_; 130}; 131 132// Returns a profile with all fields set. Contains identical data to the data 133// returned from ConstructCompleteSyncData(). 134scoped_ptr<AutofillProfile> ConstructCompleteProfile() { 135 scoped_ptr<AutofillProfile> profile( 136 new AutofillProfile(kGuid1, kHttpsOrigin)); 137 138 std::vector<base::string16> names; 139 names.push_back(ASCIIToUTF16("John K. Doe")); 140 names.push_back(ASCIIToUTF16("Jane Luise Smith")); 141 profile->SetRawMultiInfo(NAME_FULL, names); 142 143 std::vector<base::string16> emails; 144 emails.push_back(ASCIIToUTF16("user@example.com")); 145 emails.push_back(ASCIIToUTF16("superuser@example.org")); 146 profile->SetRawMultiInfo(EMAIL_ADDRESS, emails); 147 148 std::vector<base::string16> phones; 149 phones.push_back(ASCIIToUTF16("1.800.555.1234")); 150 phones.push_back(ASCIIToUTF16("1.866.650.0000")); 151 profile->SetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, phones); 152 153 profile->SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, 154 ASCIIToUTF16("123 Fake St.\n" 155 "Apt. 42")); 156 EXPECT_EQ(ASCIIToUTF16("123 Fake St."), 157 profile->GetRawInfo(ADDRESS_HOME_LINE1)); 158 EXPECT_EQ(ASCIIToUTF16("Apt. 42"), profile->GetRawInfo(ADDRESS_HOME_LINE2)); 159 160 profile->SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Google, Inc.")); 161 profile->SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("Mountain View")); 162 profile->SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("California")); 163 profile->SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("94043")); 164 profile->SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("US")); 165 profile->SetRawInfo(ADDRESS_HOME_SORTING_CODE, ASCIIToUTF16("CEDEX")); 166 profile->SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY, 167 ASCIIToUTF16("Santa Clara")); 168 return profile.Pass(); 169} 170 171// Returns SyncData with all Autofill profile fields set. Contains identical 172// data to the data returned from ConstructCompleteProfile(). 173syncer::SyncData ConstructCompleteSyncData() { 174 sync_pb::EntitySpecifics entity_specifics; 175 sync_pb::AutofillProfileSpecifics* specifics = 176 entity_specifics.mutable_autofill_profile(); 177 178 specifics->set_guid(kGuid1); 179 specifics->set_origin(kHttpsOrigin); 180 181 specifics->add_name_first("John"); 182 specifics->add_name_middle("K."); 183 specifics->add_name_last("Doe"); 184 185 specifics->add_name_first("Jane"); 186 specifics->add_name_middle("Luise"); 187 specifics->add_name_last("Smith"); 188 189 specifics->add_email_address("user@example.com"); 190 specifics->add_email_address("superuser@example.org"); 191 192 specifics->add_phone_home_whole_number("1.800.555.1234"); 193 specifics->add_phone_home_whole_number("1.866.650.0000"); 194 195 specifics->set_address_home_line1("123 Fake St."); 196 specifics->set_address_home_line2("Apt. 42"); 197 specifics->set_address_home_street_address("123 Fake St.\n" 198 "Apt. 42"); 199 200 specifics->set_company_name("Google, Inc."); 201 specifics->set_address_home_city("Mountain View"); 202 specifics->set_address_home_state("California"); 203 specifics->set_address_home_zip("94043"); 204 specifics->set_address_home_country("US"); 205 specifics->set_address_home_sorting_code("CEDEX"); 206 specifics->set_address_home_dependent_locality("Santa Clara"); 207 208 return syncer::SyncData::CreateLocalData(kGuid1, kGuid1, entity_specifics); 209} 210 211} // namespace 212 213class AutofillProfileSyncableServiceTest : public testing::Test { 214 public: 215 AutofillProfileSyncableServiceTest() 216 : ui_thread_(BrowserThread::UI, &message_loop_), 217 db_thread_(BrowserThread::DB, &message_loop_) {} 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 content::TestBrowserThread ui_thread_; 259 content::TestBrowserThread db_thread_; 260 MockAutofillProfileSyncableService autofill_syncable_service_; 261 scoped_ptr<MockSyncChangeProcessor> sync_processor_; 262}; 263 264TEST_F(AutofillProfileSyncableServiceTest, MergeDataAndStartSyncing) { 265 std::vector<AutofillProfile*> profiles_from_web_db; 266 std::string guid_present1 = kGuid1; 267 std::string guid_present2 = kGuid2; 268 std::string guid_synced1 = kGuid3; 269 std::string guid_synced2 = kGuid4; 270 std::string origin_present1 = kHttpOrigin; 271 std::string origin_present2 = std::string(); 272 std::string origin_synced1 = kHttpsOrigin; 273 std::string origin_synced2 = kSettingsOrigin; 274 275 profiles_from_web_db.push_back( 276 new AutofillProfile(guid_present1, origin_present1)); 277 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John")); 278 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1, 279 ASCIIToUTF16("1 1st st")); 280 profiles_from_web_db.push_back( 281 new AutofillProfile(guid_present2, origin_present2)); 282 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom")); 283 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1, 284 ASCIIToUTF16("2 2nd st")); 285 286 syncer::SyncDataList data_list; 287 AutofillProfile profile1(guid_synced1, origin_synced1); 288 profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane")); 289 data_list.push_back(autofill_syncable_service_.CreateData(profile1)); 290 AutofillProfile profile2(guid_synced2, origin_synced2); 291 profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Harry")); 292 data_list.push_back(autofill_syncable_service_.CreateData(profile2)); 293 // This one will have the name and origin updated. 294 AutofillProfile profile3(guid_present2, origin_synced2); 295 profile3.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom Doe")); 296 data_list.push_back(autofill_syncable_service_.CreateData(profile3)); 297 298 syncer::SyncChangeList expected_change_list; 299 expected_change_list.push_back( 300 syncer::SyncChange(FROM_HERE, 301 syncer::SyncChange::ACTION_ADD, 302 MockAutofillProfileSyncableService::CreateData( 303 *profiles_from_web_db.front()))); 304 305 MockAutofillProfileSyncableService::DataBundle expected_bundle; 306 expected_bundle.profiles_to_add.push_back(&profile1); 307 expected_bundle.profiles_to_add.push_back(&profile2); 308 expected_bundle.profiles_to_update.push_back(&profile3); 309 310 MergeDataAndStartSyncing( 311 profiles_from_web_db, data_list, expected_bundle, expected_change_list); 312 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE); 313} 314 315TEST_F(AutofillProfileSyncableServiceTest, MergeIdenticalProfiles) { 316 std::vector<AutofillProfile*> profiles_from_web_db; 317 std::string guid_present1 = kGuid1; 318 std::string guid_present2 = kGuid2; 319 std::string guid_synced1 = kGuid3; 320 std::string guid_synced2 = kGuid4; 321 std::string origin_present1 = kHttpOrigin; 322 std::string origin_present2 = kSettingsOrigin; 323 std::string origin_synced1 = kHttpsOrigin; 324 std::string origin_synced2 = kHttpsOrigin; 325 326 profiles_from_web_db.push_back( 327 new AutofillProfile(guid_present1, origin_present1)); 328 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John")); 329 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1, 330 ASCIIToUTF16("1 1st st")); 331 profiles_from_web_db.push_back( 332 new AutofillProfile(guid_present2, origin_present2)); 333 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom")); 334 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1, 335 ASCIIToUTF16("2 2nd st")); 336 337 // The synced profiles are identical to the local ones, except that the guids 338 // are different. 339 syncer::SyncDataList data_list; 340 AutofillProfile profile1(guid_synced1, origin_synced1); 341 profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John")); 342 profile1.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1 1st st")); 343 data_list.push_back(autofill_syncable_service_.CreateData(profile1)); 344 AutofillProfile profile2(guid_synced2, origin_synced2); 345 profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom")); 346 profile2.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("2 2nd st")); 347 data_list.push_back(autofill_syncable_service_.CreateData(profile2)); 348 349 AutofillProfile expected_profile(profile2); 350 expected_profile.set_origin(kSettingsOrigin); 351 syncer::SyncChangeList expected_change_list; 352 expected_change_list.push_back( 353 syncer::SyncChange(FROM_HERE, 354 syncer::SyncChange::ACTION_UPDATE, 355 MockAutofillProfileSyncableService::CreateData( 356 expected_profile))); 357 358 MockAutofillProfileSyncableService::DataBundle expected_bundle; 359 expected_bundle.profiles_to_delete.push_back(guid_present1); 360 expected_bundle.profiles_to_delete.push_back(guid_present2); 361 expected_bundle.profiles_to_add.push_back(&profile1); 362 expected_bundle.profiles_to_add.push_back(&expected_profile); 363 364 MergeDataAndStartSyncing( 365 profiles_from_web_db, data_list, expected_bundle, expected_change_list); 366 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE); 367} 368 369TEST_F(AutofillProfileSyncableServiceTest, MergeSimilarProfiles) { 370 std::vector<AutofillProfile*> profiles_from_web_db; 371 std::string guid_present1 = kGuid1; 372 std::string guid_present2 = kGuid2; 373 std::string guid_synced1 = kGuid3; 374 std::string guid_synced2 = kGuid4; 375 std::string origin_present1 = kHttpOrigin; 376 std::string origin_present2 = kSettingsOrigin; 377 std::string origin_synced1 = kHttpsOrigin; 378 std::string origin_synced2 = kHttpsOrigin; 379 380 profiles_from_web_db.push_back( 381 new AutofillProfile(guid_present1, origin_present1)); 382 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John")); 383 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1, 384 ASCIIToUTF16("1 1st st")); 385 profiles_from_web_db.push_back( 386 new AutofillProfile(guid_present2, origin_present2)); 387 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom")); 388 profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1, 389 ASCIIToUTF16("2 2nd st")); 390 391 // The synced profiles are identical to the local ones, except that the guids 392 // are different. 393 syncer::SyncDataList data_list; 394 AutofillProfile profile1(guid_synced1, origin_synced1); 395 profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John")); 396 profile1.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1 1st st")); 397 profile1.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Frobbers, Inc.")); 398 data_list.push_back(autofill_syncable_service_.CreateData(profile1)); 399 AutofillProfile profile2(guid_synced2, origin_synced2); 400 profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom")); 401 profile2.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("2 2nd st")); 402 profile2.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Fizzbang, LLC.")); 403 data_list.push_back(autofill_syncable_service_.CreateData(profile2)); 404 405 // The first profile should have its origin updated. 406 // The second profile should remain as-is, because an unverified profile 407 // should never overwrite a verified one. 408 AutofillProfile expected_profile(profile1); 409 expected_profile.set_origin(origin_present1); 410 syncer::SyncChangeList expected_change_list; 411 expected_change_list.push_back( 412 syncer::SyncChange(FROM_HERE, 413 syncer::SyncChange::ACTION_ADD, 414 MockAutofillProfileSyncableService::CreateData( 415 *profiles_from_web_db.back()))); 416 expected_change_list.push_back( 417 syncer::SyncChange(FROM_HERE, 418 syncer::SyncChange::ACTION_UPDATE, 419 MockAutofillProfileSyncableService::CreateData( 420 expected_profile))); 421 422 MockAutofillProfileSyncableService::DataBundle expected_bundle; 423 expected_bundle.profiles_to_delete.push_back(guid_present1); 424 expected_bundle.profiles_to_add.push_back(&expected_profile); 425 expected_bundle.profiles_to_add.push_back(&profile2); 426 427 MergeDataAndStartSyncing( 428 profiles_from_web_db, data_list, expected_bundle, expected_change_list); 429 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE); 430} 431 432// Ensure that no Sync events are generated to fill in missing origins from Sync 433// with explicitly present empty ones. This ensures that the migration to add 434// origins to profiles does not generate lots of needless Sync updates. 435TEST_F(AutofillProfileSyncableServiceTest, MergeDataEmptyOrigins) { 436 std::vector<AutofillProfile*> profiles_from_web_db; 437 438 // Create a profile with an empty origin. 439 AutofillProfile profile(kGuid1, std::string()); 440 profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John")); 441 profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1 1st st")); 442 443 profiles_from_web_db.push_back(new AutofillProfile(profile)); 444 445 // Create a Sync profile identical to |profile|, except with no origin set. 446 sync_pb::EntitySpecifics specifics; 447 sync_pb::AutofillProfileSpecifics* autofill_specifics = 448 specifics.mutable_autofill_profile(); 449 autofill_specifics->set_guid(profile.guid()); 450 autofill_specifics->add_name_first("John"); 451 autofill_specifics->add_name_middle(std::string()); 452 autofill_specifics->add_name_last(std::string()); 453 autofill_specifics->add_email_address(std::string()); 454 autofill_specifics->add_phone_home_whole_number(std::string()); 455 autofill_specifics->set_address_home_line1("1 1st st"); 456 EXPECT_FALSE(autofill_specifics->has_origin()); 457 458 syncer::SyncDataList data_list; 459 data_list.push_back( 460 syncer::SyncData::CreateLocalData( 461 profile.guid(), profile.guid(), specifics)); 462 463 MockAutofillProfileSyncableService::DataBundle expected_bundle; 464 syncer::SyncChangeList expected_change_list; 465 MergeDataAndStartSyncing( 466 profiles_from_web_db, data_list, expected_bundle, expected_change_list); 467 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE); 468} 469 470TEST_F(AutofillProfileSyncableServiceTest, GetAllSyncData) { 471 std::vector<AutofillProfile*> profiles_from_web_db; 472 std::string guid_present1 = kGuid1; 473 std::string guid_present2 = kGuid2; 474 475 profiles_from_web_db.push_back( 476 new AutofillProfile(guid_present1, kHttpOrigin)); 477 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John")); 478 profiles_from_web_db.push_back( 479 new AutofillProfile(guid_present2, kHttpsOrigin)); 480 profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane")); 481 482 syncer::SyncChangeList expected_change_list; 483 expected_change_list.push_back( 484 syncer::SyncChange(FROM_HERE, 485 syncer::SyncChange::ACTION_ADD, 486 MockAutofillProfileSyncableService::CreateData( 487 *profiles_from_web_db.front()))); 488 expected_change_list.push_back( 489 syncer::SyncChange(FROM_HERE, 490 syncer::SyncChange::ACTION_ADD, 491 MockAutofillProfileSyncableService::CreateData( 492 *profiles_from_web_db.back()))); 493 494 MockAutofillProfileSyncableService::DataBundle expected_bundle; 495 syncer::SyncDataList data_list; 496 MergeDataAndStartSyncing( 497 profiles_from_web_db, data_list, expected_bundle, expected_change_list); 498 499 syncer::SyncDataList data = 500 autofill_syncable_service_.GetAllSyncData(syncer::AUTOFILL_PROFILE); 501 502 ASSERT_EQ(2U, data.size()); 503 EXPECT_EQ(guid_present1, data[0].GetSpecifics().autofill_profile().guid()); 504 EXPECT_EQ(guid_present2, data[1].GetSpecifics().autofill_profile().guid()); 505 EXPECT_EQ(kHttpOrigin, data[0].GetSpecifics().autofill_profile().origin()); 506 EXPECT_EQ(kHttpsOrigin, data[1].GetSpecifics().autofill_profile().origin()); 507 508 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE); 509} 510 511TEST_F(AutofillProfileSyncableServiceTest, ProcessSyncChanges) { 512 std::vector<AutofillProfile *> profiles_from_web_db; 513 std::string guid_present = kGuid1; 514 std::string guid_synced = kGuid2; 515 516 syncer::SyncChangeList change_list; 517 AutofillProfile profile(guid_synced, kHttpOrigin); 518 profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane")); 519 change_list.push_back( 520 syncer::SyncChange( 521 FROM_HERE, 522 syncer::SyncChange::ACTION_ADD, 523 MockAutofillProfileSyncableService::CreateData(profile))); 524 AutofillProfile empty_profile(guid_present, kHttpsOrigin); 525 change_list.push_back( 526 syncer::SyncChange( 527 FROM_HERE, 528 syncer::SyncChange::ACTION_DELETE, 529 MockAutofillProfileSyncableService::CreateData(empty_profile))); 530 531 MockAutofillProfileSyncableService::DataBundle expected_bundle; 532 expected_bundle.profiles_to_delete.push_back(guid_present); 533 expected_bundle.profiles_to_add.push_back(&profile); 534 535 EXPECT_CALL(autofill_syncable_service_, SaveChangesToWebData( 536 DataBundleCheck(expected_bundle))) 537 .Times(1) 538 .WillOnce(Return(true)); 539 540 autofill_syncable_service_.set_sync_processor(sync_processor_.release()); 541 syncer::SyncError error = autofill_syncable_service_.ProcessSyncChanges( 542 FROM_HERE, change_list); 543 544 EXPECT_FALSE(error.IsSet()); 545} 546 547TEST_F(AutofillProfileSyncableServiceTest, AutofillProfileAdded) { 548 // Will be owned by the syncable service. Keep a reference available here for 549 // verifying test expectations. 550 TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor; 551 autofill_syncable_service_.set_sync_processor(sync_change_processor); 552 553 AutofillProfile profile(kGuid1, kHttpsOrigin); 554 profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane")); 555 AutofillProfileChange change(AutofillProfileChange::ADD, kGuid1, &profile); 556 autofill_syncable_service_.AutofillProfileChanged(change); 557 558 ASSERT_EQ(1U, sync_change_processor->changes().size()); 559 syncer::SyncChange result = sync_change_processor->changes()[0]; 560 EXPECT_EQ(syncer::SyncChange::ACTION_ADD, result.change_type()); 561 562 sync_pb::AutofillProfileSpecifics specifics = 563 result.sync_data().GetSpecifics().autofill_profile(); 564 EXPECT_EQ(kGuid1, specifics.guid()); 565 EXPECT_EQ(kHttpsOrigin, specifics.origin()); 566 EXPECT_THAT(specifics.name_first(), testing::ElementsAre("Jane")); 567} 568 569TEST_F(AutofillProfileSyncableServiceTest, AutofillProfileDeleted) { 570 // Will be owned by the syncable service. Keep a reference available here for 571 // verifying test expectations. 572 TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor; 573 autofill_syncable_service_.set_sync_processor(sync_change_processor); 574 575 AutofillProfileChange change(AutofillProfileChange::REMOVE, kGuid2, NULL); 576 autofill_syncable_service_.AutofillProfileChanged(change); 577 578 ASSERT_EQ(1U, sync_change_processor->changes().size()); 579 syncer::SyncChange result = sync_change_processor->changes()[0]; 580 EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, result.change_type()); 581 sync_pb::AutofillProfileSpecifics specifics = 582 result.sync_data().GetSpecifics().autofill_profile(); 583 EXPECT_EQ(kGuid2, specifics.guid()); 584} 585 586TEST_F(AutofillProfileSyncableServiceTest, UpdateField) { 587 AutofillProfile profile(kGuid1, kSettingsOrigin); 588 std::string company1 = "A Company"; 589 std::string company2 = "Another Company"; 590 profile.SetRawInfo(COMPANY_NAME, ASCIIToUTF16(company1)); 591 EXPECT_FALSE(AutofillProfileSyncableService::UpdateField( 592 COMPANY_NAME, company1, &profile)); 593 EXPECT_EQ(profile.GetRawInfo(COMPANY_NAME), ASCIIToUTF16(company1)); 594 EXPECT_TRUE(AutofillProfileSyncableService::UpdateField( 595 COMPANY_NAME, company2, &profile)); 596 EXPECT_EQ(profile.GetRawInfo(COMPANY_NAME), ASCIIToUTF16(company2)); 597 EXPECT_FALSE(AutofillProfileSyncableService::UpdateField( 598 COMPANY_NAME, company2, &profile)); 599 EXPECT_EQ(profile.GetRawInfo(COMPANY_NAME), ASCIIToUTF16(company2)); 600} 601 602TEST_F(AutofillProfileSyncableServiceTest, UpdateMultivaluedField) { 603 AutofillProfile profile(kGuid1, kHttpsOrigin); 604 605 std::vector<base::string16> values; 606 values.push_back(ASCIIToUTF16("1@1.com")); 607 values.push_back(ASCIIToUTF16("2@1.com")); 608 profile.SetRawMultiInfo(EMAIL_ADDRESS, values); 609 610 ::google::protobuf::RepeatedPtrField<std::string> specifics_fields; 611 specifics_fields.AddAllocated(new std::string("2@1.com")); 612 specifics_fields.AddAllocated(new std::string("3@1.com")); 613 614 EXPECT_TRUE(AutofillProfileSyncableService::UpdateMultivaluedField( 615 EMAIL_ADDRESS, specifics_fields, &profile)); 616 profile.GetRawMultiInfo(EMAIL_ADDRESS, &values); 617 ASSERT_TRUE(values.size() == 2); 618 EXPECT_EQ(values[0], ASCIIToUTF16("2@1.com")); 619 EXPECT_EQ(values[1], ASCIIToUTF16("3@1.com")); 620 621 EXPECT_FALSE(AutofillProfileSyncableService::UpdateMultivaluedField( 622 EMAIL_ADDRESS, specifics_fields, &profile)); 623 profile.GetRawMultiInfo(EMAIL_ADDRESS, &values); 624 ASSERT_EQ(values.size(), 2U); 625 EXPECT_EQ(values[0], ASCIIToUTF16("2@1.com")); 626 EXPECT_EQ(values[1], ASCIIToUTF16("3@1.com")); 627 EXPECT_TRUE(AutofillProfileSyncableService::UpdateMultivaluedField( 628 EMAIL_ADDRESS, ::google::protobuf::RepeatedPtrField<std::string>(), 629 &profile)); 630 profile.GetRawMultiInfo(EMAIL_ADDRESS, &values); 631 ASSERT_EQ(values.size(), 1U); // Always have at least an empty string. 632 EXPECT_EQ(values[0], ASCIIToUTF16("")); 633} 634 635TEST_F(AutofillProfileSyncableServiceTest, MergeProfile) { 636 AutofillProfile profile1(kGuid1, kHttpOrigin); 637 profile1.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("111 First St.")); 638 639 std::vector<base::string16> values; 640 values.push_back(ASCIIToUTF16("1@1.com")); 641 values.push_back(ASCIIToUTF16("2@1.com")); 642 profile1.SetRawMultiInfo(EMAIL_ADDRESS, values); 643 644 AutofillProfile profile2(kGuid2, kHttpsOrigin); 645 profile2.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("111 First St.")); 646 647 // |values| now is [ "1@1.com", "2@1.com", "3@1.com" ]. 648 values.push_back(ASCIIToUTF16("3@1.com")); 649 profile2.SetRawMultiInfo(EMAIL_ADDRESS, values); 650 651 values.clear(); 652 values.push_back(ASCIIToUTF16("John")); 653 profile1.SetRawMultiInfo(NAME_FIRST, values); 654 values.push_back(ASCIIToUTF16("Jane")); 655 profile2.SetRawMultiInfo(NAME_FIRST, values); 656 657 values.clear(); 658 values.push_back(ASCIIToUTF16("Doe")); 659 profile1.SetRawMultiInfo(NAME_LAST, values); 660 values.push_back(ASCIIToUTF16("Other")); 661 profile2.SetRawMultiInfo(NAME_LAST, values); 662 663 values.clear(); 664 values.push_back(ASCIIToUTF16("650234567")); 665 profile2.SetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, values); 666 667 EXPECT_FALSE(AutofillProfileSyncableService::MergeProfile(profile2, 668 &profile1, 669 "en-US")); 670 671 profile1.GetRawMultiInfo(NAME_FIRST, &values); 672 ASSERT_EQ(values.size(), 2U); 673 EXPECT_EQ(values[0], ASCIIToUTF16("John")); 674 EXPECT_EQ(values[1], ASCIIToUTF16("Jane")); 675 676 profile1.GetRawMultiInfo(NAME_LAST, &values); 677 ASSERT_EQ(values.size(), 2U); 678 EXPECT_EQ(values[0], ASCIIToUTF16("Doe")); 679 EXPECT_EQ(values[1], ASCIIToUTF16("Other")); 680 681 profile1.GetRawMultiInfo(EMAIL_ADDRESS, &values); 682 ASSERT_EQ(values.size(), 3U); 683 EXPECT_EQ(values[0], ASCIIToUTF16("1@1.com")); 684 EXPECT_EQ(values[1], ASCIIToUTF16("2@1.com")); 685 EXPECT_EQ(values[2], ASCIIToUTF16("3@1.com")); 686 687 profile1.GetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, &values); 688 ASSERT_EQ(values.size(), 1U); 689 EXPECT_EQ(values[0], ASCIIToUTF16("650234567")); 690 691 EXPECT_EQ(profile2.origin(), profile1.origin()); 692 693 AutofillProfile profile3(kGuid3, kHttpOrigin); 694 profile3.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("111 First St.")); 695 696 values.clear(); 697 values.push_back(ASCIIToUTF16("Jane")); 698 profile3.SetRawMultiInfo(NAME_FIRST, values); 699 700 values.clear(); 701 values.push_back(ASCIIToUTF16("Doe")); 702 profile3.SetRawMultiInfo(NAME_LAST, values); 703 704 EXPECT_TRUE(AutofillProfileSyncableService::MergeProfile(profile3, 705 &profile1, 706 "en-US")); 707 708 profile1.GetRawMultiInfo(NAME_FIRST, &values); 709 ASSERT_EQ(values.size(), 3U); 710 EXPECT_EQ(values[0], ASCIIToUTF16("John")); 711 EXPECT_EQ(values[1], ASCIIToUTF16("Jane")); 712 EXPECT_EQ(values[2], ASCIIToUTF16("Jane")); 713 714 profile1.GetRawMultiInfo(NAME_LAST, &values); 715 ASSERT_EQ(values.size(), 3U); 716 EXPECT_EQ(values[0], ASCIIToUTF16("Doe")); 717 EXPECT_EQ(values[1], ASCIIToUTF16("Other")); 718 EXPECT_EQ(values[2], ASCIIToUTF16("Doe")); 719 720 // Middle name should have three entries as well. 721 profile1.GetRawMultiInfo(NAME_MIDDLE, &values); 722 ASSERT_EQ(values.size(), 3U); 723 EXPECT_TRUE(values[0].empty()); 724 EXPECT_TRUE(values[1].empty()); 725 EXPECT_TRUE(values[2].empty()); 726 727 profile1.GetRawMultiInfo(EMAIL_ADDRESS, &values); 728 ASSERT_EQ(values.size(), 3U); 729 EXPECT_EQ(values[0], ASCIIToUTF16("1@1.com")); 730 EXPECT_EQ(values[1], ASCIIToUTF16("2@1.com")); 731 EXPECT_EQ(values[2], ASCIIToUTF16("3@1.com")); 732 733 profile1.GetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, &values); 734 ASSERT_EQ(values.size(), 1U); 735 EXPECT_EQ(values[0], ASCIIToUTF16("650234567")); 736} 737 738// Ensure that all profile fields are able to be synced up from the client to 739// the server. 740TEST_F(AutofillProfileSyncableServiceTest, SyncAllFieldsToServer) { 741 std::vector<AutofillProfile*> profiles_from_web_db; 742 743 // Create a profile with all fields set. 744 profiles_from_web_db.push_back(ConstructCompleteProfile().release()); 745 746 // Set up expectations: No changes to the WebDB, and all fields correctly 747 // copied to Sync. 748 MockAutofillProfileSyncableService::DataBundle expected_bundle; 749 syncer::SyncChangeList expected_change_list; 750 expected_change_list.push_back( 751 syncer::SyncChange(FROM_HERE, 752 syncer::SyncChange::ACTION_ADD, 753 ConstructCompleteSyncData())); 754 755 // Verify the expectations. 756 syncer::SyncDataList data_list; 757 MergeDataAndStartSyncing( 758 profiles_from_web_db, data_list, expected_bundle, expected_change_list); 759 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE); 760} 761 762// Ensure that all profile fields are able to be synced down from the server to 763// the client. 764TEST_F(AutofillProfileSyncableServiceTest, SyncAllFieldsToClient) { 765 // Create a profile with all fields set. 766 syncer::SyncDataList data_list; 767 data_list.push_back(ConstructCompleteSyncData()); 768 769 // Set up expectations: All fields correctly copied to the WebDB, and no 770 // changes propagated to Sync. 771 syncer::SyncChangeList expected_change_list; 772 scoped_ptr<AutofillProfile> expected_profile = ConstructCompleteProfile(); 773 MockAutofillProfileSyncableService::DataBundle expected_bundle; 774 expected_bundle.profiles_to_add.push_back(expected_profile.get()); 775 776 // Verify the expectations. 777 std::vector<AutofillProfile*> profiles_from_web_db; 778 MergeDataAndStartSyncing( 779 profiles_from_web_db, data_list, expected_bundle, expected_change_list); 780 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE); 781} 782 783// Ensure that the street address field takes precedence over the address line 1 784// and line 2 fields, even though these are expected to always be in sync in 785// practice. 786TEST_F(AutofillProfileSyncableServiceTest, 787 StreetAddressTakesPrecedenceOverAddressLines) { 788 // Create a Sync profile with conflicting address data in the street address 789 // field vs. the address line 1 and address line 2 fields. 790 sync_pb::EntitySpecifics specifics; 791 sync_pb::AutofillProfileSpecifics* autofill_specifics = 792 specifics.mutable_autofill_profile(); 793 autofill_specifics->set_guid(kGuid1); 794 autofill_specifics->set_origin(kHttpsOrigin); 795 autofill_specifics->add_name_first(std::string()); 796 autofill_specifics->add_name_middle(std::string()); 797 autofill_specifics->add_name_last(std::string()); 798 autofill_specifics->add_email_address(std::string()); 799 autofill_specifics->add_phone_home_whole_number(std::string()); 800 autofill_specifics->set_address_home_line1("123 Example St."); 801 autofill_specifics->set_address_home_line2("Apt. 42"); 802 autofill_specifics->set_address_home_street_address("456 El Camino Real\n" 803 "Suite #1337"); 804 805 syncer::SyncDataList data_list; 806 data_list.push_back( 807 syncer::SyncData::CreateLocalData(kGuid1, kGuid1, specifics)); 808 809 // Set up expectations: Full street address takes precedence over address 810 // lines. 811 syncer::SyncChangeList expected_change_list; 812 AutofillProfile expected_profile(kGuid1, kHttpsOrigin); 813 expected_profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, 814 ASCIIToUTF16("456 El Camino Real\n" 815 "Suite #1337")); 816 EXPECT_EQ(ASCIIToUTF16("456 El Camino Real"), 817 expected_profile.GetRawInfo(ADDRESS_HOME_LINE1)); 818 EXPECT_EQ(ASCIIToUTF16("Suite #1337"), 819 expected_profile.GetRawInfo(ADDRESS_HOME_LINE2)); 820 MockAutofillProfileSyncableService::DataBundle expected_bundle; 821 expected_bundle.profiles_to_add.push_back(&expected_profile); 822 823 // Verify the expectations. 824 std::vector<AutofillProfile*> profiles_from_web_db; 825 MergeDataAndStartSyncing( 826 profiles_from_web_db, data_list, expected_bundle, expected_change_list); 827 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE); 828} 829 830// Ensure that no Sync events are generated to fill in missing street address 831// fields from Sync with explicitly present ones identical to the data stored in 832// the line1 and line2 fields. This ensures that the migration to add the 833// street address field to profiles does not generate lots of needless Sync 834// updates. 835TEST_F(AutofillProfileSyncableServiceTest, MergeDataEmptyStreetAddress) { 836 std::vector<AutofillProfile*> profiles_from_web_db; 837 838 // Create a profile with the street address set. 839 AutofillProfile profile(kGuid1, kHttpsOrigin); 840 profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, 841 ASCIIToUTF16("123 Example St.\n" 842 "Apt. 42")); 843 EXPECT_EQ(ASCIIToUTF16("123 Example St."), 844 profile.GetRawInfo(ADDRESS_HOME_LINE1)); 845 EXPECT_EQ(ASCIIToUTF16("Apt. 42"), profile.GetRawInfo(ADDRESS_HOME_LINE2)); 846 847 profiles_from_web_db.push_back(new AutofillProfile(profile)); 848 849 // Create a Sync profile identical to |profile|, except without street address 850 // explicitly set. 851 sync_pb::EntitySpecifics specifics; 852 sync_pb::AutofillProfileSpecifics* autofill_specifics = 853 specifics.mutable_autofill_profile(); 854 autofill_specifics->set_guid(profile.guid()); 855 autofill_specifics->set_origin(profile.origin()); 856 autofill_specifics->add_name_first(std::string()); 857 autofill_specifics->add_name_middle(std::string()); 858 autofill_specifics->add_name_last(std::string()); 859 autofill_specifics->add_email_address(std::string()); 860 autofill_specifics->add_phone_home_whole_number(std::string()); 861 autofill_specifics->set_address_home_line1("123 Example St."); 862 autofill_specifics->set_address_home_line2("Apt. 42"); 863 EXPECT_FALSE(autofill_specifics->has_address_home_street_address()); 864 865 syncer::SyncDataList data_list; 866 data_list.push_back( 867 syncer::SyncData::CreateLocalData( 868 profile.guid(), profile.guid(), specifics)); 869 870 MockAutofillProfileSyncableService::DataBundle expected_bundle; 871 syncer::SyncChangeList expected_change_list; 872 MergeDataAndStartSyncing( 873 profiles_from_web_db, data_list, expected_bundle, expected_change_list); 874 autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE); 875} 876 877} // namespace autofill 878