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