Support SizeClassIdiom on iOS7.
[chromium-blink-merge.git] / chrome / browser / signin / account_reconcilor_unittest.cc
blob3b17a24b8ed75d3c7027fab568742871a8dd572e
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.
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/account_tracker_service_factory.h"
15 #include "chrome/browser/signin/chrome_signin_client_factory.h"
16 #include "chrome/browser/signin/fake_gaia_cookie_manager_service.h"
17 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
18 #include "chrome/browser/signin/fake_signin_manager_builder.h"
19 #include "chrome/browser/signin/gaia_cookie_manager_service_factory.h"
20 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
21 #include "chrome/browser/signin/signin_manager_factory.h"
22 #include "chrome/browser/signin/test_signin_client_builder.h"
23 #include "chrome/test/base/testing_browser_process.h"
24 #include "chrome/test/base/testing_profile.h"
25 #include "chrome/test/base/testing_profile_manager.h"
26 #include "components/signin/core/browser/account_reconcilor.h"
27 #include "components/signin/core/browser/account_tracker_service.h"
28 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
29 #include "components/signin/core/browser/profile_oauth2_token_service.h"
30 #include "components/signin/core/browser/signin_manager.h"
31 #include "components/signin/core/browser/signin_metrics.h"
32 #include "components/signin/core/browser/test_signin_client.h"
33 #include "components/signin/core/common/profile_management_switches.h"
34 #include "components/signin/core/common/signin_switches.h"
35 #include "content/public/test/test_browser_thread_bundle.h"
36 #include "google_apis/gaia/fake_oauth2_token_service_delegate.h"
37 #include "google_apis/gaia/gaia_constants.h"
38 #include "google_apis/gaia/gaia_urls.h"
39 #include "net/url_request/test_url_fetcher_factory.h"
40 #include "testing/gmock/include/gmock/gmock.h"
41 #include "testing/gtest/include/gtest/gtest.h"
43 namespace {
45 class MockAccountReconcilor : public testing::StrictMock<AccountReconcilor> {
46 public:
47 static scoped_ptr<KeyedService> Build(content::BrowserContext* context);
49 MockAccountReconcilor(ProfileOAuth2TokenService* token_service,
50 SigninManagerBase* signin_manager,
51 SigninClient* client,
52 GaiaCookieManagerService* cookie_manager_service);
53 ~MockAccountReconcilor() override {}
55 MOCK_METHOD1(PerformMergeAction, void(const std::string& account_id));
56 MOCK_METHOD0(PerformLogoutAllAccountsAction, void());
59 // static
60 scoped_ptr<KeyedService> MockAccountReconcilor::Build(
61 content::BrowserContext* context) {
62 Profile* profile = Profile::FromBrowserContext(context);
63 scoped_ptr<AccountReconcilor> reconcilor(new MockAccountReconcilor(
64 ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
65 SigninManagerFactory::GetForProfile(profile),
66 ChromeSigninClientFactory::GetForProfile(profile),
67 GaiaCookieManagerServiceFactory::GetForProfile(profile)));
68 reconcilor->Initialize(false /* start_reconcile_if_tokens_available */);
69 return reconcilor.Pass();
72 MockAccountReconcilor::MockAccountReconcilor(
73 ProfileOAuth2TokenService* token_service,
74 SigninManagerBase* signin_manager,
75 SigninClient* client,
76 GaiaCookieManagerService* cookie_manager_service)
77 : testing::StrictMock<AccountReconcilor>(token_service,
78 signin_manager,
79 client,
80 cookie_manager_service) {}
82 } // namespace
84 class AccountReconcilorTest : public ::testing::TestWithParam<bool> {
85 public:
86 AccountReconcilorTest();
87 void SetUp() override;
89 TestingProfile* profile() { return profile_; }
90 FakeSigninManagerForTesting* signin_manager() { return signin_manager_; }
91 FakeProfileOAuth2TokenService* token_service() { return token_service_; }
92 FakeOAuth2TokenServiceDelegate* token_service_delegate() {
93 return static_cast<FakeOAuth2TokenServiceDelegate*>(
94 token_service_->GetDelegate());
96 TestSigninClient* test_signin_client() { return test_signin_client_; }
97 AccountTrackerService* account_tracker() { return account_tracker_; }
98 FakeGaiaCookieManagerService* cookie_manager_service() {
99 return cookie_manager_service_;
101 base::HistogramTester* histogram_tester() { return &histogram_tester_; }
103 void SetFakeResponse(const std::string& url,
104 const std::string& data,
105 net::HttpStatusCode code,
106 net::URLRequestStatus::Status status) {
107 url_fetcher_factory_.SetFakeResponse(GURL(url), data, code, status);
110 MockAccountReconcilor* GetMockReconcilor();
112 std::string ConnectProfileToAccount(const std::string& gaia_id,
113 const std::string& username);
115 std::string PickAccountIdForAccount(const std::string& gaia_id,
116 const std::string& username);
118 void SimulateAddAccountToCookieCompleted(
119 GaiaCookieManagerService::Observer* observer,
120 const std::string& account_id,
121 const GoogleServiceAuthError& error);
123 void SimulateCookieContentSettingsChanged(
124 content_settings::Observer* observer,
125 const ContentSettingsPattern& primary_pattern);
127 GURL get_check_connection_info_url() {
128 return get_check_connection_info_url_;
131 private:
132 content::TestBrowserThreadBundle bundle_;
133 TestingProfile* profile_;
134 FakeSigninManagerForTesting* signin_manager_;
135 FakeProfileOAuth2TokenService* token_service_;
136 TestSigninClient* test_signin_client_;
137 AccountTrackerService* account_tracker_;
138 FakeGaiaCookieManagerService* cookie_manager_service_;
139 MockAccountReconcilor* mock_reconcilor_;
140 net::FakeURLFetcherFactory url_fetcher_factory_;
141 scoped_ptr<TestingProfileManager> testing_profile_manager_;
142 base::HistogramTester histogram_tester_;
143 GURL get_check_connection_info_url_;
145 DISALLOW_COPY_AND_ASSIGN(AccountReconcilorTest);
148 AccountReconcilorTest::AccountReconcilorTest()
149 : signin_manager_(NULL),
150 token_service_(NULL),
151 test_signin_client_(NULL),
152 cookie_manager_service_(NULL),
153 mock_reconcilor_(NULL),
154 url_fetcher_factory_(NULL) {}
156 void AccountReconcilorTest::SetUp() {
157 // If it's a non-parameterized test, or we have a parameter of true, set flag.
158 if (!::testing::UnitTest::GetInstance()->current_test_info()->value_param() ||
159 GetParam()) {
160 base::CommandLine::ForCurrentProcess()->AppendSwitch(
161 switches::kEnableNewProfileManagement);
164 get_check_connection_info_url_ =
165 GaiaUrls::GetInstance()->GetCheckConnectionInfoURLWithSource(
166 GaiaConstants::kChromeSource);
168 testing_profile_manager_.reset(
169 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
170 ASSERT_TRUE(testing_profile_manager_.get()->SetUp());
172 TestingProfile::TestingFactories factories;
173 factories.push_back(std::make_pair(ChromeSigninClientFactory::GetInstance(),
174 signin::BuildTestSigninClient));
175 factories.push_back(std::make_pair(
176 ProfileOAuth2TokenServiceFactory::GetInstance(),
177 BuildFakeProfileOAuth2TokenService));
178 factories.push_back(std::make_pair(
179 GaiaCookieManagerServiceFactory::GetInstance(),
180 FakeGaiaCookieManagerService::Build));
181 factories.push_back(std::make_pair(SigninManagerFactory::GetInstance(),
182 BuildFakeSigninManagerBase));
183 factories.push_back(std::make_pair(AccountReconcilorFactory::GetInstance(),
184 MockAccountReconcilor::Build));
186 profile_ = testing_profile_manager_.get()->CreateTestingProfile("name",
187 scoped_ptr<PrefServiceSyncable>(),
188 base::UTF8ToUTF16("name"), 0, std::string(),
189 factories);
191 test_signin_client_ =
192 static_cast<TestSigninClient*>(
193 ChromeSigninClientFactory::GetForProfile(profile()));
195 token_service_ =
196 static_cast<FakeProfileOAuth2TokenService*>(
197 ProfileOAuth2TokenServiceFactory::GetForProfile(profile()));
199 account_tracker_ =
200 AccountTrackerServiceFactory::GetForProfile(profile());
202 signin_manager_ =
203 static_cast<FakeSigninManagerForTesting*>(
204 SigninManagerFactory::GetForProfile(profile()));
206 test_signin_client_ =
207 static_cast<TestSigninClient*>(
208 ChromeSigninClientFactory::GetForProfile(profile()));
210 cookie_manager_service_ =
211 static_cast<FakeGaiaCookieManagerService*>(
212 GaiaCookieManagerServiceFactory::GetForProfile(profile()));
213 cookie_manager_service_->Init(&url_fetcher_factory_);
215 cookie_manager_service_->SetListAccountsResponseHttpNotFound();
218 MockAccountReconcilor* AccountReconcilorTest::GetMockReconcilor() {
219 if (!mock_reconcilor_) {
220 mock_reconcilor_ =
221 static_cast<MockAccountReconcilor*>(
222 AccountReconcilorFactory::GetForProfile(profile()));
225 return mock_reconcilor_;
228 std::string AccountReconcilorTest::ConnectProfileToAccount(
229 const std::string& gaia_id,
230 const std::string& username) {
231 const std::string account_id = PickAccountIdForAccount(gaia_id, username);
232 #if !defined(OS_CHROMEOS)
233 signin_manager()->set_password("password");
234 #endif
235 signin_manager()->SetAuthenticatedAccountInfo(gaia_id, username);
236 token_service()->UpdateCredentials(account_id, "refresh_token");
237 return account_id;
240 std::string AccountReconcilorTest::PickAccountIdForAccount(
241 const std::string& gaia_id,
242 const std::string& username) {
243 return account_tracker()->PickAccountIdForAccount(gaia_id, username);
246 void AccountReconcilorTest::SimulateAddAccountToCookieCompleted(
247 GaiaCookieManagerService::Observer* observer,
248 const std::string& account_id,
249 const GoogleServiceAuthError& error) {
250 observer->OnAddAccountToCookieCompleted(account_id, error);
253 void AccountReconcilorTest::SimulateCookieContentSettingsChanged(
254 content_settings::Observer* observer,
255 const ContentSettingsPattern& primary_pattern) {
256 observer->OnContentSettingChanged(
257 primary_pattern,
258 ContentSettingsPattern::Wildcard(),
259 CONTENT_SETTINGS_TYPE_COOKIES,
260 std::string());
263 TEST_F(AccountReconcilorTest, Basic) {
264 AccountReconcilor* reconcilor =
265 AccountReconcilorFactory::GetForProfile(profile());
266 ASSERT_TRUE(reconcilor);
269 #if !defined(OS_CHROMEOS)
271 // This method requires the use of the |TestSigninClient| to be created from the
272 // |ChromeSigninClientFactory| because it overrides the |GoogleSigninSucceeded|
273 // method with an empty implementation. On MacOS, the normal implementation
274 // causes the try_bots to time out.
275 TEST_F(AccountReconcilorTest, SigninManagerRegistration) {
276 AccountReconcilor* reconcilor =
277 AccountReconcilorFactory::GetForProfile(profile());
278 ASSERT_TRUE(reconcilor);
279 ASSERT_FALSE(reconcilor->IsRegisteredWithTokenService());
281 account_tracker()->SeedAccountInfo("12345", "user@gmail.com");
282 signin_manager()->SignIn("12345", "user@gmail.com", "password");
283 ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService());
285 EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
287 signin_manager()->SignOut(signin_metrics::SIGNOUT_TEST);
288 ASSERT_FALSE(reconcilor->IsRegisteredWithTokenService());
291 // This method requires the use of the |TestSigninClient| to be created from the
292 // |ChromeSigninClientFactory| because it overrides the |GoogleSigninSucceeded|
293 // method with an empty implementation. On MacOS, the normal implementation
294 // causes the try_bots to time out.
295 TEST_F(AccountReconcilorTest, Reauth) {
296 const std::string email = "user@gmail.com";
297 const std::string account_id =
298 ConnectProfileToAccount("12345", email);
300 AccountReconcilor* reconcilor =
301 AccountReconcilorFactory::GetForProfile(profile());
302 ASSERT_TRUE(reconcilor);
303 ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService());
305 // Simulate reauth. The state of the reconcilor should not change.
306 signin_manager()->OnExternalSigninCompleted(email);
307 ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService());
310 #endif // !defined(OS_CHROMEOS)
312 TEST_F(AccountReconcilorTest, ProfileAlreadyConnected) {
313 ConnectProfileToAccount("12345", "user@gmail.com");
315 AccountReconcilor* reconcilor =
316 AccountReconcilorFactory::GetForProfile(profile());
317 ASSERT_TRUE(reconcilor);
318 ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService());
321 TEST_F(AccountReconcilorTest, GetAccountsFromCookieSuccess) {
322 const std::string account_id =
323 ConnectProfileToAccount("12345", "user@gmail.com");
324 cookie_manager_service()->SetListAccountsResponseOneAccountWithExpiry(
325 "user@gmail.com", "12345", true);
326 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
328 AccountReconcilor* reconcilor =
329 AccountReconcilorFactory::GetForProfile(profile());
330 ASSERT_TRUE(reconcilor);
332 ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
333 reconcilor->StartReconcile();
334 ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_RUNNING,
335 reconcilor->GetState());
336 base::RunLoop().RunUntilIdle();
337 ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_RUNNING, reconcilor->GetState());
339 std::vector<gaia::ListedAccount> accounts;
340 ASSERT_TRUE(cookie_manager_service()->ListAccounts(&accounts));
341 ASSERT_EQ(1u, accounts.size());
342 ASSERT_EQ(account_id, accounts[0].id);
345 TEST_F(AccountReconcilorTest, GetAccountsFromCookieFailure) {
346 ConnectProfileToAccount("12345", "user@gmail.com");
347 cookie_manager_service()->SetListAccountsResponseWebLoginRequired();
349 AccountReconcilor* reconcilor =
350 AccountReconcilorFactory::GetForProfile(profile());
351 ASSERT_TRUE(reconcilor);
353 ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
354 reconcilor->StartReconcile();
355 ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_RUNNING,
356 reconcilor->GetState());
357 base::RunLoop().RunUntilIdle();
359 std::vector<gaia::ListedAccount> accounts;
360 ASSERT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
361 ASSERT_EQ(0u, accounts.size());
363 base::RunLoop().RunUntilIdle();
364 ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_ERROR,
365 reconcilor->GetState());
368 TEST_P(AccountReconcilorTest, StartReconcileNoop) {
369 const std::string account_id =
370 ConnectProfileToAccount("12345", "user@gmail.com");
372 AccountReconcilor* reconcilor =
373 AccountReconcilorFactory::GetForProfile(profile());
374 ASSERT_TRUE(reconcilor);
376 cookie_manager_service()->SetListAccountsResponseOneAccount(
377 "user@gmail.com", "12345");
379 reconcilor->StartReconcile();
380 ASSERT_TRUE(reconcilor->is_reconcile_started_);
382 base::RunLoop().RunUntilIdle();
383 ASSERT_FALSE(reconcilor->is_reconcile_started_);
385 histogram_tester()->ExpectTotalCount(
386 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 1);
387 histogram_tester()->ExpectUniqueSample(
388 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
389 signin_metrics::ACCOUNTS_SAME,
393 TEST_P(AccountReconcilorTest, StartReconcileCookiesDisabled) {
394 const std::string account_id =
395 ConnectProfileToAccount("12345", "user@gmail.com");
396 token_service()->UpdateCredentials(account_id, "refresh_token");
397 test_signin_client()->set_are_signin_cookies_allowed(false);
399 AccountReconcilor* reconcilor =
400 AccountReconcilorFactory::GetForProfile(profile());
401 ASSERT_TRUE(reconcilor);
403 reconcilor->StartReconcile();
404 ASSERT_FALSE(reconcilor->is_reconcile_started_);
406 base::RunLoop().RunUntilIdle();
407 std::vector<gaia::ListedAccount> accounts;
408 // This will be the first call to ListAccounts.
409 ASSERT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
410 ASSERT_FALSE(reconcilor->is_reconcile_started_);
413 TEST_P(AccountReconcilorTest, StartReconcileContentSettings) {
414 const std::string account_id =
415 ConnectProfileToAccount("12345", "user@gmail.com");
416 token_service()->UpdateCredentials(account_id, "refresh_token");
418 AccountReconcilor* reconcilor =
419 AccountReconcilorFactory::GetForProfile(profile());
420 ASSERT_TRUE(reconcilor);
422 test_signin_client()->set_are_signin_cookies_allowed(false);
423 SimulateCookieContentSettingsChanged(reconcilor,
424 ContentSettingsPattern::Wildcard());
425 ASSERT_FALSE(reconcilor->is_reconcile_started_);
427 test_signin_client()->set_are_signin_cookies_allowed(true);
428 SimulateCookieContentSettingsChanged(reconcilor,
429 ContentSettingsPattern::Wildcard());
430 ASSERT_TRUE(reconcilor->is_reconcile_started_);
433 TEST_P(AccountReconcilorTest, StartReconcileContentSettingsGaiaUrl) {
434 const std::string account_id =
435 ConnectProfileToAccount("12345", "user@gmail.com");
436 token_service()->UpdateCredentials(account_id, "refresh_token");
438 AccountReconcilor* reconcilor =
439 AccountReconcilorFactory::GetForProfile(profile());
440 ASSERT_TRUE(reconcilor);
442 SimulateCookieContentSettingsChanged(
443 reconcilor,
444 ContentSettingsPattern::FromURL(GaiaUrls::GetInstance()->gaia_url()));
445 ASSERT_TRUE(reconcilor->is_reconcile_started_);
448 TEST_P(AccountReconcilorTest, StartReconcileContentSettingsNonGaiaUrl) {
449 const std::string account_id =
450 ConnectProfileToAccount("12345", "user@gmail.com");
451 token_service()->UpdateCredentials(account_id, "refresh_token");
453 AccountReconcilor* reconcilor =
454 AccountReconcilorFactory::GetForProfile(profile());
455 ASSERT_TRUE(reconcilor);
457 SimulateCookieContentSettingsChanged(
458 reconcilor,
459 ContentSettingsPattern::FromURL(GURL("http://www.example.com")));
460 ASSERT_FALSE(reconcilor->is_reconcile_started_);
463 TEST_P(AccountReconcilorTest, StartReconcileContentSettingsInvalidPattern) {
464 const std::string account_id =
465 ConnectProfileToAccount("12345", "user@gmail.com");
466 token_service()->UpdateCredentials(account_id, "refresh_token");
468 AccountReconcilor* reconcilor =
469 AccountReconcilorFactory::GetForProfile(profile());
470 ASSERT_TRUE(reconcilor);
472 scoped_ptr<ContentSettingsPattern::BuilderInterface>
473 builder(ContentSettingsPattern::CreateBuilder(false));
474 builder->Invalid();
476 SimulateCookieContentSettingsChanged(reconcilor, builder->Build());
477 ASSERT_TRUE(reconcilor->is_reconcile_started_);
480 // This test is needed until chrome changes to use gaia obfuscated id.
481 // The signin manager and token service use the gaia "email" property, which
482 // preserves dots in usernames and preserves case. gaia::ParseListAccountsData()
483 // however uses gaia "displayEmail" which does not preserve case, and then
484 // passes the string through gaia::CanonicalizeEmail() which removes dots. This
485 // tests makes sure that an email like "Dot.S@hmail.com", as seen by the
486 // token service, will be considered the same as "dots@gmail.com" as returned
487 // by gaia::ParseListAccountsData().
488 TEST_P(AccountReconcilorTest, StartReconcileNoopWithDots) {
489 if (account_tracker()->GetMigrationState() !=
490 AccountTrackerService::MIGRATION_NOT_STARTED) {
491 return;
494 const std::string account_id =
495 ConnectProfileToAccount("12345", "Dot.S@gmail.com");
496 cookie_manager_service()->SetListAccountsResponseOneAccount(
497 "dot.s@gmail.com", "12345");
498 AccountReconcilor* reconcilor =
499 AccountReconcilorFactory::GetForProfile(profile());
500 ASSERT_TRUE(reconcilor);
502 reconcilor->StartReconcile();
503 base::RunLoop().RunUntilIdle();
504 ASSERT_FALSE(reconcilor->is_reconcile_started_);
506 histogram_tester()->ExpectUniqueSample(
507 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
508 signin_metrics::ACCOUNTS_SAME,
512 TEST_P(AccountReconcilorTest, StartReconcileNoopMultiple) {
513 const std::string account_id =
514 ConnectProfileToAccount("12345", "user@gmail.com");
515 const std::string account_id2 =
516 PickAccountIdForAccount("67890", "other@gmail.com");
517 cookie_manager_service()->SetListAccountsResponseTwoAccounts(
518 "user@gmail.com", "12345", "other@gmail.com", "67890");
519 token_service()->UpdateCredentials(account_id2, "refresh_token");
521 AccountReconcilor* reconcilor =
522 AccountReconcilorFactory::GetForProfile(profile());
523 ASSERT_TRUE(reconcilor);
525 reconcilor->StartReconcile();
526 base::RunLoop().RunUntilIdle();
527 ASSERT_FALSE(reconcilor->is_reconcile_started_);
529 histogram_tester()->ExpectTotalCount(
530 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 1);
531 histogram_tester()->ExpectUniqueSample(
532 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
533 signin_metrics::ACCOUNTS_SAME,
537 TEST_P(AccountReconcilorTest, StartReconcileAddToCookie) {
538 const std::string account_id =
539 ConnectProfileToAccount("12345", "user@gmail.com");
540 token_service()->UpdateCredentials(account_id, "refresh_token");
541 cookie_manager_service()->SetListAccountsResponseOneAccount(
542 "user@gmail.com", "12345");
544 const std::string account_id2 =
545 PickAccountIdForAccount("67890", "other@gmail.com");
546 token_service()->UpdateCredentials(account_id2, "refresh_token");
548 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2));
550 AccountReconcilor* reconcilor = GetMockReconcilor();
551 reconcilor->StartReconcile();
553 base::RunLoop().RunUntilIdle();
554 ASSERT_TRUE(reconcilor->is_reconcile_started_);
555 SimulateAddAccountToCookieCompleted(reconcilor, account_id2,
556 GoogleServiceAuthError::AuthErrorNone());
557 ASSERT_FALSE(reconcilor->is_reconcile_started_);
559 histogram_tester()->ExpectUniqueSample(
560 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
561 signin_metrics::ACCOUNTS_SAME,
563 histogram_tester()->ExpectUniqueSample(
564 "Signin.Reconciler.AddedToCookieJar.FirstRun", 1, 1);
565 histogram_tester()->ExpectUniqueSample(
566 "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1);
569 TEST_P(AccountReconcilorTest, StartReconcileRemoveFromCookie) {
570 const std::string account_id =
571 ConnectProfileToAccount("12345", "user@gmail.com");
572 token_service()->UpdateCredentials(account_id, "refresh_token");
573 cookie_manager_service()->SetListAccountsResponseTwoAccounts(
574 "user@gmail.com", "12345", "other@gmail.com", "67890");
576 EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
577 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
579 AccountReconcilor* reconcilor = GetMockReconcilor();
580 reconcilor->StartReconcile();
581 ASSERT_TRUE(reconcilor->is_reconcile_started_);
583 base::RunLoop().RunUntilIdle();
584 SimulateAddAccountToCookieCompleted(reconcilor, account_id,
585 GoogleServiceAuthError::AuthErrorNone());
586 ASSERT_FALSE(reconcilor->is_reconcile_started_);
588 histogram_tester()->ExpectUniqueSample(
589 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
590 signin_metrics::ACCOUNTS_SAME,
592 histogram_tester()->ExpectUniqueSample(
593 "Signin.Reconciler.AddedToCookieJar.FirstRun", 0, 1);
594 histogram_tester()->ExpectUniqueSample(
595 "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 1, 1);
598 TEST_P(AccountReconcilorTest, StartReconcileAddToCookieTwice) {
599 const std::string account_id =
600 ConnectProfileToAccount("12345", "user@gmail.com");
601 const std::string account_id2 =
602 PickAccountIdForAccount("67890", "other@gmail.com");
603 const std::string account_id3 =
604 PickAccountIdForAccount("34567", "third@gmail.com");
606 cookie_manager_service()->SetListAccountsResponseOneAccount(
607 "user@gmail.com", "12345");
608 token_service()->UpdateCredentials(account_id2, "refresh_token");
610 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2));
611 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id3));
613 AccountReconcilor* reconcilor = GetMockReconcilor();
614 reconcilor->StartReconcile();
616 base::RunLoop().RunUntilIdle();
617 ASSERT_TRUE(reconcilor->is_reconcile_started_);
618 SimulateAddAccountToCookieCompleted(
619 reconcilor, account_id2, GoogleServiceAuthError::AuthErrorNone());
620 ASSERT_FALSE(reconcilor->is_reconcile_started_);
622 histogram_tester()->ExpectUniqueSample(
623 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
624 signin_metrics::ACCOUNTS_SAME,
626 histogram_tester()->ExpectUniqueSample(
627 "Signin.Reconciler.AddedToCookieJar.FirstRun", 1, 1);
628 histogram_tester()->ExpectUniqueSample(
629 "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1);
631 // Do another pass after I've added a third account to the token service
632 cookie_manager_service()->SetListAccountsResponseTwoAccounts(
633 "user@gmail.com", "12345", "other@gmail.com", "67890");
634 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
636 // This will cause the reconcilor to fire.
637 token_service()->UpdateCredentials(account_id3, "refresh_token");
638 base::RunLoop().RunUntilIdle();
640 ASSERT_TRUE(reconcilor->is_reconcile_started_);
641 SimulateAddAccountToCookieCompleted(
642 reconcilor, account_id3, GoogleServiceAuthError::AuthErrorNone());
643 ASSERT_FALSE(reconcilor->is_reconcile_started_);
645 histogram_tester()->ExpectUniqueSample(
646 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
647 signin_metrics::ACCOUNTS_SAME,
649 histogram_tester()->ExpectUniqueSample(
650 "Signin.Reconciler.AddedToCookieJar.FirstRun", 1, 1);
651 histogram_tester()->ExpectUniqueSample(
652 "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1);
653 histogram_tester()->ExpectUniqueSample(
654 "Signin.Reconciler.DifferentPrimaryAccounts.SubsequentRun",
655 signin_metrics::ACCOUNTS_SAME,
657 histogram_tester()->ExpectUniqueSample(
658 "Signin.Reconciler.AddedToCookieJar.SubsequentRun", 1, 1);
659 histogram_tester()->ExpectUniqueSample(
660 "Signin.Reconciler.RemovedFromCookieJar.SubsequentRun", 0, 1);
663 TEST_P(AccountReconcilorTest, StartReconcileBadPrimary) {
664 const std::string account_id =
665 ConnectProfileToAccount("12345", "user@gmail.com");
666 const std::string account_id2 =
667 PickAccountIdForAccount("67890", "other@gmail.com");
669 token_service()->UpdateCredentials(account_id2, "refresh_token");
670 cookie_manager_service()->SetListAccountsResponseTwoAccounts(
671 "other@gmail.com", "67890", "user@gmail.com", "12345");
673 EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
674 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
675 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2));
677 AccountReconcilor* reconcilor = GetMockReconcilor();
678 reconcilor->StartReconcile();
680 base::RunLoop().RunUntilIdle();
681 ASSERT_TRUE(reconcilor->is_reconcile_started_);
682 SimulateAddAccountToCookieCompleted(reconcilor, account_id2,
683 GoogleServiceAuthError::AuthErrorNone());
684 ASSERT_TRUE(reconcilor->is_reconcile_started_);
685 SimulateAddAccountToCookieCompleted(reconcilor, account_id,
686 GoogleServiceAuthError::AuthErrorNone());
687 ASSERT_FALSE(reconcilor->is_reconcile_started_);
689 histogram_tester()->ExpectUniqueSample(
690 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
691 signin_metrics::COOKIE_AND_TOKEN_PRIMARIES_DIFFERENT,
693 histogram_tester()->ExpectUniqueSample(
694 "Signin.Reconciler.AddedToCookieJar.FirstRun", 0, 1);
695 histogram_tester()->ExpectUniqueSample(
696 "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1);
699 TEST_P(AccountReconcilorTest, StartReconcileOnlyOnce) {
700 const std::string account_id =
701 ConnectProfileToAccount("12345", "user@gmail.com");
702 cookie_manager_service()->SetListAccountsResponseOneAccount(
703 "user@gmail.com", "12345");
705 AccountReconcilor* reconcilor =
706 AccountReconcilorFactory::GetForProfile(profile());
707 ASSERT_TRUE(reconcilor);
709 ASSERT_FALSE(reconcilor->is_reconcile_started_);
710 reconcilor->StartReconcile();
711 ASSERT_TRUE(reconcilor->is_reconcile_started_);
713 base::RunLoop().RunUntilIdle();
714 ASSERT_FALSE(reconcilor->is_reconcile_started_);
717 TEST_P(AccountReconcilorTest, StartReconcileWithSessionInfoExpiredDefault) {
718 const std::string account_id =
719 ConnectProfileToAccount("12345", "user@gmail.com");
720 const std::string account_id2 =
721 PickAccountIdForAccount("67890", "other@gmail.com");
722 token_service()->UpdateCredentials(account_id2, "refresh_token");
723 cookie_manager_service()->SetListAccountsResponseTwoAccountsWithExpiry(
724 "user@gmail.com", "12345", true, "other@gmail.com", "67890", false);
726 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
728 AccountReconcilor* reconcilor =
729 AccountReconcilorFactory::GetForProfile(profile());
730 ASSERT_TRUE(reconcilor);
732 ASSERT_FALSE(reconcilor->is_reconcile_started_);
733 reconcilor->StartReconcile();
734 ASSERT_TRUE(reconcilor->is_reconcile_started_);
736 base::RunLoop().RunUntilIdle();
737 SimulateAddAccountToCookieCompleted(reconcilor, account_id,
738 GoogleServiceAuthError::AuthErrorNone());
739 ASSERT_FALSE(reconcilor->is_reconcile_started_);
742 TEST_F(AccountReconcilorTest, AddAccountToCookieCompletedWithBogusAccount) {
743 const std::string account_id =
744 ConnectProfileToAccount("12345", "user@gmail.com");
745 cookie_manager_service()->SetListAccountsResponseOneAccountWithExpiry(
746 "user@gmail.com", "12345", true);
748 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
750 AccountReconcilor* reconcilor =
751 AccountReconcilorFactory::GetForProfile(profile());
752 ASSERT_TRUE(reconcilor);
754 ASSERT_FALSE(reconcilor->is_reconcile_started_);
755 reconcilor->StartReconcile();
756 ASSERT_TRUE(reconcilor->is_reconcile_started_);
758 base::RunLoop().RunUntilIdle();
760 // If an unknown account id is sent, it should not upset the state.
761 SimulateAddAccountToCookieCompleted(reconcilor, "bogus_account_id",
762 GoogleServiceAuthError::AuthErrorNone());
763 ASSERT_TRUE(reconcilor->is_reconcile_started_);
765 SimulateAddAccountToCookieCompleted(reconcilor, account_id,
766 GoogleServiceAuthError::AuthErrorNone());
767 ASSERT_FALSE(reconcilor->is_reconcile_started_);
770 #if !defined(OS_IOS)
771 // These tests don't run on iOS because that platform uses a different
772 // implementation of FakeOAuth2TokenServiceDelegate. However, iOS also removes
773 // accounts when an auth error is detected, so the scenarios being tested here
774 // do not apply.
776 TEST_F(AccountReconcilorTest, NoLoopWithBadPrimary) {
777 // Connect profile to a primary account and then add a secondary account.
778 const std::string account_id1 =
779 ConnectProfileToAccount("12345", "user@gmail.com");
780 const std::string account_id2 =
781 PickAccountIdForAccount("67890", "other@gmail.com");
782 token_service()->UpdateCredentials(account_id2, "refresh_token");
784 EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
785 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id1));
786 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2));
788 // The primary account is in auth error, so it is not in the cookie.
789 cookie_manager_service()->SetListAccountsResponseOneAccountWithExpiry(
790 "other@gmail.com", "67890", true);
792 AccountReconcilor* reconcilor =
793 AccountReconcilorFactory::GetForProfile(profile());
794 ASSERT_TRUE(reconcilor);
796 reconcilor->StartReconcile();
797 base::RunLoop().RunUntilIdle();
798 ASSERT_TRUE(reconcilor->is_reconcile_started_);
800 GoogleServiceAuthError
801 error(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
803 // The primary cannot be added to cookie, so it fails.
804 SimulateAddAccountToCookieCompleted(
805 reconcilor, account_id1, error);
806 SimulateAddAccountToCookieCompleted(reconcilor, account_id2,
807 GoogleServiceAuthError::AuthErrorNone());
808 base::RunLoop().RunUntilIdle();
809 ASSERT_FALSE(reconcilor->is_reconcile_started_);
810 ASSERT_TRUE(reconcilor->error_during_last_reconcile_);
811 testing::Mock::VerifyAndClearExpectations(GetMockReconcilor());
813 // Now that we've tried once, the token service knows that the primary
814 // account has an auth error.
815 token_service_delegate()->SetLastErrorForAccount(account_id1, error);
817 // A second attempt to reconcile should be a noop.
818 reconcilor->StartReconcile();
819 base::RunLoop().RunUntilIdle();
820 ASSERT_FALSE(reconcilor->is_reconcile_started_);
821 testing::Mock::VerifyAndClearExpectations(GetMockReconcilor());
824 TEST_F(AccountReconcilorTest, WontMergeAccountsWithError) {
825 // Connect profile to a primary account and then add a secondary account.
826 const std::string account_id1 =
827 ConnectProfileToAccount("12345", "user@gmail.com");
828 const std::string account_id2 =
829 PickAccountIdForAccount("67890", "other@gmail.com");
830 token_service()->UpdateCredentials(account_id2, "refresh_token");
832 // Mark the secondary account in auth error state.
833 token_service_delegate()->SetLastErrorForAccount(
834 account_id2,
835 GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
837 // The cookie starts empty.
838 cookie_manager_service()->SetListAccountsResponseNoAccounts();
840 // Since the cookie jar starts empty, the reconcilor should attempt to merge
841 // accounts into it. However, it should only try accounts not in auth
842 // error state.
843 EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
844 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id1));
846 AccountReconcilor* reconcilor =
847 AccountReconcilorFactory::GetForProfile(profile());
848 ASSERT_TRUE(reconcilor);
850 reconcilor->StartReconcile();
851 base::RunLoop().RunUntilIdle();
852 ASSERT_TRUE(reconcilor->is_reconcile_started_);
854 SimulateAddAccountToCookieCompleted(
855 reconcilor, account_id1, GoogleServiceAuthError::AuthErrorNone());
856 base::RunLoop().RunUntilIdle();
857 ASSERT_FALSE(reconcilor->is_reconcile_started_);
858 ASSERT_FALSE(reconcilor->error_during_last_reconcile_);
861 #endif // OS_IOS
863 INSTANTIATE_TEST_CASE_P(AccountReconcilorMaybeEnabled,
864 AccountReconcilorTest,
865 testing::Bool());