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/profile_oauth2_token_service.h" 22#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 23#include "chrome/browser/signin/signin_manager.h" 24#include "chrome/browser/signin/signin_manager_factory.h" 25#include "chrome/browser/sync/abstract_profile_sync_service_test.h" 26#include "chrome/browser/sync/fake_oauth2_token_service.h" 27#include "chrome/browser/sync/glue/password_change_processor.h" 28#include "chrome/browser/sync/glue/password_data_type_controller.h" 29#include "chrome/browser/sync/glue/password_model_associator.h" 30#include "chrome/browser/sync/profile_sync_components_factory.h" 31#include "chrome/browser/sync/profile_sync_components_factory_mock.h" 32#include "chrome/browser/sync/profile_sync_service.h" 33#include "chrome/browser/sync/profile_sync_service_factory.h" 34#include "chrome/browser/sync/profile_sync_test_util.h" 35#include "chrome/browser/sync/test_profile_sync_service.h" 36#include "chrome/common/pref_names.h" 37#include "chrome/test/base/testing_profile.h" 38#include "components/autofill/core/common/password_form.h" 39#include "content/public/browser/notification_source.h" 40#include "content/public/test/mock_notification_observer.h" 41#include "content/public/test/test_browser_thread.h" 42#include "google_apis/gaia/gaia_constants.h" 43#include "sync/internal_api/public/read_node.h" 44#include "sync/internal_api/public/read_transaction.h" 45#include "sync/internal_api/public/write_node.h" 46#include "sync/internal_api/public/write_transaction.h" 47#include "sync/protocol/password_specifics.pb.h" 48#include "sync/test/engine/test_id_factory.h" 49#include "testing/gmock/include/gmock/gmock.h" 50 51using autofill::PasswordForm; 52using base::Time; 53using browser_sync::PasswordChangeProcessor; 54using browser_sync::PasswordDataTypeController; 55using browser_sync::PasswordModelAssociator; 56using content::BrowserThread; 57using syncer::syncable::WriteTransaction; 58using testing::_; 59using testing::AtLeast; 60using testing::DoAll; 61using testing::InvokeWithoutArgs; 62using testing::Return; 63using testing::SetArgumentPointee; 64 65ACTION_P3(MakePasswordSyncComponents, service, ps, dtc) { 66 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); 67 PasswordModelAssociator* model_associator = 68 new PasswordModelAssociator(service, ps, NULL); 69 PasswordChangeProcessor* change_processor = 70 new PasswordChangeProcessor(model_associator, ps, dtc); 71 return ProfileSyncComponentsFactory::SyncComponents(model_associator, 72 change_processor); 73} 74 75ACTION_P(AcquireSyncTransaction, password_test_service) { 76 // Check to make sure we can aquire a transaction (will crash if a transaction 77 // is already held by this thread, deadlock if held by another thread). 78 syncer::WriteTransaction trans( 79 FROM_HERE, password_test_service->GetUserShare()); 80 DVLOG(1) << "Sync transaction acquired."; 81} 82 83class NullPasswordStore : public MockPasswordStore { 84 public: 85 NullPasswordStore() {} 86 87 static scoped_refptr<RefcountedBrowserContextKeyedService> Build( 88 content::BrowserContext* profile) { 89 return scoped_refptr<RefcountedBrowserContextKeyedService>(); 90 } 91 92 protected: 93 virtual ~NullPasswordStore() {} 94}; 95 96class PasswordTestProfileSyncService : public TestProfileSyncService { 97 public: 98 PasswordTestProfileSyncService( 99 ProfileSyncComponentsFactory* factory, 100 Profile* profile, 101 SigninManagerBase* signin, 102 ProfileOAuth2TokenService* oauth2_token_service) 103 : TestProfileSyncService(factory, 104 profile, 105 signin, 106 oauth2_token_service, 107 ProfileSyncService::AUTO_START) {} 108 109 virtual ~PasswordTestProfileSyncService() {} 110 111 virtual void OnPassphraseAccepted() OVERRIDE { 112 if (!callback_.is_null()) 113 callback_.Run(); 114 115 TestProfileSyncService::OnPassphraseAccepted(); 116 } 117 118 static BrowserContextKeyedService* Build(content::BrowserContext* context) { 119 Profile* profile = static_cast<Profile*>(context); 120 SigninManagerBase* signin = 121 SigninManagerFactory::GetForProfile(profile); 122 ProfileOAuth2TokenService* oauth2_token_service = 123 ProfileOAuth2TokenServiceFactory::GetForProfile(profile); 124 ProfileSyncComponentsFactoryMock* factory = 125 new ProfileSyncComponentsFactoryMock(); 126 return new PasswordTestProfileSyncService( 127 factory, profile, signin, oauth2_token_service); 128 } 129 130 void set_passphrase_accept_callback(const base::Closure& callback) { 131 callback_ = callback; 132 } 133 134 private: 135 base::Closure callback_; 136}; 137 138class ProfileSyncServicePasswordTest : public AbstractProfileSyncServiceTest { 139 public: 140 syncer::UserShare* GetUserShare() { 141 return sync_service_->GetUserShare(); 142 } 143 144 void AddPasswordSyncNode(const PasswordForm& entry) { 145 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 146 syncer::ReadNode password_root(&trans); 147 ASSERT_EQ(syncer::BaseNode::INIT_OK, 148 password_root.InitByTagLookup(browser_sync::kPasswordTag)); 149 150 syncer::WriteNode node(&trans); 151 std::string tag = PasswordModelAssociator::MakeTag(entry); 152 syncer::WriteNode::InitUniqueByCreationResult result = 153 node.InitUniqueByCreation(syncer::PASSWORDS, password_root, tag); 154 ASSERT_EQ(syncer::WriteNode::INIT_SUCCESS, result); 155 PasswordModelAssociator::WriteToSyncNode(entry, &node); 156 } 157 158 protected: 159 ProfileSyncServicePasswordTest() {} 160 161 virtual void SetUp() { 162 AbstractProfileSyncServiceTest::SetUp(); 163 TestingProfile::Builder builder; 164 builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(), 165 FakeOAuth2TokenService::BuildTokenService); 166 profile_ = builder.Build().Pass(); 167 invalidation::InvalidationServiceFactory::GetInstance()-> 168 SetBuildOnlyFakeInvalidatorsForTest(true); 169 password_store_ = static_cast<MockPasswordStore*>( 170 PasswordStoreFactory::GetInstance()->SetTestingFactoryAndUse( 171 profile_.get(), MockPasswordStore::Build).get()); 172 } 173 174 virtual void TearDown() { 175 if (password_store_.get()) 176 password_store_->ShutdownOnUIThread(); 177 ProfileSyncServiceFactory::GetInstance()->SetTestingFactory( 178 profile_.get(), NULL); 179 profile_.reset(); 180 AbstractProfileSyncServiceTest::TearDown(); 181 } 182 183 static void SignalEvent(base::WaitableEvent* done) { 184 done->Signal(); 185 } 186 187 void FlushLastDBTask() { 188 base::WaitableEvent done(false, false); 189 BrowserThread::PostTask( 190 BrowserThread::DB, FROM_HERE, 191 base::Bind(&ProfileSyncServicePasswordTest::SignalEvent, &done)); 192 done.TimedWait(TestTimeouts::action_timeout()); 193 } 194 195 void StartSyncService(const base::Closure& root_callback, 196 const base::Closure& node_callback) { 197 if (!sync_service_) { 198 SigninManagerBase* signin = 199 SigninManagerFactory::GetForProfile(profile_.get()); 200 signin->SetAuthenticatedUsername("test_user@gmail.com"); 201 202 PasswordTestProfileSyncService* sync = 203 static_cast<PasswordTestProfileSyncService*>( 204 ProfileSyncServiceFactory::GetInstance()-> 205 SetTestingFactoryAndUse(profile_.get(), 206 &PasswordTestProfileSyncService::Build)); 207 sync->set_backend_init_callback(root_callback); 208 sync->set_passphrase_accept_callback(node_callback); 209 sync_service_ = sync; 210 211 syncer::ModelTypeSet preferred_types = 212 sync_service_->GetPreferredDataTypes(); 213 preferred_types.Put(syncer::PASSWORDS); 214 sync_service_->ChangePreferredDataTypes(preferred_types); 215 PasswordDataTypeController* data_type_controller = 216 new PasswordDataTypeController(sync_service_->factory(), 217 profile_.get(), 218 sync_service_); 219 ProfileSyncComponentsFactoryMock* components = 220 sync_service_->components_factory_mock(); 221 if (password_store_.get()) { 222 EXPECT_CALL(*components, CreatePasswordSyncComponents(_, _, _)) 223 .Times(AtLeast(1)). // Can be more if we hit NEEDS_CRYPTO. 224 WillRepeatedly(MakePasswordSyncComponents( 225 sync_service_, password_store_.get(), data_type_controller)); 226 } else { 227 // When the password store is unavailable, password sync components must 228 // not be created. 229 EXPECT_CALL(*components, CreatePasswordSyncComponents(_, _, _)) 230 .Times(0); 231 } 232 EXPECT_CALL(*components, CreateDataTypeManager(_, _, _, _, _, _)). 233 WillOnce(ReturnNewDataTypeManager()); 234 235 // We need tokens to get the tests going 236 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get()) 237 ->UpdateCredentials("test_user@gmail.com", "oauth2_login_token"); 238 239 sync_service_->RegisterDataTypeController(data_type_controller); 240 sync_service_->Initialize(); 241 base::MessageLoop::current()->Run(); 242 FlushLastDBTask(); 243 244 sync_service_->SetEncryptionPassphrase("foo", 245 ProfileSyncService::IMPLICIT); 246 base::MessageLoop::current()->Run(); 247 } 248 } 249 250 // Helper to sort the results of GetPasswordEntriesFromSyncDB. The sorting 251 // doesn't need to be particularly intelligent, it just needs to be consistent 252 // enough that we can base our tests expectations on the ordering it provides. 253 static bool PasswordFormComparator(const PasswordForm& pf1, 254 const PasswordForm& pf2) { 255 if (pf1.submit_element < pf2.submit_element) 256 return true; 257 if (pf1.username_element < pf2.username_element) 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<TestingProfile> profile_; 318 scoped_refptr<MockPasswordStore> password_store_; 319 content::NotificationRegistrar registrar_; 320}; 321 322void 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 351TEST_F(ProfileSyncServicePasswordTest, MAYBE_FailModelAssociation) { 352 StartSyncService(base::Closure(), base::Closure()); 353 EXPECT_TRUE(sync_service_->HasUnrecoverableError()); 354} 355 356TEST_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 367TEST_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 380TEST_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 411TEST_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 465TEST_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. 526TEST_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 588TEST_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