- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / profile_sync_service_password_unittest.cc
1 // Copyright (c) 2012 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 <vector>
6
7 #include "testing/gtest/include/gtest/gtest.h"
8
9 #include "base/bind.h"
10 #include "base/location.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/synchronization/waitable_event.h"
14 #include "base/test/test_timeouts.h"
15 #include "base/time/time.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/invalidation/invalidation_service_factory.h"
18 #include "chrome/browser/password_manager/mock_password_store.h"
19 #include "chrome/browser/password_manager/password_store.h"
20 #include "chrome/browser/password_manager/password_store_factory.h"
21 #include "chrome/browser/signin/signin_manager.h"
22 #include "chrome/browser/signin/signin_manager_factory.h"
23 #include "chrome/browser/signin/token_service_factory.h"
24 #include "chrome/browser/sync/abstract_profile_sync_service_test.h"
25 #include "chrome/browser/sync/glue/password_change_processor.h"
26 #include "chrome/browser/sync/glue/password_data_type_controller.h"
27 #include "chrome/browser/sync/glue/password_model_associator.h"
28 #include "chrome/browser/sync/profile_sync_components_factory.h"
29 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
30 #include "chrome/browser/sync/profile_sync_service.h"
31 #include "chrome/browser/sync/profile_sync_service_factory.h"
32 #include "chrome/browser/sync/profile_sync_test_util.h"
33 #include "chrome/browser/sync/test_profile_sync_service.h"
34 #include "chrome/common/pref_names.h"
35 #include "components/autofill/core/common/password_form.h"
36 #include "content/public/browser/notification_source.h"
37 #include "content/public/test/mock_notification_observer.h"
38 #include "content/public/test/test_browser_thread.h"
39 #include "google_apis/gaia/gaia_constants.h"
40 #include "sync/internal_api/public/read_node.h"
41 #include "sync/internal_api/public/read_transaction.h"
42 #include "sync/internal_api/public/write_node.h"
43 #include "sync/internal_api/public/write_transaction.h"
44 #include "sync/protocol/password_specifics.pb.h"
45 #include "sync/test/engine/test_id_factory.h"
46 #include "testing/gmock/include/gmock/gmock.h"
47
48 using autofill::PasswordForm;
49 using base::Time;
50 using browser_sync::PasswordChangeProcessor;
51 using browser_sync::PasswordDataTypeController;
52 using browser_sync::PasswordModelAssociator;
53 using content::BrowserThread;
54 using syncer::syncable::WriteTransaction;
55 using testing::_;
56 using testing::AtLeast;
57 using testing::DoAll;
58 using testing::InvokeWithoutArgs;
59 using testing::Return;
60 using testing::SetArgumentPointee;
61
62 ACTION_P3(MakePasswordSyncComponents, service, ps, dtc) {
63   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
64   PasswordModelAssociator* model_associator =
65       new PasswordModelAssociator(service, ps, NULL);
66   PasswordChangeProcessor* change_processor =
67       new PasswordChangeProcessor(model_associator, ps, dtc);
68   return ProfileSyncComponentsFactory::SyncComponents(model_associator,
69                                                       change_processor);
70 }
71
72 ACTION_P(AcquireSyncTransaction, password_test_service) {
73   // Check to make sure we can aquire a transaction (will crash if a transaction
74   // is already held by this thread, deadlock if held by another thread).
75   syncer::WriteTransaction trans(
76       FROM_HERE, password_test_service->GetUserShare());
77   DVLOG(1) << "Sync transaction acquired.";
78 }
79
80 class NullPasswordStore : public MockPasswordStore {
81  public:
82   NullPasswordStore() {}
83
84   static scoped_refptr<RefcountedBrowserContextKeyedService> Build(
85       content::BrowserContext* profile) {
86     return scoped_refptr<RefcountedBrowserContextKeyedService>();
87   }
88
89  protected:
90   virtual ~NullPasswordStore() {}
91 };
92
93 class PasswordTestProfileSyncService : public TestProfileSyncService {
94  public:
95   PasswordTestProfileSyncService(
96       ProfileSyncComponentsFactory* factory,
97       Profile* profile,
98       SigninManagerBase* signin,
99       ProfileOAuth2TokenService* oauth2_token_service)
100       : TestProfileSyncService(factory,
101                                profile,
102                                signin,
103                                oauth2_token_service,
104                                ProfileSyncService::AUTO_START,
105                                false) {}
106
107   virtual ~PasswordTestProfileSyncService() {}
108
109   virtual void OnPassphraseAccepted() OVERRIDE {
110     if (!callback_.is_null())
111       callback_.Run();
112
113     TestProfileSyncService::OnPassphraseAccepted();
114   }
115
116   static BrowserContextKeyedService* Build(content::BrowserContext* context) {
117     Profile* profile = static_cast<Profile*>(context);
118     SigninManagerBase* signin =
119         SigninManagerFactory::GetForProfile(profile);
120     ProfileOAuth2TokenService* oauth2_token_service =
121         ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
122     ProfileSyncComponentsFactoryMock* factory =
123         new ProfileSyncComponentsFactoryMock();
124     return new PasswordTestProfileSyncService(
125         factory, profile, signin, oauth2_token_service);
126   }
127
128   void set_passphrase_accept_callback(const base::Closure& callback) {
129     callback_ = callback;
130   }
131
132  private:
133   base::Closure callback_;
134 };
135
136 class ProfileSyncServicePasswordTest : public AbstractProfileSyncServiceTest {
137  public:
138   syncer::UserShare* GetUserShare() {
139     return sync_service_->GetUserShare();
140   }
141
142   void AddPasswordSyncNode(const PasswordForm& entry) {
143     syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
144     syncer::ReadNode password_root(&trans);
145     ASSERT_EQ(syncer::BaseNode::INIT_OK,
146               password_root.InitByTagLookup(browser_sync::kPasswordTag));
147
148     syncer::WriteNode node(&trans);
149     std::string tag = PasswordModelAssociator::MakeTag(entry);
150     syncer::WriteNode::InitUniqueByCreationResult result =
151         node.InitUniqueByCreation(syncer::PASSWORDS, password_root, tag);
152     ASSERT_EQ(syncer::WriteNode::INIT_SUCCESS, result);
153     PasswordModelAssociator::WriteToSyncNode(entry, &node);
154   }
155
156  protected:
157   ProfileSyncServicePasswordTest() {}
158
159   virtual void SetUp() {
160     AbstractProfileSyncServiceTest::SetUp();
161     TestingProfile::Builder builder;
162     builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
163                               FakeOAuth2TokenService::BuildTokenService);
164     profile_ = builder.Build().Pass();
165     invalidation::InvalidationServiceFactory::GetInstance()->
166         SetBuildOnlyFakeInvalidatorsForTest(true);
167     password_store_ = static_cast<MockPasswordStore*>(
168         PasswordStoreFactory::GetInstance()->SetTestingFactoryAndUse(
169             profile_.get(), MockPasswordStore::Build).get());
170   }
171
172   virtual void TearDown() {
173     if (password_store_.get())
174       password_store_->ShutdownOnUIThread();
175       ProfileSyncServiceFactory::GetInstance()->SetTestingFactory(
176           profile_.get(), NULL);
177       profile_.reset();
178       AbstractProfileSyncServiceTest::TearDown();
179   }
180
181   static void SignalEvent(base::WaitableEvent* done) {
182     done->Signal();
183   }
184
185   void FlushLastDBTask() {
186     base::WaitableEvent done(false, false);
187     BrowserThread::PostTask(
188         BrowserThread::DB, FROM_HERE,
189         base::Bind(&ProfileSyncServicePasswordTest::SignalEvent, &done));
190     done.TimedWait(TestTimeouts::action_timeout());
191   }
192
193   void StartSyncService(const base::Closure& root_callback,
194                         const base::Closure& node_callback) {
195     if (!sync_service_) {
196       SigninManagerBase* signin =
197           SigninManagerFactory::GetForProfile(profile_.get());
198       signin->SetAuthenticatedUsername("test_user@gmail.com");
199       token_service_ = static_cast<TokenService*>(
200           TokenServiceFactory::GetInstance()->SetTestingFactoryAndUse(
201               profile_.get(), BuildTokenService));
202
203       PasswordTestProfileSyncService* sync =
204           static_cast<PasswordTestProfileSyncService*>(
205               ProfileSyncServiceFactory::GetInstance()->
206                   SetTestingFactoryAndUse(profile_.get(),
207                       &PasswordTestProfileSyncService::Build));
208       sync->set_backend_init_callback(root_callback);
209       sync->set_passphrase_accept_callback(node_callback);
210       sync_service_ = sync;
211
212       syncer::ModelTypeSet preferred_types =
213           sync_service_->GetPreferredDataTypes();
214       preferred_types.Put(syncer::PASSWORDS);
215       sync_service_->ChangePreferredDataTypes(preferred_types);
216       PasswordDataTypeController* data_type_controller =
217           new PasswordDataTypeController(sync_service_->factory(),
218                                          profile_.get(),
219                                          sync_service_);
220       ProfileSyncComponentsFactoryMock* components =
221           sync_service_->components_factory_mock();
222       if (password_store_.get()) {
223         EXPECT_CALL(*components, CreatePasswordSyncComponents(_, _, _))
224             .Times(AtLeast(1)).  // Can be more if we hit NEEDS_CRYPTO.
225             WillRepeatedly(MakePasswordSyncComponents(
226                 sync_service_, password_store_.get(), data_type_controller));
227       } else {
228         // When the password store is unavailable, password sync components must
229         // not be created.
230         EXPECT_CALL(*components, CreatePasswordSyncComponents(_, _, _))
231             .Times(0);
232       }
233       EXPECT_CALL(*components, CreateDataTypeManager(_, _, _, _, _, _)).
234           WillOnce(ReturnNewDataTypeManager());
235
236       // We need tokens to get the tests going
237       ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get())
238           ->UpdateCredentials("test_user@gmail.com", "oauth2_login_token");
239
240       sync_service_->RegisterDataTypeController(data_type_controller);
241       sync_service_->Initialize();
242       base::MessageLoop::current()->Run();
243       FlushLastDBTask();
244
245       sync_service_->SetEncryptionPassphrase("foo",
246                                              ProfileSyncService::IMPLICIT);
247       base::MessageLoop::current()->Run();
248     }
249   }
250
251   // Helper to sort the results of GetPasswordEntriesFromSyncDB.  The sorting
252   // doesn't need to be particularly intelligent, it just needs to be consistent
253   // enough that we can base our tests expectations on the ordering it provides.
254   static bool PasswordFormComparator(const PasswordForm& pf1,
255                                      const PasswordForm& pf2) {
256     if (pf1.submit_element < pf2.submit_element)
257       return true;
258     if (pf1.username_element < pf2.username_element)
259       return true;
260     if (pf1.username_value < pf2.username_value)
261       return true;
262     if (pf1.password_element < pf2.password_element)
263       return true;
264     if (pf1.password_value < pf2.password_value)
265       return true;
266
267     return false;
268   }
269
270   void GetPasswordEntriesFromSyncDB(std::vector<PasswordForm>* entries) {
271     syncer::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare());
272     syncer::ReadNode password_root(&trans);
273     ASSERT_EQ(syncer::BaseNode::INIT_OK,
274               password_root.InitByTagLookup(browser_sync::kPasswordTag));
275
276     int64 child_id = password_root.GetFirstChildId();
277     while (child_id != syncer::kInvalidId) {
278       syncer::ReadNode child_node(&trans);
279       ASSERT_EQ(syncer::BaseNode::INIT_OK,
280                 child_node.InitByIdLookup(child_id));
281
282       const sync_pb::PasswordSpecificsData& password =
283           child_node.GetPasswordSpecifics();
284
285       PasswordForm form;
286       PasswordModelAssociator::CopyPassword(password, &form);
287
288       entries->push_back(form);
289
290       child_id = child_node.GetSuccessorId();
291     }
292
293     std::sort(entries->begin(), entries->end(), PasswordFormComparator);
294   }
295
296   bool ComparePasswords(const PasswordForm& lhs, const PasswordForm& rhs) {
297     return lhs.scheme == rhs.scheme &&
298            lhs.signon_realm == rhs.signon_realm &&
299            lhs.origin == rhs.origin &&
300            lhs.action == rhs.action &&
301            lhs.username_element == rhs.username_element &&
302            lhs.username_value == rhs.username_value &&
303            lhs.password_element == rhs.password_element &&
304            lhs.password_value == rhs.password_value &&
305            lhs.ssl_valid == rhs.ssl_valid &&
306            lhs.preferred == rhs.preferred &&
307            lhs.date_created == rhs.date_created &&
308            lhs.blacklisted_by_user == rhs.blacklisted_by_user;
309   }
310
311   void SetIdleChangeProcessorExpectations() {
312     EXPECT_CALL(*password_store_.get(), AddLoginImpl(_)).Times(0);
313     EXPECT_CALL(*password_store_.get(), UpdateLoginImpl(_)).Times(0);
314     EXPECT_CALL(*password_store_.get(), RemoveLoginImpl(_)).Times(0);
315   }
316
317   content::MockNotificationObserver observer_;
318   scoped_ptr<TestingProfile> profile_;
319   scoped_refptr<MockPasswordStore> password_store_;
320   content::NotificationRegistrar registrar_;
321 };
322
323 void AddPasswordEntriesCallback(ProfileSyncServicePasswordTest* test,
324                                 const std::vector<PasswordForm>& entries) {
325   for (size_t i = 0; i < entries.size(); ++i)
326     test->AddPasswordSyncNode(entries[i]);
327 }
328
329 // Flaky on mac_rel. See http://crbug.com/228943
330 #if defined(OS_MACOSX)
331 #define MAYBE_EmptyNativeEmptySync DISABLED_EmptyNativeEmptySync
332 #define MAYBE_EnsureNoTransactions DISABLED_EnsureNoTransactions
333 #define MAYBE_FailModelAssociation DISABLED_FailModelAssociation
334 #define MAYBE_FailPasswordStoreLoad DISABLED_FailPasswordStoreLoad
335 #define MAYBE_HasNativeEntriesEmptySync DISABLED_HasNativeEntriesEmptySync
336 #define MAYBE_HasNativeEntriesEmptySyncSameUsername \
337     DISABLED_HasNativeEntriesEmptySyncSameUsername
338 #define MAYBE_HasNativeHasSyncMergeEntry DISABLED_HasNativeHasSyncMergeEntry
339 #define MAYBE_HasNativeHasSyncNoMerge DISABLED_HasNativeHasSyncNoMerge
340 #else
341 #define MAYBE_EmptyNativeEmptySync EmptyNativeEmptySync
342 #define MAYBE_EnsureNoTransactions EnsureNoTransactions
343 #define MAYBE_FailModelAssociation FailModelAssociation
344 #define MAYBE_FailPasswordStoreLoad FailPasswordStoreLoad
345 #define MAYBE_HasNativeEntriesEmptySync HasNativeEntriesEmptySync
346 #define MAYBE_HasNativeEntriesEmptySyncSameUsername \
347     HasNativeEntriesEmptySyncSameUsername
348 #define MAYBE_HasNativeHasSyncMergeEntry HasNativeHasSyncMergeEntry
349 #define MAYBE_HasNativeHasSyncNoMerge HasNativeHasSyncNoMerge
350 #endif
351
352 TEST_F(ProfileSyncServicePasswordTest, MAYBE_FailModelAssociation) {
353   StartSyncService(base::Closure(), base::Closure());
354   EXPECT_TRUE(sync_service_->HasUnrecoverableError());
355 }
356
357 TEST_F(ProfileSyncServicePasswordTest, MAYBE_FailPasswordStoreLoad) {
358   password_store_ = static_cast<NullPasswordStore*>(
359       PasswordStoreFactory::GetInstance()->SetTestingFactoryAndUse(
360           profile_.get(), NullPasswordStore::Build).get());
361   StartSyncService(base::Closure(), base::Closure());
362   EXPECT_FALSE(sync_service_->HasUnrecoverableError());
363   syncer::ModelTypeSet failed_types =
364       sync_service_->failed_data_types_handler().GetFailedTypes();
365   EXPECT_TRUE(failed_types.Equals(syncer::ModelTypeSet(syncer::PASSWORDS)));
366 }
367
368 TEST_F(ProfileSyncServicePasswordTest, MAYBE_EmptyNativeEmptySync) {
369   EXPECT_CALL(*password_store_.get(), FillAutofillableLogins(_))
370       .WillOnce(Return(true));
371   EXPECT_CALL(*password_store_.get(), FillBlacklistLogins(_))
372       .WillOnce(Return(true));
373   SetIdleChangeProcessorExpectations();
374   CreateRootHelper create_root(this, syncer::PASSWORDS);
375   StartSyncService(create_root.callback(), base::Closure());
376   std::vector<PasswordForm> sync_entries;
377   GetPasswordEntriesFromSyncDB(&sync_entries);
378   EXPECT_EQ(0U, sync_entries.size());
379 }
380
381 TEST_F(ProfileSyncServicePasswordTest, MAYBE_HasNativeEntriesEmptySync) {
382   std::vector<PasswordForm*> forms;
383   std::vector<PasswordForm> expected_forms;
384   PasswordForm* new_form = new PasswordForm;
385   new_form->scheme = PasswordForm::SCHEME_HTML;
386   new_form->signon_realm = "pie";
387   new_form->origin = GURL("http://pie.com");
388   new_form->action = GURL("http://pie.com/submit");
389   new_form->username_element = UTF8ToUTF16("name");
390   new_form->username_value = UTF8ToUTF16("tom");
391   new_form->password_element = UTF8ToUTF16("cork");
392   new_form->password_value = UTF8ToUTF16("password1");
393   new_form->ssl_valid = true;
394   new_form->preferred = false;
395   new_form->date_created = base::Time::FromInternalValue(1234);
396   new_form->blacklisted_by_user = false;
397   forms.push_back(new_form);
398   expected_forms.push_back(*new_form);
399   EXPECT_CALL(*password_store_.get(), FillAutofillableLogins(_))
400       .WillOnce(DoAll(SetArgumentPointee<0>(forms), Return(true)));
401   EXPECT_CALL(*password_store_.get(), FillBlacklistLogins(_))
402       .WillOnce(Return(true));
403   SetIdleChangeProcessorExpectations();
404   CreateRootHelper create_root(this, syncer::PASSWORDS);
405   StartSyncService(create_root.callback(), base::Closure());
406   std::vector<PasswordForm> sync_forms;
407   GetPasswordEntriesFromSyncDB(&sync_forms);
408   ASSERT_EQ(1U, sync_forms.size());
409   EXPECT_TRUE(ComparePasswords(expected_forms[0], sync_forms[0]));
410 }
411
412 TEST_F(ProfileSyncServicePasswordTest,
413        MAYBE_HasNativeEntriesEmptySyncSameUsername) {
414   std::vector<PasswordForm*> forms;
415   std::vector<PasswordForm> expected_forms;
416
417   {
418     PasswordForm* new_form = new PasswordForm;
419     new_form->scheme = PasswordForm::SCHEME_HTML;
420     new_form->signon_realm = "pie";
421     new_form->origin = GURL("http://pie.com");
422     new_form->action = GURL("http://pie.com/submit");
423     new_form->username_element = UTF8ToUTF16("name");
424     new_form->username_value = UTF8ToUTF16("tom");
425     new_form->password_element = UTF8ToUTF16("cork");
426     new_form->password_value = UTF8ToUTF16("password1");
427     new_form->ssl_valid = true;
428     new_form->preferred = false;
429     new_form->date_created = base::Time::FromInternalValue(1234);
430     new_form->blacklisted_by_user = false;
431     forms.push_back(new_form);
432     expected_forms.push_back(*new_form);
433   }
434   {
435     PasswordForm* new_form = new PasswordForm;
436     new_form->scheme = PasswordForm::SCHEME_HTML;
437     new_form->signon_realm = "pie";
438     new_form->origin = GURL("http://pie.com");
439     new_form->action = GURL("http://pie.com/submit");
440     new_form->username_element = UTF8ToUTF16("name");
441     new_form->username_value = UTF8ToUTF16("pete");
442     new_form->password_element = UTF8ToUTF16("cork");
443     new_form->password_value = UTF8ToUTF16("password2");
444     new_form->ssl_valid = true;
445     new_form->preferred = false;
446     new_form->date_created = base::Time::FromInternalValue(1234);
447     new_form->blacklisted_by_user = false;
448     forms.push_back(new_form);
449     expected_forms.push_back(*new_form);
450   }
451
452   EXPECT_CALL(*password_store_.get(), FillAutofillableLogins(_))
453       .WillOnce(DoAll(SetArgumentPointee<0>(forms), Return(true)));
454   EXPECT_CALL(*password_store_.get(), FillBlacklistLogins(_))
455       .WillOnce(Return(true));
456   SetIdleChangeProcessorExpectations();
457   CreateRootHelper create_root(this, syncer::PASSWORDS);
458   StartSyncService(create_root.callback(), base::Closure());
459   std::vector<PasswordForm> sync_forms;
460   GetPasswordEntriesFromSyncDB(&sync_forms);
461   ASSERT_EQ(2U, sync_forms.size());
462   EXPECT_TRUE(ComparePasswords(expected_forms[0], sync_forms[1]));
463   EXPECT_TRUE(ComparePasswords(expected_forms[1], sync_forms[0]));
464 }
465
466 TEST_F(ProfileSyncServicePasswordTest, MAYBE_HasNativeHasSyncNoMerge) {
467   std::vector<PasswordForm*> native_forms;
468   std::vector<PasswordForm> sync_forms;
469   std::vector<PasswordForm> expected_forms;
470   {
471     PasswordForm* new_form = new PasswordForm;
472     new_form->scheme = PasswordForm::SCHEME_HTML;
473     new_form->signon_realm = "pie";
474     new_form->origin = GURL("http://pie.com");
475     new_form->action = GURL("http://pie.com/submit");
476     new_form->username_element = UTF8ToUTF16("name");
477     new_form->username_value = UTF8ToUTF16("tom");
478     new_form->password_element = UTF8ToUTF16("cork");
479     new_form->password_value = UTF8ToUTF16("password1");
480     new_form->ssl_valid = true;
481     new_form->preferred = false;
482     new_form->date_created = base::Time::FromInternalValue(1234);
483     new_form->blacklisted_by_user = false;
484
485     native_forms.push_back(new_form);
486     expected_forms.push_back(*new_form);
487   }
488
489   {
490     PasswordForm new_form;
491     new_form.scheme = PasswordForm::SCHEME_HTML;
492     new_form.signon_realm = "pie2";
493     new_form.origin = GURL("http://pie2.com");
494     new_form.action = GURL("http://pie2.com/submit");
495     new_form.username_element = UTF8ToUTF16("name2");
496     new_form.username_value = UTF8ToUTF16("tom2");
497     new_form.password_element = UTF8ToUTF16("cork2");
498     new_form.password_value = UTF8ToUTF16("password12");
499     new_form.ssl_valid = false;
500     new_form.preferred = true;
501     new_form.date_created = base::Time::FromInternalValue(12345);
502     new_form.blacklisted_by_user = false;
503     sync_forms.push_back(new_form);
504     expected_forms.push_back(new_form);
505   }
506
507   EXPECT_CALL(*password_store_.get(), FillAutofillableLogins(_))
508       .WillOnce(DoAll(SetArgumentPointee<0>(native_forms), Return(true)));
509   EXPECT_CALL(*password_store_.get(), FillBlacklistLogins(_))
510       .WillOnce(Return(true));
511   EXPECT_CALL(*password_store_.get(), AddLoginImpl(_)).Times(1);
512
513   CreateRootHelper create_root(this, syncer::PASSWORDS);
514   StartSyncService(create_root.callback(),
515                    base::Bind(&AddPasswordEntriesCallback, this, sync_forms));
516
517   std::vector<PasswordForm> new_sync_forms;
518   GetPasswordEntriesFromSyncDB(&new_sync_forms);
519
520   EXPECT_EQ(2U, new_sync_forms.size());
521   EXPECT_TRUE(ComparePasswords(expected_forms[0], new_sync_forms[0]));
522   EXPECT_TRUE(ComparePasswords(expected_forms[1], new_sync_forms[1]));
523 }
524
525 // Same as HasNativeHasEmptyNoMerge, but we attempt to aquire a sync transaction
526 // every time the password store is accessed.
527 TEST_F(ProfileSyncServicePasswordTest, MAYBE_EnsureNoTransactions) {
528   std::vector<PasswordForm*> native_forms;
529   std::vector<PasswordForm> sync_forms;
530   std::vector<PasswordForm> expected_forms;
531   {
532     PasswordForm* new_form = new PasswordForm;
533     new_form->scheme = PasswordForm::SCHEME_HTML;
534     new_form->signon_realm = "pie";
535     new_form->origin = GURL("http://pie.com");
536     new_form->action = GURL("http://pie.com/submit");
537     new_form->username_element = UTF8ToUTF16("name");
538     new_form->username_value = UTF8ToUTF16("tom");
539     new_form->password_element = UTF8ToUTF16("cork");
540     new_form->password_value = UTF8ToUTF16("password1");
541     new_form->ssl_valid = true;
542     new_form->preferred = false;
543     new_form->date_created = base::Time::FromInternalValue(1234);
544     new_form->blacklisted_by_user = false;
545
546     native_forms.push_back(new_form);
547     expected_forms.push_back(*new_form);
548   }
549
550   {
551     PasswordForm new_form;
552     new_form.scheme = PasswordForm::SCHEME_HTML;
553     new_form.signon_realm = "pie2";
554     new_form.origin = GURL("http://pie2.com");
555     new_form.action = GURL("http://pie2.com/submit");
556     new_form.username_element = UTF8ToUTF16("name2");
557     new_form.username_value = UTF8ToUTF16("tom2");
558     new_form.password_element = UTF8ToUTF16("cork2");
559     new_form.password_value = UTF8ToUTF16("password12");
560     new_form.ssl_valid = false;
561     new_form.preferred = true;
562     new_form.date_created = base::Time::FromInternalValue(12345);
563     new_form.blacklisted_by_user = false;
564     sync_forms.push_back(new_form);
565     expected_forms.push_back(new_form);
566   }
567
568   EXPECT_CALL(*password_store_.get(), FillAutofillableLogins(_))
569       .WillOnce(DoAll(SetArgumentPointee<0>(native_forms),
570                       AcquireSyncTransaction(this),
571                       Return(true)));
572   EXPECT_CALL(*password_store_.get(), FillBlacklistLogins(_))
573       .WillOnce(DoAll(AcquireSyncTransaction(this), Return(true)));
574   EXPECT_CALL(*password_store_.get(), AddLoginImpl(_))
575       .WillOnce(AcquireSyncTransaction(this));
576
577   CreateRootHelper create_root(this, syncer::PASSWORDS);
578   StartSyncService(create_root.callback(),
579                    base::Bind(&AddPasswordEntriesCallback, this, sync_forms));
580
581   std::vector<PasswordForm> new_sync_forms;
582   GetPasswordEntriesFromSyncDB(&new_sync_forms);
583
584   EXPECT_EQ(2U, new_sync_forms.size());
585   EXPECT_TRUE(ComparePasswords(expected_forms[0], new_sync_forms[0]));
586   EXPECT_TRUE(ComparePasswords(expected_forms[1], new_sync_forms[1]));
587 }
588
589 TEST_F(ProfileSyncServicePasswordTest, MAYBE_HasNativeHasSyncMergeEntry) {
590   std::vector<PasswordForm*> native_forms;
591   std::vector<PasswordForm> sync_forms;
592   std::vector<PasswordForm> expected_forms;
593   {
594     PasswordForm* new_form = new PasswordForm;
595     new_form->scheme = PasswordForm::SCHEME_HTML;
596     new_form->signon_realm = "pie";
597     new_form->origin = GURL("http://pie.com");
598     new_form->action = GURL("http://pie.com/submit");
599     new_form->username_element = UTF8ToUTF16("name");
600     new_form->username_value = UTF8ToUTF16("tom");
601     new_form->password_element = UTF8ToUTF16("cork");
602     new_form->password_value = UTF8ToUTF16("password1");
603     new_form->ssl_valid = true;
604     new_form->preferred = false;
605     new_form->date_created = base::Time::FromInternalValue(1234);
606     new_form->blacklisted_by_user = false;
607
608     native_forms.push_back(new_form);
609   }
610
611   {
612     PasswordForm new_form;
613     new_form.scheme = PasswordForm::SCHEME_HTML;
614     new_form.signon_realm = "pie";
615     new_form.origin = GURL("http://pie.com");
616     new_form.action = GURL("http://pie.com/submit");
617     new_form.username_element = UTF8ToUTF16("name");
618     new_form.username_value = UTF8ToUTF16("tom");
619     new_form.password_element = UTF8ToUTF16("cork");
620     new_form.password_value = UTF8ToUTF16("password12");
621     new_form.ssl_valid = false;
622     new_form.preferred = true;
623     new_form.date_created = base::Time::FromInternalValue(12345);
624     new_form.blacklisted_by_user = false;
625     sync_forms.push_back(new_form);
626   }
627
628   {
629     PasswordForm new_form;
630     new_form.scheme = PasswordForm::SCHEME_HTML;
631     new_form.signon_realm = "pie";
632     new_form.origin = GURL("http://pie.com");
633     new_form.action = GURL("http://pie.com/submit");
634     new_form.username_element = UTF8ToUTF16("name");
635     new_form.username_value = UTF8ToUTF16("tom");
636     new_form.password_element = UTF8ToUTF16("cork");
637     new_form.password_value = UTF8ToUTF16("password12");
638     new_form.ssl_valid = false;
639     new_form.preferred = true;
640     new_form.date_created = base::Time::FromInternalValue(12345);
641     new_form.blacklisted_by_user = false;
642     expected_forms.push_back(new_form);
643   }
644
645   EXPECT_CALL(*password_store_.get(), FillAutofillableLogins(_))
646       .WillOnce(DoAll(SetArgumentPointee<0>(native_forms), Return(true)));
647   EXPECT_CALL(*password_store_.get(), FillBlacklistLogins(_))
648       .WillOnce(Return(true));
649   EXPECT_CALL(*password_store_.get(), UpdateLoginImpl(_)).Times(1);
650
651   CreateRootHelper create_root(this, syncer::PASSWORDS);
652   StartSyncService(create_root.callback(),
653                    base::Bind(&AddPasswordEntriesCallback, this, sync_forms));
654
655   std::vector<PasswordForm> new_sync_forms;
656   GetPasswordEntriesFromSyncDB(&new_sync_forms);
657
658   EXPECT_EQ(1U, new_sync_forms.size());
659   EXPECT_TRUE(ComparePasswords(expected_forms[0], new_sync_forms[0]));
660 }