profile_sync_service_autofill_unittest.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2010 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 <set> 6#include <string> 7#include <vector> 8 9#include "testing/gtest/include/gtest/gtest.h" 10 11#include "base/callback.h" 12#include "base/message_loop.h" 13#include "base/ref_counted.h" 14#include "base/scoped_ptr.h" 15#include "base/string16.h" 16#include "base/task.h" 17#include "base/time.h" 18#include "base/utf_string_conversions.h" 19#include "base/waitable_event.h" 20#include "chrome/browser/autofill/autofill_common_unittest.h" 21#include "chrome/browser/chrome_thread.h" 22#include "chrome/browser/sync/abstract_profile_sync_service_test.h" 23#include "chrome/browser/sync/engine/model_changing_syncer_command.h" 24#include "chrome/browser/sync/engine/syncapi.h" 25#include "chrome/browser/sync/engine/syncer_util.h" 26#include "chrome/browser/sync/glue/autofill_change_processor.h" 27#include "chrome/browser/sync/glue/autofill_data_type_controller.h" 28#include "chrome/browser/sync/glue/autofill_model_associator.h" 29#include "chrome/browser/sync/profile_sync_factory.h" 30#include "chrome/browser/sync/profile_sync_service.h" 31#include "chrome/browser/sync/profile_sync_test_util.h" 32#include "chrome/browser/sync/protocol/autofill_specifics.pb.h" 33#include "chrome/browser/sync/syncable/syncable.h" 34#include "chrome/browser/sync/syncable/model_type.h" 35#include "chrome/browser/sync/test_profile_sync_service.h" 36#include "chrome/browser/webdata/autofill_change.h" 37#include "chrome/browser/webdata/autofill_entry.h" 38#include "chrome/browser/webdata/web_database.h" 39#include "chrome/common/net/gaia/gaia_constants.h" 40#include "chrome/common/notification_source.h" 41#include "chrome/common/notification_type.h" 42#include "chrome/test/profile_mock.h" 43#include "chrome/test/sync/engine/test_id_factory.h" 44#include "testing/gmock/include/gmock/gmock.h" 45 46using base::Time; 47using base::WaitableEvent; 48using browser_sync::AutofillChangeProcessor; 49using browser_sync::AutofillDataTypeController; 50using browser_sync::AutofillModelAssociator; 51using browser_sync::GROUP_DB; 52using browser_sync::kAutofillTag; 53using browser_sync::SyncBackendHostForProfileSyncTest; 54using browser_sync::SyncerUtil; 55using browser_sync::UnrecoverableErrorHandler; 56using syncable::CREATE_NEW_UPDATE_ITEM; 57using syncable::AUTOFILL; 58using syncable::DirectoryChangeEvent; 59using syncable::GET_BY_SERVER_TAG; 60using syncable::INVALID; 61using syncable::SERVER_PARENT_ID; 62using syncable::SERVER_SPECIFICS; 63using syncable::OriginalEntries; 64using syncable::WriterTag; 65using syncable::WriteTransaction; 66using testing::_; 67using testing::DoAll; 68using testing::DoDefault; 69using testing::ElementsAre; 70using testing::Eq; 71using testing::Invoke; 72using testing::Mock; 73using testing::Return; 74using testing::SaveArg; 75using testing::SetArgumentPointee; 76 77namespace syncable { 78class Id; 79} 80 81class WebDatabaseMock : public WebDatabase { 82 public: 83 MOCK_METHOD2(RemoveFormElement, 84 bool(const string16& name, const string16& value)); // NOLINT 85 MOCK_METHOD1(GetAllAutofillEntries, 86 bool(std::vector<AutofillEntry>* entries)); // NOLINT 87 MOCK_METHOD3(GetAutofillTimestamps, 88 bool(const string16& name, // NOLINT 89 const string16& value, 90 std::vector<base::Time>* timestamps)); 91 MOCK_METHOD1(UpdateAutofillEntries, 92 bool(const std::vector<AutofillEntry>&)); // NOLINT 93 MOCK_METHOD1(GetAutoFillProfiles, 94 bool(std::vector<AutoFillProfile*>*)); // NOLINT 95 MOCK_METHOD1(UpdateAutoFillProfile, 96 bool(const AutoFillProfile&)); // NOLINT 97 MOCK_METHOD1(AddAutoFillProfile, 98 bool(const AutoFillProfile&)); // NOLINT 99 MOCK_METHOD1(RemoveAutoFillProfile, 100 bool(int)); // NOLINT 101}; 102 103class WebDataServiceFake : public WebDataService { 104 public: 105 explicit WebDataServiceFake(WebDatabase* web_database) 106 : web_database_(web_database) {} 107 virtual bool IsDatabaseLoaded() { 108 return true; 109 } 110 111 virtual WebDatabase* GetDatabase() { 112 return web_database_; 113 } 114 115 private: 116 WebDatabase* web_database_; 117}; 118 119class PersonalDataManagerMock: public PersonalDataManager { 120 public: 121 MOCK_CONST_METHOD0(IsDataLoaded, bool()); 122 MOCK_METHOD0(LoadProfiles, void()); 123 MOCK_METHOD0(LoadCreditCards, void()); 124 MOCK_METHOD0(Refresh, void()); 125}; 126 127ACTION_P4(MakeAutofillSyncComponents, service, wd, pdm, dtc) { 128 EXPECT_TRUE(ChromeThread::CurrentlyOn(ChromeThread::DB)); 129 if (!ChromeThread::CurrentlyOn(ChromeThread::DB)) 130 return ProfileSyncFactory::SyncComponents(NULL, NULL); 131 AutofillModelAssociator* model_associator = 132 new AutofillModelAssociator(service, wd, pdm); 133 AutofillChangeProcessor* change_processor = 134 new AutofillChangeProcessor(model_associator, wd, pdm, dtc); 135 return ProfileSyncFactory::SyncComponents(model_associator, 136 change_processor); 137} 138 139class ProfileSyncServiceAutofillTest : public AbstractProfileSyncServiceTest { 140 protected: 141 ProfileSyncServiceAutofillTest() : db_thread_(ChromeThread::DB) { 142 } 143 144 virtual void SetUp() { 145 web_data_service_ = new WebDataServiceFake(&web_database_); 146 personal_data_manager_ = new PersonalDataManagerMock(); 147 EXPECT_CALL(*personal_data_manager_, LoadProfiles()).Times(1); 148 EXPECT_CALL(*personal_data_manager_, LoadCreditCards()).Times(1); 149 personal_data_manager_->Init(&profile_); 150 db_thread_.Start(); 151 152 notification_service_ = new ThreadNotificationService(&db_thread_); 153 notification_service_->Init(); 154 } 155 156 virtual void TearDown() { 157 service_.reset(); 158 notification_service_->TearDown(); 159 db_thread_.Stop(); 160 MessageLoop::current()->RunAllPending(); 161 } 162 163 void StartSyncService(Task* task, bool will_fail_association) { 164 if (!service_.get()) { 165 service_.reset( 166 new TestProfileSyncService(&factory_, &profile_, "test_user", false, 167 task)); 168 AutofillDataTypeController* data_type_controller = 169 new AutofillDataTypeController(&factory_, 170 &profile_, 171 service_.get()); 172 173 SyncBackendHostForProfileSyncTest:: 174 SetDefaultExpectationsForWorkerCreation(&profile_); 175 176 EXPECT_CALL(factory_, CreateAutofillSyncComponents(_, _, _, _)). 177 WillOnce(MakeAutofillSyncComponents(service_.get(), 178 &web_database_, 179 personal_data_manager_.get(), 180 data_type_controller)); 181 EXPECT_CALL(factory_, CreateDataTypeManager(_, _)). 182 WillOnce(ReturnNewDataTypeManager()); 183 184 EXPECT_CALL(profile_, GetWebDataService(_)). 185 WillOnce(Return(web_data_service_.get())); 186 187 EXPECT_CALL(profile_, GetPersonalDataManager()). 188 WillRepeatedly(Return(personal_data_manager_.get())); 189 190 EXPECT_CALL(*personal_data_manager_, IsDataLoaded()). 191 WillRepeatedly(Return(true)); 192 193 // We need tokens to get the tests going 194 token_service_.IssueAuthTokenForTest( 195 GaiaConstants::kSyncService, "token"); 196 197 EXPECT_CALL(profile_, GetTokenService()). 198 WillRepeatedly(Return(&token_service_)); 199 200 service_->set_num_expected_resumes(will_fail_association ? 0 : 1); 201 service_->RegisterDataTypeController(data_type_controller); 202 service_->Initialize(); 203 MessageLoop::current()->Run(); 204 } 205 } 206 207 bool AddAutofillSyncNode(const AutofillEntry& entry) { 208 sync_api::WriteTransaction trans( 209 service_->backend()->GetUserShareHandle()); 210 sync_api::ReadNode autofill_root(&trans); 211 if (!autofill_root.InitByTagLookup(browser_sync::kAutofillTag)) 212 return false; 213 214 sync_api::WriteNode node(&trans); 215 std::string tag = AutofillModelAssociator::KeyToTag(entry.key().name(), 216 entry.key().value()); 217 if (!node.InitUniqueByCreation(syncable::AUTOFILL, autofill_root, tag)) 218 return false; 219 220 AutofillChangeProcessor::WriteAutofillEntry(entry, &node); 221 return true; 222 } 223 224 bool AddAutofillProfileSyncNode(const AutoFillProfile& profile) { 225 sync_api::WriteTransaction trans( 226 service_->backend()->GetUserShareHandle()); 227 sync_api::ReadNode autofill_root(&trans); 228 if (!autofill_root.InitByTagLookup(browser_sync::kAutofillTag)) 229 return false; 230 sync_api::WriteNode node(&trans); 231 std::string tag = AutofillModelAssociator::ProfileLabelToTag( 232 profile.Label()); 233 if (!node.InitUniqueByCreation(syncable::AUTOFILL, autofill_root, tag)) 234 return false; 235 AutofillChangeProcessor::WriteAutofillProfile(profile, &node); 236 sync_pb::AutofillSpecifics s(node.GetAutofillSpecifics()); 237 s.mutable_profile()->set_label(UTF16ToUTF8(profile.Label())); 238 node.SetAutofillSpecifics(s); 239 return true; 240 } 241 242 bool GetAutofillEntriesFromSyncDB(std::vector<AutofillEntry>* entries, 243 std::vector<AutoFillProfile>* profiles) { 244 sync_api::ReadTransaction trans(service_->backend()->GetUserShareHandle()); 245 sync_api::ReadNode autofill_root(&trans); 246 if (!autofill_root.InitByTagLookup(browser_sync::kAutofillTag)) 247 return false; 248 249 int64 child_id = autofill_root.GetFirstChildId(); 250 while (child_id != sync_api::kInvalidId) { 251 sync_api::ReadNode child_node(&trans); 252 if (!child_node.InitByIdLookup(child_id)) 253 return false; 254 255 const sync_pb::AutofillSpecifics& autofill( 256 child_node.GetAutofillSpecifics()); 257 if (autofill.has_value()) { 258 AutofillKey key(UTF8ToUTF16(autofill.name()), 259 UTF8ToUTF16(autofill.value())); 260 std::vector<base::Time> timestamps; 261 int timestamps_count = autofill.usage_timestamp_size(); 262 for (int i = 0; i < timestamps_count; ++i) { 263 timestamps.push_back(Time::FromInternalValue( 264 autofill.usage_timestamp(i))); 265 } 266 entries->push_back(AutofillEntry(key, timestamps)); 267 } else if (autofill.has_profile()) { 268 AutoFillProfile p(UTF8ToUTF16(autofill.profile().label()), 0); 269 AutofillModelAssociator::OverwriteProfileWithServerData(&p, 270 autofill.profile()); 271 profiles->push_back(p); 272 } 273 child_id = child_node.GetSuccessorId(); 274 } 275 return true; 276 } 277 278 void SetIdleChangeProcessorExpectations() { 279 EXPECT_CALL(web_database_, RemoveFormElement(_, _)).Times(0); 280 EXPECT_CALL(web_database_, GetAutofillTimestamps(_, _, _)).Times(0); 281 EXPECT_CALL(web_database_, UpdateAutofillEntries(_)).Times(0); 282 } 283 284 static AutofillEntry MakeAutofillEntry(const char* name, 285 const char* value, 286 time_t timestamp0, 287 time_t timestamp1) { 288 std::vector<Time> timestamps; 289 if (timestamp0 > 0) 290 timestamps.push_back(Time::FromTimeT(timestamp0)); 291 if (timestamp1 > 0) 292 timestamps.push_back(Time::FromTimeT(timestamp1)); 293 return AutofillEntry( 294 AutofillKey(ASCIIToUTF16(name), ASCIIToUTF16(value)), timestamps); 295 } 296 297 static AutofillEntry MakeAutofillEntry(const char* name, 298 const char* value, 299 time_t timestamp) { 300 return MakeAutofillEntry(name, value, timestamp, -1); 301 } 302 303 friend class AddAutofillEntriesTask; 304 friend class FakeServerUpdater; 305 306 ChromeThread db_thread_; 307 scoped_refptr<ThreadNotificationService> notification_service_; 308 309 ProfileMock profile_; 310 WebDatabaseMock web_database_; 311 scoped_refptr<WebDataService> web_data_service_; 312 scoped_refptr<PersonalDataManagerMock> personal_data_manager_; 313}; 314 315class AddAutofillEntriesTask : public Task { 316 public: 317 AddAutofillEntriesTask(ProfileSyncServiceAutofillTest* test, 318 const std::vector<AutofillEntry>& entries, 319 const std::vector<AutoFillProfile>& profiles) 320 : test_(test), entries_(entries), profiles_(profiles), success_(false) { 321 } 322 323 virtual void Run() { 324 if (!test_->CreateRoot(syncable::AUTOFILL)) 325 return; 326 for (size_t i = 0; i < entries_.size(); ++i) { 327 if (!test_->AddAutofillSyncNode(entries_[i])) 328 return; 329 } 330 for (size_t i = 0; i < profiles_.size(); ++i) { 331 if (!test_->AddAutofillProfileSyncNode(profiles_[i])) 332 return; 333 } 334 success_ = true; 335 } 336 337 bool success() { return success_; } 338 339 private: 340 ProfileSyncServiceAutofillTest* test_; 341 const std::vector<AutofillEntry>& entries_; 342 const std::vector<AutoFillProfile>& profiles_; 343 bool success_; 344}; 345 346// Overload write transaction to use custom NotifyTransactionComplete 347static const bool kLoggingInfo = true; 348class WriteTransactionTest: public WriteTransaction { 349 public: 350 WriteTransactionTest(const ScopedDirLookup& directory, 351 WriterTag writer, const char* source_file, 352 int line, 353 scoped_ptr<WaitableEvent> *wait_for_syncapi) 354 : WriteTransaction(directory, writer, source_file, line), 355 wait_for_syncapi_(wait_for_syncapi) { } 356 357 virtual void NotifyTransactionComplete() { 358 // This is where we differ. Force a thread change here, giving another 359 // thread a chance to create a WriteTransaction 360 (*wait_for_syncapi_)->Wait(); 361 362 WriteTransaction::NotifyTransactionComplete(); 363 } 364 365 private: 366 scoped_ptr<WaitableEvent> *wait_for_syncapi_; 367}; 368 369// Our fake server updater. Needs the RefCountedThreadSafe inheritance so we can 370// post tasks with it. 371class FakeServerUpdater: public base::RefCountedThreadSafe<FakeServerUpdater> { 372 public: 373 FakeServerUpdater(TestProfileSyncService *service, 374 scoped_ptr<WaitableEvent> *wait_for_start, 375 scoped_ptr<WaitableEvent> *wait_for_syncapi) 376 : entry_(ProfileSyncServiceAutofillTest::MakeAutofillEntry("0", "0", 0)), 377 service_(service), 378 wait_for_start_(wait_for_start), 379 wait_for_syncapi_(wait_for_syncapi), 380 is_finished_(false, false) { } 381 382 void Update() { 383 // This gets called in a modelsafeworker thread. 384 ASSERT_TRUE(ChromeThread::CurrentlyOn(ChromeThread::DB)); 385 386 UserShare* user_share = service_->backend()->GetUserShareHandle(); 387 DirectoryManager* dir_manager = user_share->dir_manager.get(); 388 ScopedDirLookup dir(dir_manager, user_share->name); 389 ASSERT_TRUE(dir.good()); 390 391 // Create autofill protobuf 392 std::string tag = AutofillModelAssociator::KeyToTag(entry_.key().name(), 393 entry_.key().value()); 394 sync_pb::AutofillSpecifics new_autofill; 395 new_autofill.set_name(UTF16ToUTF8(entry_.key().name())); 396 new_autofill.set_value(UTF16ToUTF8(entry_.key().value())); 397 const std::vector<base::Time>& ts(entry_.timestamps()); 398 for (std::vector<base::Time>::const_iterator timestamp = ts.begin(); 399 timestamp != ts.end(); ++timestamp) { 400 new_autofill.add_usage_timestamp(timestamp->ToInternalValue()); 401 } 402 403 sync_pb::EntitySpecifics entity_specifics; 404 entity_specifics.MutableExtension(sync_pb::autofill)-> 405 CopyFrom(new_autofill); 406 407 { 408 // Tell main thread we've started 409 (*wait_for_start_)->Signal(); 410 411 // Create write transaction. 412 WriteTransactionTest trans(dir, UNITTEST, __FILE__, __LINE__, 413 wait_for_syncapi_); 414 415 // Create actual entry based on autofill protobuf information. 416 // Simulates effects of SyncerUtil::UpdateLocalDataFromServerData 417 MutableEntry parent(&trans, GET_BY_SERVER_TAG, kAutofillTag); 418 MutableEntry item(&trans, CREATE, parent.Get(syncable::ID), tag); 419 ASSERT_TRUE(item.good()); 420 item.Put(SPECIFICS, entity_specifics); 421 item.Put(SERVER_SPECIFICS, entity_specifics); 422 item.Put(BASE_VERSION, 1); 423 syncable::Id server_parent_id = ids_.NewServerId(); 424 item.Put(syncable::ID, server_parent_id); 425 syncable::Id new_predecessor = 426 SyncerUtil::ComputePrevIdFromServerPosition(&trans, &item, 427 server_parent_id); 428 ASSERT_TRUE(item.PutPredecessor(new_predecessor)); 429 } 430 LOG(INFO) << "FakeServerUpdater finishing."; 431 is_finished_.Signal(); 432 } 433 434 void CreateNewEntry(const AutofillEntry& entry) { 435 entry_ = entry; 436 scoped_ptr<Callback0::Type> c(NewCallback((FakeServerUpdater *)this, 437 &FakeServerUpdater::Update)); 438 std::vector<browser_sync::ModelSafeWorker*> workers; 439 service_->backend()->GetWorkers(&workers); 440 441 ASSERT_FALSE(ChromeThread::CurrentlyOn(ChromeThread::DB)); 442 if (!ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, 443 NewRunnableMethod(this, &FakeServerUpdater::Update))) { 444 NOTREACHED() << "Failed to post task to the db thread."; 445 return; 446 } 447 } 448 449 void CreateNewEntryAndWait(const AutofillEntry& entry) { 450 entry_ = entry; 451 scoped_ptr<Callback0::Type> c(NewCallback((FakeServerUpdater *)this, 452 &FakeServerUpdater::Update)); 453 std::vector<browser_sync::ModelSafeWorker*> workers; 454 service_->backend()->GetWorkers(&workers); 455 456 ASSERT_FALSE(ChromeThread::CurrentlyOn(ChromeThread::DB)); 457 is_finished_.Reset(); 458 if (!ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, 459 NewRunnableMethod(this, &FakeServerUpdater::Update))) { 460 NOTREACHED() << "Failed to post task to the db thread."; 461 return; 462 } 463 is_finished_.Wait(); 464 } 465 466 private: 467 friend class base::RefCountedThreadSafe<FakeServerUpdater>; 468 ~FakeServerUpdater() { } 469 470 AutofillEntry entry_; 471 TestProfileSyncService *service_; 472 scoped_ptr<WaitableEvent> *wait_for_start_; 473 scoped_ptr<WaitableEvent> *wait_for_syncapi_; 474 WaitableEvent is_finished_; 475 syncable::Id parent_id_; 476 TestIdFactory ids_; 477}; 478 479// TODO(skrul): Test abort startup. 480// TODO(skrul): Test processing of cloud changes. 481// TODO(tim): Add autofill data type controller test, and a case to cover 482// waiting for the PersonalDataManager. 483TEST_F(ProfileSyncServiceAutofillTest, FailModelAssociation) { 484 // Don't create the root autofill node so startup fails. 485 StartSyncService(NULL, true); 486 EXPECT_TRUE(service_->unrecoverable_error_detected()); 487} 488 489TEST_F(ProfileSyncServiceAutofillTest, EmptyNativeEmptySync) { 490 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true)); 491 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true)); 492 SetIdleChangeProcessorExpectations(); 493 CreateRootTask task(this, syncable::AUTOFILL); 494 EXPECT_CALL(*personal_data_manager_, Refresh()); 495 StartSyncService(&task, false); 496 ASSERT_TRUE(task.success()); 497 std::vector<AutofillEntry> sync_entries; 498 std::vector<AutoFillProfile> sync_profiles; 499 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles)); 500 EXPECT_EQ(0U, sync_entries.size()); 501 EXPECT_EQ(0U, sync_profiles.size()); 502} 503 504TEST_F(ProfileSyncServiceAutofillTest, HasNativeEntriesEmptySync) { 505 std::vector<AutofillEntry> entries; 506 entries.push_back(MakeAutofillEntry("foo", "bar", 1)); 507 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). 508 WillOnce(DoAll(SetArgumentPointee<0>(entries), Return(true))); 509 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true)); 510 SetIdleChangeProcessorExpectations(); 511 CreateRootTask task(this, syncable::AUTOFILL); 512 EXPECT_CALL(*personal_data_manager_, Refresh()); 513 StartSyncService(&task, false); 514 ASSERT_TRUE(task.success()); 515 std::vector<AutofillEntry> sync_entries; 516 std::vector<AutoFillProfile> sync_profiles; 517 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles)); 518 ASSERT_EQ(1U, entries.size()); 519 EXPECT_TRUE(entries[0] == sync_entries[0]); 520 EXPECT_EQ(0U, sync_profiles.size()); 521} 522 523TEST_F(ProfileSyncServiceAutofillTest, HasMixedNativeEmptySync) { 524 std::vector<AutofillEntry> entries; 525 entries.push_back(MakeAutofillEntry("foo", "bar", 1)); 526 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). 527 WillOnce(DoAll(SetArgumentPointee<0>(entries), Return(true))); 528 529 std::vector<AutoFillProfile*> profiles; 530 std::vector<AutoFillProfile> expected_profiles; 531 // Owned by GetAutoFillProfiles caller. 532 AutoFillProfile* profile0 = new AutoFillProfile(string16(), 0); 533 autofill_unittest::SetProfileInfo(profile0, 534 "Billing", "Marion", "Mitchell", "Morrison", 535 "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA", 536 "91601", "US", "12345678910", "01987654321"); 537 profiles.push_back(profile0); 538 expected_profiles.push_back(*profile0); 539 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)). 540 WillOnce(DoAll(SetArgumentPointee<0>(profiles), Return(true))); 541 EXPECT_CALL(*personal_data_manager_, Refresh()); 542 SetIdleChangeProcessorExpectations(); 543 CreateRootTask task(this, syncable::AUTOFILL); 544 StartSyncService(&task, false); 545 ASSERT_TRUE(task.success()); 546 std::vector<AutofillEntry> sync_entries; 547 std::vector<AutoFillProfile> sync_profiles; 548 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles)); 549 ASSERT_EQ(1U, entries.size()); 550 EXPECT_TRUE(entries[0] == sync_entries[0]); 551 EXPECT_EQ(1U, sync_profiles.size()); 552 EXPECT_EQ(expected_profiles[0], sync_profiles[0]); 553} 554 555bool ProfilesMatchExceptLabelImpl(AutoFillProfile p1, AutoFillProfile p2) { 556 const AutoFillFieldType types[] = { NAME_FIRST, 557 NAME_MIDDLE, 558 NAME_LAST, 559 EMAIL_ADDRESS, 560 COMPANY_NAME, 561 ADDRESS_HOME_LINE1, 562 ADDRESS_HOME_LINE2, 563 ADDRESS_HOME_CITY, 564 ADDRESS_HOME_STATE, 565 ADDRESS_HOME_ZIP, 566 ADDRESS_HOME_COUNTRY, 567 PHONE_HOME_NUMBER, 568 PHONE_FAX_NUMBER }; 569 if (p1.Label() == p2.Label()) 570 return false; 571 572 for (size_t index = 0; index < arraysize(types); ++index) { 573 if (p1.GetFieldText(AutoFillType(types[index])) != 574 p2.GetFieldText(AutoFillType(types[index]))) 575 return false; 576 } 577 return true; 578} 579 580MATCHER_P(ProfileMatchesExceptLabel, profile, "") { 581 return ProfilesMatchExceptLabelImpl(arg, profile); 582} 583 584TEST_F(ProfileSyncServiceAutofillTest, HasDuplicateProfileLabelsEmptySync) { 585 std::vector<AutoFillProfile> expected_profiles; 586 std::vector<AutoFillProfile*> profiles; 587 AutoFillProfile* profile0 = new AutoFillProfile(string16(), 0); 588 autofill_unittest::SetProfileInfo(profile0, 589 "Billing", "Marion", "Mitchell", "Morrison", 590 "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA", 591 "91601", "US", "12345678910", "01987654321"); 592 AutoFillProfile* profile1 = new AutoFillProfile(string16(), 0); 593 autofill_unittest::SetProfileInfo(profile1, 594 "Billing", "Same", "Label", "Morrison", 595 "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA", 596 "91601", "US", "12345678910", "01987654321"); 597 profiles.push_back(profile0); 598 profiles.push_back(profile1); 599 expected_profiles.push_back(*profile0); 600 expected_profiles.push_back(*profile1); 601 AutoFillProfile relabelled_profile; 602 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true)); 603 EXPECT_CALL(*personal_data_manager_, Refresh()); 604 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)). 605 WillOnce(DoAll(SetArgumentPointee<0>(profiles), Return(true))); 606 EXPECT_CALL(web_database_, UpdateAutoFillProfile( 607 ProfileMatchesExceptLabel(expected_profiles[1]))). 608 WillOnce(DoAll(SaveArg<0>(&relabelled_profile), Return(true))); 609 610 SetIdleChangeProcessorExpectations(); 611 CreateRootTask task(this, syncable::AUTOFILL); 612 StartSyncService(&task, false); 613 ASSERT_TRUE(task.success()); 614 std::vector<AutofillEntry> sync_entries; 615 std::vector<AutoFillProfile> sync_profiles; 616 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles)); 617 EXPECT_EQ(0U, sync_entries.size()); 618 EXPECT_EQ(2U, sync_profiles.size()); 619 EXPECT_EQ(expected_profiles[0], sync_profiles[1]); 620 EXPECT_TRUE(ProfilesMatchExceptLabelImpl(expected_profiles[1], 621 sync_profiles[0])); 622 EXPECT_EQ(sync_profiles[0].Label(), relabelled_profile.Label()); 623} 624 625TEST_F(ProfileSyncServiceAutofillTest, HasNativeWithDuplicatesEmptySync) { 626 // There is buggy autofill code that allows duplicate name/value 627 // pairs to exist in the database with separate pair_ids. 628 std::vector<AutofillEntry> entries; 629 entries.push_back(MakeAutofillEntry("foo", "bar", 1)); 630 entries.push_back(MakeAutofillEntry("dup", "", 2)); 631 entries.push_back(MakeAutofillEntry("dup", "", 3)); 632 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). 633 WillOnce(DoAll(SetArgumentPointee<0>(entries), Return(true))); 634 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true)); 635 SetIdleChangeProcessorExpectations(); 636 CreateRootTask task(this, syncable::AUTOFILL); 637 EXPECT_CALL(*personal_data_manager_, Refresh()); 638 StartSyncService(&task, false); 639 ASSERT_TRUE(task.success()); 640 std::vector<AutofillEntry> sync_entries; 641 std::vector<AutoFillProfile> sync_profiles; 642 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles)); 643 EXPECT_EQ(2U, sync_entries.size()); 644} 645 646TEST_F(ProfileSyncServiceAutofillTest, HasNativeHasSyncNoMerge) { 647 AutofillEntry native_entry(MakeAutofillEntry("native", "entry", 1)); 648 AutofillEntry sync_entry(MakeAutofillEntry("sync", "entry", 2)); 649 AutoFillProfile sync_profile(string16(), 0); 650 autofill_unittest::SetProfileInfo(&sync_profile, 651 "Billing", "Marion", "Mitchell", "Morrison", 652 "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA", 653 "91601", "US", "12345678910", "01987654321"); 654 655 AutoFillProfile* native_profile = new AutoFillProfile(string16(), 0); 656 autofill_unittest::SetProfileInfo(native_profile, 657 "Work", "Josephine", "Alicia", "Saenz", 658 "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL", 659 "32801", "US", "19482937549", "13502849239"); 660 661 std::vector<AutofillEntry> native_entries; 662 native_entries.push_back(native_entry); 663 std::vector<AutoFillProfile*> native_profiles; 664 native_profiles.push_back(native_profile); 665 666 std::vector<AutoFillProfile> expected_profiles; 667 expected_profiles.push_back(*native_profile); 668 expected_profiles.push_back(sync_profile); 669 670 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). 671 WillOnce(DoAll(SetArgumentPointee<0>(native_entries), Return(true))); 672 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)). 673 WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true))); 674 std::vector<AutofillEntry> sync_entries; 675 sync_entries.push_back(sync_entry); 676 std::vector<AutoFillProfile> sync_profiles; 677 sync_profiles.push_back(sync_profile); 678 AddAutofillEntriesTask task(this, sync_entries, sync_profiles); 679 680 AutoFillProfile to_be_added(sync_profile); 681 to_be_added.set_unique_id(1); 682 EXPECT_CALL(web_database_, UpdateAutofillEntries(ElementsAre(sync_entry))). 683 WillOnce(Return(true)); 684 EXPECT_CALL(web_database_, AddAutoFillProfile(Eq(to_be_added))). 685 WillOnce(Return(true)); 686 EXPECT_CALL(*personal_data_manager_, Refresh()); 687 StartSyncService(&task, false); 688 ASSERT_TRUE(task.success()); 689 690 std::set<AutofillEntry> expected_entries; 691 expected_entries.insert(native_entry); 692 expected_entries.insert(sync_entry); 693 694 std::vector<AutofillEntry> new_sync_entries; 695 std::vector<AutoFillProfile> new_sync_profiles; 696 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, 697 &new_sync_profiles)); 698 std::set<AutofillEntry> new_sync_entries_set(new_sync_entries.begin(), 699 new_sync_entries.end()); 700 701 EXPECT_TRUE(expected_entries == new_sync_entries_set); 702 EXPECT_EQ(2U, new_sync_profiles.size()); 703 EXPECT_EQ(expected_profiles[0], new_sync_profiles[0]); 704 EXPECT_EQ(expected_profiles[1], new_sync_profiles[1]); 705} 706 707TEST_F(ProfileSyncServiceAutofillTest, HasNativeHasSyncMergeEntry) { 708 AutofillEntry native_entry(MakeAutofillEntry("merge", "entry", 1)); 709 AutofillEntry sync_entry(MakeAutofillEntry("merge", "entry", 2)); 710 AutofillEntry merged_entry(MakeAutofillEntry("merge", "entry", 1, 2)); 711 712 std::vector<AutofillEntry> native_entries; 713 native_entries.push_back(native_entry); 714 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). 715 WillOnce(DoAll(SetArgumentPointee<0>(native_entries), Return(true))); 716 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true)); 717 718 std::vector<AutofillEntry> sync_entries; 719 std::vector<AutoFillProfile> sync_profiles; 720 sync_entries.push_back(sync_entry); 721 AddAutofillEntriesTask task(this, sync_entries, sync_profiles); 722 723 EXPECT_CALL(web_database_, UpdateAutofillEntries(ElementsAre(merged_entry))). 724 WillOnce(Return(true)); 725 EXPECT_CALL(*personal_data_manager_, Refresh()); 726 StartSyncService(&task, false); 727 ASSERT_TRUE(task.success()); 728 729 std::vector<AutofillEntry> new_sync_entries; 730 std::vector<AutoFillProfile> new_sync_profiles; 731 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, 732 &new_sync_profiles)); 733 ASSERT_EQ(1U, new_sync_entries.size()); 734 EXPECT_TRUE(merged_entry == new_sync_entries[0]); 735} 736 737TEST_F(ProfileSyncServiceAutofillTest, HasNativeHasSyncMergeProfile) { 738 AutoFillProfile sync_profile(string16(), 0); 739 autofill_unittest::SetProfileInfo(&sync_profile, 740 "Billing", "Marion", "Mitchell", "Morrison", 741 "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA", 742 "91601", "US", "12345678910", "01987654321"); 743 744 AutoFillProfile* native_profile = new AutoFillProfile(string16(), 0); 745 autofill_unittest::SetProfileInfo(native_profile, 746 "Billing", "Josephine", "Alicia", "Saenz", 747 "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL", 748 "32801", "US", "19482937549", "13502849239"); 749 750 std::vector<AutoFillProfile*> native_profiles; 751 native_profiles.push_back(native_profile); 752 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). WillOnce(Return(true)); 753 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)). 754 WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true))); 755 756 std::vector<AutofillEntry> sync_entries; 757 std::vector<AutoFillProfile> sync_profiles; 758 sync_profiles.push_back(sync_profile); 759 AddAutofillEntriesTask task(this, sync_entries, sync_profiles); 760 761 EXPECT_CALL(web_database_, UpdateAutoFillProfile(Eq(sync_profile))). 762 WillOnce(Return(true)); 763 EXPECT_CALL(*personal_data_manager_, Refresh()); 764 StartSyncService(&task, false); 765 ASSERT_TRUE(task.success()); 766 767 std::vector<AutofillEntry> new_sync_entries; 768 std::vector<AutoFillProfile> new_sync_profiles; 769 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, 770 &new_sync_profiles)); 771 ASSERT_EQ(1U, new_sync_profiles.size()); 772 EXPECT_TRUE(sync_profile == new_sync_profiles[0]); 773} 774 775TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeAddEntry) { 776 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true)); 777 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true)); 778 EXPECT_CALL(*personal_data_manager_, Refresh()); 779 SetIdleChangeProcessorExpectations(); 780 CreateRootTask task(this, syncable::AUTOFILL); 781 StartSyncService(&task, false); 782 ASSERT_TRUE(task.success()); 783 784 AutofillEntry added_entry(MakeAutofillEntry("added", "entry", 1)); 785 std::vector<base::Time> timestamps(added_entry.timestamps()); 786 787 EXPECT_CALL(web_database_, GetAutofillTimestamps(_, _, _)). 788 WillOnce(DoAll(SetArgumentPointee<2>(timestamps), Return(true))); 789 790 AutofillChangeList changes; 791 changes.push_back(AutofillChange(AutofillChange::ADD, added_entry.key())); 792 scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_); 793 notifier->Notify(NotificationType::AUTOFILL_ENTRIES_CHANGED, 794 Source<WebDataService>(web_data_service_.get()), 795 Details<AutofillChangeList>(&changes)); 796 797 std::vector<AutofillEntry> new_sync_entries; 798 std::vector<AutoFillProfile> new_sync_profiles; 799 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, 800 &new_sync_profiles)); 801 ASSERT_EQ(1U, new_sync_entries.size()); 802 EXPECT_TRUE(added_entry == new_sync_entries[0]); 803} 804 805TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeAddProfile) { 806 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true)); 807 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true)); 808 EXPECT_CALL(*personal_data_manager_, Refresh()); 809 SetIdleChangeProcessorExpectations(); 810 CreateRootTask task(this, syncable::AUTOFILL); 811 StartSyncService(&task, false); 812 ASSERT_TRUE(task.success()); 813 814 AutoFillProfile added_profile(string16(), 0); 815 autofill_unittest::SetProfileInfo(&added_profile, 816 "Billing", "Josephine", "Alicia", "Saenz", 817 "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL", 818 "32801", "US", "19482937549", "13502849239"); 819 820 AutofillProfileChange change(AutofillProfileChange::ADD, 821 added_profile.Label(), &added_profile, string16()); 822 scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_); 823 notifier->Notify(NotificationType::AUTOFILL_PROFILE_CHANGED, 824 Source<WebDataService>(web_data_service_.get()), 825 Details<AutofillProfileChange>(&change)); 826 827 std::vector<AutofillEntry> new_sync_entries; 828 std::vector<AutoFillProfile> new_sync_profiles; 829 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, 830 &new_sync_profiles)); 831 ASSERT_EQ(1U, new_sync_profiles.size()); 832 EXPECT_TRUE(added_profile == new_sync_profiles[0]); 833} 834 835TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeAddProfileConflict) { 836 AutoFillProfile sync_profile(string16(), 0); 837 autofill_unittest::SetProfileInfo(&sync_profile, 838 "Billing", "Marion", "Mitchell", "Morrison", 839 "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA", 840 "91601", "US", "12345678910", "01987654321"); 841 842 std::vector<AutofillEntry> sync_entries; 843 std::vector<AutoFillProfile> sync_profiles; 844 sync_profiles.push_back(sync_profile); 845 AddAutofillEntriesTask task(this, sync_entries, sync_profiles); 846 847 sync_profile.set_unique_id(1); 848 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true)); 849 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true)); 850 EXPECT_CALL(web_database_, AddAutoFillProfile(Eq(sync_profile))). 851 WillOnce(Return(true)); 852 EXPECT_CALL(*personal_data_manager_, Refresh()); 853 SetIdleChangeProcessorExpectations(); 854 StartSyncService(&task, false); 855 ASSERT_TRUE(task.success()); 856 857 AutoFillProfile added_profile(string16(), 0); 858 autofill_unittest::SetProfileInfo(&added_profile, 859 "Billing", "Josephine", "Alicia", "Saenz", 860 "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL", 861 "32801", "US", "19482937549", "13502849239"); 862 863 AutofillProfileChange change(AutofillProfileChange::ADD, 864 added_profile.Label(), &added_profile, string16()); 865 866 AutoFillProfile relabelled_profile; 867 EXPECT_CALL(web_database_, UpdateAutoFillProfile( 868 ProfileMatchesExceptLabel(added_profile))). 869 WillOnce(DoAll(SaveArg<0>(&relabelled_profile), Return(true))); 870 EXPECT_CALL(*personal_data_manager_, Refresh()); 871 872 scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_); 873 notifier->Notify(NotificationType::AUTOFILL_PROFILE_CHANGED, 874 Source<WebDataService>(web_data_service_.get()), 875 Details<AutofillProfileChange>(&change)); 876 877 std::vector<AutofillEntry> new_sync_entries; 878 std::vector<AutoFillProfile> new_sync_profiles; 879 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, 880 &new_sync_profiles)); 881 ASSERT_EQ(2U, new_sync_profiles.size()); 882 sync_profile.set_unique_id(0); // The sync DB doesn't store IDs. 883 EXPECT_EQ(sync_profile, new_sync_profiles[1]); 884 EXPECT_TRUE(ProfilesMatchExceptLabelImpl(added_profile, 885 new_sync_profiles[0])); 886 EXPECT_EQ(new_sync_profiles[0].Label(), relabelled_profile.Label()); 887} 888 889TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeUpdateEntry) { 890 AutofillEntry original_entry(MakeAutofillEntry("my", "entry", 1)); 891 std::vector<AutofillEntry> original_entries; 892 original_entries.push_back(original_entry); 893 894 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). 895 WillOnce(DoAll(SetArgumentPointee<0>(original_entries), Return(true))); 896 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true)); 897 EXPECT_CALL(*personal_data_manager_, Refresh()); 898 CreateRootTask task(this, syncable::AUTOFILL); 899 StartSyncService(&task, false); 900 ASSERT_TRUE(task.success()); 901 902 AutofillEntry updated_entry(MakeAutofillEntry("my", "entry", 1, 2)); 903 std::vector<base::Time> timestamps(updated_entry.timestamps()); 904 905 EXPECT_CALL(web_database_, GetAutofillTimestamps(_, _, _)). 906 WillOnce(DoAll(SetArgumentPointee<2>(timestamps), Return(true))); 907 908 AutofillChangeList changes; 909 changes.push_back(AutofillChange(AutofillChange::UPDATE, 910 updated_entry.key())); 911 scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_); 912 notifier->Notify(NotificationType::AUTOFILL_ENTRIES_CHANGED, 913 Source<WebDataService>(web_data_service_.get()), 914 Details<AutofillChangeList>(&changes)); 915 916 std::vector<AutofillEntry> new_sync_entries; 917 std::vector<AutoFillProfile> new_sync_profiles; 918 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, 919 &new_sync_profiles)); 920 ASSERT_EQ(1U, new_sync_entries.size()); 921 EXPECT_TRUE(updated_entry == new_sync_entries[0]); 922} 923 924 925TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeUpdateProfile) { 926 AutoFillProfile* native_profile = new AutoFillProfile(string16(), 0); 927 autofill_unittest::SetProfileInfo(native_profile, 928 "Billing", "Josephine", "Alicia", "Saenz", 929 "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL", 930 "32801", "US", "19482937549", "13502849239"); 931 std::vector<AutoFillProfile*> native_profiles; 932 native_profiles.push_back(native_profile); 933 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). WillOnce(Return(true)); 934 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)). 935 WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true))); 936 EXPECT_CALL(*personal_data_manager_, Refresh()); 937 CreateRootTask task(this, syncable::AUTOFILL); 938 StartSyncService(&task, false); 939 ASSERT_TRUE(task.success()); 940 941 AutoFillProfile update_profile(string16(), 0); 942 autofill_unittest::SetProfileInfo(&update_profile, 943 "Billing", "Changin'", "Mah", "Namez", 944 "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL", 945 "32801", "US", "19482937549", "13502849239"); 946 947 AutofillProfileChange change(AutofillProfileChange::UPDATE, 948 update_profile.Label(), &update_profile, 949 ASCIIToUTF16("Billing")); 950 scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_); 951 notifier->Notify(NotificationType::AUTOFILL_PROFILE_CHANGED, 952 Source<WebDataService>(web_data_service_.get()), 953 Details<AutofillProfileChange>(&change)); 954 955 std::vector<AutofillEntry> new_sync_entries; 956 std::vector<AutoFillProfile> new_sync_profiles; 957 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, 958 &new_sync_profiles)); 959 ASSERT_EQ(1U, new_sync_profiles.size()); 960 EXPECT_TRUE(update_profile == new_sync_profiles[0]); 961} 962 963TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeUpdateProfileRelabel) { 964 AutoFillProfile* native_profile = new AutoFillProfile(string16(), 0); 965 autofill_unittest::SetProfileInfo(native_profile, 966 "Billing", "Josephine", "Alicia", "Saenz", 967 "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL", 968 "32801", "US", "19482937549", "13502849239"); 969 std::vector<AutoFillProfile*> native_profiles; 970 native_profiles.push_back(native_profile); 971 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). WillOnce(Return(true)); 972 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)). 973 WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true))); 974 EXPECT_CALL(*personal_data_manager_, Refresh()); 975 CreateRootTask task(this, syncable::AUTOFILL); 976 StartSyncService(&task, false); 977 ASSERT_TRUE(task.success()); 978 979 AutoFillProfile update_profile(string16(), 0); 980 autofill_unittest::SetProfileInfo(&update_profile, 981 "TRYIN 2 FOOL U", "Josephine", "Alicia", "Saenz", 982 "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL", 983 "32801", "US", "19482937549", "13502849239"); 984 985 AutofillProfileChange change(AutofillProfileChange::UPDATE, 986 update_profile.Label(), &update_profile, 987 ASCIIToUTF16("Billing")); 988 scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_); 989 notifier->Notify(NotificationType::AUTOFILL_PROFILE_CHANGED, 990 Source<WebDataService>(web_data_service_.get()), 991 Details<AutofillProfileChange>(&change)); 992 993 std::vector<AutofillEntry> new_sync_entries; 994 std::vector<AutoFillProfile> new_sync_profiles; 995 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, 996 &new_sync_profiles)); 997 ASSERT_EQ(1U, new_sync_profiles.size()); 998 EXPECT_TRUE(update_profile == new_sync_profiles[0]); 999} 1000 1001TEST_F(ProfileSyncServiceAutofillTest, 1002 ProcessUserChangeUpdateProfileRelabelConflict) { 1003 std::vector<AutoFillProfile*> native_profiles; 1004 native_profiles.push_back(new AutoFillProfile(string16(), 0)); 1005 native_profiles.push_back(new AutoFillProfile(string16(), 0)); 1006 autofill_unittest::SetProfileInfo(native_profiles[0], 1007 "Billing", "Josephine", "Alicia", "Saenz", 1008 "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL", 1009 "32801", "US", "19482937549", "13502849239"); 1010 autofill_unittest::SetProfileInfo(native_profiles[1], 1011 "ExistingLabel", "Marion", "Mitchell", "Morrison", 1012 "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA", 1013 "91601", "US", "12345678910", "01987654321"); 1014 AutoFillProfile marion(*native_profiles[1]); 1015 AutoFillProfile josephine(*native_profiles[0]); 1016 1017 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). WillOnce(Return(true)); 1018 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)). 1019 WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true))); 1020 EXPECT_CALL(*personal_data_manager_, Refresh()); 1021 CreateRootTask task(this, syncable::AUTOFILL); 1022 StartSyncService(&task, false); 1023 ASSERT_TRUE(task.success()); 1024 MessageLoop::current()->RunAllPending(); 1025 Mock::VerifyAndClearExpectations(&web_database_); 1026 native_profiles.clear(); // Contents freed. 1027 1028 // Update josephine twice with marion's label. The second time ought to be 1029 // idempotent, settling on the same name and not triggering a sync upload. 1030 for (int pass = 0; pass < 2; ++pass) { 1031 AutoFillProfile josephine_update(josephine); 1032 josephine_update.set_label(ASCIIToUTF16("ExistingLabel")); 1033 1034 AutoFillProfile relabelled_profile; 1035 EXPECT_CALL(web_database_, UpdateAutoFillProfile( 1036 ProfileMatchesExceptLabel(josephine_update))). 1037 WillOnce(DoAll(SaveArg<0>(&relabelled_profile), Return(true))); 1038 EXPECT_CALL(*personal_data_manager_, Refresh()); 1039 1040 AutofillProfileChange change(AutofillProfileChange::UPDATE, 1041 josephine_update.Label(), &josephine_update, 1042 josephine.Label()); 1043 scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_); 1044 notifier->Notify(NotificationType::AUTOFILL_PROFILE_CHANGED, 1045 Source<WebDataService>(web_data_service_.get()), 1046 Details<AutofillProfileChange>(&change)); 1047 MessageLoop::current()->RunAllPending(); // Run the Refresh task. 1048 Mock::VerifyAndClearExpectations(&web_database_); 1049 1050 std::vector<AutofillEntry> new_sync_entries; 1051 std::vector<AutoFillProfile> new_sync_profiles; 1052 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, 1053 &new_sync_profiles)); 1054 ASSERT_EQ(2U, new_sync_profiles.size()); 1055 marion.set_unique_id(0); // The sync DB doesn't store IDs. 1056 EXPECT_EQ(marion, new_sync_profiles[1]); 1057 EXPECT_TRUE(ProfilesMatchExceptLabelImpl(josephine_update, 1058 new_sync_profiles[0])); 1059 EXPECT_EQ(ASCIIToUTF16("ExistingLabel2"), new_sync_profiles[0].Label()); 1060 EXPECT_EQ(ASCIIToUTF16("ExistingLabel2"), relabelled_profile.Label()); 1061 josephine = relabelled_profile; 1062 } 1063} 1064 1065TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeRemoveEntry) { 1066 AutofillEntry original_entry(MakeAutofillEntry("my", "entry", 1)); 1067 std::vector<AutofillEntry> original_entries; 1068 original_entries.push_back(original_entry); 1069 1070 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). 1071 WillOnce(DoAll(SetArgumentPointee<0>(original_entries), Return(true))); 1072 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true)); 1073 EXPECT_CALL(*personal_data_manager_, Refresh()); 1074 CreateRootTask task(this, syncable::AUTOFILL); 1075 StartSyncService(&task, false); 1076 ASSERT_TRUE(task.success()); 1077 1078 AutofillChangeList changes; 1079 changes.push_back(AutofillChange(AutofillChange::REMOVE, 1080 original_entry.key())); 1081 scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_); 1082 notifier->Notify(NotificationType::AUTOFILL_ENTRIES_CHANGED, 1083 Source<WebDataService>(web_data_service_.get()), 1084 Details<AutofillChangeList>(&changes)); 1085 1086 std::vector<AutofillEntry> new_sync_entries; 1087 std::vector<AutoFillProfile> new_sync_profiles; 1088 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, 1089 &new_sync_profiles)); 1090 ASSERT_EQ(0U, new_sync_entries.size()); 1091} 1092 1093TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeRemoveProfile) { 1094 AutoFillProfile sync_profile(string16(), 0); 1095 autofill_unittest::SetProfileInfo(&sync_profile, 1096 "Billing", "Josephine", "Alicia", "Saenz", 1097 "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL", 1098 "32801", "US", "19482937549", "13502849239"); 1099 AutoFillProfile* native_profile = new AutoFillProfile(string16(), 0); 1100 autofill_unittest::SetProfileInfo(native_profile, 1101 "Billing", "Josephine", "Alicia", "Saenz", 1102 "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL", 1103 "32801", "US", "19482937549", "13502849239"); 1104 1105 std::vector<AutoFillProfile*> native_profiles; 1106 native_profiles.push_back(native_profile); 1107 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). WillOnce(Return(true)); 1108 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)). 1109 WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true))); 1110 1111 std::vector<AutofillEntry> sync_entries; 1112 std::vector<AutoFillProfile> sync_profiles; 1113 sync_profiles.push_back(sync_profile); 1114 AddAutofillEntriesTask task(this, sync_entries, sync_profiles); 1115 EXPECT_CALL(*personal_data_manager_, Refresh()); 1116 StartSyncService(&task, false); 1117 ASSERT_TRUE(task.success()); 1118 1119 AutofillProfileChange change(AutofillProfileChange::REMOVE, 1120 sync_profile.Label(), NULL, string16()); 1121 scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_); 1122 notifier->Notify(NotificationType::AUTOFILL_PROFILE_CHANGED, 1123 Source<WebDataService>(web_data_service_.get()), 1124 Details<AutofillProfileChange>(&change)); 1125 1126 std::vector<AutofillEntry> new_sync_entries; 1127 std::vector<AutoFillProfile> new_sync_profiles; 1128 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, 1129 &new_sync_profiles)); 1130 ASSERT_EQ(0U, new_sync_entries.size()); 1131} 1132 1133TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeError) { 1134 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true)); 1135 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true)); 1136 EXPECT_CALL(*personal_data_manager_, Refresh()); 1137 CreateRootTask task(this, syncable::AUTOFILL); 1138 StartSyncService(&task, false); 1139 ASSERT_TRUE(task.success()); 1140 1141 // Inject an evil entry into the sync db to conflict with the same 1142 // entry added by the user. 1143 AutofillEntry evil_entry(MakeAutofillEntry("evil", "entry", 1)); 1144 ASSERT_TRUE(AddAutofillSyncNode(evil_entry)); 1145 1146 AutofillChangeList changes; 1147 changes.push_back(AutofillChange(AutofillChange::ADD, 1148 evil_entry.key())); 1149 scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_); 1150 notifier->Notify(NotificationType::AUTOFILL_ENTRIES_CHANGED, 1151 Source<WebDataService>(web_data_service_.get()), 1152 Details<AutofillChangeList>(&changes)); 1153 1154 // Wait for the PPS to shut everything down and signal us. 1155 ProfileSyncServiceObserverMock observer; 1156 service_->AddObserver(&observer); 1157 EXPECT_CALL(observer, OnStateChanged()).WillOnce(QuitUIMessageLoop()); 1158 MessageLoop::current()->Run(); 1159 EXPECT_TRUE(service_->unrecoverable_error_detected()); 1160 1161 // Ensure future autofill notifications don't crash. 1162 notifier->Notify(NotificationType::AUTOFILL_ENTRIES_CHANGED, 1163 Source<WebDataService>(web_data_service_.get()), 1164 Details<AutofillChangeList>(&changes)); 1165} 1166 1167TEST_F(ProfileSyncServiceAutofillTest, ServerChangeRace) { 1168 EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true)); 1169 EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true)); 1170 EXPECT_CALL(web_database_, UpdateAutofillEntries(_)). 1171 WillRepeatedly(Return(true)); 1172 EXPECT_CALL(*personal_data_manager_, Refresh()).Times(3); 1173 CreateRootTask task(this, syncable::AUTOFILL); 1174 StartSyncService(&task, false); 1175 ASSERT_TRUE(task.success()); 1176 1177 // (true, false) means we have to reset after |Signal|, init to unsignaled. 1178 scoped_ptr<WaitableEvent> wait_for_start(new WaitableEvent(true, false)); 1179 scoped_ptr<WaitableEvent> wait_for_syncapi(new WaitableEvent(true, false)); 1180 scoped_refptr<FakeServerUpdater> updater = new FakeServerUpdater( 1181 service_.get(), &wait_for_start, &wait_for_syncapi); 1182 1183 // This server side update will stall waiting for CommitWaiter. 1184 updater->CreateNewEntry(MakeAutofillEntry("server", "entry", 1)); 1185 wait_for_start->Wait(); 1186 1187 AutofillEntry syncapi_entry(MakeAutofillEntry("syncapi", "entry", 2)); 1188 ASSERT_TRUE(AddAutofillSyncNode(syncapi_entry)); 1189 LOG(INFO) << "Syncapi update finished."; 1190 1191 // If we reach here, it means syncapi succeeded and we didn't deadlock. Yay! 1192 // Signal FakeServerUpdater that it can complete. 1193 wait_for_syncapi->Signal(); 1194 1195 // Make another entry to ensure nothing broke afterwards and wait for finish 1196 // to clean up. 1197 updater->CreateNewEntryAndWait(MakeAutofillEntry("server2", "entry2", 3)); 1198 1199 std::vector<AutofillEntry> sync_entries; 1200 std::vector<AutoFillProfile> sync_profiles; 1201 ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles)); 1202 EXPECT_EQ(3U, sync_entries.size()); 1203 EXPECT_EQ(0U, sync_profiles.size()); 1204 for (size_t i = 0; i < sync_entries.size(); i++) { 1205 LOG(INFO) << "Entry " << i << ": " << sync_entries[i].key().name() << ", " 1206 << sync_entries[i].key().value(); 1207 } 1208} 1209