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
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;
29 using testing::_;
30
31 namespace password_manager {
32
33 namespace {
34
35 typedef std::vector<SyncChange> SyncChangeList;
36
GetPasswordSpecifics(const syncer::SyncData & sync_data)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();
41 }
42
PasswordsEqual(const sync_pb::PasswordSpecificsData & expected_password,const sync_pb::PasswordSpecificsData & actual_password)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());
63 }
64
65 // Creates a sync data consisting of password specifics. The sign on realm is
66 // set to |signon_realm|.
CreateSyncData(const std::string & 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);
74
75 std::string tag = MakePasswordSyncTag(*password_specifics);
76 return syncer::SyncData::CreateLocalData(tag, tag, password_data);
77 }
78
CreateSyncChange(const autofill::PasswordForm & password,SyncChange::SyncChangeType type)79 SyncChange CreateSyncChange(const autofill::PasswordForm& password,
80 SyncChange::SyncChangeType type) {
81 SyncData data = SyncDataFromPassword(password);
82 return SyncChange(FROM_HERE, type, data);
83 }
84
85 class FormFinder {
86 public:
FormFinder(const autofill::PasswordForm & form)87 explicit FormFinder(const autofill::PasswordForm& form) : form_(form) {}
~FormFinder()88 ~FormFinder() {}
89
90 bool operator()(const autofill::PasswordForm& form) const;
91
92 private:
93 const autofill::PasswordForm form_;
94 };
95
operator ()(const autofill::PasswordForm & form) const96 bool 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.
106 class MockPasswordSyncableService : public PasswordSyncableService {
107 public:
MockPasswordSyncableService(PasswordStoreSync * password_store)108 explicit MockPasswordSyncableService(PasswordStoreSync* password_store)
109 : PasswordSyncableService(password_store) {}
~MockPasswordSyncableService()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|.
119 class PasswordStoreDataVerifier {
120 public:
PasswordStoreDataVerifier()121 PasswordStoreDataVerifier() {}
~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.
VerifyAdd(const autofill::PasswordForm & password)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.
VerifyUpdate(const autofill::PasswordForm & password)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.
VerifyDelete(const autofill::PasswordForm & password)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
180 class PasswordStoreDataVerifier::TestSyncChangeProcessor
181 : public syncer::SyncChangeProcessor {
182 public:
TestSyncChangeProcessor(PasswordStoreDataVerifier * verifier)183 explicit TestSyncChangeProcessor(PasswordStoreDataVerifier* verifier)
184 : verifier_(verifier) {
185 }
~TestSyncChangeProcessor()186 virtual ~TestSyncChangeProcessor() {}
187
ProcessSyncChanges(const tracked_objects::Location &,const SyncChangeList & list)188 virtual SyncError ProcessSyncChanges(const tracked_objects::Location&,
189 const SyncChangeList& list) OVERRIDE {
190 return verifier_->TestSyncChanges(list);
191 }
192
GetAllSyncData(syncer::ModelType type) const193 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
SetExpectedDBChanges(const SyncDataList & add_forms,const std::vector<autofill::PasswordForm * > & update_forms,const std::vector<autofill::PasswordForm * > & delete_forms,MockPasswordStore * password_store)202 void 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
SetExpectedSyncChanges(SyncChangeList list)252 void PasswordStoreDataVerifier::SetExpectedSyncChanges(SyncChangeList list) {
253 expected_sync_change_list_.swap(list);
254 }
255
TestSyncChanges(const SyncChangeList & change_list)256 SyncError 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
VerifyChange(PasswordStoreChange::Type type,const autofill::PasswordForm & password,std::vector<autofill::PasswordForm> * password_list)285 PasswordStoreChangeList 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
302 class PasswordSyncableServiceWrapper {
303 public:
PasswordSyncableServiceWrapper()304 PasswordSyncableServiceWrapper() {
305 password_store_ = new MockPasswordStore;
306 service_.reset(new MockPasswordSyncableService(
307 password_store_->GetSyncInterface()));
308 }
309
~PasswordSyncableServiceWrapper()310 ~PasswordSyncableServiceWrapper() {
311 password_store_->Shutdown();
312 }
313
password_store()314 MockPasswordStore* password_store() {
315 return password_store_;
316 }
317
service()318 MockPasswordSyncableService* service() {
319 return service_.get();
320 }
321
322 // Returnes the scoped_ptr to |service_| thus NULLing out it.
ReleaseSyncableService()323 scoped_ptr<syncer::SyncChangeProcessor> ReleaseSyncableService() {
324 return service_.PassAs<syncer::SyncChangeProcessor>();
325 }
326
verifier()327 PasswordStoreDataVerifier* verifier() {
328 return &verifier_;
329 }
330
CreateSyncChangeProcessor()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.
SetPasswordStoreData(const std::vector<autofill::PasswordForm * > & forms,const std::vector<autofill::PasswordForm * > & blacklist_forms)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 {
AppendVectorpassword_manager::__anon65a1d5b10111::PasswordSyncableServiceWrapper::AppendVector355 explicit AppendVector(
356 const std::vector<autofill::PasswordForm*>& append_forms)
357 : append_forms_(append_forms) {
358 }
359
~AppendVectorpassword_manager::__anon65a1d5b10111::PasswordSyncableServiceWrapper::AppendVector360 ~AppendVector() {}
361
operator ()password_manager::__anon65a1d5b10111::PasswordSyncableServiceWrapper::AppendVector362 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
373 class PasswordSyncableServiceTest : public testing::Test,
374 public PasswordSyncableServiceWrapper {
375 public:
PasswordSyncableServiceTest()376 PasswordSyncableServiceTest() {}
~PasswordSyncableServiceTest()377 virtual ~PasswordSyncableServiceTest() {}
378 };
379
380
381 // Both sync and password db have data that are not present in the other.
TEST_F(PasswordSyncableServiceTest,AdditionsInBoth)382 TEST_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.
TEST_F(PasswordSyncableServiceTest,AdditionOnlyInSync)408 TEST_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.
TEST_F(PasswordSyncableServiceTest,AdditionOnlyInPasswordStore)430 TEST_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.
TEST_F(PasswordSyncableServiceTest,BothInSync)455 TEST_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.
TEST_F(PasswordSyncableServiceTest,Merge)480 TEST_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.
TEST_F(PasswordSyncableServiceTest,PasswordStoreChanges)509 TEST_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.
TEST_F(PasswordSyncableServiceTest,ProcessSyncChanges)547 TEST_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.
TEST_F(PasswordSyncableServiceTest,GetAllSyncData)578 TEST_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.
TEST_F(PasswordSyncableServiceTest,MergeDataAndPushBack)611 TEST_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.
TEST_F(PasswordSyncableServiceTest,StartSyncFlare)651 TEST_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