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_profile_oauth2_token_service.h"
17 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
18 #include "chrome/browser/signin/fake_signin_manager.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/profile_oauth2_token_service.h"
29 #include "components/signin/core/browser/signin_manager.h"
30 #include "components/signin/core/browser/signin_metrics.h"
31 #include "components/signin/core/browser/test_signin_client.h"
32 #include "components/signin/core/common/profile_management_switches.h"
33 #include "components/signin/core/common/signin_switches.h"
34 #include "content/public/test/test_browser_thread_bundle.h"
35 #include "google_apis/gaia/gaia_constants.h"
36 #include "google_apis/gaia/gaia_urls.h"
37 #include "net/url_request/test_url_fetcher_factory.h"
38 #include "testing/gmock/include/gmock/gmock.h"
39 #include "testing/gtest/include/gtest/gtest.h"
43 class MockAccountReconcilor
: public testing::StrictMock
<AccountReconcilor
> {
45 static KeyedService
* Build(content::BrowserContext
* context
);
47 MockAccountReconcilor(ProfileOAuth2TokenService
* token_service
,
48 SigninManagerBase
* signin_manager
,
50 GaiaCookieManagerService
* cookie_manager_service
);
51 ~MockAccountReconcilor() override
{}
53 MOCK_METHOD1(PerformMergeAction
, void(const std::string
& account_id
));
54 MOCK_METHOD0(PerformLogoutAllAccountsAction
, void());
58 KeyedService
* 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 GaiaCookieManagerServiceFactory::GetForProfile(profile
));
65 reconcilor
->Initialize(false /* start_reconcile_if_tokens_available */);
69 MockAccountReconcilor::MockAccountReconcilor(
70 ProfileOAuth2TokenService
* token_service
,
71 SigninManagerBase
* signin_manager
,
73 GaiaCookieManagerService
* cookie_manager_service
)
74 : testing::StrictMock
<AccountReconcilor
>(token_service
,
77 cookie_manager_service
) {}
81 class AccountReconcilorTest
: public ::testing::TestWithParam
<bool> {
83 AccountReconcilorTest();
84 void SetUp() override
;
86 TestingProfile
* profile() { return profile_
; }
87 FakeSigninManagerForTesting
* signin_manager() { return signin_manager_
; }
88 FakeProfileOAuth2TokenService
* token_service() { return token_service_
; }
89 TestSigninClient
* test_signin_client() { return test_signin_client_
; }
90 AccountTrackerService
* account_tracker() { return account_tracker_
; }
91 base::HistogramTester
* histogram_tester() { return &histogram_tester_
; }
93 void SetFakeResponse(const std::string
& url
,
94 const std::string
& data
,
95 net::HttpStatusCode code
,
96 net::URLRequestStatus::Status status
) {
97 url_fetcher_factory_
.SetFakeResponse(GURL(url
), data
, code
, status
);
100 MockAccountReconcilor
* GetMockReconcilor();
102 std::string
ConnectProfileToAccount(const std::string
& gaia_id
,
103 const std::string
& username
);
105 std::string
PickAccountIdForAccount(const std::string
& gaia_id
,
106 const std::string
& username
);
108 void SimulateAddAccountToCookieCompleted(
109 GaiaCookieManagerService::Observer
* observer
,
110 const std::string
& account_id
,
111 const GoogleServiceAuthError
& error
);
113 void SimulateCookieContentSettingsChanged(
114 content_settings::Observer
* observer
,
115 const ContentSettingsPattern
& primary_pattern
);
117 GURL
list_accounts_url() { return list_accounts_url_
; }
118 GURL
get_check_connection_info_url() {
119 return get_check_connection_info_url_
;
123 content::TestBrowserThreadBundle bundle_
;
124 TestingProfile
* profile_
;
125 FakeSigninManagerForTesting
* signin_manager_
;
126 FakeProfileOAuth2TokenService
* token_service_
;
127 TestSigninClient
* test_signin_client_
;
128 AccountTrackerService
* account_tracker_
;
129 MockAccountReconcilor
* mock_reconcilor_
;
130 net::FakeURLFetcherFactory url_fetcher_factory_
;
131 scoped_ptr
<TestingProfileManager
> testing_profile_manager_
;
132 base::HistogramTester histogram_tester_
;
133 GURL list_accounts_url_
;
134 GURL get_check_connection_info_url_
;
136 DISALLOW_COPY_AND_ASSIGN(AccountReconcilorTest
);
139 AccountReconcilorTest::AccountReconcilorTest()
140 : signin_manager_(NULL
),
141 token_service_(NULL
),
142 test_signin_client_(NULL
),
143 mock_reconcilor_(NULL
),
144 url_fetcher_factory_(NULL
) {}
146 void AccountReconcilorTest::SetUp() {
147 // If it's a non-parameterized test, or we have a parameter of true, set flag.
148 if (!::testing::UnitTest::GetInstance()->current_test_info()->value_param() ||
150 base::CommandLine::ForCurrentProcess()->AppendSwitch(
151 switches::kEnableNewProfileManagement
);
154 list_accounts_url_
= GaiaUrls::GetInstance()->ListAccountsURLWithSource(
155 GaiaConstants::kReconcilorSource
);
156 get_check_connection_info_url_
=
157 GaiaUrls::GetInstance()->GetCheckConnectionInfoURLWithSource(
158 GaiaConstants::kChromeSource
);
160 // Specific tests may set a response that includes specific accounts.
161 SetFakeResponse(list_accounts_url().spec(), "",
162 net::HTTP_NOT_FOUND
, net::URLRequestStatus::SUCCESS
);
164 testing_profile_manager_
.reset(
165 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
166 ASSERT_TRUE(testing_profile_manager_
.get()->SetUp());
168 TestingProfile::TestingFactories factories
;
169 factories
.push_back(std::make_pair(ChromeSigninClientFactory::GetInstance(),
170 signin::BuildTestSigninClient
));
171 factories
.push_back(std::make_pair(
172 ProfileOAuth2TokenServiceFactory::GetInstance(),
173 BuildFakeProfileOAuth2TokenService
));
174 factories
.push_back(std::make_pair(SigninManagerFactory::GetInstance(),
175 FakeSigninManagerBase::Build
));
176 factories
.push_back(std::make_pair(AccountReconcilorFactory::GetInstance(),
177 MockAccountReconcilor::Build
));
179 profile_
= testing_profile_manager_
.get()->CreateTestingProfile("name",
180 scoped_ptr
<PrefServiceSyncable
>(),
181 base::UTF8ToUTF16("name"), 0, std::string(),
184 test_signin_client_
=
185 static_cast<TestSigninClient
*>(
186 ChromeSigninClientFactory::GetForProfile(profile()));
189 static_cast<FakeProfileOAuth2TokenService
*>(
190 ProfileOAuth2TokenServiceFactory::GetForProfile(profile()));
193 AccountTrackerServiceFactory::GetForProfile(profile());
196 static_cast<FakeSigninManagerForTesting
*>(
197 SigninManagerFactory::GetForProfile(profile()));
200 MockAccountReconcilor
* AccountReconcilorTest::GetMockReconcilor() {
201 if (!mock_reconcilor_
) {
203 static_cast<MockAccountReconcilor
*>(
204 AccountReconcilorFactory::GetForProfile(profile()));
207 return mock_reconcilor_
;
210 std::string
AccountReconcilorTest::ConnectProfileToAccount(
211 const std::string
& gaia_id
,
212 const std::string
& username
) {
213 const std::string account_id
= PickAccountIdForAccount(gaia_id
, username
);
214 #if !defined(OS_CHROMEOS)
215 signin_manager()->set_password("password");
217 signin_manager()->SetAuthenticatedAccountInfo(gaia_id
, username
);
218 token_service()->UpdateCredentials(account_id
, "refresh_token");
222 std::string
AccountReconcilorTest::PickAccountIdForAccount(
223 const std::string
& gaia_id
,
224 const std::string
& username
) {
225 return account_tracker()->PickAccountIdForAccount(gaia_id
, username
);
228 void AccountReconcilorTest::SimulateAddAccountToCookieCompleted(
229 GaiaCookieManagerService::Observer
* observer
,
230 const std::string
& account_id
,
231 const GoogleServiceAuthError
& error
) {
232 observer
->OnAddAccountToCookieCompleted(account_id
, error
);
235 void AccountReconcilorTest::SimulateCookieContentSettingsChanged(
236 content_settings::Observer
* observer
,
237 const ContentSettingsPattern
& primary_pattern
) {
238 observer
->OnContentSettingChanged(
240 ContentSettingsPattern::Wildcard(),
241 CONTENT_SETTINGS_TYPE_COOKIES
,
245 TEST_F(AccountReconcilorTest
, Basic
) {
246 AccountReconcilor
* reconcilor
=
247 AccountReconcilorFactory::GetForProfile(profile());
248 ASSERT_TRUE(reconcilor
);
251 #if !defined(OS_CHROMEOS)
253 // This method requires the use of the |TestSigninClient| to be created from the
254 // |ChromeSigninClientFactory| because it overrides the |GoogleSigninSucceeded|
255 // method with an empty implementation. On MacOS, the normal implementation
256 // causes the try_bots to time out.
257 TEST_F(AccountReconcilorTest
, SigninManagerRegistration
) {
258 AccountReconcilor
* reconcilor
=
259 AccountReconcilorFactory::GetForProfile(profile());
260 ASSERT_TRUE(reconcilor
);
261 ASSERT_FALSE(reconcilor
->IsRegisteredWithTokenService());
263 account_tracker()->SeedAccountInfo("12345", "user@gmail.com");
264 signin_manager()->SignIn("12345", "user@gmail.com", "password");
265 ASSERT_TRUE(reconcilor
->IsRegisteredWithTokenService());
267 EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
269 signin_manager()->SignOut(signin_metrics::SIGNOUT_TEST
);
270 ASSERT_FALSE(reconcilor
->IsRegisteredWithTokenService());
273 // This method requires the use of the |TestSigninClient| to be created from the
274 // |ChromeSigninClientFactory| because it overrides the |GoogleSigninSucceeded|
275 // method with an empty implementation. On MacOS, the normal implementation
276 // causes the try_bots to time out.
277 TEST_F(AccountReconcilorTest
, Reauth
) {
278 const std::string email
= "user@gmail.com";
279 const std::string account_id
=
280 ConnectProfileToAccount("12345", email
);
282 AccountReconcilor
* reconcilor
=
283 AccountReconcilorFactory::GetForProfile(profile());
284 ASSERT_TRUE(reconcilor
);
285 ASSERT_TRUE(reconcilor
->IsRegisteredWithTokenService());
287 // Simulate reauth. The state of the reconcilor should not change.
288 signin_manager()->OnExternalSigninCompleted(email
);
289 ASSERT_TRUE(reconcilor
->IsRegisteredWithTokenService());
292 #endif // !defined(OS_CHROMEOS)
294 TEST_F(AccountReconcilorTest
, ProfileAlreadyConnected
) {
295 ConnectProfileToAccount("12345", "user@gmail.com");
297 AccountReconcilor
* reconcilor
=
298 AccountReconcilorFactory::GetForProfile(profile());
299 ASSERT_TRUE(reconcilor
);
300 ASSERT_TRUE(reconcilor
->IsRegisteredWithTokenService());
303 TEST_F(AccountReconcilorTest
, GetAccountsFromCookieSuccess
) {
304 const std::string account_id
=
305 ConnectProfileToAccount("12345", "user@gmail.com");
306 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id
));
308 AccountReconcilor
* reconcilor
=
309 AccountReconcilorFactory::GetForProfile(profile());
310 ASSERT_TRUE(reconcilor
);
312 SetFakeResponse(list_accounts_url().spec(),
313 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 0]]]",
314 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
316 reconcilor
->StartReconcile();
317 ASSERT_FALSE(reconcilor
->AreGaiaAccountsSet());
319 base::RunLoop().RunUntilIdle();
320 ASSERT_TRUE(reconcilor
->AreGaiaAccountsSet());
321 const std::vector
<std::pair
<std::string
, bool> >& accounts
=
322 reconcilor
->GetGaiaAccountsForTesting();
323 ASSERT_EQ(1u, accounts
.size());
324 ASSERT_EQ(account_id
, accounts
[0].first
);
327 TEST_F(AccountReconcilorTest
, GetAccountsFromCookieFailure
) {
328 ConnectProfileToAccount("12345", "user@gmail.com");
329 AccountReconcilor
* reconcilor
=
330 AccountReconcilorFactory::GetForProfile(profile());
331 ASSERT_TRUE(reconcilor
);
333 SetFakeResponse(list_accounts_url().spec(), "",
334 net::HTTP_NOT_FOUND
, net::URLRequestStatus::SUCCESS
);
336 reconcilor
->StartReconcile();
337 ASSERT_FALSE(reconcilor
->AreGaiaAccountsSet());
339 base::RunLoop().RunUntilIdle();
340 ASSERT_FALSE(reconcilor
->AreGaiaAccountsSet());
343 TEST_P(AccountReconcilorTest
, StartReconcileNoop
) {
344 const std::string account_id
=
345 ConnectProfileToAccount("12345", "user@gmail.com");
347 AccountReconcilor
* reconcilor
=
348 AccountReconcilorFactory::GetForProfile(profile());
349 ASSERT_TRUE(reconcilor
);
351 SetFakeResponse(list_accounts_url().spec(),
352 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
353 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
355 reconcilor
->StartReconcile();
356 ASSERT_TRUE(reconcilor
->is_reconcile_started_
);
357 ASSERT_FALSE(reconcilor
->AreGaiaAccountsSet());
359 base::RunLoop().RunUntilIdle();
360 ASSERT_FALSE(reconcilor
->is_reconcile_started_
);
362 histogram_tester()->ExpectTotalCount(
363 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 1);
364 histogram_tester()->ExpectUniqueSample(
365 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
366 signin_metrics::ACCOUNTS_SAME
,
370 TEST_P(AccountReconcilorTest
, StartReconcileCookiesDisabled
) {
371 const std::string account_id
=
372 ConnectProfileToAccount("12345", "user@gmail.com");
373 token_service()->UpdateCredentials(account_id
, "refresh_token");
374 test_signin_client()->set_are_signin_cookies_allowed(false);
376 AccountReconcilor
* reconcilor
=
377 AccountReconcilorFactory::GetForProfile(profile());
378 ASSERT_TRUE(reconcilor
);
380 reconcilor
->StartReconcile();
381 ASSERT_FALSE(reconcilor
->is_reconcile_started_
);
382 ASSERT_FALSE(reconcilor
->AreGaiaAccountsSet());
384 base::RunLoop().RunUntilIdle();
385 ASSERT_FALSE(reconcilor
->is_reconcile_started_
);
388 TEST_P(AccountReconcilorTest
, StartReconcileContentSettings
) {
389 const std::string account_id
=
390 ConnectProfileToAccount("12345", "user@gmail.com");
391 token_service()->UpdateCredentials(account_id
, "refresh_token");
393 AccountReconcilor
* reconcilor
=
394 AccountReconcilorFactory::GetForProfile(profile());
395 ASSERT_TRUE(reconcilor
);
397 test_signin_client()->set_are_signin_cookies_allowed(false);
398 SimulateCookieContentSettingsChanged(reconcilor
,
399 ContentSettingsPattern::Wildcard());
400 ASSERT_FALSE(reconcilor
->is_reconcile_started_
);
402 test_signin_client()->set_are_signin_cookies_allowed(true);
403 SimulateCookieContentSettingsChanged(reconcilor
,
404 ContentSettingsPattern::Wildcard());
405 ASSERT_TRUE(reconcilor
->is_reconcile_started_
);
408 TEST_P(AccountReconcilorTest
, StartReconcileContentSettingsGaiaUrl
) {
409 const std::string account_id
=
410 ConnectProfileToAccount("12345", "user@gmail.com");
411 token_service()->UpdateCredentials(account_id
, "refresh_token");
413 AccountReconcilor
* reconcilor
=
414 AccountReconcilorFactory::GetForProfile(profile());
415 ASSERT_TRUE(reconcilor
);
417 SimulateCookieContentSettingsChanged(
419 ContentSettingsPattern::FromURL(GaiaUrls::GetInstance()->gaia_url()));
420 ASSERT_TRUE(reconcilor
->is_reconcile_started_
);
423 TEST_P(AccountReconcilorTest
, StartReconcileContentSettingsNonGaiaUrl
) {
424 const std::string account_id
=
425 ConnectProfileToAccount("12345", "user@gmail.com");
426 token_service()->UpdateCredentials(account_id
, "refresh_token");
428 AccountReconcilor
* reconcilor
=
429 AccountReconcilorFactory::GetForProfile(profile());
430 ASSERT_TRUE(reconcilor
);
432 SimulateCookieContentSettingsChanged(
434 ContentSettingsPattern::FromURL(GURL("http://www.example.com")));
435 ASSERT_FALSE(reconcilor
->is_reconcile_started_
);
438 TEST_P(AccountReconcilorTest
, StartReconcileContentSettingsInvalidPattern
) {
439 const std::string account_id
=
440 ConnectProfileToAccount("12345", "user@gmail.com");
441 token_service()->UpdateCredentials(account_id
, "refresh_token");
443 AccountReconcilor
* reconcilor
=
444 AccountReconcilorFactory::GetForProfile(profile());
445 ASSERT_TRUE(reconcilor
);
447 scoped_ptr
<ContentSettingsPattern::BuilderInterface
>
448 builder(ContentSettingsPattern::CreateBuilder(false));
451 SimulateCookieContentSettingsChanged(reconcilor
, builder
->Build());
452 ASSERT_TRUE(reconcilor
->is_reconcile_started_
);
455 // This test is needed until chrome changes to use gaia obfuscated id.
456 // The signin manager and token service use the gaia "email" property, which
457 // preserves dots in usernames and preserves case. gaia::ParseListAccountsData()
458 // however uses gaia "displayEmail" which does not preserve case, and then
459 // passes the string through gaia::CanonicalizeEmail() which removes dots. This
460 // tests makes sure that an email like "Dot.S@hmail.com", as seen by the
461 // token service, will be considered the same as "dots@gmail.com" as returned
462 // by gaia::ParseListAccountsData().
463 TEST_P(AccountReconcilorTest
, StartReconcileNoopWithDots
) {
464 if (account_tracker()->GetMigrationState() !=
465 AccountTrackerService::MIGRATION_NOT_STARTED
) {
469 const std::string account_id
=
470 ConnectProfileToAccount("12345", "Dot.S@gmail.com");
471 AccountReconcilor
* reconcilor
=
472 AccountReconcilorFactory::GetForProfile(profile());
473 ASSERT_TRUE(reconcilor
);
475 SetFakeResponse(list_accounts_url().spec(),
476 "[\"f\", [[\"b\", 0, \"n\", \"dot.s@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
477 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
479 reconcilor
->StartReconcile();
480 ASSERT_FALSE(reconcilor
->AreGaiaAccountsSet());
482 base::RunLoop().RunUntilIdle();
483 ASSERT_FALSE(reconcilor
->is_reconcile_started_
);
485 histogram_tester()->ExpectUniqueSample(
486 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
487 signin_metrics::ACCOUNTS_SAME
,
491 TEST_P(AccountReconcilorTest
, StartReconcileNoopMultiple
) {
492 const std::string account_id
=
493 ConnectProfileToAccount("12345", "user@gmail.com");
494 const std::string account_id2
=
495 PickAccountIdForAccount("67890", "other@gmail.com");
496 token_service()->UpdateCredentials(account_id2
, "refresh_token");
498 AccountReconcilor
* reconcilor
=
499 AccountReconcilorFactory::GetForProfile(profile());
500 ASSERT_TRUE(reconcilor
);
502 SetFakeResponse(list_accounts_url().spec(),
503 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1], "
504 "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
505 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
507 reconcilor
->StartReconcile();
508 ASSERT_FALSE(reconcilor
->AreGaiaAccountsSet());
509 base::RunLoop().RunUntilIdle();
510 ASSERT_FALSE(reconcilor
->is_reconcile_started_
);
512 histogram_tester()->ExpectTotalCount(
513 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 1);
514 histogram_tester()->ExpectUniqueSample(
515 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
516 signin_metrics::ACCOUNTS_SAME
,
520 TEST_P(AccountReconcilorTest
, StartReconcileAddToCookie
) {
521 const std::string account_id
=
522 ConnectProfileToAccount("12345", "user@gmail.com");
523 token_service()->UpdateCredentials(account_id
, "refresh_token");
525 const std::string account_id2
=
526 PickAccountIdForAccount("67890", "other@gmail.com");
527 token_service()->UpdateCredentials(account_id2
, "refresh_token");
529 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2
));
531 SetFakeResponse(list_accounts_url().spec(),
532 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
533 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
535 AccountReconcilor
* reconcilor
= GetMockReconcilor();
536 reconcilor
->StartReconcile();
538 base::RunLoop().RunUntilIdle();
539 ASSERT_TRUE(reconcilor
->is_reconcile_started_
);
540 SimulateAddAccountToCookieCompleted(reconcilor
, account_id2
,
541 GoogleServiceAuthError::AuthErrorNone());
542 ASSERT_FALSE(reconcilor
->is_reconcile_started_
);
544 histogram_tester()->ExpectUniqueSample(
545 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
546 signin_metrics::ACCOUNTS_SAME
,
548 histogram_tester()->ExpectUniqueSample(
549 "Signin.Reconciler.AddedToCookieJar.FirstRun", 1, 1);
550 histogram_tester()->ExpectUniqueSample(
551 "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1);
554 TEST_P(AccountReconcilorTest
, StartReconcileRemoveFromCookie
) {
555 const std::string account_id
=
556 ConnectProfileToAccount("12345", "user@gmail.com");
557 token_service()->UpdateCredentials(account_id
, "refresh_token");
559 EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
560 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id
));
562 SetFakeResponse(list_accounts_url().spec(),
563 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1], "
564 "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
565 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
567 AccountReconcilor
* reconcilor
= GetMockReconcilor();
568 reconcilor
->StartReconcile();
569 ASSERT_TRUE(reconcilor
->is_reconcile_started_
);
571 base::RunLoop().RunUntilIdle();
572 SimulateAddAccountToCookieCompleted(reconcilor
, "user@gmail.com",
573 GoogleServiceAuthError::AuthErrorNone());
574 ASSERT_FALSE(reconcilor
->is_reconcile_started_
);
576 histogram_tester()->ExpectUniqueSample(
577 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
578 signin_metrics::ACCOUNTS_SAME
,
580 histogram_tester()->ExpectUniqueSample(
581 "Signin.Reconciler.AddedToCookieJar.FirstRun", 0, 1);
582 histogram_tester()->ExpectUniqueSample(
583 "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 1, 1);
586 TEST_P(AccountReconcilorTest
, StartReconcileAddToCookieTwice
) {
587 const std::string account_id
=
588 ConnectProfileToAccount("12345", "user@gmail.com");
589 const std::string account_id2
=
590 PickAccountIdForAccount("67890", "other@gmail.com");
591 const std::string account_id3
=
592 PickAccountIdForAccount("34567", "third@gmail.com");
594 token_service()->UpdateCredentials(account_id2
, "refresh_token");
596 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2
));
597 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id3
));
600 list_accounts_url().spec(),
601 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
603 net::URLRequestStatus::SUCCESS
);
605 AccountReconcilor
* reconcilor
= GetMockReconcilor();
606 reconcilor
->StartReconcile();
608 base::RunLoop().RunUntilIdle();
609 ASSERT_TRUE(reconcilor
->is_reconcile_started_
);
610 SimulateAddAccountToCookieCompleted(
611 reconcilor
, account_id2
, GoogleServiceAuthError::AuthErrorNone());
612 ASSERT_FALSE(reconcilor
->is_reconcile_started_
);
614 histogram_tester()->ExpectUniqueSample(
615 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
616 signin_metrics::ACCOUNTS_SAME
,
618 histogram_tester()->ExpectUniqueSample(
619 "Signin.Reconciler.AddedToCookieJar.FirstRun", 1, 1);
620 histogram_tester()->ExpectUniqueSample(
621 "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1);
623 // Do another pass after I've added a third account to the token service
626 list_accounts_url().spec(),
627 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1], "
628 "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
630 net::URLRequestStatus::SUCCESS
);
631 // This will cause the reconcilor to fire.
632 token_service()->UpdateCredentials(account_id3
, "refresh_token");
633 base::RunLoop().RunUntilIdle();
635 ASSERT_TRUE(reconcilor
->is_reconcile_started_
);
636 SimulateAddAccountToCookieCompleted(
637 reconcilor
, account_id3
, GoogleServiceAuthError::AuthErrorNone());
638 ASSERT_FALSE(reconcilor
->is_reconcile_started_
);
640 histogram_tester()->ExpectUniqueSample(
641 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
642 signin_metrics::ACCOUNTS_SAME
,
644 histogram_tester()->ExpectUniqueSample(
645 "Signin.Reconciler.AddedToCookieJar.FirstRun", 1, 1);
646 histogram_tester()->ExpectUniqueSample(
647 "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1);
648 histogram_tester()->ExpectUniqueSample(
649 "Signin.Reconciler.DifferentPrimaryAccounts.SubsequentRun",
650 signin_metrics::ACCOUNTS_SAME
,
652 histogram_tester()->ExpectUniqueSample(
653 "Signin.Reconciler.AddedToCookieJar.SubsequentRun", 1, 1);
654 histogram_tester()->ExpectUniqueSample(
655 "Signin.Reconciler.RemovedFromCookieJar.SubsequentRun", 0, 1);
658 TEST_P(AccountReconcilorTest
, StartReconcileBadPrimary
) {
659 const std::string account_id
=
660 ConnectProfileToAccount("12345", "user@gmail.com");
661 const std::string account_id2
=
662 PickAccountIdForAccount("67890", "other@gmail.com");
664 token_service()->UpdateCredentials(account_id2
, "refresh_token");
666 EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
667 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id
));
668 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2
));
670 SetFakeResponse(list_accounts_url().spec(),
671 "[\"f\", [[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1], "
672 "[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
673 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
675 AccountReconcilor
* reconcilor
= GetMockReconcilor();
676 reconcilor
->StartReconcile();
678 base::RunLoop().RunUntilIdle();
679 ASSERT_TRUE(reconcilor
->is_reconcile_started_
);
680 SimulateAddAccountToCookieCompleted(reconcilor
, account_id2
,
681 GoogleServiceAuthError::AuthErrorNone());
682 ASSERT_TRUE(reconcilor
->is_reconcile_started_
);
683 SimulateAddAccountToCookieCompleted(reconcilor
, account_id
,
684 GoogleServiceAuthError::AuthErrorNone());
685 ASSERT_FALSE(reconcilor
->is_reconcile_started_
);
687 histogram_tester()->ExpectUniqueSample(
688 "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
689 signin_metrics::COOKIE_AND_TOKEN_PRIMARIES_DIFFERENT
,
691 histogram_tester()->ExpectUniqueSample(
692 "Signin.Reconciler.AddedToCookieJar.FirstRun", 0, 1);
693 histogram_tester()->ExpectUniqueSample(
694 "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1);
697 TEST_P(AccountReconcilorTest
, StartReconcileOnlyOnce
) {
698 const std::string account_id
=
699 ConnectProfileToAccount("12345", "user@gmail.com");
701 AccountReconcilor
* reconcilor
=
702 AccountReconcilorFactory::GetForProfile(profile());
703 ASSERT_TRUE(reconcilor
);
705 SetFakeResponse(list_accounts_url().spec(),
706 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
707 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
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");
724 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id
));
726 SetFakeResponse(list_accounts_url().spec(),
727 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 0],"
728 "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
729 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
731 AccountReconcilor
* reconcilor
=
732 AccountReconcilorFactory::GetForProfile(profile());
733 ASSERT_TRUE(reconcilor
);
735 ASSERT_FALSE(reconcilor
->is_reconcile_started_
);
736 reconcilor
->StartReconcile();
737 ASSERT_TRUE(reconcilor
->is_reconcile_started_
);
739 base::RunLoop().RunUntilIdle();
740 SimulateAddAccountToCookieCompleted(reconcilor
, account_id
,
741 GoogleServiceAuthError::AuthErrorNone());
742 ASSERT_FALSE(reconcilor
->is_reconcile_started_
);
745 TEST_F(AccountReconcilorTest
, AddAccountToCookieCompletedWithBogusAccount
) {
746 const std::string account_id
=
747 ConnectProfileToAccount("12345", "user@gmail.com");
749 EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id
));
751 SetFakeResponse(list_accounts_url().spec(),
752 "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 0]]]",
753 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
755 AccountReconcilor
* reconcilor
=
756 AccountReconcilorFactory::GetForProfile(profile());
757 ASSERT_TRUE(reconcilor
);
759 ASSERT_FALSE(reconcilor
->is_reconcile_started_
);
760 reconcilor
->StartReconcile();
761 ASSERT_TRUE(reconcilor
->is_reconcile_started_
);
763 base::RunLoop().RunUntilIdle();
765 // If an unknown account id is sent, it should not upset the state.
766 SimulateAddAccountToCookieCompleted(reconcilor
, "bogus_account_id",
767 GoogleServiceAuthError::AuthErrorNone());
768 ASSERT_TRUE(reconcilor
->is_reconcile_started_
);
770 SimulateAddAccountToCookieCompleted(reconcilor
, account_id
,
771 GoogleServiceAuthError::AuthErrorNone());
772 ASSERT_FALSE(reconcilor
->is_reconcile_started_
);
775 INSTANTIATE_TEST_CASE_P(AccountReconcilorMaybeEnabled
,
776 AccountReconcilorTest
,