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.
5 #include "components/password_manager/core/browser/password_syncable_service.h"
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"
22 using syncer::SyncChange;
23 using syncer::SyncData;
24 using syncer::SyncDataList;
25 using syncer::SyncError;
26 using testing::Invoke;
27 using testing::Return;
28 using testing::SetArgPointee;
31 namespace password_manager {
35 typedef std::vector<SyncChange> SyncChangeList;
37 const 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();
43 void 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());
65 // Creates a sync data consisting of password specifics. The sign on realm is
66 // set to |signon_realm|.
67 SyncData 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);
75 std::string tag = MakePasswordSyncTag(*password_specifics);
76 return syncer::SyncData::CreateLocalData(tag, tag, password_data);
79 SyncChange CreateSyncChange(const autofill::PasswordForm& password,
80 SyncChange::SyncChangeType type) {
81 SyncData data = SyncDataFromPassword(password);
82 return SyncChange(FROM_HERE, type, data);
85 // A testable implementation of the |PasswordSyncableService| that mocks
86 // out all interaction with the password database.
87 class MockPasswordSyncableService : public PasswordSyncableService {
89 explicit MockPasswordSyncableService(PasswordStoreSync* password_store)
90 : PasswordSyncableService(password_store) {}
91 virtual ~MockPasswordSyncableService() {}
93 MOCK_METHOD1(NotifyPasswordStoreOfLoginChanges,
94 void (const PasswordStoreChangeList&));
96 MOCK_METHOD1(StartSyncFlare, void(syncer::ModelType));
99 // Class to verify the arguments passed to |PasswordStore|.
100 class PasswordStoreDataVerifier {
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());
109 class TestSyncChangeProcessor;
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);
121 // Checks that |change_list| matches |expected_sync_change_list_|.
122 SyncError TestSyncChanges(const SyncChangeList& change_list);
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_);
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_);
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_);
148 static PasswordStoreChangeList VerifyChange(
149 PasswordStoreChange::Type type,
150 const autofill::PasswordForm& password,
151 std::vector<autofill::PasswordForm>* password_list);
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_;
158 DISALLOW_COPY_AND_ASSIGN(PasswordStoreDataVerifier);
161 class PasswordStoreDataVerifier::TestSyncChangeProcessor
162 : public syncer::SyncChangeProcessor {
164 explicit TestSyncChangeProcessor(PasswordStoreDataVerifier* verifier)
165 : verifier_(verifier) {
167 virtual ~TestSyncChangeProcessor() {}
169 virtual SyncError ProcessSyncChanges(const tracked_objects::Location&,
170 const SyncChangeList& list) OVERRIDE {
171 return verifier_->TestSyncChanges(list);
174 virtual SyncDataList GetAllSyncData(syncer::ModelType type) const OVERRIDE {
175 return SyncDataList();
178 PasswordStoreDataVerifier* verifier_;
180 DISALLOW_COPY_AND_ASSIGN(TestSyncChangeProcessor);
183 void 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);
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);
198 if (expected_db_add_changes_.empty()) {
199 EXPECT_CALL(*password_store, AddLoginImpl(_)).Times(0);
201 EXPECT_CALL(*password_store, AddLoginImpl(_))
202 .Times(expected_db_add_changes_.size())
203 .WillRepeatedly(Invoke(this, &PasswordStoreDataVerifier::VerifyAdd));
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);
211 if (expected_db_update_changes_.empty()) {
212 EXPECT_CALL(*password_store, UpdateLoginImpl(_)).Times(0);
214 EXPECT_CALL(*password_store, UpdateLoginImpl(_))
215 .Times(expected_db_update_changes_.size())
216 .WillRepeatedly(Invoke(this, &PasswordStoreDataVerifier::VerifyUpdate));
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);
224 if (expected_db_delete_changes_.empty()) {
225 EXPECT_CALL(*password_store, RemoveLoginImpl(_)).Times(0);
227 EXPECT_CALL(*password_store, RemoveLoginImpl(_))
228 .Times(expected_db_delete_changes_.size())
229 .WillRepeatedly(Invoke(this, &PasswordStoreDataVerifier::VerifyDelete));
233 void PasswordStoreDataVerifier::SetExpectedSyncChanges(SyncChangeList list) {
234 expected_sync_change_list_.swap(list);
237 SyncError 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);
246 bool matched = false;
247 for (SyncChangeList::iterator expected_it =
248 expected_sync_change_list_.begin();
249 expected_it != expected_sync_change_list_.end();
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());
260 EXPECT_TRUE(matched) << actual_tag;
262 EXPECT_EQ(expected_sync_change_list_.size(), change_list.size());
267 PasswordStoreChangeList 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));
278 class PasswordSyncableServiceWrapper {
280 PasswordSyncableServiceWrapper() {
281 password_store_ = new MockPasswordStore;
282 service_.reset(new MockPasswordSyncableService(
283 password_store_->GetSyncInterface()));
286 ~PasswordSyncableServiceWrapper() {
287 password_store_->Shutdown();
290 MockPasswordStore* password_store() {
291 return password_store_;
294 MockPasswordSyncableService* service() {
295 return service_.get();
298 // Returnes the scoped_ptr to |service_| thus NULLing out it.
299 scoped_ptr<syncer::SyncChangeProcessor> ReleaseSyncableService() {
300 return service_.PassAs<syncer::SyncChangeProcessor>();
303 PasswordStoreDataVerifier* verifier() {
307 scoped_ptr<syncer::SyncChangeProcessor> CreateSyncChangeProcessor() {
308 return make_scoped_ptr<syncer::SyncChangeProcessor>(
309 new PasswordStoreDataVerifier::TestSyncChangeProcessor(verifier()));
312 // Sets the data that will be returned to the caller accessing password store.
313 void SetPasswordStoreData(
314 const std::vector<autofill::PasswordForm*>& forms,
315 const std::vector<autofill::PasswordForm*>& blacklist_forms) {
316 EXPECT_CALL(*password_store_, FillAutofillableLogins(_))
317 .WillOnce(Invoke(AppendVector(forms)))
318 .RetiresOnSaturation();
319 EXPECT_CALL(*password_store_, FillBlacklistLogins(_))
320 .WillOnce(Invoke(AppendVector(blacklist_forms)))
321 .RetiresOnSaturation();
325 scoped_refptr<MockPasswordStore> password_store_;
326 scoped_ptr<MockPasswordSyncableService> service_;
327 PasswordStoreDataVerifier verifier_;
330 struct AppendVector {
331 explicit AppendVector(
332 const std::vector<autofill::PasswordForm*>& append_forms)
333 : append_forms_(append_forms) {
338 bool operator()(std::vector<autofill::PasswordForm*>* forms) const {
339 forms->insert(forms->end(), append_forms_.begin(), append_forms_.end());
343 std::vector<autofill::PasswordForm*> append_forms_;
346 DISALLOW_COPY_AND_ASSIGN(PasswordSyncableServiceWrapper);
349 class PasswordSyncableServiceTest : public testing::Test,
350 public PasswordSyncableServiceWrapper {
352 PasswordSyncableServiceTest() {}
353 virtual ~PasswordSyncableServiceTest() {}
357 // Both sync and password db have data that are not present in the other.
358 TEST_F(PasswordSyncableServiceTest, AdditionsInBoth) {
359 scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm);
360 form1->signon_realm = "abc";
361 std::vector<autofill::PasswordForm*> forms;
362 forms.push_back(form1.release());
363 SetPasswordStoreData(forms, std::vector<autofill::PasswordForm*>());
365 SyncData sync_data = CreateSyncData("def");
367 list.push_back(sync_data);
369 verifier()->SetExpectedDBChanges(list,
370 std::vector<autofill::PasswordForm*>(),
371 std::vector<autofill::PasswordForm*>(),
373 verifier()->SetExpectedSyncChanges(
374 SyncChangeList(1, CreateSyncChange(*forms[0], SyncChange::ACTION_ADD)));
375 EXPECT_CALL(*service(), NotifyPasswordStoreOfLoginChanges(_));
377 service()->MergeDataAndStartSyncing(syncer::PASSWORDS,
379 CreateSyncChangeProcessor(),
380 scoped_ptr<syncer::SyncErrorFactory>());
383 // Sync has data that is not present in the password db.
384 TEST_F(PasswordSyncableServiceTest, AdditionOnlyInSync) {
385 SetPasswordStoreData(std::vector<autofill::PasswordForm*>(),
386 std::vector<autofill::PasswordForm*>());
388 SyncData sync_data = CreateSyncData("def");
390 list.push_back(sync_data);
392 verifier()->SetExpectedDBChanges(list,
393 std::vector<autofill::PasswordForm*>(),
394 std::vector<autofill::PasswordForm*>(),
396 verifier()->SetExpectedSyncChanges(SyncChangeList());
397 EXPECT_CALL(*service(), NotifyPasswordStoreOfLoginChanges(_));
399 service()->MergeDataAndStartSyncing(syncer::PASSWORDS,
401 CreateSyncChangeProcessor(),
402 scoped_ptr<syncer::SyncErrorFactory>());
405 // Passwords db has data that is not present in sync.
406 TEST_F(PasswordSyncableServiceTest, AdditionOnlyInPasswordStore) {
407 scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm);
408 form1->signon_realm = "abc";
409 form1->times_used = 2;
410 form1->type = autofill::PasswordForm::TYPE_GENERATED;
411 std::vector<autofill::PasswordForm*> forms;
412 forms.push_back(form1.release());
413 SetPasswordStoreData(forms, std::vector<autofill::PasswordForm*>());
415 verifier()->SetExpectedDBChanges(SyncDataList(),
416 std::vector<autofill::PasswordForm*>(),
417 std::vector<autofill::PasswordForm*>(),
419 verifier()->SetExpectedSyncChanges(
420 SyncChangeList(1, CreateSyncChange(*forms[0], SyncChange::ACTION_ADD)));
421 EXPECT_CALL(*service_,
422 NotifyPasswordStoreOfLoginChanges(PasswordStoreChangeList()));
424 service()->MergeDataAndStartSyncing(syncer::PASSWORDS,
426 CreateSyncChangeProcessor(),
427 scoped_ptr<syncer::SyncErrorFactory>());
430 // Both passwords db and sync contain the same data.
431 TEST_F(PasswordSyncableServiceTest, BothInSync) {
432 scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm);
433 form1->signon_realm = "abc";
434 form1->times_used = 3;
435 form1->type = autofill::PasswordForm::TYPE_GENERATED;
436 std::vector<autofill::PasswordForm*> forms;
437 forms.push_back(form1.release());
438 SetPasswordStoreData(forms, std::vector<autofill::PasswordForm*>());
440 verifier()->SetExpectedDBChanges(SyncDataList(),
441 std::vector<autofill::PasswordForm*>(),
442 std::vector<autofill::PasswordForm*>(),
444 verifier()->SetExpectedSyncChanges(SyncChangeList());
445 EXPECT_CALL(*service_,
446 NotifyPasswordStoreOfLoginChanges(PasswordStoreChangeList()));
448 service()->MergeDataAndStartSyncing(syncer::PASSWORDS,
449 SyncDataList(1, CreateSyncData("abc")),
450 CreateSyncChangeProcessor(),
451 scoped_ptr<syncer::SyncErrorFactory>());
454 // Both passwords db and sync have the same data but they need to be merged
455 // as some fields of the data differ.
456 TEST_F(PasswordSyncableServiceTest, Merge) {
457 scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm);
458 form1->signon_realm = "abc";
459 form1->action = GURL("http://pie.com");
460 form1->date_created = base::Time::Now();
461 form1->preferred = true;
462 std::vector<autofill::PasswordForm*> forms;
463 forms.push_back(form1.release());
464 SetPasswordStoreData(forms, std::vector<autofill::PasswordForm*>());
466 autofill::PasswordForm form2(*forms[0]);
467 form2.preferred = false;
468 verifier()->SetExpectedDBChanges(SyncDataList(),
469 std::vector<autofill::PasswordForm*>(1,
471 std::vector<autofill::PasswordForm*>(),
473 verifier()->SetExpectedSyncChanges(SyncChangeList());
475 EXPECT_CALL(*service(), NotifyPasswordStoreOfLoginChanges(_));
477 service()->MergeDataAndStartSyncing(syncer::PASSWORDS,
479 SyncDataFromPassword(form2)),
480 CreateSyncChangeProcessor(),
481 scoped_ptr<syncer::SyncErrorFactory>());
484 // Initiate sync due to local DB changes.
485 TEST_F(PasswordSyncableServiceTest, PasswordStoreChanges) {
486 // Set the sync change processor first.
487 SetPasswordStoreData(std::vector<autofill::PasswordForm*>(),
488 std::vector<autofill::PasswordForm*>());
489 verifier()->SetExpectedSyncChanges(SyncChangeList());
490 EXPECT_CALL(*service_,
491 NotifyPasswordStoreOfLoginChanges(PasswordStoreChangeList()));
492 service_->MergeDataAndStartSyncing(syncer::PASSWORDS,
494 CreateSyncChangeProcessor(),
495 scoped_ptr<syncer::SyncErrorFactory>());
497 autofill::PasswordForm form1;
498 form1.signon_realm = "abc";
499 autofill::PasswordForm form2;
500 form2.signon_realm = "def";
501 autofill::PasswordForm form3;
502 form3.signon_realm = "xyz";
504 SyncChangeList sync_list;
505 sync_list.push_back(CreateSyncChange(form1, SyncChange::ACTION_ADD));
506 sync_list.push_back(CreateSyncChange(form2, SyncChange::ACTION_UPDATE));
507 sync_list.push_back(CreateSyncChange(form3, SyncChange::ACTION_DELETE));
509 verifier()->SetExpectedDBChanges(SyncDataList(),
510 std::vector<autofill::PasswordForm*>(),
511 std::vector<autofill::PasswordForm*>(),
513 verifier()->SetExpectedSyncChanges(sync_list);
515 PasswordStoreChangeList list;
516 list.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form1));
517 list.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE, form2));
518 list.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form3));
519 service()->ActOnPasswordStoreChanges(list);
522 // Process all types of changes from sync.
523 TEST_F(PasswordSyncableServiceTest, ProcessSyncChanges) {
524 autofill::PasswordForm updated_form;
525 updated_form.signon_realm = "abc";
526 updated_form.action = GURL("http://foo.com");
527 updated_form.date_created = base::Time::Now();
528 autofill::PasswordForm deleted_form;
529 deleted_form.signon_realm = "xyz";
530 deleted_form.action = GURL("http://bar.com");
531 deleted_form.blacklisted_by_user = true;
533 SyncData add_data = CreateSyncData("def");
534 std::vector<autofill::PasswordForm*> updated_passwords(1, &updated_form);
535 std::vector<autofill::PasswordForm*> deleted_passwords(1, &deleted_form);
536 verifier()->SetExpectedDBChanges(SyncDataList(1, add_data),
542 list.push_back(SyncChange(FROM_HERE,
543 syncer::SyncChange::ACTION_ADD,
545 list.push_back(CreateSyncChange(updated_form,
546 syncer::SyncChange::ACTION_UPDATE));
547 list.push_back(CreateSyncChange(deleted_form,
548 syncer::SyncChange::ACTION_DELETE));
549 EXPECT_CALL(*service(), NotifyPasswordStoreOfLoginChanges(_));
550 service()->ProcessSyncChanges(FROM_HERE, list);
553 // Retrives sync data from the model.
554 TEST_F(PasswordSyncableServiceTest, GetAllSyncData) {
555 scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm);
556 form1->signon_realm = "abc";
557 form1->action = GURL("http://foo.com");
558 form1->times_used = 5;
559 form1->type = autofill::PasswordForm::TYPE_GENERATED;
560 scoped_ptr<autofill::PasswordForm> form2(new autofill::PasswordForm);
561 form2->signon_realm = "xyz";
562 form2->action = GURL("http://bar.com");
563 form2->blacklisted_by_user = true;
564 std::vector<autofill::PasswordForm*> forms(1, form1.release());
565 std::vector<autofill::PasswordForm*> blacklist_forms(1, form2.release());
566 SetPasswordStoreData(forms, blacklist_forms);
568 SyncDataList expected_list;
569 expected_list.push_back(SyncDataFromPassword(*forms[0]));
570 expected_list.push_back(SyncDataFromPassword(*blacklist_forms[0]));
572 verifier()->SetExpectedDBChanges(SyncDataList(),
573 std::vector<autofill::PasswordForm*>(),
574 std::vector<autofill::PasswordForm*>(),
577 SyncDataList actual_list = service()->GetAllSyncData(syncer::PASSWORDS);
578 EXPECT_EQ(expected_list.size(), actual_list.size());
579 for (SyncDataList::iterator i(actual_list.begin()), j(expected_list.begin());
580 i != actual_list.end() && j != expected_list.end(); ++i, ++j) {
581 PasswordsEqual(GetPasswordSpecifics(*j), GetPasswordSpecifics(*i));
585 // Creates 2 PasswordSyncableService instances, merges the content of the first
586 // one to the second one and back.
587 TEST_F(PasswordSyncableServiceTest, MergeDataAndPushBack) {
588 scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm);
589 form1->signon_realm = "abc";
590 form1->action = GURL("http://foo.com");
591 std::vector<autofill::PasswordForm*> forms(1, form1.release());
592 SetPasswordStoreData(forms, std::vector<autofill::PasswordForm*>());
594 PasswordSyncableServiceWrapper other_service_wrapper;
595 scoped_ptr<autofill::PasswordForm> form2(new autofill::PasswordForm);
596 form2->signon_realm = "xyz";
597 form2->action = GURL("http://bar.com");
598 syncer::SyncData form2_sync_data = SyncDataFromPassword(*form2);
599 other_service_wrapper.SetPasswordStoreData(
600 std::vector<autofill::PasswordForm*>(1, form2.release()),
601 std::vector<autofill::PasswordForm*>());
603 verifier()->SetExpectedDBChanges(SyncDataList(1, form2_sync_data),
604 std::vector<autofill::PasswordForm*>(),
605 std::vector<autofill::PasswordForm*>(),
607 other_service_wrapper.verifier()->SetExpectedDBChanges(
608 SyncDataList(1, SyncDataFromPassword(*forms[0])),
609 std::vector<autofill::PasswordForm*>(),
610 std::vector<autofill::PasswordForm*>(),
611 other_service_wrapper.password_store());
612 EXPECT_CALL(*service(), NotifyPasswordStoreOfLoginChanges(_));
613 EXPECT_CALL(*other_service_wrapper.service(),
614 NotifyPasswordStoreOfLoginChanges(_));
616 syncer::SyncDataList other_service_data =
617 other_service_wrapper.service()->GetAllSyncData(syncer::PASSWORDS);
618 service()->MergeDataAndStartSyncing(
621 other_service_wrapper.ReleaseSyncableService(),
622 scoped_ptr<syncer::SyncErrorFactory>());
625 // Calls ActOnPasswordStoreChanges without SyncChangeProcessor. StartSyncFlare
627 TEST_F(PasswordSyncableServiceTest, StartSyncFlare) {
628 autofill::PasswordForm form;
629 form.signon_realm = "abc";
630 PasswordStoreChangeList list;
631 list.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form));
633 // No flare and no SyncChangeProcessor, the call shouldn't crash.
634 service()->ActOnPasswordStoreChanges(list);
636 // Set the flare. It should be called as there is no SyncChangeProcessor.
637 service()->InjectStartSyncFlare(
638 base::Bind(&MockPasswordSyncableService::StartSyncFlare,
639 base::Unretained(service())));
640 EXPECT_CALL(*service(), StartSyncFlare(syncer::PASSWORDS));
641 service()->ActOnPasswordStoreChanges(list);
646 } // namespace password_manager