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