password_syncable_service_unittest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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 "components/password_manager/core/browser/password_syncable_service.h" 6 7#include <algorithm> 8#include <string> 9#include <vector> 10 11#include "base/basictypes.h" 12#include "base/location.h" 13#include "base/memory/ref_counted.h" 14#include "base/memory/scoped_ptr.h" 15#include "components/password_manager/core/browser/mock_password_store.h" 16#include "sync/api/sync_change_processor.h" 17#include "sync/api/sync_error.h" 18#include "sync/api/sync_error_factory.h" 19#include "testing/gmock/include/gmock/gmock.h" 20#include "testing/gtest/include/gtest/gtest.h" 21 22using syncer::SyncChange; 23using syncer::SyncData; 24using syncer::SyncDataList; 25using syncer::SyncError; 26using testing::Invoke; 27using testing::Return; 28using testing::SetArgPointee; 29using testing::_; 30 31namespace password_manager { 32 33namespace { 34 35typedef std::vector<SyncChange> SyncChangeList; 36 37const sync_pb::PasswordSpecificsData& GetPasswordSpecifics( 38 const syncer::SyncData& sync_data) { 39 const sync_pb::EntitySpecifics& specifics = sync_data.GetSpecifics(); 40 return specifics.password().client_only_encrypted_data(); 41} 42 43void PasswordsEqual(const sync_pb::PasswordSpecificsData& expected_password, 44 const sync_pb::PasswordSpecificsData& actual_password) { 45 EXPECT_EQ(expected_password.scheme(), actual_password.scheme()); 46 EXPECT_EQ(expected_password.signon_realm(), actual_password.signon_realm()); 47 EXPECT_EQ(expected_password.origin(), actual_password.origin()); 48 EXPECT_EQ(expected_password.action(), actual_password.action()); 49 EXPECT_EQ(expected_password.username_element(), 50 actual_password.username_element()); 51 EXPECT_EQ(expected_password.password_element(), 52 actual_password.password_element()); 53 EXPECT_EQ(expected_password.username_value(), 54 actual_password.username_value()); 55 EXPECT_EQ(expected_password.password_value(), 56 actual_password.password_value()); 57 EXPECT_EQ(expected_password.ssl_valid(), actual_password.ssl_valid()); 58 EXPECT_EQ(expected_password.preferred(), actual_password.preferred()); 59 EXPECT_EQ(expected_password.date_created(), actual_password.date_created()); 60 EXPECT_EQ(expected_password.blacklisted(), actual_password.blacklisted()); 61 EXPECT_EQ(expected_password.type(), actual_password.type()); 62 EXPECT_EQ(expected_password.times_used(), actual_password.times_used()); 63} 64 65// Creates a sync data consisting of password specifics. The sign on realm is 66// set to |signon_realm|. 67SyncData CreateSyncData(const std::string& signon_realm) { 68 sync_pb::EntitySpecifics password_data; 69 sync_pb::PasswordSpecificsData* password_specifics = 70 password_data.mutable_password()->mutable_client_only_encrypted_data(); 71 password_specifics->set_signon_realm(signon_realm); 72 password_specifics->set_type(autofill::PasswordForm::TYPE_GENERATED); 73 password_specifics->set_times_used(3); 74 75 std::string tag = MakePasswordSyncTag(*password_specifics); 76 return syncer::SyncData::CreateLocalData(tag, tag, password_data); 77} 78 79SyncChange CreateSyncChange(const autofill::PasswordForm& password, 80 SyncChange::SyncChangeType type) { 81 SyncData data = SyncDataFromPassword(password); 82 return SyncChange(FROM_HERE, type, data); 83} 84 85class FormFinder { 86 public: 87 explicit FormFinder(const autofill::PasswordForm& form) : form_(form) {} 88 ~FormFinder() {} 89 90 bool operator()(const autofill::PasswordForm& form) const; 91 92 private: 93 const autofill::PasswordForm form_; 94}; 95 96bool FormFinder::operator()(const autofill::PasswordForm& form) const { 97 return form.origin == form_.origin && 98 form.username_element == form_.username_element && 99 form.username_value == form_.username_value && 100 form.password_element == form_.password_element && 101 form.signon_realm == form_.signon_realm; 102} 103 104// A testable implementation of the |PasswordSyncableService| that mocks 105// out all interaction with the password database. 106class MockPasswordSyncableService : public PasswordSyncableService { 107 public: 108 explicit MockPasswordSyncableService(PasswordStoreSync* password_store) 109 : PasswordSyncableService(password_store) {} 110 virtual ~MockPasswordSyncableService() {} 111 112 MOCK_METHOD1(NotifyPasswordStoreOfLoginChanges, 113 void (const PasswordStoreChangeList&)); 114 115 MOCK_METHOD1(StartSyncFlare, void(syncer::ModelType)); 116}; 117 118// Class to verify the arguments passed to |PasswordStore|. 119class PasswordStoreDataVerifier { 120 public: 121 PasswordStoreDataVerifier() {} 122 ~PasswordStoreDataVerifier() { 123 EXPECT_TRUE(expected_db_add_changes_.empty()); 124 EXPECT_TRUE(expected_db_update_changes_.empty()); 125 EXPECT_TRUE(expected_db_delete_changes_.empty()); 126 } 127 128 class TestSyncChangeProcessor; 129 130 // Sets expected changes to the password database. 131 void SetExpectedDBChanges( 132 const SyncDataList& add_forms, 133 const std::vector<autofill::PasswordForm*>& update_forms, 134 const std::vector<autofill::PasswordForm*>& delete_forms, 135 MockPasswordStore* password_store); 136 // Sets expected changes to TestSyncChangeProcessor. 137 void SetExpectedSyncChanges(SyncChangeList list); 138 139 private: 140 // Checks that |change_list| matches |expected_sync_change_list_|. 141 SyncError TestSyncChanges(const SyncChangeList& change_list); 142 143 // Verifies that the |password| is present in the |expected_db_add_changes_| 144 // list. If found, |password| would be removed from 145 // |expected_db_add_changes_| list. 146 PasswordStoreChangeList VerifyAdd(const autofill::PasswordForm& password) { 147 return VerifyChange(PasswordStoreChange::ADD, password, 148 &expected_db_add_changes_); 149 } 150 151 // Verifies that the |password| is present in the 152 // |expected_db_update_changes_| list. If found, |password| would be removed 153 // from |expected_db_update_changes_| list. 154 PasswordStoreChangeList VerifyUpdate(const autofill::PasswordForm& password) { 155 return VerifyChange(PasswordStoreChange::UPDATE, password, 156 &expected_db_update_changes_); 157 } 158 159 // Verifies that the |password| is present in the 160 // |expected_db_delete_changes_| list. If found, |password| would be removed 161 // from |expected_db_delete_changes_| list. 162 PasswordStoreChangeList VerifyDelete(const autofill::PasswordForm& password) { 163 return VerifyChange(PasswordStoreChange::REMOVE, password, 164 &expected_db_delete_changes_); 165 } 166 167 static PasswordStoreChangeList VerifyChange( 168 PasswordStoreChange::Type type, 169 const autofill::PasswordForm& password, 170 std::vector<autofill::PasswordForm>* password_list); 171 172 std::vector<autofill::PasswordForm> expected_db_add_changes_; 173 std::vector<autofill::PasswordForm> expected_db_update_changes_; 174 std::vector<autofill::PasswordForm> expected_db_delete_changes_; 175 SyncChangeList expected_sync_change_list_; 176 177 DISALLOW_COPY_AND_ASSIGN(PasswordStoreDataVerifier); 178}; 179 180class PasswordStoreDataVerifier::TestSyncChangeProcessor 181 : public syncer::SyncChangeProcessor { 182 public: 183 explicit TestSyncChangeProcessor(PasswordStoreDataVerifier* verifier) 184 : verifier_(verifier) { 185 } 186 virtual ~TestSyncChangeProcessor() {} 187 188 virtual SyncError ProcessSyncChanges(const tracked_objects::Location&, 189 const SyncChangeList& list) OVERRIDE { 190 return verifier_->TestSyncChanges(list); 191 } 192 193 virtual SyncDataList GetAllSyncData(syncer::ModelType type) const OVERRIDE { 194 return SyncDataList(); 195 } 196 private: 197 PasswordStoreDataVerifier* verifier_; 198 199 DISALLOW_COPY_AND_ASSIGN(TestSyncChangeProcessor); 200}; 201 202void PasswordStoreDataVerifier::SetExpectedDBChanges( 203 const SyncDataList& add_forms, 204 const std::vector<autofill::PasswordForm*>& update_forms, 205 const std::vector<autofill::PasswordForm*>& delete_forms, 206 MockPasswordStore* password_store) { 207 DCHECK(expected_db_add_changes_.empty()); 208 DCHECK(expected_db_update_changes_.empty()); 209 DCHECK(password_store); 210 211 for (SyncDataList::const_iterator it = add_forms.begin(); 212 it != add_forms.end(); ++it) { 213 autofill::PasswordForm form; 214 PasswordFromSpecifics(GetPasswordSpecifics(*it), &form); 215 expected_db_add_changes_.push_back(form); 216 } 217 if (expected_db_add_changes_.empty()) { 218 EXPECT_CALL(*password_store, AddLoginImpl(_)).Times(0); 219 } else { 220 EXPECT_CALL(*password_store, AddLoginImpl(_)) 221 .Times(expected_db_add_changes_.size()) 222 .WillRepeatedly(Invoke(this, &PasswordStoreDataVerifier::VerifyAdd)); 223 } 224 225 for (std::vector<autofill::PasswordForm*>::const_iterator it = 226 update_forms.begin(); 227 it != update_forms.end(); ++it) { 228 expected_db_update_changes_.push_back(**it); 229 } 230 if (expected_db_update_changes_.empty()) { 231 EXPECT_CALL(*password_store, UpdateLoginImpl(_)).Times(0); 232 } else { 233 EXPECT_CALL(*password_store, UpdateLoginImpl(_)) 234 .Times(expected_db_update_changes_.size()) 235 .WillRepeatedly(Invoke(this, &PasswordStoreDataVerifier::VerifyUpdate)); 236 } 237 238 for (std::vector<autofill::PasswordForm*>::const_iterator it = 239 delete_forms.begin(); 240 it != delete_forms.end(); ++it) { 241 expected_db_delete_changes_.push_back(**it); 242 } 243 if (expected_db_delete_changes_.empty()) { 244 EXPECT_CALL(*password_store, RemoveLoginImpl(_)).Times(0); 245 } else { 246 EXPECT_CALL(*password_store, RemoveLoginImpl(_)) 247 .Times(expected_db_delete_changes_.size()) 248 .WillRepeatedly(Invoke(this, &PasswordStoreDataVerifier::VerifyDelete)); 249 } 250} 251 252void PasswordStoreDataVerifier::SetExpectedSyncChanges(SyncChangeList list) { 253 expected_sync_change_list_.swap(list); 254} 255 256SyncError PasswordStoreDataVerifier::TestSyncChanges( 257 const SyncChangeList& change_list) { 258 for (SyncChangeList::const_iterator it = change_list.begin(); 259 it != change_list.end(); ++it) { 260 SyncData data = it->sync_data(); 261 std::string actual_tag = syncer::SyncDataLocal(data).GetTag(); 262 263 bool matched = false; 264 for (SyncChangeList::iterator expected_it = 265 expected_sync_change_list_.begin(); 266 expected_it != expected_sync_change_list_.end(); 267 ++expected_it) { 268 const sync_pb::PasswordSpecificsData& expected_password( 269 GetPasswordSpecifics(expected_it->sync_data())); 270 if (actual_tag == MakePasswordSyncTag(expected_password)) { 271 EXPECT_EQ(expected_it->change_type(), it->change_type()); 272 matched = true; 273 if (it->change_type() != SyncChange::ACTION_DELETE) 274 PasswordsEqual(expected_password, GetPasswordSpecifics(data)); 275 break; 276 } 277 } 278 EXPECT_TRUE(matched) << actual_tag; 279 } 280 EXPECT_EQ(expected_sync_change_list_.size(), change_list.size()); 281 return SyncError(); 282} 283 284// static 285PasswordStoreChangeList PasswordStoreDataVerifier::VerifyChange( 286 PasswordStoreChange::Type type, 287 const autofill::PasswordForm& password, 288 std::vector<autofill::PasswordForm>* password_list) { 289 std::vector<autofill::PasswordForm>::iterator it = std::find_if( 290 password_list->begin(), password_list->end(), FormFinder(password)); 291 EXPECT_NE(password_list->end(), it); 292 PasswordsEqual(GetPasswordSpecifics(SyncDataFromPassword(*it)), 293 GetPasswordSpecifics(SyncDataFromPassword(password))); 294 if (type != PasswordStoreChange::REMOVE) { 295 EXPECT_FALSE(password.date_synced.is_null()) << password.signon_realm; 296 EXPECT_FALSE(password.date_synced.is_max()) << password.signon_realm; 297 } 298 password_list->erase(it); 299 return PasswordStoreChangeList(1, PasswordStoreChange(type, password)); 300} 301 302class PasswordSyncableServiceWrapper { 303 public: 304 PasswordSyncableServiceWrapper() { 305 password_store_ = new MockPasswordStore; 306 service_.reset(new MockPasswordSyncableService( 307 password_store_->GetSyncInterface())); 308 } 309 310 ~PasswordSyncableServiceWrapper() { 311 password_store_->Shutdown(); 312 } 313 314 MockPasswordStore* password_store() { 315 return password_store_; 316 } 317 318 MockPasswordSyncableService* service() { 319 return service_.get(); 320 } 321 322 // Returnes the scoped_ptr to |service_| thus NULLing out it. 323 scoped_ptr<syncer::SyncChangeProcessor> ReleaseSyncableService() { 324 return service_.PassAs<syncer::SyncChangeProcessor>(); 325 } 326 327 PasswordStoreDataVerifier* verifier() { 328 return &verifier_; 329 } 330 331 scoped_ptr<syncer::SyncChangeProcessor> CreateSyncChangeProcessor() { 332 return make_scoped_ptr<syncer::SyncChangeProcessor>( 333 new PasswordStoreDataVerifier::TestSyncChangeProcessor(verifier())); 334 } 335 336 // Sets the data that will be returned to the caller accessing password store. 337 void SetPasswordStoreData( 338 const std::vector<autofill::PasswordForm*>& forms, 339 const std::vector<autofill::PasswordForm*>& blacklist_forms) { 340 EXPECT_CALL(*password_store_, FillAutofillableLogins(_)) 341 .WillOnce(Invoke(AppendVector(forms))) 342 .RetiresOnSaturation(); 343 EXPECT_CALL(*password_store_, FillBlacklistLogins(_)) 344 .WillOnce(Invoke(AppendVector(blacklist_forms))) 345 .RetiresOnSaturation(); 346 } 347 348 protected: 349 scoped_refptr<MockPasswordStore> password_store_; 350 scoped_ptr<MockPasswordSyncableService> service_; 351 PasswordStoreDataVerifier verifier_; 352 353 private: 354 struct AppendVector { 355 explicit AppendVector( 356 const std::vector<autofill::PasswordForm*>& append_forms) 357 : append_forms_(append_forms) { 358 } 359 360 ~AppendVector() {} 361 362 bool operator()(std::vector<autofill::PasswordForm*>* forms) const { 363 forms->insert(forms->end(), append_forms_.begin(), append_forms_.end()); 364 return true; 365 } 366 367 std::vector<autofill::PasswordForm*> append_forms_; 368 }; 369 370 DISALLOW_COPY_AND_ASSIGN(PasswordSyncableServiceWrapper); 371}; 372 373class PasswordSyncableServiceTest : public testing::Test, 374 public PasswordSyncableServiceWrapper { 375 public: 376 PasswordSyncableServiceTest() {} 377 virtual ~PasswordSyncableServiceTest() {} 378}; 379 380 381// Both sync and password db have data that are not present in the other. 382TEST_F(PasswordSyncableServiceTest, AdditionsInBoth) { 383 scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm); 384 form1->signon_realm = "abc"; 385 std::vector<autofill::PasswordForm*> forms; 386 forms.push_back(form1.release()); 387 SetPasswordStoreData(forms, std::vector<autofill::PasswordForm*>()); 388 389 SyncData sync_data = CreateSyncData("def"); 390 SyncDataList list; 391 list.push_back(sync_data); 392 393 verifier()->SetExpectedDBChanges(list, 394 std::vector<autofill::PasswordForm*>(), 395 std::vector<autofill::PasswordForm*>(), 396 password_store()); 397 verifier()->SetExpectedSyncChanges( 398 SyncChangeList(1, CreateSyncChange(*forms[0], SyncChange::ACTION_ADD))); 399 EXPECT_CALL(*service(), NotifyPasswordStoreOfLoginChanges(_)); 400 401 service()->MergeDataAndStartSyncing(syncer::PASSWORDS, 402 list, 403 CreateSyncChangeProcessor(), 404 scoped_ptr<syncer::SyncErrorFactory>()); 405} 406 407// Sync has data that is not present in the password db. 408TEST_F(PasswordSyncableServiceTest, AdditionOnlyInSync) { 409 SetPasswordStoreData(std::vector<autofill::PasswordForm*>(), 410 std::vector<autofill::PasswordForm*>()); 411 412 SyncData sync_data = CreateSyncData("def"); 413 SyncDataList list; 414 list.push_back(sync_data); 415 416 verifier()->SetExpectedDBChanges(list, 417 std::vector<autofill::PasswordForm*>(), 418 std::vector<autofill::PasswordForm*>(), 419 password_store()); 420 verifier()->SetExpectedSyncChanges(SyncChangeList()); 421 EXPECT_CALL(*service(), NotifyPasswordStoreOfLoginChanges(_)); 422 423 service()->MergeDataAndStartSyncing(syncer::PASSWORDS, 424 list, 425 CreateSyncChangeProcessor(), 426 scoped_ptr<syncer::SyncErrorFactory>()); 427} 428 429// Passwords db has data that is not present in sync. 430TEST_F(PasswordSyncableServiceTest, AdditionOnlyInPasswordStore) { 431 scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm); 432 form1->signon_realm = "abc"; 433 form1->times_used = 2; 434 form1->type = autofill::PasswordForm::TYPE_GENERATED; 435 std::vector<autofill::PasswordForm*> forms; 436 forms.push_back(form1.release()); 437 SetPasswordStoreData(forms, std::vector<autofill::PasswordForm*>()); 438 439 verifier()->SetExpectedDBChanges(SyncDataList(), 440 std::vector<autofill::PasswordForm*>(), 441 std::vector<autofill::PasswordForm*>(), 442 password_store()); 443 verifier()->SetExpectedSyncChanges( 444 SyncChangeList(1, CreateSyncChange(*forms[0], SyncChange::ACTION_ADD))); 445 EXPECT_CALL(*service_, 446 NotifyPasswordStoreOfLoginChanges(PasswordStoreChangeList())); 447 448 service()->MergeDataAndStartSyncing(syncer::PASSWORDS, 449 SyncDataList(), 450 CreateSyncChangeProcessor(), 451 scoped_ptr<syncer::SyncErrorFactory>()); 452} 453 454// Both passwords db and sync contain the same data. 455TEST_F(PasswordSyncableServiceTest, BothInSync) { 456 scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm); 457 form1->signon_realm = "abc"; 458 form1->times_used = 3; 459 form1->type = autofill::PasswordForm::TYPE_GENERATED; 460 std::vector<autofill::PasswordForm*> forms; 461 forms.push_back(form1.release()); 462 SetPasswordStoreData(forms, std::vector<autofill::PasswordForm*>()); 463 464 verifier()->SetExpectedDBChanges(SyncDataList(), 465 std::vector<autofill::PasswordForm*>(), 466 std::vector<autofill::PasswordForm*>(), 467 password_store()); 468 verifier()->SetExpectedSyncChanges(SyncChangeList()); 469 EXPECT_CALL(*service_, 470 NotifyPasswordStoreOfLoginChanges(PasswordStoreChangeList())); 471 472 service()->MergeDataAndStartSyncing(syncer::PASSWORDS, 473 SyncDataList(1, CreateSyncData("abc")), 474 CreateSyncChangeProcessor(), 475 scoped_ptr<syncer::SyncErrorFactory>()); 476} 477 478// Both passwords db and sync have the same data but they need to be merged 479// as some fields of the data differ. 480TEST_F(PasswordSyncableServiceTest, Merge) { 481 scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm); 482 form1->signon_realm = "abc"; 483 form1->action = GURL("http://pie.com"); 484 form1->date_created = base::Time::Now(); 485 form1->preferred = true; 486 std::vector<autofill::PasswordForm*> forms; 487 forms.push_back(form1.release()); 488 SetPasswordStoreData(forms, std::vector<autofill::PasswordForm*>()); 489 490 autofill::PasswordForm form2(*forms[0]); 491 form2.preferred = false; 492 verifier()->SetExpectedDBChanges(SyncDataList(), 493 std::vector<autofill::PasswordForm*>(1, 494 &form2), 495 std::vector<autofill::PasswordForm*>(), 496 password_store()); 497 verifier()->SetExpectedSyncChanges(SyncChangeList()); 498 499 EXPECT_CALL(*service(), NotifyPasswordStoreOfLoginChanges(_)); 500 501 service()->MergeDataAndStartSyncing(syncer::PASSWORDS, 502 SyncDataList(1, 503 SyncDataFromPassword(form2)), 504 CreateSyncChangeProcessor(), 505 scoped_ptr<syncer::SyncErrorFactory>()); 506} 507 508// Initiate sync due to local DB changes. 509TEST_F(PasswordSyncableServiceTest, PasswordStoreChanges) { 510 // Set the sync change processor first. 511 SetPasswordStoreData(std::vector<autofill::PasswordForm*>(), 512 std::vector<autofill::PasswordForm*>()); 513 verifier()->SetExpectedSyncChanges(SyncChangeList()); 514 EXPECT_CALL(*service_, 515 NotifyPasswordStoreOfLoginChanges(PasswordStoreChangeList())); 516 service_->MergeDataAndStartSyncing(syncer::PASSWORDS, 517 SyncDataList(), 518 CreateSyncChangeProcessor(), 519 scoped_ptr<syncer::SyncErrorFactory>()); 520 521 autofill::PasswordForm form1; 522 form1.signon_realm = "abc"; 523 autofill::PasswordForm form2; 524 form2.signon_realm = "def"; 525 autofill::PasswordForm form3; 526 form3.signon_realm = "xyz"; 527 528 SyncChangeList sync_list; 529 sync_list.push_back(CreateSyncChange(form1, SyncChange::ACTION_ADD)); 530 sync_list.push_back(CreateSyncChange(form2, SyncChange::ACTION_UPDATE)); 531 sync_list.push_back(CreateSyncChange(form3, SyncChange::ACTION_DELETE)); 532 533 verifier()->SetExpectedDBChanges(SyncDataList(), 534 std::vector<autofill::PasswordForm*>(), 535 std::vector<autofill::PasswordForm*>(), 536 password_store()); 537 verifier()->SetExpectedSyncChanges(sync_list); 538 539 PasswordStoreChangeList list; 540 list.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form1)); 541 list.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE, form2)); 542 list.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form3)); 543 service()->ActOnPasswordStoreChanges(list); 544} 545 546// Process all types of changes from sync. 547TEST_F(PasswordSyncableServiceTest, ProcessSyncChanges) { 548 autofill::PasswordForm updated_form; 549 updated_form.signon_realm = "abc"; 550 updated_form.action = GURL("http://foo.com"); 551 updated_form.date_created = base::Time::Now(); 552 autofill::PasswordForm deleted_form; 553 deleted_form.signon_realm = "xyz"; 554 deleted_form.action = GURL("http://bar.com"); 555 deleted_form.blacklisted_by_user = true; 556 557 SyncData add_data = CreateSyncData("def"); 558 std::vector<autofill::PasswordForm*> updated_passwords(1, &updated_form); 559 std::vector<autofill::PasswordForm*> deleted_passwords(1, &deleted_form); 560 verifier()->SetExpectedDBChanges(SyncDataList(1, add_data), 561 updated_passwords, 562 deleted_passwords, 563 password_store()); 564 565 SyncChangeList list; 566 list.push_back(SyncChange(FROM_HERE, 567 syncer::SyncChange::ACTION_ADD, 568 add_data)); 569 list.push_back(CreateSyncChange(updated_form, 570 syncer::SyncChange::ACTION_UPDATE)); 571 list.push_back(CreateSyncChange(deleted_form, 572 syncer::SyncChange::ACTION_DELETE)); 573 EXPECT_CALL(*service(), NotifyPasswordStoreOfLoginChanges(_)); 574 service()->ProcessSyncChanges(FROM_HERE, list); 575} 576 577// Retrives sync data from the model. 578TEST_F(PasswordSyncableServiceTest, GetAllSyncData) { 579 scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm); 580 form1->signon_realm = "abc"; 581 form1->action = GURL("http://foo.com"); 582 form1->times_used = 5; 583 form1->type = autofill::PasswordForm::TYPE_GENERATED; 584 scoped_ptr<autofill::PasswordForm> form2(new autofill::PasswordForm); 585 form2->signon_realm = "xyz"; 586 form2->action = GURL("http://bar.com"); 587 form2->blacklisted_by_user = true; 588 std::vector<autofill::PasswordForm*> forms(1, form1.release()); 589 std::vector<autofill::PasswordForm*> blacklist_forms(1, form2.release()); 590 SetPasswordStoreData(forms, blacklist_forms); 591 592 SyncDataList expected_list; 593 expected_list.push_back(SyncDataFromPassword(*forms[0])); 594 expected_list.push_back(SyncDataFromPassword(*blacklist_forms[0])); 595 596 verifier()->SetExpectedDBChanges(SyncDataList(), 597 std::vector<autofill::PasswordForm*>(), 598 std::vector<autofill::PasswordForm*>(), 599 password_store()); 600 601 SyncDataList actual_list = service()->GetAllSyncData(syncer::PASSWORDS); 602 EXPECT_EQ(expected_list.size(), actual_list.size()); 603 for (SyncDataList::iterator i(actual_list.begin()), j(expected_list.begin()); 604 i != actual_list.end() && j != expected_list.end(); ++i, ++j) { 605 PasswordsEqual(GetPasswordSpecifics(*j), GetPasswordSpecifics(*i)); 606 } 607} 608 609// Creates 2 PasswordSyncableService instances, merges the content of the first 610// one to the second one and back. 611TEST_F(PasswordSyncableServiceTest, MergeDataAndPushBack) { 612 scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm); 613 form1->signon_realm = "abc"; 614 form1->action = GURL("http://foo.com"); 615 std::vector<autofill::PasswordForm*> forms(1, form1.release()); 616 SetPasswordStoreData(forms, std::vector<autofill::PasswordForm*>()); 617 618 PasswordSyncableServiceWrapper other_service_wrapper; 619 scoped_ptr<autofill::PasswordForm> form2(new autofill::PasswordForm); 620 form2->signon_realm = "xyz"; 621 form2->action = GURL("http://bar.com"); 622 syncer::SyncData form2_sync_data = SyncDataFromPassword(*form2); 623 other_service_wrapper.SetPasswordStoreData( 624 std::vector<autofill::PasswordForm*>(1, form2.release()), 625 std::vector<autofill::PasswordForm*>()); 626 627 verifier()->SetExpectedDBChanges(SyncDataList(1, form2_sync_data), 628 std::vector<autofill::PasswordForm*>(), 629 std::vector<autofill::PasswordForm*>(), 630 password_store()); 631 other_service_wrapper.verifier()->SetExpectedDBChanges( 632 SyncDataList(1, SyncDataFromPassword(*forms[0])), 633 std::vector<autofill::PasswordForm*>(), 634 std::vector<autofill::PasswordForm*>(), 635 other_service_wrapper.password_store()); 636 EXPECT_CALL(*service(), NotifyPasswordStoreOfLoginChanges(_)); 637 EXPECT_CALL(*other_service_wrapper.service(), 638 NotifyPasswordStoreOfLoginChanges(_)); 639 640 syncer::SyncDataList other_service_data = 641 other_service_wrapper.service()->GetAllSyncData(syncer::PASSWORDS); 642 service()->MergeDataAndStartSyncing( 643 syncer::PASSWORDS, 644 other_service_data, 645 other_service_wrapper.ReleaseSyncableService(), 646 scoped_ptr<syncer::SyncErrorFactory>()); 647} 648 649// Calls ActOnPasswordStoreChanges without SyncChangeProcessor. StartSyncFlare 650// should be called. 651TEST_F(PasswordSyncableServiceTest, StartSyncFlare) { 652 autofill::PasswordForm form; 653 form.signon_realm = "abc"; 654 PasswordStoreChangeList list; 655 list.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form)); 656 657 // No flare and no SyncChangeProcessor, the call shouldn't crash. 658 service()->ActOnPasswordStoreChanges(list); 659 660 // Set the flare. It should be called as there is no SyncChangeProcessor. 661 service()->InjectStartSyncFlare( 662 base::Bind(&MockPasswordSyncableService::StartSyncFlare, 663 base::Unretained(service()))); 664 EXPECT_CALL(*service(), StartSyncFlare(syncer::PASSWORDS)); 665 service()->ActOnPasswordStoreChanges(list); 666} 667 668} // namespace 669 670} // namespace password_manager 671