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_tracker_service.h"
14 #include "components/signin/core/browser/fake_account_fetcher_service.h"
15 #include "components/signin/core/browser/test_signin_client.h"
16 #include "components/signin/core/common/signin_pref_names.h"
17 #include "google_apis/gaia/fake_oauth2_token_service.h"
18 #include "google_apis/gaia/gaia_oauth_client.h"
19 #include "net/http/http_status_code.h"
20 #include "net/url_request/test_url_fetcher_factory.h"
21 #include "net/url_request/url_fetcher_delegate.h"
22 #include "net/url_request/url_request_test_util.h"
23 #include "testing/gtest/include/gtest/gtest.h"
27 const std::string kTokenInfoResponseFormat
=
33 \"given_name\": \"%s\", \
38 const std::string kTokenInfoIncompleteResponseFormat
=
45 enum TrackingEventType
{
50 std::string
AccountIdToEmail(const std::string account_id
) {
51 return account_id
+ "@gmail.com";
54 std::string
AccountIdToGaiaId(const std::string account_id
) {
55 return "gaia-" + account_id
;
58 std::string
AccountIdToFullName(const std::string account_id
) {
59 return "full-name-" + account_id
;
62 std::string
AccountIdToGivenName(const std::string account_id
) {
63 return "given-name-" + account_id
;
66 std::string
AccountIdToLocale(const std::string account_id
) {
67 return "locale-" + account_id
;
70 std::string
AccountIdToPictureURL(const std::string account_id
) {
71 return "picture_url-" + account_id
;
74 void CheckAccountDetails(const std::string account_id
,
75 const AccountTrackerService::AccountInfo
& info
) {
76 EXPECT_EQ(account_id
, info
.account_id
);
77 EXPECT_EQ(AccountIdToGaiaId(account_id
), info
.gaia
);
78 EXPECT_EQ(AccountIdToEmail(account_id
), info
.email
);
79 EXPECT_EQ(AccountTrackerService::kNoHostedDomainFound
,
81 EXPECT_EQ(AccountIdToFullName(account_id
), info
.full_name
);
82 EXPECT_EQ(AccountIdToGivenName(account_id
), info
.given_name
);
83 EXPECT_EQ(AccountIdToLocale(account_id
), info
.locale
);
86 void FakeUserInfoFetchSuccess(FakeAccountFetcherService
* fetcher
,
87 const std::string
& account_id
) {
88 fetcher
->FakeUserInfoFetchSuccess(
89 account_id
, AccountIdToEmail(account_id
), AccountIdToGaiaId(account_id
),
90 AccountTrackerService::kNoHostedDomainFound
,
91 AccountIdToFullName(account_id
), AccountIdToGivenName(account_id
),
92 AccountIdToLocale(account_id
), AccountIdToPictureURL(account_id
));
97 TrackingEvent(TrackingEventType type
,
98 const std::string
& account_id
,
99 const std::string
& gaia_id
)
101 account_id_(account_id
),
104 TrackingEvent(TrackingEventType type
,
105 const std::string
& account_id
)
107 account_id_(account_id
),
108 gaia_id_(AccountIdToGaiaId(account_id
)) {}
110 bool operator==(const TrackingEvent
& event
) const {
111 return type_
== event
.type_
&& account_id_
== event
.account_id_
&&
112 gaia_id_
== event
.gaia_id_
;
115 std::string
ToString() const {
116 const char * typestr
= "INVALID";
125 return base::StringPrintf("{ type: %s, account_id: %s, gaia: %s }",
132 friend bool CompareByUser(TrackingEvent a
, TrackingEvent b
);
134 TrackingEventType type_
;
135 std::string account_id_
;
136 std::string gaia_id_
;
139 bool CompareByUser(TrackingEvent a
, TrackingEvent b
) {
140 return a
.account_id_
< b
.account_id_
;
143 std::string
Str(const std::vector
<TrackingEvent
>& events
) {
144 std::string str
= "[";
145 bool needs_comma
= false;
146 for (std::vector
<TrackingEvent
>::const_iterator it
=
147 events
.begin(); it
!= events
.end(); ++it
) {
151 str
+= it
->ToString();
157 class AccountTrackerObserver
: public AccountTrackerService::Observer
{
159 AccountTrackerObserver() {}
160 ~AccountTrackerObserver() override
{}
163 void SortEventsByUser();
165 testing::AssertionResult
CheckEvents();
166 testing::AssertionResult
CheckEvents(const TrackingEvent
& e1
);
167 testing::AssertionResult
CheckEvents(const TrackingEvent
& e1
,
168 const TrackingEvent
& e2
);
169 testing::AssertionResult
CheckEvents(const TrackingEvent
& e1
,
170 const TrackingEvent
& e2
,
171 const TrackingEvent
& e3
);
174 // AccountTrackerService::Observer implementation
175 void OnAccountUpdated(const AccountTrackerService::AccountInfo
& ids
) override
;
176 void OnAccountRemoved(const AccountTrackerService::AccountInfo
& ids
) override
;
178 testing::AssertionResult
CheckEvents(
179 const std::vector
<TrackingEvent
>& events
);
181 std::vector
<TrackingEvent
> events_
;
184 void AccountTrackerObserver::OnAccountUpdated(
185 const AccountTrackerService::AccountInfo
& ids
) {
186 events_
.push_back(TrackingEvent(UPDATED
, ids
.account_id
, ids
.gaia
));
189 void AccountTrackerObserver::OnAccountRemoved(
190 const AccountTrackerService::AccountInfo
& ids
) {
191 events_
.push_back(TrackingEvent(REMOVED
, ids
.account_id
, ids
.gaia
));
194 void AccountTrackerObserver::Clear() {
198 void AccountTrackerObserver::SortEventsByUser() {
199 std::stable_sort(events_
.begin(), events_
.end(), CompareByUser
);
202 testing::AssertionResult
AccountTrackerObserver::CheckEvents() {
203 std::vector
<TrackingEvent
> events
;
204 return CheckEvents(events
);
207 testing::AssertionResult
AccountTrackerObserver::CheckEvents(
208 const TrackingEvent
& e1
) {
209 std::vector
<TrackingEvent
> events
;
210 events
.push_back(e1
);
211 return CheckEvents(events
);
214 testing::AssertionResult
AccountTrackerObserver::CheckEvents(
215 const TrackingEvent
& e1
,
216 const TrackingEvent
& e2
) {
217 std::vector
<TrackingEvent
> events
;
218 events
.push_back(e1
);
219 events
.push_back(e2
);
220 return CheckEvents(events
);
223 testing::AssertionResult
AccountTrackerObserver::CheckEvents(
224 const TrackingEvent
& e1
,
225 const TrackingEvent
& e2
,
226 const TrackingEvent
& e3
) {
227 std::vector
<TrackingEvent
> events
;
228 events
.push_back(e1
);
229 events
.push_back(e2
);
230 events
.push_back(e3
);
231 return CheckEvents(events
);
234 testing::AssertionResult
AccountTrackerObserver::CheckEvents(
235 const std::vector
<TrackingEvent
>& events
) {
236 std::string maybe_newline
= (events
.size() + events_
.size()) > 2 ? "\n" : "";
237 testing::AssertionResult
result(
239 ? testing::AssertionSuccess()
240 : (testing::AssertionFailure()
241 << "Expected " << maybe_newline
<< Str(events
) << ", "
242 << maybe_newline
<< "Got " << maybe_newline
<< Str(events_
)));
249 class AccountTrackerServiceTest
: public testing::Test
{
251 AccountTrackerServiceTest() {}
253 ~AccountTrackerServiceTest() override
{}
255 void SetUp() override
{
256 fake_oauth2_token_service_
.reset(new FakeOAuth2TokenService());
258 pref_service_
.registry()->RegisterListPref(
259 AccountTrackerService::kAccountInfoPref
);
260 pref_service_
.registry()->RegisterIntegerPref(
261 prefs::kAccountIdMigrationState
,
262 AccountTrackerService::MIGRATION_NOT_STARTED
);
263 pref_service_
.registry()->RegisterInt64Pref(
264 AccountFetcherService::kLastUpdatePref
, 0);
265 signin_client_
.reset(new TestSigninClient(&pref_service_
));
266 signin_client_
.get()->SetURLRequestContext(
267 new net::TestURLRequestContextGetter(message_loop_
.task_runner()));
269 account_tracker_
.reset(new AccountTrackerService());
270 account_tracker_
->Initialize(signin_client_
.get());
272 account_fetcher_
.reset(new AccountFetcherService());
273 account_fetcher_
->Initialize(signin_client_
.get(),
274 fake_oauth2_token_service_
.get(),
275 account_tracker_
.get(), nullptr);
277 account_fetcher_
->EnableNetworkFetches();
280 void TearDown() override
{
281 account_fetcher_
->Shutdown();
282 account_tracker_
->Shutdown();
285 void SimulateTokenAvailable(const std::string
& account_id
) {
286 fake_oauth2_token_service_
->AddAccount(account_id
);
289 void SimulateTokenRevoked(const std::string
& account_id
) {
290 fake_oauth2_token_service_
->RemoveAccount(account_id
);
293 // Helpers to fake access token and user info fetching
294 void IssueAccessToken(const std::string
& account_id
) {
295 fake_oauth2_token_service_
->IssueAllTokensForAccount(
296 account_id
, "access_token-" + account_id
, base::Time::Max());
299 std::string
GenerateValidTokenInfoResponse(const std::string
& account_id
) {
300 return base::StringPrintf(
301 kTokenInfoResponseFormat
.c_str(),
302 AccountIdToGaiaId(account_id
).c_str(),
303 AccountIdToEmail(account_id
).c_str(),
304 AccountIdToFullName(account_id
).c_str(),
305 AccountIdToGivenName(account_id
).c_str(),
306 AccountIdToLocale(account_id
).c_str(),
307 AccountIdToPictureURL(account_id
).c_str());
310 std::string
GenerateIncompleteTokenInfoResponse(
311 const std::string
& account_id
) {
312 return base::StringPrintf(
313 kTokenInfoIncompleteResponseFormat
.c_str(),
314 AccountIdToGaiaId(account_id
).c_str(),
315 AccountIdToEmail(account_id
).c_str());
317 void ReturnOAuthUrlFetchSuccess(const std::string
& account_id
);
318 void ReturnOAuthUrlFetchSuccessIncomplete(const std::string
& account_id
);
319 void ReturnOAuthUrlFetchFailure(const std::string
& account_id
);
321 net::TestURLFetcherFactory
* test_fetcher_factory() {
322 return &test_fetcher_factory_
;
324 AccountFetcherService
* account_fetcher() { return account_fetcher_
.get(); }
325 AccountTrackerService
* account_tracker() { return account_tracker_
.get(); }
326 OAuth2TokenService
* token_service() {
327 return fake_oauth2_token_service_
.get();
329 SigninClient
* signin_client() { return signin_client_
.get(); }
332 void ReturnOAuthUrlFetchResults(int fetcher_id
,
333 net::HttpStatusCode response_code
,
334 const std::string
& response_string
);
336 base::MessageLoopForIO message_loop_
;
337 net::TestURLFetcherFactory test_fetcher_factory_
;
338 scoped_ptr
<FakeOAuth2TokenService
> fake_oauth2_token_service_
;
339 TestingPrefServiceSimple pref_service_
;
340 scoped_ptr
<AccountFetcherService
> account_fetcher_
;
341 scoped_ptr
<AccountTrackerService
> account_tracker_
;
342 scoped_ptr
<TestSigninClient
> signin_client_
;
345 void AccountTrackerServiceTest::ReturnOAuthUrlFetchResults(
347 net::HttpStatusCode response_code
,
348 const std::string
& response_string
) {
349 net::TestURLFetcher
* fetcher
=
350 test_fetcher_factory_
.GetFetcherByID(fetcher_id
);
351 ASSERT_TRUE(fetcher
);
352 fetcher
->set_response_code(response_code
);
353 fetcher
->SetResponseString(response_string
);
354 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
357 void AccountTrackerServiceTest::ReturnOAuthUrlFetchSuccess(
358 const std::string
& account_id
) {
359 IssueAccessToken(account_id
);
360 ReturnOAuthUrlFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId
,
362 GenerateValidTokenInfoResponse(account_id
));
365 void AccountTrackerServiceTest::ReturnOAuthUrlFetchSuccessIncomplete(
366 const std::string
& account_id
) {
367 IssueAccessToken(account_id
);
368 ReturnOAuthUrlFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId
,
370 GenerateIncompleteTokenInfoResponse(account_id
));
373 void AccountTrackerServiceTest::ReturnOAuthUrlFetchFailure(
374 const std::string
& account_id
) {
375 IssueAccessToken(account_id
);
376 ReturnOAuthUrlFetchResults(
377 gaia::GaiaOAuthClient::kUrlFetcherId
, net::HTTP_BAD_REQUEST
, "");
380 TEST_F(AccountTrackerServiceTest
, Basic
) {
383 TEST_F(AccountTrackerServiceTest
, TokenAvailable
) {
384 AccountTrackerObserver observer
;
385 account_tracker()->AddObserver(&observer
);
386 SimulateTokenAvailable("alpha");
387 ASSERT_FALSE(account_fetcher()->IsAllUserInfoFetched());
388 ASSERT_TRUE(observer
.CheckEvents());
389 account_tracker()->RemoveObserver(&observer
);
392 TEST_F(AccountTrackerServiceTest
, TokenAvailable_Revoked
) {
393 AccountTrackerObserver observer
;
394 account_tracker()->AddObserver(&observer
);
395 SimulateTokenAvailable("alpha");
396 SimulateTokenRevoked("alpha");
397 ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
398 ASSERT_TRUE(observer
.CheckEvents());
399 account_tracker()->RemoveObserver(&observer
);
402 TEST_F(AccountTrackerServiceTest
, TokenAvailable_UserInfo
) {
403 AccountTrackerObserver observer
;
404 account_tracker()->AddObserver(&observer
);
405 SimulateTokenAvailable("alpha");
406 ReturnOAuthUrlFetchSuccess("alpha");
407 ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
408 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, "alpha")));
409 account_tracker()->RemoveObserver(&observer
);
412 TEST_F(AccountTrackerServiceTest
, TokenAvailable_UserInfo_Revoked
) {
413 AccountTrackerObserver observer
;
414 account_tracker()->AddObserver(&observer
);
415 SimulateTokenAvailable("alpha");
416 ReturnOAuthUrlFetchSuccess("alpha");
417 ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
418 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, "alpha")));
419 SimulateTokenRevoked("alpha");
420 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(REMOVED
, "alpha")));
421 account_tracker()->RemoveObserver(&observer
);
424 TEST_F(AccountTrackerServiceTest
, TokenAvailable_UserInfoFailed
) {
425 AccountTrackerObserver observer
;
426 account_tracker()->AddObserver(&observer
);
427 SimulateTokenAvailable("alpha");
428 ReturnOAuthUrlFetchFailure("alpha");
429 ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
430 ASSERT_TRUE(observer
.CheckEvents());
431 account_tracker()->RemoveObserver(&observer
);
434 TEST_F(AccountTrackerServiceTest
, TokenAvailableTwice_UserInfoOnce
) {
435 AccountTrackerObserver observer
;
436 account_tracker()->AddObserver(&observer
);
437 SimulateTokenAvailable("alpha");
438 ReturnOAuthUrlFetchSuccess("alpha");
439 ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
440 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, "alpha")));
442 SimulateTokenAvailable("alpha");
443 ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
444 ASSERT_TRUE(observer
.CheckEvents());
445 account_tracker()->RemoveObserver(&observer
);
448 TEST_F(AccountTrackerServiceTest
, TokenAlreadyExists
) {
449 SimulateTokenAvailable("alpha");
450 AccountTrackerService tracker
;
451 AccountTrackerObserver observer
;
452 AccountFetcherService fetcher
;
454 tracker
.AddObserver(&observer
);
455 tracker
.Initialize(signin_client());
457 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
458 fetcher
.EnableNetworkFetches();
459 ASSERT_FALSE(fetcher
.IsAllUserInfoFetched());
460 ASSERT_TRUE(observer
.CheckEvents());
461 tracker
.RemoveObserver(&observer
);
466 TEST_F(AccountTrackerServiceTest
, TwoTokenAvailable_TwoUserInfo
) {
467 AccountTrackerObserver observer
;
468 account_tracker()->AddObserver(&observer
);
469 SimulateTokenAvailable("alpha");
470 SimulateTokenAvailable("beta");
471 ReturnOAuthUrlFetchSuccess("alpha");
472 ReturnOAuthUrlFetchSuccess("beta");
473 ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
474 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, "alpha"),
475 TrackingEvent(UPDATED
, "beta")));
476 account_tracker()->RemoveObserver(&observer
);
479 TEST_F(AccountTrackerServiceTest
, TwoTokenAvailable_OneUserInfo
) {
480 AccountTrackerObserver observer
;
481 account_tracker()->AddObserver(&observer
);
482 SimulateTokenAvailable("alpha");
483 SimulateTokenAvailable("beta");
484 ReturnOAuthUrlFetchSuccess("beta");
485 ASSERT_FALSE(account_fetcher()->IsAllUserInfoFetched());
486 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, "beta")));
487 ReturnOAuthUrlFetchSuccess("alpha");
488 ASSERT_TRUE(account_fetcher()->IsAllUserInfoFetched());
489 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, "alpha")));
490 account_tracker()->RemoveObserver(&observer
);
493 TEST_F(AccountTrackerServiceTest
, GetAccounts
) {
494 SimulateTokenAvailable("alpha");
495 SimulateTokenAvailable("beta");
496 SimulateTokenAvailable("gamma");
497 ReturnOAuthUrlFetchSuccess("alpha");
498 ReturnOAuthUrlFetchSuccess("beta");
499 ReturnOAuthUrlFetchSuccess("gamma");
501 std::vector
<AccountTrackerService::AccountInfo
> infos
=
502 account_tracker()->GetAccounts();
504 EXPECT_EQ(3u, infos
.size());
505 CheckAccountDetails("alpha", infos
[0]);
506 CheckAccountDetails("beta", infos
[1]);
507 CheckAccountDetails("gamma", infos
[2]);
510 TEST_F(AccountTrackerServiceTest
, GetAccountInfo_Empty
) {
511 AccountTrackerService::AccountInfo info
=
512 account_tracker()->GetAccountInfo("alpha");
513 ASSERT_EQ("", info
.account_id
);
516 TEST_F(AccountTrackerServiceTest
, GetAccountInfo_TokenAvailable
) {
517 SimulateTokenAvailable("alpha");
518 AccountTrackerService::AccountInfo info
=
519 account_tracker()->GetAccountInfo("alpha");
520 ASSERT_EQ("alpha", info
.account_id
);
521 ASSERT_EQ("", info
.gaia
);
522 ASSERT_EQ("", info
.email
);
525 TEST_F(AccountTrackerServiceTest
, GetAccountInfo_TokenAvailable_UserInfo
) {
526 SimulateTokenAvailable("alpha");
527 ReturnOAuthUrlFetchSuccess("alpha");
528 AccountTrackerService::AccountInfo info
=
529 account_tracker()->GetAccountInfo("alpha");
530 CheckAccountDetails("alpha", info
);
533 TEST_F(AccountTrackerServiceTest
, GetAccountInfo_TokenAvailable_EnableNetwork
) {
534 // Shutdown the network-enabled tracker built into the test case.
537 // Create an account tracker and an account fetcher service but do not enable
539 AccountTrackerService tracker
;
540 tracker
.Initialize(signin_client());
542 AccountFetcherService fetcher_service
;
543 fetcher_service
.Initialize(signin_client(), token_service(), &tracker
,
546 SimulateTokenAvailable("alpha");
547 IssueAccessToken("alpha");
548 // No fetcher has been created yet.
549 net::TestURLFetcher
* fetcher
= test_fetcher_factory()->GetFetcherByID(
550 gaia::GaiaOAuthClient::kUrlFetcherId
);
551 ASSERT_FALSE(fetcher
);
553 // Enable the network to create the fetcher then issue the access token.
554 fetcher_service
.EnableNetworkFetches();
556 // Fetcher was created and executes properly.
557 ReturnOAuthUrlFetchSuccess("alpha");
559 AccountTrackerService::AccountInfo info
=
560 tracker
.GetAccountInfo("alpha");
561 CheckAccountDetails("alpha", info
);
562 fetcher_service
.Shutdown();
566 TEST_F(AccountTrackerServiceTest
, FindAccountInfoByGaiaId
) {
567 SimulateTokenAvailable("alpha");
568 ReturnOAuthUrlFetchSuccess("alpha");
570 std::string gaia_id
= AccountIdToGaiaId("alpha");
571 AccountTrackerService::AccountInfo info
=
572 account_tracker()->FindAccountInfoByGaiaId(gaia_id
);
573 ASSERT_EQ("alpha", info
.account_id
);
574 ASSERT_EQ(gaia_id
, info
.gaia
);
576 gaia_id
= AccountIdToGaiaId("beta");
577 info
= account_tracker()->FindAccountInfoByGaiaId(gaia_id
);
578 ASSERT_EQ("", info
.account_id
);
581 TEST_F(AccountTrackerServiceTest
, FindAccountInfoByEmail
) {
582 SimulateTokenAvailable("alpha");
583 ReturnOAuthUrlFetchSuccess("alpha");
585 std::string email
= AccountIdToEmail("alpha");
586 AccountTrackerService::AccountInfo info
=
587 account_tracker()->FindAccountInfoByEmail(email
);
588 ASSERT_EQ("alpha", info
.account_id
);
589 ASSERT_EQ(email
, info
.email
);
591 // Should also work with "canonically-equal" email addresses.
592 info
= account_tracker()->FindAccountInfoByEmail("Alpha@Gmail.COM");
593 ASSERT_EQ("alpha", info
.account_id
);
594 ASSERT_EQ(email
, info
.email
);
595 info
= account_tracker()->FindAccountInfoByEmail("al.pha@gmail.com");
596 ASSERT_EQ("alpha", info
.account_id
);
597 ASSERT_EQ(email
, info
.email
);
599 email
= AccountIdToEmail("beta");
600 info
= account_tracker()->FindAccountInfoByEmail(email
);
601 ASSERT_EQ("", info
.account_id
);
604 TEST_F(AccountTrackerServiceTest
, Persistence
) {
605 // Create a tracker and add two accounts. This should cause the accounts
606 // to be saved to persistence.
608 AccountTrackerService tracker
;
609 tracker
.Initialize(signin_client());
610 SimulateTokenAvailable("alpha");
611 ReturnOAuthUrlFetchSuccess("alpha");
612 SimulateTokenAvailable("beta");
613 ReturnOAuthUrlFetchSuccess("beta");
617 // Create a new tracker and make sure it loads the accounts correctly from
620 AccountTrackerService tracker
;
621 AccountTrackerObserver observer
;
622 tracker
.AddObserver(&observer
);
623 tracker
.Initialize(signin_client());
624 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, "alpha"),
625 TrackingEvent(UPDATED
, "beta")));
626 tracker
.RemoveObserver(&observer
);
628 std::vector
<AccountTrackerService::AccountInfo
> infos
=
629 tracker
.GetAccounts();
630 ASSERT_EQ(2u, infos
.size());
631 CheckAccountDetails("alpha", infos
[0]);
632 CheckAccountDetails("beta", infos
[1]);
634 FakeAccountFetcherService fetcher
;
635 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
636 fetcher
.EnableNetworkFetches();
637 // Remove an account.
638 // This will allow testing removal as well as child accounts which is only
639 // allowed for a single account.
640 SimulateTokenRevoked("alpha");
641 fetcher
.FakeSetIsChildAccount("beta", true);
647 // Create a new tracker and make sure it loads the single account from
648 // persistence. Also verify it is a child account.
650 AccountTrackerService tracker
;
651 tracker
.Initialize(signin_client());
653 std::vector
<AccountTrackerService::AccountInfo
> infos
=
654 tracker
.GetAccounts();
655 ASSERT_EQ(1u, infos
.size());
656 CheckAccountDetails("beta", infos
[0]);
657 ASSERT_TRUE(infos
[0].is_child_account
);
662 TEST_F(AccountTrackerServiceTest
, SeedAccountInfo
) {
663 std::vector
<AccountTrackerService::AccountInfo
> infos
=
664 account_tracker()->GetAccounts();
665 EXPECT_EQ(0u, infos
.size());
667 const std::string gaia_id
= AccountIdToGaiaId("alpha");
668 const std::string email
= AccountIdToEmail("alpha");
669 const std::string account_id
=
670 account_tracker()->PickAccountIdForAccount(gaia_id
, email
);
671 account_tracker()->SeedAccountInfo(gaia_id
, email
);
673 infos
= account_tracker()->GetAccounts();
674 EXPECT_EQ(1u, infos
.size());
675 EXPECT_EQ(account_id
, infos
[0].account_id
);
676 EXPECT_EQ(gaia_id
, infos
[0].gaia
);
677 EXPECT_EQ(email
, infos
[0].email
);
680 TEST_F(AccountTrackerServiceTest
, UpgradeToFullAccountInfo
) {
681 // Start by simulating an incomplete account info and let it be saved to
684 AccountTrackerService tracker
;
685 tracker
.Initialize(signin_client());
686 AccountFetcherService fetcher
;
687 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
688 fetcher
.EnableNetworkFetches();
689 SimulateTokenAvailable("incomplete");
690 ReturnOAuthUrlFetchSuccessIncomplete("incomplete");
696 AccountTrackerService tracker
;
697 tracker
.Initialize(signin_client());
698 AccountFetcherService fetcher
;
699 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
700 // Validate that the loaded AccountInfo from prefs is considered invalid.
701 std::vector
<AccountTrackerService::AccountInfo
> infos
=
702 tracker
.GetAccounts();
703 ASSERT_EQ(1u, infos
.size());
704 ASSERT_FALSE(infos
[0].IsValid());
706 // Enable network fetches and simulate the same account getting a refresh
707 // token containing all the info.
708 fetcher
.EnableNetworkFetches();
709 SimulateTokenAvailable("incomplete");
710 ReturnOAuthUrlFetchSuccess("incomplete");
712 // Validate that the account is now considered valid.
713 infos
= tracker
.GetAccounts();
714 ASSERT_EQ(1u, infos
.size());
715 ASSERT_TRUE(infos
[0].IsValid());
721 // Reinstantiate a tracker to validate that the AccountInfo saved to prefs is
722 // now the upgraded one, considered valid.
724 AccountTrackerService tracker
;
725 AccountTrackerObserver observer
;
726 tracker
.AddObserver(&observer
);
727 tracker
.Initialize(signin_client());
728 AccountFetcherService fetcher
;
729 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
731 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, "incomplete")));
732 // Enabling network fetches shouldn't cause any actual fetch since the
733 // AccountInfos loaded from prefs should be valid.
734 fetcher
.EnableNetworkFetches();
736 std::vector
<AccountTrackerService::AccountInfo
> infos
=
737 tracker
.GetAccounts();
738 ASSERT_EQ(1u, infos
.size());
739 ASSERT_TRUE(infos
[0].IsValid());
740 // Check that no network fetches were made.
741 ASSERT_TRUE(observer
.CheckEvents());
743 tracker
.RemoveObserver(&observer
);
749 TEST_F(AccountTrackerServiceTest
, TimerRefresh
) {
750 // Start by creating a tracker and adding a couple accounts to be persisted to
753 AccountTrackerService tracker
;
754 tracker
.Initialize(signin_client());
755 AccountFetcherService fetcher
;
756 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
757 fetcher
.EnableNetworkFetches();
758 SimulateTokenAvailable("alpha");
759 ReturnOAuthUrlFetchSuccess("alpha");
760 SimulateTokenAvailable("beta");
761 ReturnOAuthUrlFetchSuccess("beta");
766 // Rewind the time by half a day, which shouldn't be enough to trigger a
768 base::Time fake_update
= base::Time::Now() - base::TimeDelta::FromHours(12);
769 signin_client()->GetPrefs()->SetInt64(
770 AccountFetcherService::kLastUpdatePref
,
771 fake_update
.ToInternalValue());
773 // Instantiate a new ATS, making sure the persisted accounts are still there
774 // and that no network fetches happen.
776 AccountTrackerService tracker
;
777 tracker
.Initialize(signin_client());
778 AccountFetcherService fetcher
;
779 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
781 ASSERT_TRUE(fetcher
.IsAllUserInfoFetched());
782 std::vector
<AccountTrackerService::AccountInfo
> infos
=
783 tracker
.GetAccounts();
784 ASSERT_EQ(2u, infos
.size());
785 ASSERT_TRUE(infos
[0].IsValid());
786 ASSERT_TRUE(infos
[1].IsValid());
788 fetcher
.EnableNetworkFetches();
789 ASSERT_TRUE(fetcher
.IsAllUserInfoFetched());
794 // Rewind the last updated time enough to trigger a network refresh.
795 fake_update
= base::Time::Now() - base::TimeDelta::FromHours(25);
796 signin_client()->GetPrefs()->SetInt64(
797 AccountFetcherService::kLastUpdatePref
,
798 fake_update
.ToInternalValue());
800 // Instantiate a new tracker and validate that even though the AccountInfos
801 // are still valid, the network fetches are started.
803 AccountTrackerService tracker
;
804 tracker
.Initialize(signin_client());
805 AccountFetcherService fetcher
;
806 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
808 ASSERT_TRUE(fetcher
.IsAllUserInfoFetched());
809 std::vector
<AccountTrackerService::AccountInfo
> infos
=
810 tracker
.GetAccounts();
811 ASSERT_EQ(2u, infos
.size());
812 ASSERT_TRUE(infos
[0].IsValid());
813 ASSERT_TRUE(infos
[1].IsValid());
815 fetcher
.EnableNetworkFetches();
816 ASSERT_FALSE(fetcher
.IsAllUserInfoFetched());
822 TEST_F(AccountTrackerServiceTest
, LegacyDottedAccountIds
) {
823 // Start by creating a tracker and adding an account with a dotted account id
824 // because of an old bug in token service. The token service would also add
825 // a correct non-dotted account id for the same account.
827 AccountTrackerService tracker
;
828 tracker
.Initialize(signin_client());
829 AccountFetcherService fetcher
;
830 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
831 fetcher
.EnableNetworkFetches();
832 SimulateTokenAvailable("foo.bar@gmail.com");
833 SimulateTokenAvailable("foobar@gmail.com");
834 ReturnOAuthUrlFetchSuccess("foo.bar@gmail.com");
835 ReturnOAuthUrlFetchSuccess("foobar@gmail.com");
840 // Remove the bad account now from the token service to simulate that it
842 SimulateTokenRevoked("foo.bar@gmail.com");
844 // Instantiate a new tracker and validate that it has only one account, and
845 // it is the correct non dotted one.
847 AccountTrackerService tracker
;
848 tracker
.Initialize(signin_client());
849 AccountFetcherService fetcher
;
850 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
852 ASSERT_TRUE(fetcher
.IsAllUserInfoFetched());
853 std::vector
<AccountTrackerService::AccountInfo
> infos
=
854 tracker
.GetAccounts();
855 ASSERT_EQ(1u, infos
.size());
856 ASSERT_STREQ("foobar@gmail.com", infos
[0].account_id
.c_str());
862 TEST_F(AccountTrackerServiceTest
, MigrateAccountIdToGaiaId
) {
863 if (account_tracker()->GetMigrationState() !=
864 AccountTrackerService::MIGRATION_NOT_STARTED
) {
865 AccountTrackerService tracker
;
866 TestingPrefServiceSimple pref
;
867 AccountTrackerService::AccountInfo account_info
;
869 std::string email_alpha
= AccountIdToEmail("alpha");
870 std::string gaia_alpha
= AccountIdToGaiaId("alpha");
871 std::string email_beta
= AccountIdToEmail("beta");
872 std::string gaia_beta
= AccountIdToGaiaId("beta");
874 pref
.registry()->RegisterListPref(AccountTrackerService::kAccountInfoPref
);
875 pref
.registry()->RegisterIntegerPref(
876 prefs::kAccountIdMigrationState
,
877 AccountTrackerService::MIGRATION_NOT_STARTED
);
879 ListPrefUpdate
update(&pref
, AccountTrackerService::kAccountInfoPref
);
881 base::DictionaryValue
* dict
= new base::DictionaryValue();
882 update
->Append(dict
);
883 dict
->SetString("account_id", base::UTF8ToUTF16(email_alpha
));
884 dict
->SetString("email", base::UTF8ToUTF16(email_alpha
));
885 dict
->SetString("gaia", base::UTF8ToUTF16(gaia_alpha
));
887 dict
= new base::DictionaryValue();
888 update
->Append(dict
);
889 dict
->SetString("account_id", base::UTF8ToUTF16(email_beta
));
890 dict
->SetString("email", base::UTF8ToUTF16(email_beta
));
891 dict
->SetString("gaia", base::UTF8ToUTF16(gaia_beta
));
893 scoped_ptr
<TestSigninClient
> client
;
894 client
.reset(new TestSigninClient(&pref
));
895 tracker
.Initialize(client
.get());
897 ASSERT_EQ(tracker
.GetMigrationState(),
898 AccountTrackerService::MIGRATION_IN_PROGRESS
);
900 account_info
= tracker
.GetAccountInfo(gaia_alpha
);
901 ASSERT_EQ(account_info
.account_id
, gaia_alpha
);
902 ASSERT_EQ(account_info
.gaia
, gaia_alpha
);
903 ASSERT_EQ(account_info
.email
, email_alpha
);
905 account_info
= tracker
.GetAccountInfo(gaia_beta
);
906 ASSERT_EQ(account_info
.account_id
, gaia_beta
);
907 ASSERT_EQ(account_info
.gaia
, gaia_beta
);
908 ASSERT_EQ(account_info
.email
, email_beta
);
910 std::vector
<AccountTrackerService::AccountInfo
> accounts
=
911 tracker
.GetAccounts();
912 ASSERT_EQ(2u, accounts
.size());
916 TEST_F(AccountTrackerServiceTest
, CanNotMigrateAccountIdToGaiaId
) {
917 if ((account_tracker()->GetMigrationState() !=
918 AccountTrackerService::MIGRATION_NOT_STARTED
)) {
919 AccountTrackerService tracker
;
920 TestingPrefServiceSimple pref
;
921 AccountTrackerService::AccountInfo account_info
;
923 std::string email_alpha
= AccountIdToEmail("alpha");
924 std::string gaia_alpha
= AccountIdToGaiaId("alpha");
925 std::string email_beta
= AccountIdToEmail("beta");
927 pref
.registry()->RegisterListPref(AccountTrackerService::kAccountInfoPref
);
928 pref
.registry()->RegisterIntegerPref(
929 prefs::kAccountIdMigrationState
,
930 AccountTrackerService::MIGRATION_NOT_STARTED
);
932 ListPrefUpdate
update(&pref
, AccountTrackerService::kAccountInfoPref
);
934 base::DictionaryValue
* dict
= new base::DictionaryValue();
935 update
->Append(dict
);
936 dict
->SetString("account_id", base::UTF8ToUTF16(email_alpha
));
937 dict
->SetString("email", base::UTF8ToUTF16(email_alpha
));
938 dict
->SetString("gaia", base::UTF8ToUTF16(gaia_alpha
));
940 dict
= new base::DictionaryValue();
941 update
->Append(dict
);
942 dict
->SetString("account_id", base::UTF8ToUTF16(email_beta
));
943 dict
->SetString("email", base::UTF8ToUTF16(email_beta
));
944 dict
->SetString("gaia", base::UTF8ToUTF16(std::string()));
946 scoped_ptr
<TestSigninClient
> client
;
947 client
.reset(new TestSigninClient(&pref
));
948 tracker
.Initialize(client
.get());
950 ASSERT_EQ(tracker
.GetMigrationState(),
951 AccountTrackerService::MIGRATION_NOT_STARTED
);
953 account_info
= tracker
.GetAccountInfo(email_alpha
);
954 ASSERT_EQ(account_info
.account_id
, email_alpha
);
955 ASSERT_EQ(account_info
.gaia
, gaia_alpha
);
956 ASSERT_EQ(account_info
.email
, email_alpha
);
958 account_info
= tracker
.GetAccountInfo(email_beta
);
959 ASSERT_EQ(account_info
.account_id
, email_beta
);
960 ASSERT_EQ(account_info
.email
, email_beta
);
962 std::vector
<AccountTrackerService::AccountInfo
> accounts
=
963 tracker
.GetAccounts();
964 ASSERT_EQ(2u, accounts
.size());
968 TEST_F(AccountTrackerServiceTest
, GaiaIdMigrationCrashInTheMiddle
) {
969 if (account_tracker()->GetMigrationState() !=
970 AccountTrackerService::MIGRATION_NOT_STARTED
) {
971 AccountTrackerService tracker
;
972 TestingPrefServiceSimple pref
;
973 AccountTrackerService::AccountInfo account_info
;
975 std::string email_alpha
= AccountIdToEmail("alpha");
976 std::string gaia_alpha
= AccountIdToGaiaId("alpha");
977 std::string email_beta
= AccountIdToEmail("beta");
978 std::string gaia_beta
= AccountIdToGaiaId("beta");
980 pref
.registry()->RegisterListPref(AccountTrackerService::kAccountInfoPref
);
981 pref
.registry()->RegisterIntegerPref(
982 prefs::kAccountIdMigrationState
,
983 AccountTrackerService::MIGRATION_IN_PROGRESS
);
985 ListPrefUpdate
update(&pref
, AccountTrackerService::kAccountInfoPref
);
987 base::DictionaryValue
* dict
= new base::DictionaryValue();
988 update
->Append(dict
);
989 dict
->SetString("account_id", base::UTF8ToUTF16(email_alpha
));
990 dict
->SetString("email", base::UTF8ToUTF16(email_alpha
));
991 dict
->SetString("gaia", base::UTF8ToUTF16(gaia_alpha
));
993 dict
= new base::DictionaryValue();
994 update
->Append(dict
);
995 dict
->SetString("account_id", base::UTF8ToUTF16(email_beta
));
996 dict
->SetString("email", base::UTF8ToUTF16(email_beta
));
997 dict
->SetString("gaia", base::UTF8ToUTF16(gaia_beta
));
999 // Succeed miggrated account.
1000 dict
= new base::DictionaryValue();
1001 update
->Append(dict
);
1002 dict
->SetString("account_id", base::UTF8ToUTF16(gaia_alpha
));
1003 dict
->SetString("email", base::UTF8ToUTF16(email_alpha
));
1004 dict
->SetString("gaia", base::UTF8ToUTF16(gaia_alpha
));
1006 scoped_ptr
<TestSigninClient
> client
;
1007 client
.reset(new TestSigninClient(&pref
));
1008 tracker
.Initialize(client
.get());
1010 ASSERT_EQ(tracker
.GetMigrationState(),
1011 AccountTrackerService::MIGRATION_IN_PROGRESS
);
1013 account_info
= tracker
.GetAccountInfo(gaia_alpha
);
1014 ASSERT_EQ(account_info
.account_id
, gaia_alpha
);
1015 ASSERT_EQ(account_info
.gaia
, gaia_alpha
);
1016 ASSERT_EQ(account_info
.email
, email_alpha
);
1018 account_info
= tracker
.GetAccountInfo(gaia_beta
);
1019 ASSERT_EQ(account_info
.account_id
, gaia_beta
);
1020 ASSERT_EQ(account_info
.gaia
, gaia_beta
);
1021 ASSERT_EQ(account_info
.email
, email_beta
);
1023 std::vector
<AccountTrackerService::AccountInfo
> accounts
=
1024 tracker
.GetAccounts();
1025 ASSERT_EQ(2u, accounts
.size());
1027 tracker
.SetMigrationDone();
1029 tracker
.Initialize(client
.get());
1031 ASSERT_EQ(tracker
.GetMigrationState(),
1032 AccountTrackerService::MIGRATION_DONE
);
1034 account_info
= tracker
.GetAccountInfo(gaia_alpha
);
1035 ASSERT_EQ(account_info
.account_id
, gaia_alpha
);
1036 ASSERT_EQ(account_info
.gaia
, gaia_alpha
);
1037 ASSERT_EQ(account_info
.email
, email_alpha
);
1039 account_info
= tracker
.GetAccountInfo(gaia_beta
);
1040 ASSERT_EQ(account_info
.account_id
, gaia_beta
);
1041 ASSERT_EQ(account_info
.gaia
, gaia_beta
);
1042 ASSERT_EQ(account_info
.email
, email_beta
);
1045 accounts
= tracker
.GetAccounts();
1046 ASSERT_EQ(2u, accounts
.size());
1050 TEST_F(AccountTrackerServiceTest
, ChildAccountBasic
) {
1051 AccountTrackerService tracker
;
1052 tracker
.Initialize(signin_client());
1053 FakeAccountFetcherService fetcher
;
1054 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
1055 fetcher
.EnableNetworkFetches();
1056 AccountTrackerObserver observer
;
1057 tracker
.AddObserver(&observer
);
1058 std::string
child_id("child");
1060 // Responses are processed iff there is a single account with a valid token
1061 // and the response is for that account.
1062 fetcher
.FakeSetIsChildAccount(child_id
, true);
1063 ASSERT_TRUE(observer
.CheckEvents());
1066 SimulateTokenAvailable(child_id
);
1067 IssueAccessToken(child_id
);
1068 fetcher
.FakeSetIsChildAccount(child_id
, true);
1069 // Response was processed but observer is not notified as the account state
1071 ASSERT_TRUE(observer
.CheckEvents());
1072 AccountTrackerService::AccountInfo info
= tracker
.GetAccountInfo(child_id
);
1073 ASSERT_TRUE(info
.is_child_account
);
1074 SimulateTokenRevoked(child_id
);
1076 tracker
.RemoveObserver(&observer
);
1081 TEST_F(AccountTrackerServiceTest
, ChildAccountUpdatedAndRevoked
) {
1082 AccountTrackerService tracker
;
1083 tracker
.Initialize(signin_client());
1084 FakeAccountFetcherService fetcher
;
1085 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
1086 fetcher
.EnableNetworkFetches();
1087 AccountTrackerObserver observer
;
1088 tracker
.AddObserver(&observer
);
1089 std::string
child_id("child");
1091 SimulateTokenAvailable(child_id
);
1092 IssueAccessToken(child_id
);
1093 fetcher
.FakeSetIsChildAccount(child_id
, false);
1094 FakeUserInfoFetchSuccess(&fetcher
, child_id
);
1095 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, child_id
)));
1096 AccountTrackerService::AccountInfo info
= tracker
.GetAccountInfo(child_id
);
1097 ASSERT_FALSE(info
.is_child_account
);
1098 SimulateTokenRevoked(child_id
);
1099 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(REMOVED
, child_id
)));
1101 tracker
.RemoveObserver(&observer
);
1106 TEST_F(AccountTrackerServiceTest
, ChildAccountUpdatedAndRevokedWithUpdate
) {
1107 AccountTrackerService tracker
;
1108 tracker
.Initialize(signin_client());
1109 FakeAccountFetcherService fetcher
;
1110 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
1111 fetcher
.EnableNetworkFetches();
1112 AccountTrackerObserver observer
;
1113 tracker
.AddObserver(&observer
);
1114 std::string
child_id("child");
1116 SimulateTokenAvailable(child_id
);
1117 IssueAccessToken(child_id
);
1118 fetcher
.FakeSetIsChildAccount(child_id
, true);
1119 FakeUserInfoFetchSuccess(&fetcher
, child_id
);
1120 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, child_id
)));
1121 AccountTrackerService::AccountInfo info
= tracker
.GetAccountInfo(child_id
);
1122 ASSERT_TRUE(info
.is_child_account
);
1123 SimulateTokenRevoked(child_id
);
1124 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, child_id
),
1125 TrackingEvent(REMOVED
, child_id
)));
1127 tracker
.RemoveObserver(&observer
);
1132 TEST_F(AccountTrackerServiceTest
, ChildAccountUpdatedTwiceThenRevoked
) {
1133 AccountTrackerService tracker
;
1134 tracker
.Initialize(signin_client());
1135 FakeAccountFetcherService fetcher
;
1136 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
1137 fetcher
.EnableNetworkFetches();
1138 AccountTrackerObserver observer
;
1139 tracker
.AddObserver(&observer
);
1140 std::string
child_id("child");
1142 SimulateTokenAvailable(child_id
);
1143 IssueAccessToken(child_id
);
1144 // Observers notified the first time.
1145 FakeUserInfoFetchSuccess(&fetcher
, child_id
);
1146 // Since the account state is already valid, this will notify the
1147 // observers for the second time.
1148 fetcher
.FakeSetIsChildAccount(child_id
, true);
1149 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, child_id
),
1150 TrackingEvent(UPDATED
, child_id
)));
1151 SimulateTokenRevoked(child_id
);
1152 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, child_id
),
1153 TrackingEvent(REMOVED
, child_id
)));
1155 tracker
.RemoveObserver(&observer
);
1160 TEST_F(AccountTrackerServiceTest
, ChildAccountGraduation
) {
1161 AccountTrackerService tracker
;
1162 tracker
.Initialize(signin_client());
1163 FakeAccountFetcherService fetcher
;
1164 fetcher
.Initialize(signin_client(), token_service(), &tracker
, nullptr);
1165 fetcher
.EnableNetworkFetches();
1166 AccountTrackerObserver observer
;
1167 tracker
.AddObserver(&observer
);
1168 std::string
child_id("child");
1170 SimulateTokenAvailable(child_id
);
1171 IssueAccessToken(child_id
);
1173 // Set and verify this is a child account.
1174 fetcher
.FakeSetIsChildAccount(child_id
, true);
1175 AccountTrackerService::AccountInfo info
= tracker
.GetAccountInfo(child_id
);
1176 ASSERT_TRUE(info
.is_child_account
);
1177 FakeUserInfoFetchSuccess(&fetcher
, child_id
);
1178 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, child_id
)));
1180 // Now simulate child account graduation.
1181 fetcher
.FakeSetIsChildAccount(child_id
, false);
1182 info
= tracker
.GetAccountInfo(child_id
);
1183 ASSERT_FALSE(info
.is_child_account
);
1184 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(UPDATED
, child_id
)));
1186 SimulateTokenRevoked(child_id
);
1187 ASSERT_TRUE(observer
.CheckEvents(TrackingEvent(REMOVED
, child_id
)));
1189 tracker
.RemoveObserver(&observer
);