1 // Copyright 2014 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.
8 #include "base/prefs/pref_registry_simple.h"
9 #include "base/prefs/scoped_user_pref_update.h"
10 #include "base/prefs/testing_pref_service.h"
11 #include "base/strings/stringprintf.h"
12 #include "components/signin/core/browser/account_fetcher_service.h"
13 #include "components/signin/core/browser/account_info.h"
14 #include "components/signin/core/browser/account_tracker_service.h"
15 #include "components/signin/core/browser/fake_account_fetcher_service.h"
16 #include "components/signin/core/browser/test_signin_client.h"
17 #include "components/signin/core/common/signin_pref_names.h"
18 #include "google_apis/gaia/fake_oauth2_token_service.h"
19 #include "google_apis/gaia/gaia_oauth_client.h"
20 #include "net/http/http_status_code.h"
21 #include "net/url_request/test_url_fetcher_factory.h"
22 #include "net/url_request/url_fetcher_delegate.h"
23 #include "net/url_request/url_request_test_util.h"
24 #include "testing/gtest/include/gtest/gtest.h"
28 const std::string kTokenInfoResponseFormat
=
34 \"given_name\": \"%s\", \
39 const std::string kTokenInfoIncompleteResponseFormat
=
46 enum TrackingEventType
{
51 std::string
AccountIdToEmail(const std::string account_id
) {
52 return account_id
+ "@gmail.com";
55 std::string
AccountIdToGaiaId(const std::string account_id
) {
56 return "gaia-" + account_id
;
59 std::string
AccountIdToFullName(const std::string account_id
) {
60 return "full-name-" + account_id
;
63 std::string
AccountIdToGivenName(const std::string account_id
) {
64 return "given-name-" + account_id
;
67 std::string
AccountIdToLocale(const std::string account_id
) {
68 return "locale-" + account_id
;
71 std::string
AccountIdToPictureURL(const std::string account_id
) {
72 return "picture_url-" + account_id
;
75 void CheckAccountDetails(const std::string account_id
,
76 const AccountInfo
& info
) {
77 EXPECT_EQ(account_id
, info
.account_id
);
78 EXPECT_EQ(AccountIdToGaiaId(account_id
), info
.gaia
);
79 EXPECT_EQ(AccountIdToEmail(account_id
), info
.email
);
80 EXPECT_EQ(AccountTrackerService::kNoHostedDomainFound
,
82 EXPECT_EQ(AccountIdToFullName(account_id
), info
.full_name
);
83 EXPECT_EQ(AccountIdToGivenName(account_id
), info
.given_name
);
84 EXPECT_EQ(AccountIdToLocale(account_id
), info
.locale
);
87 void FakeUserInfoFetchSuccess(FakeAccountFetcherService
* fetcher
,
88 const std::string
& account_id
) {
89 fetcher
->FakeUserInfoFetchSuccess(
90 account_id
, AccountIdToEmail(account_id
), AccountIdToGaiaId(account_id
),
91 AccountTrackerService::kNoHostedDomainFound
,
92 AccountIdToFullName(account_id
), AccountIdToGivenName(account_id
),
93 AccountIdToLocale(account_id
), AccountIdToPictureURL(account_id
));
98 TrackingEvent(TrackingEventType type
,
99 const std::string
& account_id
,
100 const std::string
& gaia_id
)
102 account_id_(account_id
),
105 TrackingEvent(TrackingEventType type
,
106 const std::string
& account_id
)
108 account_id_(account_id
),
109 gaia_id_(AccountIdToGaiaId(account_id
)) {}
111 bool operator==(const TrackingEvent
& event
) const {
112 return type_
== event
.type_
&& account_id_
== event
.account_id_
&&
113 gaia_id_
== event
.gaia_id_
;
116 std::string
ToString() const {
117 const char * typestr
= "INVALID";
126 return base::StringPrintf("{ type: %s, account_id: %s, gaia: %s }",
133 friend bool CompareByUser(TrackingEvent a
, TrackingEvent b
);
135 TrackingEventType type_
;
136 std::string account_id_
;
137 std::string gaia_id_
;
140 bool CompareByUser(TrackingEvent a
, TrackingEvent b
) {
141 return a
.account_id_
< b
.account_id_
;
144 std::string
Str(const std::vector
<TrackingEvent
>& events
) {
145 std::string str
= "[";
146 bool needs_comma
= false;
147 for (std::vector
<TrackingEvent
>::const_iterator it
=
148 events
.begin(); it
!= events
.end(); ++it
) {
152 str
+= it
->ToString();
158 class AccountTrackerObserver
: public AccountTrackerService::Observer
{
160 AccountTrackerObserver() {}
161 ~AccountTrackerObserver() override
{}
164 void SortEventsByUser();
166 testing::AssertionResult
CheckEvents();
167 testing::AssertionResult
CheckEvents(const TrackingEvent
& e1
);
168 testing::AssertionResult
CheckEvents(const TrackingEvent
& e1
,
169 const TrackingEvent
& e2
);
170 testing::AssertionResult
CheckEvents(const TrackingEvent
& e1
,
171 const TrackingEvent
& e2
,
172 const TrackingEvent
& e3
);
175 // AccountTrackerService::Observer implementation
176 void OnAccountUpdated(const AccountInfo
& ids
) override
;
177 void OnAccountRemoved(const AccountInfo
& ids
) override
;
179 testing::AssertionResult
CheckEvents(
180 const std::vector
<TrackingEvent
>& events
);
182 std::vector
<TrackingEvent
> events_
;
185 void AccountTrackerObserver::OnAccountUpdated(const AccountInfo
& ids
) {
186 events_
.push_back(TrackingEvent(UPDATED
, ids
.account_id
, ids
.gaia
));
189 void AccountTrackerObserver::OnAccountRemoved(const AccountInfo
& ids
) {
190 events_
.push_back(TrackingEvent(REMOVED
, ids
.account_id
, ids
.gaia
));
193 void AccountTrackerObserver::Clear() {
197 void AccountTrackerObserver::SortEventsByUser() {
198 std::stable_sort(events_
.begin(), events_
.end(), CompareByUser
);
201 testing::AssertionResult
AccountTrackerObserver::CheckEvents() {
202 std::vector
<TrackingEvent
> events
;
203 return CheckEvents(events
);
206 testing::AssertionResult
AccountTrackerObserver::CheckEvents(
207 const TrackingEvent
& e1
) {
208 std::vector
<TrackingEvent
> events
;
209 events
.push_back(e1
);
210 return CheckEvents(events
);
213 testing::AssertionResult
AccountTrackerObserver::CheckEvents(
214 const TrackingEvent
& e1
,
215 const TrackingEvent
& e2
) {
216 std::vector
<TrackingEvent
> events
;
217 events
.push_back(e1
);
218 events
.push_back(e2
);
219 return CheckEvents(events
);
222 testing::AssertionResult
AccountTrackerObserver::CheckEvents(
223 const TrackingEvent
& e1
,
224 const TrackingEvent
& e2
,
225 const TrackingEvent
& e3
) {
226 std::vector
<TrackingEvent
> events
;
227 events
.push_back(e1
);
228 events
.push_back(e2
);
229 events
.push_back(e3
);
230 return CheckEvents(events
);
233 testing::AssertionResult
AccountTrackerObserver::CheckEvents(
234 const std::vector
<TrackingEvent
>& events
) {
235 std::string maybe_newline
= (events
.size() + events_
.size()) > 2 ? "\n" : "";
236 testing::AssertionResult
result(
238 ? testing::AssertionSuccess()
239 : (testing::AssertionFailure()
240 << "Expected " << maybe_newline
<< Str(events
) << ", "
241 << maybe_newline
<< "Got " << maybe_newline
<< Str(events_
)));
248 class AccountTrackerServiceTest
: public testing::Test
{
250 AccountTrackerServiceTest() {}
252 ~AccountTrackerServiceTest() override
{}
254 void SetUp() override
{
255 fake_oauth2_token_service_
.reset(new FakeOAuth2TokenService());
257 pref_service_
.registry()->RegisterListPref(
258 AccountTrackerService::kAccountInfoPref
);
259 pref_service_
.registry()->RegisterIntegerPref(
260 prefs::kAccountIdMigrationState
,
261 AccountTrackerService::MIGRATION_NOT_STARTED
);
262 pref_service_
.registry()->RegisterInt64Pref(
263 AccountFetcherService::kLastUpdatePref
, 0);
264 signin_client_
.reset(new TestSigninClient(&pref_service_
));
265 signin_client_
.get()->SetURLRequestContext(
266 new net::TestURLRequestContextGetter(message_loop_
.task_runner()));
268 account_tracker_
.reset(new AccountTrackerService());
269 account_tracker_
->Initialize(signin_client_
.get());
271 account_fetcher_
.reset(new AccountFetcherService());
272 account_fetcher_
->Initialize(signin_client_
.get(),
273 fake_oauth2_token_service_
.get(),
274 account_tracker_
.get(), nullptr);
276 account_fetcher_
->EnableNetworkFetches();
279 void TearDown() override
{
280 account_fetcher_
->Shutdown();
281 account_tracker_
->Shutdown();
284 void SimulateTokenAvailable(const std::string
& account_id
) {
285 fake_oauth2_token_service_
->AddAccount(account_id
);
288 void SimulateTokenRevoked(const std::string
& account_id
) {
289 fake_oauth2_token_service_
->RemoveAccount(account_id
);
292 // Helpers to fake access token and user info fetching
293 void IssueAccessToken(const std::string
& account_id
) {
294 fake_oauth2_token_service_
->IssueAllTokensForAccount(
295 account_id
, "access_token-" + account_id
, base::Time::Max());
298 std::string
GenerateValidTokenInfoResponse(const std::string
& account_id
) {
299 return base::StringPrintf(
300 kTokenInfoResponseFormat
.c_str(),
301 AccountIdToGaiaId(account_id
).c_str(),
302 AccountIdToEmail(account_id
).c_str(),
303 AccountIdToFullName(account_id
).c_str(),
304 AccountIdToGivenName(account_id
).c_str(),
305 AccountIdToLocale(account_id
).c_str(),
306 AccountIdToPictureURL(account_id
).c_str());
309 std::string
GenerateIncompleteTokenInfoResponse(
310 const std::string
& account_id
) {
311 return base::StringPrintf(
312 kTokenInfoIncompleteResponseFormat
.c_str(),
313 AccountIdToGaiaId(account_id
).c_str(),
314 AccountIdToEmail(account_id
).c_str());
316 void ReturnOAuthUrlFetchSuccess(const std::string
& account_id
);
317 void ReturnOAuthUrlFetchSuccessIncomplete(const std::string
& account_id
);
318 void ReturnOAuthUrlFetchFailure(const std::string
& account_id
);
320 net::TestURLFetcherFactory
* test_fetcher_factory() {
321 return &test_fetcher_factory_
;
323 AccountFetcherService
* account_fetcher() { return account_fetcher_
.get(); }
324 AccountTrackerService
* account_tracker() { return account_tracker_
.get(); }
325 OAuth2TokenService
* token_service() {
326 return fake_oauth2_token_service_
.get();
328 SigninClient
* signin_client() { return signin_client_
.get(); }
331 void ReturnOAuthUrlFetchResults(int fetcher_id
,
332 net::HttpStatusCode response_code
,
333 const std::string
& response_string
);
335 base::MessageLoopForIO message_loop_
;
336 net::TestURLFetcherFactory test_fetcher_factory_
;
337 scoped_ptr
<FakeOAuth2TokenService
> fake_oauth2_token_service_
;
338 TestingPrefServiceSimple pref_service_
;
339 scoped_ptr
<AccountFetcherService
> account_fetcher_
;
340 scoped_ptr
<AccountTrackerService
> account_tracker_
;
341 scoped_ptr
<TestSigninClient
> signin_client_
;
344 void AccountTrackerServiceTest::ReturnOAuthUrlFetchResults(
346 net::HttpStatusCode response_code
,
347 const std::string
& response_string
) {
348 net::TestURLFetcher
* fetcher
=
349 test_fetcher_factory_
.GetFetcherByID(fetcher_id
);
350 ASSERT_TRUE(fetcher
);
351 fetcher
->set_response_code(response_code
);
352 fetcher
->SetResponseString(response_string
);
353 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
356 void AccountTrackerServiceTest::ReturnOAuthUrlFetchSuccess(
357 const std::string
& account_id
) {
358 IssueAccessToken(account_id
);
359 ReturnOAuthUrlFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId
,
361 GenerateValidTokenInfoResponse(account_id
));
364 void AccountTrackerServiceTest::ReturnOAuthUrlFetchSuccessIncomplete(
365 const std::string
& account_id
) {
366 IssueAccessToken(account_id
);
367 ReturnOAuthUrlFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId
,
369 GenerateIncompleteTokenInfoResponse(account_id
));
372 void AccountTrackerServiceTest::ReturnOAuthUrlFetchFailure(
373 const std::string
& account_id
) {
374 IssueAccessToken(account_id
);
375 ReturnOAuthUrlFetchResults(
376 gaia::GaiaOAuthClient::kUrlFetcherId
, net::HTTP_BAD_REQUEST
, "");
379 TEST_F(AccountTrackerServiceTest
, Basic
) {
382 TEST_F(AccountTrackerServiceTest
, TokenAvailable
) {
383 AccountTrackerObserver observer
;
384 account_tracker()->AddObserver(&observer
);
385 SimulateTokenAvailable("alpha");
386 ASSERT_FALSE(account_fetcher()->IsAllUserInfoFetched());
387 ASSERT_TRUE(observer
.CheckEvents());
388 account_tracker()->RemoveObserver(&observer
);
391 TEST_F(AccountTrackerServiceTest
, TokenAvailable_Revoked
) {
392 AccountTrackerObserver observer
;
393 account_tracker()->AddObserver(&observer
);
394 SimulateTokenAvailable("alpha");
395 SimulateTokenRevoked("alpha");
396 ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
397 ASSERT_TRUE(observer
.CheckEvents());
398 account_tracker()->RemoveObserver(&observer
);
401 TEST_F(AccountTrackerServiceTest
, TokenAvailable_UserInfo
) {
402 AccountTrackerObserver observer
;
403 account_tracker()->AddObserver(&observer
);
404 SimulateTokenAvailable("alpha");
405 ReturnOAuthUrlFetchSuccess("alpha");
406 ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
407 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, "alpha")));
408 account_tracker()->RemoveObserver(&observer
);
411 TEST_F(AccountTrackerServiceTest
, TokenAvailable_UserInfo_Revoked
) {
412 AccountTrackerObserver observer
;
413 account_tracker()->AddObserver(&observer
);
414 SimulateTokenAvailable("alpha");
415 ReturnOAuthUrlFetchSuccess("alpha");
416 ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
417 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, "alpha")));
418 SimulateTokenRevoked("alpha");
419 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(REMOVED
, "alpha")));
420 account_tracker()->RemoveObserver(&observer
);
423 TEST_F(AccountTrackerServiceTest
, TokenAvailable_UserInfoFailed
) {
424 AccountTrackerObserver observer
;
425 account_tracker()->AddObserver(&observer
);
426 SimulateTokenAvailable("alpha");
427 ReturnOAuthUrlFetchFailure("alpha");
428 ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
429 ASSERT_TRUE(observer
.CheckEvents());
430 account_tracker()->RemoveObserver(&observer
);
433 TEST_F(AccountTrackerServiceTest
, TokenAvailableTwice_UserInfoOnce
) {
434 AccountTrackerObserver observer
;
435 account_tracker()->AddObserver(&observer
);
436 SimulateTokenAvailable("alpha");
437 ReturnOAuthUrlFetchSuccess("alpha");
438 ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
439 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, "alpha")));
441 SimulateTokenAvailable("alpha");
442 ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
443 ASSERT_TRUE(observer
.CheckEvents());
444 account_tracker()->RemoveObserver(&observer
);
447 TEST_F(AccountTrackerServiceTest
, TokenAlreadyExists
) {
448 SimulateTokenAvailable("alpha");
449 AccountTrackerService tracker
;
450 AccountTrackerObserver observer
;
451 AccountFetcherService fetcher
;
453 tracker
.AddObserver(&observer
);
454 tracker
.Initialize(signin_client());
456 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
457 fetcher
.EnableNetworkFetches();
458 ASSERT_FALSE(fetcher
.IsAllUserInfoFetched());
459 ASSERT_TRUE(observer
.CheckEvents());
460 tracker
.RemoveObserver(&observer
);
465 TEST_F(AccountTrackerServiceTest
, TwoTokenAvailable_TwoUserInfo
) {
466 AccountTrackerObserver observer
;
467 account_tracker()->AddObserver(&observer
);
468 SimulateTokenAvailable("alpha");
469 SimulateTokenAvailable("beta");
470 ReturnOAuthUrlFetchSuccess("alpha");
471 ReturnOAuthUrlFetchSuccess("beta");
472 ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
473 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, "alpha"),
474 TrackingEvent(UPDATED
, "beta")));
475 account_tracker()->RemoveObserver(&observer
);
478 TEST_F(AccountTrackerServiceTest
, TwoTokenAvailable_OneUserInfo
) {
479 AccountTrackerObserver observer
;
480 account_tracker()->AddObserver(&observer
);
481 SimulateTokenAvailable("alpha");
482 SimulateTokenAvailable("beta");
483 ReturnOAuthUrlFetchSuccess("beta");
484 ASSERT_FALSE(account_fetcher()->IsAllUserInfoFetched());
485 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, "beta")));
486 ReturnOAuthUrlFetchSuccess("alpha");
487 ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
488 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, "alpha")));
489 account_tracker()->RemoveObserver(&observer
);
492 TEST_F(AccountTrackerServiceTest
, GetAccounts
) {
493 SimulateTokenAvailable("alpha");
494 SimulateTokenAvailable("beta");
495 SimulateTokenAvailable("gamma");
496 ReturnOAuthUrlFetchSuccess("alpha");
497 ReturnOAuthUrlFetchSuccess("beta");
498 ReturnOAuthUrlFetchSuccess("gamma");
500 std::vector
<AccountInfo
> infos
= account_tracker()->GetAccounts();
502 EXPECT_EQ(3u, infos
.size());
503 CheckAccountDetails("alpha", infos
[0]);
504 CheckAccountDetails("beta", infos
[1]);
505 CheckAccountDetails("gamma", infos
[2]);
508 TEST_F(AccountTrackerServiceTest
, GetAccountInfo_Empty
) {
509 AccountInfo info
= account_tracker()->GetAccountInfo("alpha");
510 ASSERT_EQ("", info
.account_id
);
513 TEST_F(AccountTrackerServiceTest
, GetAccountInfo_TokenAvailable
) {
514 SimulateTokenAvailable("alpha");
515 AccountInfo info
= account_tracker()->GetAccountInfo("alpha");
516 ASSERT_EQ("alpha", info
.account_id
);
517 ASSERT_EQ("", info
.gaia
);
518 ASSERT_EQ("", info
.email
);
521 TEST_F(AccountTrackerServiceTest
, GetAccountInfo_TokenAvailable_UserInfo
) {
522 SimulateTokenAvailable("alpha");
523 ReturnOAuthUrlFetchSuccess("alpha");
524 AccountInfo info
= account_tracker()->GetAccountInfo("alpha");
525 CheckAccountDetails("alpha", info
);
528 TEST_F(AccountTrackerServiceTest
, GetAccountInfo_TokenAvailable_EnableNetwork
) {
529 // Shutdown the network-enabled tracker built into the test case.
532 // Create an account tracker and an account fetcher service but do not enable
534 AccountTrackerService tracker
;
535 tracker
.Initialize(signin_client());
537 AccountFetcherService fetcher_service
;
538 fetcher_service
.Initialize(signin_client(), token_service(), &tracker
,
541 SimulateTokenAvailable("alpha");
542 IssueAccessToken("alpha");
543 // No fetcher has been created yet.
544 net::TestURLFetcher
* fetcher
= test_fetcher_factory()->GetFetcherByID(
545 gaia::GaiaOAuthClient::kUrlFetcherId
);
546 ASSERT_FALSE(fetcher
);
548 // Enable the network to create the fetcher then issue the access token.
549 fetcher_service
.EnableNetworkFetches();
551 // Fetcher was created and executes properly.
552 ReturnOAuthUrlFetchSuccess("alpha");
554 AccountInfo info
= tracker
.GetAccountInfo("alpha");
555 CheckAccountDetails("alpha", info
);
556 fetcher_service
.Shutdown();
560 TEST_F(AccountTrackerServiceTest
, FindAccountInfoByGaiaId
) {
561 SimulateTokenAvailable("alpha");
562 ReturnOAuthUrlFetchSuccess("alpha");
564 std::string gaia_id
= AccountIdToGaiaId("alpha");
565 AccountInfo info
= account_tracker()->FindAccountInfoByGaiaId(gaia_id
);
566 ASSERT_EQ("alpha", info
.account_id
);
567 ASSERT_EQ(gaia_id
, info
.gaia
);
569 gaia_id
= AccountIdToGaiaId("beta");
570 info
= account_tracker()->FindAccountInfoByGaiaId(gaia_id
);
571 ASSERT_EQ("", info
.account_id
);
574 TEST_F(AccountTrackerServiceTest
, FindAccountInfoByEmail
) {
575 SimulateTokenAvailable("alpha");
576 ReturnOAuthUrlFetchSuccess("alpha");
578 std::string email
= AccountIdToEmail("alpha");
579 AccountInfo info
= account_tracker()->FindAccountInfoByEmail(email
);
580 ASSERT_EQ("alpha", info
.account_id
);
581 ASSERT_EQ(email
, info
.email
);
583 // Should also work with "canonically-equal" email addresses.
584 info
= account_tracker()->FindAccountInfoByEmail("Alpha@Gmail.COM");
585 ASSERT_EQ("alpha", info
.account_id
);
586 ASSERT_EQ(email
, info
.email
);
587 info
= account_tracker()->FindAccountInfoByEmail("al.pha@gmail.com");
588 ASSERT_EQ("alpha", info
.account_id
);
589 ASSERT_EQ(email
, info
.email
);
591 email
= AccountIdToEmail("beta");
592 info
= account_tracker()->FindAccountInfoByEmail(email
);
593 ASSERT_EQ("", info
.account_id
);
596 TEST_F(AccountTrackerServiceTest
, Persistence
) {
597 // Create a tracker and add two accounts. This should cause the accounts
598 // to be saved to persistence.
600 AccountTrackerService tracker
;
601 tracker
.Initialize(signin_client());
602 SimulateTokenAvailable("alpha");
603 ReturnOAuthUrlFetchSuccess("alpha");
604 SimulateTokenAvailable("beta");
605 ReturnOAuthUrlFetchSuccess("beta");
609 // Create a new tracker and make sure it loads the accounts correctly from
612 AccountTrackerService tracker
;
613 AccountTrackerObserver observer
;
614 tracker
.AddObserver(&observer
);
615 tracker
.Initialize(signin_client());
616 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, "alpha"),
617 TrackingEvent(UPDATED
, "beta")));
618 tracker
.RemoveObserver(&observer
);
620 std::vector
<AccountInfo
> infos
= tracker
.GetAccounts();
621 ASSERT_EQ(2u, infos
.size());
622 CheckAccountDetails("alpha", infos
[0]);
623 CheckAccountDetails("beta", infos
[1]);
625 FakeAccountFetcherService fetcher
;
626 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
627 fetcher
.EnableNetworkFetches();
628 // Remove an account.
629 // This will allow testing removal as well as child accounts which is only
630 // allowed for a single account.
631 SimulateTokenRevoked("alpha");
632 fetcher
.FakeSetIsChildAccount("beta", true);
638 // Create a new tracker and make sure it loads the single account from
639 // persistence. Also verify it is a child account.
641 AccountTrackerService tracker
;
642 tracker
.Initialize(signin_client());
644 std::vector
<AccountInfo
> infos
= tracker
.GetAccounts();
645 ASSERT_EQ(1u, infos
.size());
646 CheckAccountDetails("beta", infos
[0]);
647 ASSERT_TRUE(infos
[0].is_child_account
);
652 TEST_F(AccountTrackerServiceTest
, SeedAccountInfo
) {
653 std::vector
<AccountInfo
> infos
= account_tracker()->GetAccounts();
654 EXPECT_EQ(0u, infos
.size());
656 const std::string gaia_id
= AccountIdToGaiaId("alpha");
657 const std::string email
= AccountIdToEmail("alpha");
658 const std::string account_id
=
659 account_tracker()->PickAccountIdForAccount(gaia_id
, email
);
660 account_tracker()->SeedAccountInfo(gaia_id
, email
);
662 infos
= account_tracker()->GetAccounts();
663 EXPECT_EQ(1u, infos
.size());
664 EXPECT_EQ(account_id
, infos
[0].account_id
);
665 EXPECT_EQ(gaia_id
, infos
[0].gaia
);
666 EXPECT_EQ(email
, infos
[0].email
);
669 TEST_F(AccountTrackerServiceTest
, UpgradeToFullAccountInfo
) {
670 // Start by simulating an incomplete account info and let it be saved to
673 AccountTrackerService tracker
;
674 tracker
.Initialize(signin_client());
675 AccountFetcherService fetcher
;
676 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
677 fetcher
.EnableNetworkFetches();
678 SimulateTokenAvailable("incomplete");
679 ReturnOAuthUrlFetchSuccessIncomplete("incomplete");
685 AccountTrackerService tracker
;
686 tracker
.Initialize(signin_client());
687 AccountFetcherService fetcher
;
688 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
689 // Validate that the loaded AccountInfo from prefs is considered invalid.
690 std::vector
<AccountInfo
> infos
= tracker
.GetAccounts();
691 ASSERT_EQ(1u, infos
.size());
692 ASSERT_FALSE(infos
[0].IsValid());
694 // Enable network fetches and simulate the same account getting a refresh
695 // token containing all the info.
696 fetcher
.EnableNetworkFetches();
697 SimulateTokenAvailable("incomplete");
698 ReturnOAuthUrlFetchSuccess("incomplete");
700 // Validate that the account is now considered valid.
701 infos
= tracker
.GetAccounts();
702 ASSERT_EQ(1u, infos
.size());
703 ASSERT_TRUE(infos
[0].IsValid());
709 // Reinstantiate a tracker to validate that the AccountInfo saved to prefs is
710 // now the upgraded one, considered valid.
712 AccountTrackerService tracker
;
713 AccountTrackerObserver observer
;
714 tracker
.AddObserver(&observer
);
715 tracker
.Initialize(signin_client());
716 AccountFetcherService fetcher
;
717 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
719 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, "incomplete")));
720 // Enabling network fetches shouldn't cause any actual fetch since the
721 // AccountInfos loaded from prefs should be valid.
722 fetcher
.EnableNetworkFetches();
724 std::vector
<AccountInfo
> infos
= tracker
.GetAccounts();
725 ASSERT_EQ(1u, infos
.size());
726 ASSERT_TRUE(infos
[0].IsValid());
727 // Check that no network fetches were made.
728 ASSERT_TRUE(observer
.CheckEvents());
730 tracker
.RemoveObserver(&observer
);
736 TEST_F(AccountTrackerServiceTest
, TimerRefresh
) {
737 // Start by creating a tracker and adding a couple accounts to be persisted to
740 AccountTrackerService tracker
;
741 tracker
.Initialize(signin_client());
742 AccountFetcherService fetcher
;
743 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
744 fetcher
.EnableNetworkFetches();
745 SimulateTokenAvailable("alpha");
746 ReturnOAuthUrlFetchSuccess("alpha");
747 SimulateTokenAvailable("beta");
748 ReturnOAuthUrlFetchSuccess("beta");
753 // Rewind the time by half a day, which shouldn't be enough to trigger a
755 base::Time fake_update
= base::Time::Now() - base::TimeDelta::FromHours(12);
756 signin_client()->GetPrefs()->SetInt64(
757 AccountFetcherService::kLastUpdatePref
,
758 fake_update
.ToInternalValue());
760 // Instantiate a new ATS, making sure the persisted accounts are still there
761 // and that no network fetches happen.
763 AccountTrackerService tracker
;
764 tracker
.Initialize(signin_client());
765 AccountFetcherService fetcher
;
766 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
768 ASSERT_TRUE(fetcher
.IsAllUserInfoFetched());
769 std::vector
<AccountInfo
> infos
= tracker
.GetAccounts();
770 ASSERT_EQ(2u, infos
.size());
771 ASSERT_TRUE(infos
[0].IsValid());
772 ASSERT_TRUE(infos
[1].IsValid());
774 fetcher
.EnableNetworkFetches();
775 ASSERT_TRUE(fetcher
.IsAllUserInfoFetched());
780 // Rewind the last updated time enough to trigger a network refresh.
781 fake_update
= base::Time::Now() - base::TimeDelta::FromHours(25);
782 signin_client()->GetPrefs()->SetInt64(
783 AccountFetcherService::kLastUpdatePref
,
784 fake_update
.ToInternalValue());
786 // Instantiate a new tracker and validate that even though the AccountInfos
787 // are still valid, the network fetches are started.
789 AccountTrackerService tracker
;
790 tracker
.Initialize(signin_client());
791 AccountFetcherService fetcher
;
792 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
794 ASSERT_TRUE(fetcher
.IsAllUserInfoFetched());
795 std::vector
<AccountInfo
> infos
= tracker
.GetAccounts();
796 ASSERT_EQ(2u, infos
.size());
797 ASSERT_TRUE(infos
[0].IsValid());
798 ASSERT_TRUE(infos
[1].IsValid());
800 fetcher
.EnableNetworkFetches();
801 ASSERT_FALSE(fetcher
.IsAllUserInfoFetched());
807 TEST_F(AccountTrackerServiceTest
, LegacyDottedAccountIds
) {
808 // Start by creating a tracker and adding an account with a dotted account id
809 // because of an old bug in token service. The token service would also add
810 // a correct non-dotted account id for the same account.
812 AccountTrackerService tracker
;
813 tracker
.Initialize(signin_client());
814 AccountFetcherService fetcher
;
815 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
816 fetcher
.EnableNetworkFetches();
817 SimulateTokenAvailable("foo.bar@gmail.com");
818 SimulateTokenAvailable("foobar@gmail.com");
819 ReturnOAuthUrlFetchSuccess("foo.bar@gmail.com");
820 ReturnOAuthUrlFetchSuccess("foobar@gmail.com");
825 // Remove the bad account now from the token service to simulate that it
827 SimulateTokenRevoked("foo.bar@gmail.com");
829 // Instantiate a new tracker and validate that it has only one account, and
830 // it is the correct non dotted one.
832 AccountTrackerService tracker
;
833 tracker
.Initialize(signin_client());
834 AccountFetcherService fetcher
;
835 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
837 ASSERT_TRUE(fetcher
.IsAllUserInfoFetched());
838 std::vector
<AccountInfo
> infos
= tracker
.GetAccounts();
839 ASSERT_EQ(1u, infos
.size());
840 ASSERT_STREQ("foobar@gmail.com", infos
[0].account_id
.c_str());
846 TEST_F(AccountTrackerServiceTest
, MigrateAccountIdToGaiaId
) {
847 if (account_tracker()->GetMigrationState() !=
848 AccountTrackerService::MIGRATION_NOT_STARTED
) {
849 AccountTrackerService tracker
;
850 TestingPrefServiceSimple pref
;
851 AccountInfo account_info
;
853 std::string email_alpha
= AccountIdToEmail("alpha");
854 std::string gaia_alpha
= AccountIdToGaiaId("alpha");
855 std::string email_beta
= AccountIdToEmail("beta");
856 std::string gaia_beta
= AccountIdToGaiaId("beta");
858 pref
.registry()->RegisterListPref(AccountTrackerService::kAccountInfoPref
);
859 pref
.registry()->RegisterIntegerPref(
860 prefs::kAccountIdMigrationState
,
861 AccountTrackerService::MIGRATION_NOT_STARTED
);
863 ListPrefUpdate
update(&pref
, AccountTrackerService::kAccountInfoPref
);
865 base::DictionaryValue
* dict
= new base::DictionaryValue();
866 update
->Append(dict
);
867 dict
->SetString("account_id", base::UTF8ToUTF16(email_alpha
));
868 dict
->SetString("email", base::UTF8ToUTF16(email_alpha
));
869 dict
->SetString("gaia", base::UTF8ToUTF16(gaia_alpha
));
871 dict
= new base::DictionaryValue();
872 update
->Append(dict
);
873 dict
->SetString("account_id", base::UTF8ToUTF16(email_beta
));
874 dict
->SetString("email", base::UTF8ToUTF16(email_beta
));
875 dict
->SetString("gaia", base::UTF8ToUTF16(gaia_beta
));
877 scoped_ptr
<TestSigninClient
> client
;
878 client
.reset(new TestSigninClient(&pref
));
879 tracker
.Initialize(client
.get());
881 ASSERT_EQ(tracker
.GetMigrationState(),
882 AccountTrackerService::MIGRATION_IN_PROGRESS
);
884 account_info
= tracker
.GetAccountInfo(gaia_alpha
);
885 ASSERT_EQ(account_info
.account_id
, gaia_alpha
);
886 ASSERT_EQ(account_info
.gaia
, gaia_alpha
);
887 ASSERT_EQ(account_info
.email
, email_alpha
);
889 account_info
= tracker
.GetAccountInfo(gaia_beta
);
890 ASSERT_EQ(account_info
.account_id
, gaia_beta
);
891 ASSERT_EQ(account_info
.gaia
, gaia_beta
);
892 ASSERT_EQ(account_info
.email
, email_beta
);
894 std::vector
<AccountInfo
> accounts
= tracker
.GetAccounts();
895 ASSERT_EQ(2u, accounts
.size());
899 TEST_F(AccountTrackerServiceTest
, CanNotMigrateAccountIdToGaiaId
) {
900 if ((account_tracker()->GetMigrationState() !=
901 AccountTrackerService::MIGRATION_NOT_STARTED
)) {
902 AccountTrackerService tracker
;
903 TestingPrefServiceSimple pref
;
904 AccountInfo account_info
;
906 std::string email_alpha
= AccountIdToEmail("alpha");
907 std::string gaia_alpha
= AccountIdToGaiaId("alpha");
908 std::string email_beta
= AccountIdToEmail("beta");
910 pref
.registry()->RegisterListPref(AccountTrackerService::kAccountInfoPref
);
911 pref
.registry()->RegisterIntegerPref(
912 prefs::kAccountIdMigrationState
,
913 AccountTrackerService::MIGRATION_NOT_STARTED
);
915 ListPrefUpdate
update(&pref
, AccountTrackerService::kAccountInfoPref
);
917 base::DictionaryValue
* dict
= new base::DictionaryValue();
918 update
->Append(dict
);
919 dict
->SetString("account_id", base::UTF8ToUTF16(email_alpha
));
920 dict
->SetString("email", base::UTF8ToUTF16(email_alpha
));
921 dict
->SetString("gaia", base::UTF8ToUTF16(gaia_alpha
));
923 dict
= new base::DictionaryValue();
924 update
->Append(dict
);
925 dict
->SetString("account_id", base::UTF8ToUTF16(email_beta
));
926 dict
->SetString("email", base::UTF8ToUTF16(email_beta
));
927 dict
->SetString("gaia", base::UTF8ToUTF16(std::string()));
929 scoped_ptr
<TestSigninClient
> client
;
930 client
.reset(new TestSigninClient(&pref
));
931 tracker
.Initialize(client
.get());
933 ASSERT_EQ(tracker
.GetMigrationState(),
934 AccountTrackerService::MIGRATION_NOT_STARTED
);
936 account_info
= tracker
.GetAccountInfo(email_alpha
);
937 ASSERT_EQ(account_info
.account_id
, email_alpha
);
938 ASSERT_EQ(account_info
.gaia
, gaia_alpha
);
939 ASSERT_EQ(account_info
.email
, email_alpha
);
941 account_info
= tracker
.GetAccountInfo(email_beta
);
942 ASSERT_EQ(account_info
.account_id
, email_beta
);
943 ASSERT_EQ(account_info
.email
, email_beta
);
945 std::vector
<AccountInfo
> accounts
= tracker
.GetAccounts();
946 ASSERT_EQ(2u, accounts
.size());
950 TEST_F(AccountTrackerServiceTest
, GaiaIdMigrationCrashInTheMiddle
) {
951 if (account_tracker()->GetMigrationState() !=
952 AccountTrackerService::MIGRATION_NOT_STARTED
) {
953 AccountTrackerService tracker
;
954 TestingPrefServiceSimple pref
;
955 AccountInfo account_info
;
957 std::string email_alpha
= AccountIdToEmail("alpha");
958 std::string gaia_alpha
= AccountIdToGaiaId("alpha");
959 std::string email_beta
= AccountIdToEmail("beta");
960 std::string gaia_beta
= AccountIdToGaiaId("beta");
962 pref
.registry()->RegisterListPref(AccountTrackerService::kAccountInfoPref
);
963 pref
.registry()->RegisterIntegerPref(
964 prefs::kAccountIdMigrationState
,
965 AccountTrackerService::MIGRATION_IN_PROGRESS
);
967 ListPrefUpdate
update(&pref
, AccountTrackerService::kAccountInfoPref
);
969 base::DictionaryValue
* dict
= new base::DictionaryValue();
970 update
->Append(dict
);
971 dict
->SetString("account_id", base::UTF8ToUTF16(email_alpha
));
972 dict
->SetString("email", base::UTF8ToUTF16(email_alpha
));
973 dict
->SetString("gaia", base::UTF8ToUTF16(gaia_alpha
));
975 dict
= new base::DictionaryValue();
976 update
->Append(dict
);
977 dict
->SetString("account_id", base::UTF8ToUTF16(email_beta
));
978 dict
->SetString("email", base::UTF8ToUTF16(email_beta
));
979 dict
->SetString("gaia", base::UTF8ToUTF16(gaia_beta
));
981 // Succeed miggrated account.
982 dict
= new base::DictionaryValue();
983 update
->Append(dict
);
984 dict
->SetString("account_id", base::UTF8ToUTF16(gaia_alpha
));
985 dict
->SetString("email", base::UTF8ToUTF16(email_alpha
));
986 dict
->SetString("gaia", base::UTF8ToUTF16(gaia_alpha
));
988 scoped_ptr
<TestSigninClient
> client
;
989 client
.reset(new TestSigninClient(&pref
));
990 tracker
.Initialize(client
.get());
992 ASSERT_EQ(tracker
.GetMigrationState(),
993 AccountTrackerService::MIGRATION_IN_PROGRESS
);
995 account_info
= tracker
.GetAccountInfo(gaia_alpha
);
996 ASSERT_EQ(account_info
.account_id
, gaia_alpha
);
997 ASSERT_EQ(account_info
.gaia
, gaia_alpha
);
998 ASSERT_EQ(account_info
.email
, email_alpha
);
1000 account_info
= tracker
.GetAccountInfo(gaia_beta
);
1001 ASSERT_EQ(account_info
.account_id
, gaia_beta
);
1002 ASSERT_EQ(account_info
.gaia
, gaia_beta
);
1003 ASSERT_EQ(account_info
.email
, email_beta
);
1005 std::vector
<AccountInfo
> accounts
= tracker
.GetAccounts();
1006 ASSERT_EQ(2u, accounts
.size());
1008 tracker
.SetMigrationDone();
1010 tracker
.Initialize(client
.get());
1012 ASSERT_EQ(tracker
.GetMigrationState(),
1013 AccountTrackerService::MIGRATION_DONE
);
1015 account_info
= tracker
.GetAccountInfo(gaia_alpha
);
1016 ASSERT_EQ(account_info
.account_id
, gaia_alpha
);
1017 ASSERT_EQ(account_info
.gaia
, gaia_alpha
);
1018 ASSERT_EQ(account_info
.email
, email_alpha
);
1020 account_info
= tracker
.GetAccountInfo(gaia_beta
);
1021 ASSERT_EQ(account_info
.account_id
, gaia_beta
);
1022 ASSERT_EQ(account_info
.gaia
, gaia_beta
);
1023 ASSERT_EQ(account_info
.email
, email_beta
);
1026 accounts
= tracker
.GetAccounts();
1027 ASSERT_EQ(2u, accounts
.size());
1031 TEST_F(AccountTrackerServiceTest
, ChildAccountBasic
) {
1032 AccountTrackerService tracker
;
1033 tracker
.Initialize(signin_client());
1034 FakeAccountFetcherService fetcher
;
1035 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
1036 fetcher
.EnableNetworkFetches();
1037 AccountTrackerObserver observer
;
1038 tracker
.AddObserver(&observer
);
1039 std::string
child_id("child");
1041 // Responses are processed iff there is a single account with a valid token
1042 // and the response is for that account.
1043 fetcher
.FakeSetIsChildAccount(child_id
, true);
1044 ASSERT_TRUE(observer
.CheckEvents());
1047 SimulateTokenAvailable(child_id
);
1048 IssueAccessToken(child_id
);
1049 fetcher
.FakeSetIsChildAccount(child_id
, true);
1050 // Response was processed but observer is not notified as the account state
1052 ASSERT_TRUE(observer
.CheckEvents());
1053 AccountInfo info
= tracker
.GetAccountInfo(child_id
);
1054 ASSERT_TRUE(info
.is_child_account
);
1055 SimulateTokenRevoked(child_id
);
1057 tracker
.RemoveObserver(&observer
);
1062 TEST_F(AccountTrackerServiceTest
, ChildAccountUpdatedAndRevoked
) {
1063 AccountTrackerService tracker
;
1064 tracker
.Initialize(signin_client());
1065 FakeAccountFetcherService fetcher
;
1066 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
1067 fetcher
.EnableNetworkFetches();
1068 AccountTrackerObserver observer
;
1069 tracker
.AddObserver(&observer
);
1070 std::string
child_id("child");
1072 SimulateTokenAvailable(child_id
);
1073 IssueAccessToken(child_id
);
1074 fetcher
.FakeSetIsChildAccount(child_id
, false);
1075 FakeUserInfoFetchSuccess(&fetcher
, child_id
);
1076 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, child_id
)));
1077 AccountInfo info
= tracker
.GetAccountInfo(child_id
);
1078 ASSERT_FALSE(info
.is_child_account
);
1079 SimulateTokenRevoked(child_id
);
1080 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(REMOVED
, child_id
)));
1082 tracker
.RemoveObserver(&observer
);
1087 TEST_F(AccountTrackerServiceTest
, ChildAccountUpdatedAndRevokedWithUpdate
) {
1088 AccountTrackerService tracker
;
1089 tracker
.Initialize(signin_client());
1090 FakeAccountFetcherService fetcher
;
1091 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
1092 fetcher
.EnableNetworkFetches();
1093 AccountTrackerObserver observer
;
1094 tracker
.AddObserver(&observer
);
1095 std::string
child_id("child");
1097 SimulateTokenAvailable(child_id
);
1098 IssueAccessToken(child_id
);
1099 fetcher
.FakeSetIsChildAccount(child_id
, true);
1100 FakeUserInfoFetchSuccess(&fetcher
, child_id
);
1101 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, child_id
)));
1102 AccountInfo info
= tracker
.GetAccountInfo(child_id
);
1103 ASSERT_TRUE(info
.is_child_account
);
1104 SimulateTokenRevoked(child_id
);
1105 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, child_id
),
1106 TrackingEvent(REMOVED
, child_id
)));
1108 tracker
.RemoveObserver(&observer
);
1113 TEST_F(AccountTrackerServiceTest
, ChildAccountUpdatedTwiceThenRevoked
) {
1114 AccountTrackerService tracker
;
1115 tracker
.Initialize(signin_client());
1116 FakeAccountFetcherService fetcher
;
1117 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
1118 fetcher
.EnableNetworkFetches();
1119 AccountTrackerObserver observer
;
1120 tracker
.AddObserver(&observer
);
1121 std::string
child_id("child");
1123 SimulateTokenAvailable(child_id
);
1124 IssueAccessToken(child_id
);
1125 // Observers notified the first time.
1126 FakeUserInfoFetchSuccess(&fetcher
, child_id
);
1127 // Since the account state is already valid, this will notify the
1128 // observers for the second time.
1129 fetcher
.FakeSetIsChildAccount(child_id
, true);
1130 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, child_id
),
1131 TrackingEvent(UPDATED
, child_id
)));
1132 SimulateTokenRevoked(child_id
);
1133 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, child_id
),
1134 TrackingEvent(REMOVED
, child_id
)));
1136 tracker
.RemoveObserver(&observer
);
1141 TEST_F(AccountTrackerServiceTest
, ChildAccountGraduation
) {
1142 AccountTrackerService tracker
;
1143 tracker
.Initialize(signin_client());
1144 FakeAccountFetcherService fetcher
;
1145 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
1146 fetcher
.EnableNetworkFetches();
1147 AccountTrackerObserver observer
;
1148 tracker
.AddObserver(&observer
);
1149 std::string
child_id("child");
1151 SimulateTokenAvailable(child_id
);
1152 IssueAccessToken(child_id
);
1154 // Set and verify this is a child account.
1155 fetcher
.FakeSetIsChildAccount(child_id
, true);
1156 AccountInfo info
= tracker
.GetAccountInfo(child_id
);
1157 ASSERT_TRUE(info
.is_child_account
);
1158 FakeUserInfoFetchSuccess(&fetcher
, child_id
);
1159 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, child_id
)));
1161 // Now simulate child account graduation.
1162 fetcher
.FakeSetIsChildAccount(child_id
, false);
1163 info
= tracker
.GetAccountInfo(child_id
);
1164 ASSERT_FALSE(info
.is_child_account
);
1165 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, child_id
)));
1167 SimulateTokenRevoked(child_id
);
1168 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(REMOVED
, child_id
)));
1170 tracker
.RemoveObserver(&observer
);