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