1// Copyright 2013 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 "base/command_line.h" 6#include "base/memory/scoped_ptr.h" 7#include "base/run_loop.h" 8#include "base/strings/utf_string_conversions.h" 9#include "base/test/histogram_tester.h" 10#include "base/time/time.h" 11#include "build/build_config.h" 12#include "chrome/browser/prefs/pref_service_syncable.h" 13#include "chrome/browser/signin/account_reconcilor_factory.h" 14#include "chrome/browser/signin/chrome_signin_client_factory.h" 15#include "chrome/browser/signin/fake_profile_oauth2_token_service.h" 16#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h" 17#include "chrome/browser/signin/fake_signin_manager.h" 18#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 19#include "chrome/browser/signin/signin_manager_factory.h" 20#include "chrome/browser/signin/test_signin_client_builder.h" 21#include "chrome/test/base/testing_browser_process.h" 22#include "chrome/test/base/testing_profile.h" 23#include "chrome/test/base/testing_profile_manager.h" 24#include "components/signin/core/browser/account_reconcilor.h" 25#include "components/signin/core/browser/profile_oauth2_token_service.h" 26#include "components/signin/core/browser/signin_manager.h" 27#include "components/signin/core/browser/signin_metrics.h" 28#include "components/signin/core/common/profile_management_switches.h" 29#include "components/signin/core/common/signin_switches.h" 30#include "content/public/test/test_browser_thread_bundle.h" 31#include "google_apis/gaia/gaia_urls.h" 32#include "net/url_request/test_url_fetcher_factory.h" 33#include "testing/gmock/include/gmock/gmock.h" 34#include "testing/gtest/include/gtest/gtest.h" 35 36namespace { 37 38const char kTestEmail[] = "user@gmail.com"; 39 40class MockAccountReconcilor : public testing::StrictMock<AccountReconcilor> { 41 public: 42 static KeyedService* Build(content::BrowserContext* context); 43 44 MockAccountReconcilor(ProfileOAuth2TokenService* token_service, 45 SigninManagerBase* signin_manager, 46 SigninClient* client); 47 virtual ~MockAccountReconcilor() {} 48 49 virtual void StartFetchingExternalCcResult() OVERRIDE { 50 // Don't do this in tests. 51 } 52 53 MOCK_METHOD1(PerformMergeAction, void(const std::string& account_id)); 54 MOCK_METHOD0(PerformLogoutAllAccountsAction, void()); 55}; 56 57// static 58KeyedService* MockAccountReconcilor::Build(content::BrowserContext* context) { 59 Profile* profile = Profile::FromBrowserContext(context); 60 AccountReconcilor* reconcilor = new MockAccountReconcilor( 61 ProfileOAuth2TokenServiceFactory::GetForProfile(profile), 62 SigninManagerFactory::GetForProfile(profile), 63 ChromeSigninClientFactory::GetForProfile(profile)); 64 reconcilor->Initialize(false /* start_reconcile_if_tokens_available */); 65 return reconcilor; 66} 67 68MockAccountReconcilor::MockAccountReconcilor( 69 ProfileOAuth2TokenService* token_service, 70 SigninManagerBase* signin_manager, 71 SigninClient* client) 72 : testing::StrictMock<AccountReconcilor>(token_service, 73 signin_manager, 74 client) {} 75 76} // namespace 77 78class AccountReconcilorTest : public ::testing::TestWithParam<bool> { 79 public: 80 AccountReconcilorTest(); 81 virtual void SetUp() OVERRIDE; 82 83 TestingProfile* profile() { return profile_; } 84 FakeSigninManagerForTesting* signin_manager() { return signin_manager_; } 85 FakeProfileOAuth2TokenService* token_service() { return token_service_; } 86 base::HistogramTester* histogram_tester() { return &histogram_tester_; } 87 88 void SetFakeResponse(const std::string& url, 89 const std::string& data, 90 net::HttpStatusCode code, 91 net::URLRequestStatus::Status status) { 92 url_fetcher_factory_.SetFakeResponse(GURL(url), data, code, status); 93 } 94 95 MockAccountReconcilor* GetMockReconcilor(); 96 97 void SimulateMergeSessionCompleted( 98 MergeSessionHelper::Observer* observer, 99 const std::string& account_id, 100 const GoogleServiceAuthError& error); 101 102 private: 103 content::TestBrowserThreadBundle bundle_; 104 TestingProfile* profile_; 105 FakeSigninManagerForTesting* signin_manager_; 106 FakeProfileOAuth2TokenService* token_service_; 107 MockAccountReconcilor* mock_reconcilor_; 108 net::FakeURLFetcherFactory url_fetcher_factory_; 109 scoped_ptr<TestingProfileManager> testing_profile_manager_; 110 base::HistogramTester histogram_tester_; 111 112 DISALLOW_COPY_AND_ASSIGN(AccountReconcilorTest); 113}; 114 115AccountReconcilorTest::AccountReconcilorTest() 116 : signin_manager_(NULL), 117 token_service_(NULL), 118 mock_reconcilor_(NULL), 119 url_fetcher_factory_(NULL) {} 120 121void AccountReconcilorTest::SetUp() { 122 // If it's a non-parameterized test, or we have a parameter of true, set flag. 123 if (!::testing::UnitTest::GetInstance()->current_test_info()->value_param() || 124 GetParam()) { 125 CommandLine::ForCurrentProcess()->AppendSwitch( 126 switches::kEnableNewProfileManagement); 127 } 128 129 testing_profile_manager_.reset( 130 new TestingProfileManager(TestingBrowserProcess::GetGlobal())); 131 ASSERT_TRUE(testing_profile_manager_.get()->SetUp()); 132 133 TestingProfile::TestingFactories factories; 134 factories.push_back(std::make_pair(ChromeSigninClientFactory::GetInstance(), 135 signin::BuildTestSigninClient)); 136 factories.push_back(std::make_pair( 137 ProfileOAuth2TokenServiceFactory::GetInstance(), 138 BuildFakeProfileOAuth2TokenService)); 139 factories.push_back(std::make_pair(SigninManagerFactory::GetInstance(), 140 FakeSigninManagerBase::Build)); 141 factories.push_back(std::make_pair(AccountReconcilorFactory::GetInstance(), 142 MockAccountReconcilor::Build)); 143 144 profile_ = testing_profile_manager_.get()->CreateTestingProfile("name", 145 scoped_ptr<PrefServiceSyncable>(), 146 base::UTF8ToUTF16("name"), 0, std::string(), 147 factories); 148 149 signin_manager_ = 150 static_cast<FakeSigninManagerForTesting*>( 151 SigninManagerFactory::GetForProfile(profile())); 152 153 token_service_ = 154 static_cast<FakeProfileOAuth2TokenService*>( 155 ProfileOAuth2TokenServiceFactory::GetForProfile(profile())); 156} 157 158MockAccountReconcilor* AccountReconcilorTest::GetMockReconcilor() { 159 if (!mock_reconcilor_) { 160 mock_reconcilor_ = 161 static_cast<MockAccountReconcilor*>( 162 AccountReconcilorFactory::GetForProfile(profile())); 163 } 164 165 return mock_reconcilor_; 166} 167 168void AccountReconcilorTest::SimulateMergeSessionCompleted( 169 MergeSessionHelper::Observer* observer, 170 const std::string& account_id, 171 const GoogleServiceAuthError& error) { 172 observer->MergeSessionCompleted(account_id, error); 173} 174 175TEST_F(AccountReconcilorTest, Basic) { 176 AccountReconcilor* reconcilor = 177 AccountReconcilorFactory::GetForProfile(profile()); 178 ASSERT_TRUE(reconcilor); 179 ASSERT_EQ(token_service(), reconcilor->token_service()); 180} 181 182#if !defined(OS_CHROMEOS) 183 184// This method requires the use of the |TestSigninClient| to be created from the 185// |ChromeSigninClientFactory| because it overrides the |GoogleSigninSucceeded| 186// method with an empty implementation. On MacOS, the normal implementation 187// causes the try_bots to time out. 188TEST_F(AccountReconcilorTest, SigninManagerRegistration) { 189 AccountReconcilor* reconcilor = 190 AccountReconcilorFactory::GetForProfile(profile()); 191 ASSERT_TRUE(reconcilor); 192 ASSERT_FALSE(reconcilor->IsRegisteredWithTokenService()); 193 194 signin_manager()->set_password("password"); 195 signin_manager()->OnExternalSigninCompleted(kTestEmail); 196 ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService()); 197 198 EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction()); 199 200 signin_manager()->SignOut(signin_metrics::SIGNOUT_TEST); 201 ASSERT_FALSE(reconcilor->IsRegisteredWithTokenService()); 202} 203 204// This method requires the use of the |TestSigninClient| to be created from the 205// |ChromeSigninClientFactory| because it overrides the |GoogleSigninSucceeded| 206// method with an empty implementation. On MacOS, the normal implementation 207// causes the try_bots to time out. 208TEST_F(AccountReconcilorTest, Reauth) { 209 signin_manager()->SetAuthenticatedUsername(kTestEmail); 210 signin_manager()->set_password("password"); 211 212 AccountReconcilor* reconcilor = 213 AccountReconcilorFactory::GetForProfile(profile()); 214 ASSERT_TRUE(reconcilor); 215 ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService()); 216 217 // Simulate reauth. The state of the reconcilor should not change. 218 signin_manager()->OnExternalSigninCompleted(kTestEmail); 219 ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService()); 220} 221 222#endif // !defined(OS_CHROMEOS) 223 224TEST_F(AccountReconcilorTest, ProfileAlreadyConnected) { 225 signin_manager()->SetAuthenticatedUsername(kTestEmail); 226 227 AccountReconcilor* reconcilor = 228 AccountReconcilorFactory::GetForProfile(profile()); 229 ASSERT_TRUE(reconcilor); 230 ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService()); 231} 232 233TEST_F(AccountReconcilorTest, GetAccountsFromCookieSuccess) { 234 signin_manager()->SetAuthenticatedUsername(kTestEmail); 235 token_service()->UpdateCredentials(kTestEmail, "refresh_token"); 236 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(kTestEmail)); 237 AccountReconcilor* reconcilor = 238 AccountReconcilorFactory::GetForProfile(profile()); 239 ASSERT_TRUE(reconcilor); 240 241 SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(), 242 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 0]]]", 243 net::HTTP_OK, net::URLRequestStatus::SUCCESS); 244 245 reconcilor->StartReconcile(); 246 ASSERT_FALSE(reconcilor->AreGaiaAccountsSet()); 247 248 base::RunLoop().RunUntilIdle(); 249 ASSERT_TRUE(reconcilor->AreGaiaAccountsSet()); 250 const std::vector<std::pair<std::string, bool> >& accounts = 251 reconcilor->GetGaiaAccountsForTesting(); 252 ASSERT_EQ(1u, accounts.size()); 253 ASSERT_EQ("user@gmail.com", accounts[0].first); 254} 255 256TEST_F(AccountReconcilorTest, GetAccountsFromCookieFailure) { 257 signin_manager()->SetAuthenticatedUsername(kTestEmail); 258 token_service()->UpdateCredentials(kTestEmail, "refresh_token"); 259 AccountReconcilor* reconcilor = 260 AccountReconcilorFactory::GetForProfile(profile()); 261 ASSERT_TRUE(reconcilor); 262 263 SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(), "", 264 net::HTTP_NOT_FOUND, net::URLRequestStatus::SUCCESS); 265 266 reconcilor->StartReconcile(); 267 ASSERT_FALSE(reconcilor->AreGaiaAccountsSet()); 268 269 base::RunLoop().RunUntilIdle(); 270 ASSERT_FALSE(reconcilor->AreGaiaAccountsSet()); 271} 272 273TEST_P(AccountReconcilorTest, StartReconcileNoop) { 274 signin_manager()->SetAuthenticatedUsername(kTestEmail); 275 token_service()->UpdateCredentials(kTestEmail, "refresh_token"); 276 277 AccountReconcilor* reconcilor = 278 AccountReconcilorFactory::GetForProfile(profile()); 279 ASSERT_TRUE(reconcilor); 280 281 SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(), 282 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", 283 net::HTTP_OK, net::URLRequestStatus::SUCCESS); 284 285 reconcilor->StartReconcile(); 286 ASSERT_TRUE(reconcilor->is_reconcile_started_); 287 ASSERT_FALSE(reconcilor->AreGaiaAccountsSet()); 288 289 base::RunLoop().RunUntilIdle(); 290 ASSERT_FALSE(reconcilor->is_reconcile_started_); 291 292 histogram_tester()->ExpectTotalCount( 293 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 1); 294 histogram_tester()->ExpectUniqueSample( 295 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 296 signin_metrics::ACCOUNTS_SAME, 297 1); 298} 299 300// This is test is needed until chrome changes to use gaia obfuscated id. 301// The signin manager and token service use the gaia "email" property, which 302// preserves dots in usernames and preserves case. gaia::ParseListAccountsData() 303// however uses gaia "displayEmail" which does not preserve case, and then 304// passes the string through gaia::CanonicalizeEmail() which removes dots. This 305// tests makes sure that an email like "Dot.S@hmail.com", as seen by the 306// token service, will be considered the same as "dots@gmail.com" as returned 307// by gaia::ParseListAccountsData(). 308TEST_P(AccountReconcilorTest, StartReconcileNoopWithDots) { 309 signin_manager()->SetAuthenticatedUsername("Dot.S@gmail.com"); 310 token_service()->UpdateCredentials("Dot.S@gmail.com", "refresh_token"); 311 312 AccountReconcilor* reconcilor = 313 AccountReconcilorFactory::GetForProfile(profile()); 314 ASSERT_TRUE(reconcilor); 315 316 SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(), 317 "[\"f\", [[\"b\", 0, \"n\", \"dot.s@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", 318 net::HTTP_OK, net::URLRequestStatus::SUCCESS); 319 320 reconcilor->StartReconcile(); 321 ASSERT_FALSE(reconcilor->AreGaiaAccountsSet()); 322 323 base::RunLoop().RunUntilIdle(); 324 ASSERT_FALSE(reconcilor->is_reconcile_started_); 325 326 histogram_tester()->ExpectUniqueSample( 327 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 328 signin_metrics::ACCOUNTS_SAME, 329 1); 330} 331 332TEST_P(AccountReconcilorTest, StartReconcileNoopMultiple) { 333 signin_manager()->SetAuthenticatedUsername("user@gmail.com"); 334 token_service()->UpdateCredentials("user@gmail.com", "refresh_token"); 335 token_service()->UpdateCredentials("other@gmail.com", "refresh_token"); 336 337 AccountReconcilor* reconcilor = 338 AccountReconcilorFactory::GetForProfile(profile()); 339 ASSERT_TRUE(reconcilor); 340 341 SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(), 342 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1], " 343 "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", 344 net::HTTP_OK, net::URLRequestStatus::SUCCESS); 345 346 reconcilor->StartReconcile(); 347 ASSERT_FALSE(reconcilor->AreGaiaAccountsSet()); 348 base::RunLoop().RunUntilIdle(); 349 ASSERT_FALSE(reconcilor->is_reconcile_started_); 350 351 histogram_tester()->ExpectTotalCount( 352 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 1); 353 histogram_tester()->ExpectUniqueSample( 354 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 355 signin_metrics::ACCOUNTS_SAME, 356 1); 357} 358 359TEST_P(AccountReconcilorTest, StartReconcileAddToCookie) { 360 signin_manager()->SetAuthenticatedUsername("user@gmail.com"); 361 token_service()->UpdateCredentials("user@gmail.com", "refresh_token"); 362 token_service()->UpdateCredentials("other@gmail.com", "refresh_token"); 363 364 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("other@gmail.com")); 365 366 SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(), 367 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", 368 net::HTTP_OK, net::URLRequestStatus::SUCCESS); 369 370 AccountReconcilor* reconcilor = GetMockReconcilor(); 371 reconcilor->StartReconcile(); 372 373 base::RunLoop().RunUntilIdle(); 374 ASSERT_TRUE(reconcilor->is_reconcile_started_); 375 SimulateMergeSessionCompleted(reconcilor, "other@gmail.com", 376 GoogleServiceAuthError::AuthErrorNone()); 377 ASSERT_FALSE(reconcilor->is_reconcile_started_); 378 379 histogram_tester()->ExpectUniqueSample( 380 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 381 signin_metrics::ACCOUNTS_SAME, 382 1); 383 histogram_tester()->ExpectUniqueSample( 384 "Signin.Reconciler.AddedToCookieJar.FirstRun", 1, 1); 385 histogram_tester()->ExpectUniqueSample( 386 "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1); 387} 388 389TEST_P(AccountReconcilorTest, StartReconcileRemoveFromCookie) { 390 signin_manager()->SetAuthenticatedUsername("user@gmail.com"); 391 token_service()->UpdateCredentials("user@gmail.com", "refresh_token"); 392 393 EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction()); 394 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("user@gmail.com")); 395 396 SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(), 397 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1], " 398 "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", 399 net::HTTP_OK, net::URLRequestStatus::SUCCESS); 400 401 AccountReconcilor* reconcilor = GetMockReconcilor(); 402 reconcilor->StartReconcile(); 403 ASSERT_TRUE(reconcilor->is_reconcile_started_); 404 405 base::RunLoop().RunUntilIdle(); 406 SimulateMergeSessionCompleted(reconcilor, "user@gmail.com", 407 GoogleServiceAuthError::AuthErrorNone()); 408 ASSERT_FALSE(reconcilor->is_reconcile_started_); 409 410 histogram_tester()->ExpectUniqueSample( 411 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 412 signin_metrics::ACCOUNTS_SAME, 413 1); 414 histogram_tester()->ExpectUniqueSample( 415 "Signin.Reconciler.AddedToCookieJar.FirstRun", 0, 1); 416 histogram_tester()->ExpectUniqueSample( 417 "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 1, 1); 418} 419 420TEST_P(AccountReconcilorTest, StartReconcileAddToCookieTwice) { 421 signin_manager()->SetAuthenticatedUsername("user@gmail.com"); 422 token_service()->UpdateCredentials("user@gmail.com", "refresh_token"); 423 token_service()->UpdateCredentials("other@gmail.com", "refresh_token"); 424 425 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("other@gmail.com")); 426 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("third@gmail.com")); 427 428 SetFakeResponse( 429 GaiaUrls::GetInstance()->list_accounts_url().spec(), 430 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", 431 net::HTTP_OK, 432 net::URLRequestStatus::SUCCESS); 433 434 AccountReconcilor* reconcilor = GetMockReconcilor(); 435 reconcilor->StartReconcile(); 436 437 base::RunLoop().RunUntilIdle(); 438 ASSERT_TRUE(reconcilor->is_reconcile_started_); 439 SimulateMergeSessionCompleted( 440 reconcilor, "other@gmail.com", GoogleServiceAuthError::AuthErrorNone()); 441 ASSERT_FALSE(reconcilor->is_reconcile_started_); 442 443 histogram_tester()->ExpectUniqueSample( 444 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 445 signin_metrics::ACCOUNTS_SAME, 446 1); 447 histogram_tester()->ExpectUniqueSample( 448 "Signin.Reconciler.AddedToCookieJar.FirstRun", 1, 1); 449 histogram_tester()->ExpectUniqueSample( 450 "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1); 451 452 // Do another pass after I've added a third account to the token service 453 454 SetFakeResponse( 455 GaiaUrls::GetInstance()->list_accounts_url().spec(), 456 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1], " 457 "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", 458 net::HTTP_OK, 459 net::URLRequestStatus::SUCCESS); 460 // This will cause the reconcilor to fire. 461 token_service()->UpdateCredentials("third@gmail.com", "refresh_token"); 462 463 base::RunLoop().RunUntilIdle(); 464 465 ASSERT_TRUE(reconcilor->is_reconcile_started_); 466 SimulateMergeSessionCompleted( 467 reconcilor, "third@gmail.com", GoogleServiceAuthError::AuthErrorNone()); 468 ASSERT_FALSE(reconcilor->is_reconcile_started_); 469 470 histogram_tester()->ExpectUniqueSample( 471 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 472 signin_metrics::ACCOUNTS_SAME, 473 1); 474 histogram_tester()->ExpectUniqueSample( 475 "Signin.Reconciler.AddedToCookieJar.FirstRun", 1, 1); 476 histogram_tester()->ExpectUniqueSample( 477 "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1); 478 histogram_tester()->ExpectUniqueSample( 479 "Signin.Reconciler.DifferentPrimaryAccounts.SubsequentRun", 480 signin_metrics::ACCOUNTS_SAME, 481 1); 482 histogram_tester()->ExpectUniqueSample( 483 "Signin.Reconciler.AddedToCookieJar.SubsequentRun", 1, 1); 484 histogram_tester()->ExpectUniqueSample( 485 "Signin.Reconciler.RemovedFromCookieJar.SubsequentRun", 0, 1); 486} 487 488TEST_P(AccountReconcilorTest, StartReconcileBadPrimary) { 489 signin_manager()->SetAuthenticatedUsername("user@gmail.com"); 490 token_service()->UpdateCredentials("user@gmail.com", "refresh_token"); 491 token_service()->UpdateCredentials("other@gmail.com", "refresh_token"); 492 493 EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction()); 494 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("user@gmail.com")); 495 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("other@gmail.com")); 496 497 SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(), 498 "[\"f\", [[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1], " 499 "[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", 500 net::HTTP_OK, net::URLRequestStatus::SUCCESS); 501 502 AccountReconcilor* reconcilor = GetMockReconcilor(); 503 reconcilor->StartReconcile(); 504 505 base::RunLoop().RunUntilIdle(); 506 ASSERT_TRUE(reconcilor->is_reconcile_started_); 507 SimulateMergeSessionCompleted(reconcilor, "other@gmail.com", 508 GoogleServiceAuthError::AuthErrorNone()); 509 ASSERT_TRUE(reconcilor->is_reconcile_started_); 510 SimulateMergeSessionCompleted(reconcilor, "user@gmail.com", 511 GoogleServiceAuthError::AuthErrorNone()); 512 ASSERT_FALSE(reconcilor->is_reconcile_started_); 513 514 histogram_tester()->ExpectUniqueSample( 515 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 516 signin_metrics::COOKIE_AND_TOKEN_PRIMARIES_DIFFERENT, 517 1); 518 histogram_tester()->ExpectUniqueSample( 519 "Signin.Reconciler.AddedToCookieJar.FirstRun", 0, 1); 520 histogram_tester()->ExpectUniqueSample( 521 "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1); 522} 523 524TEST_P(AccountReconcilorTest, StartReconcileOnlyOnce) { 525 signin_manager()->SetAuthenticatedUsername(kTestEmail); 526 token_service()->UpdateCredentials(kTestEmail, "refresh_token"); 527 528 AccountReconcilor* reconcilor = 529 AccountReconcilorFactory::GetForProfile(profile()); 530 ASSERT_TRUE(reconcilor); 531 532 SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(), 533 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", 534 net::HTTP_OK, net::URLRequestStatus::SUCCESS); 535 536 ASSERT_FALSE(reconcilor->is_reconcile_started_); 537 reconcilor->StartReconcile(); 538 ASSERT_TRUE(reconcilor->is_reconcile_started_); 539 540 base::RunLoop().RunUntilIdle(); 541 ASSERT_FALSE(reconcilor->is_reconcile_started_); 542} 543 544TEST_P(AccountReconcilorTest, StartReconcileWithSessionInfoExpiredDefault) { 545 signin_manager()->SetAuthenticatedUsername("user@gmail.com"); 546 token_service()->UpdateCredentials("user@gmail.com", "refresh_token"); 547 token_service()->UpdateCredentials("other@gmail.com", "refresh_token"); 548 549 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("user@gmail.com")); 550 551 SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(), 552 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 0]," 553 "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", 554 net::HTTP_OK, net::URLRequestStatus::SUCCESS); 555 556 AccountReconcilor* reconcilor = 557 AccountReconcilorFactory::GetForProfile(profile()); 558 ASSERT_TRUE(reconcilor); 559 560 ASSERT_FALSE(reconcilor->is_reconcile_started_); 561 reconcilor->StartReconcile(); 562 ASSERT_TRUE(reconcilor->is_reconcile_started_); 563 564 base::RunLoop().RunUntilIdle(); 565 SimulateMergeSessionCompleted(reconcilor, "user@gmail.com", 566 GoogleServiceAuthError::AuthErrorNone()); 567 ASSERT_FALSE(reconcilor->is_reconcile_started_); 568} 569 570TEST_F(AccountReconcilorTest, MergeSessionCompletedWithBogusAccount) { 571 signin_manager()->SetAuthenticatedUsername("user@gmail.com"); 572 token_service()->UpdateCredentials("user@gmail.com", "refresh_token"); 573 574 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("user@gmail.com")); 575 576 SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(), 577 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 0]]]", 578 net::HTTP_OK, net::URLRequestStatus::SUCCESS); 579 580 AccountReconcilor* reconcilor = 581 AccountReconcilorFactory::GetForProfile(profile()); 582 ASSERT_TRUE(reconcilor); 583 584 ASSERT_FALSE(reconcilor->is_reconcile_started_); 585 reconcilor->StartReconcile(); 586 ASSERT_TRUE(reconcilor->is_reconcile_started_); 587 588 base::RunLoop().RunUntilIdle(); 589 590 // If an unknown account id is sent, it should not upset the state. 591 SimulateMergeSessionCompleted(reconcilor, "bogus@gmail.com", 592 GoogleServiceAuthError::AuthErrorNone()); 593 ASSERT_TRUE(reconcilor->is_reconcile_started_); 594 595 SimulateMergeSessionCompleted(reconcilor, "user@gmail.com", 596 GoogleServiceAuthError::AuthErrorNone()); 597 ASSERT_FALSE(reconcilor->is_reconcile_started_); 598} 599 600INSTANTIATE_TEST_CASE_P(AccountReconcilorMaybeEnabled, 601 AccountReconcilorTest, 602 testing::Bool()); 603 604