• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "google_apis/gaia/account_tracker.h"
6 
7 #include <algorithm>
8 #include <vector>
9 
10 #include "base/message_loop/message_loop.h"
11 #include "base/strings/stringprintf.h"
12 #include "google_apis/gaia/fake_identity_provider.h"
13 #include "google_apis/gaia/fake_oauth2_token_service.h"
14 #include "google_apis/gaia/gaia_oauth_client.h"
15 #include "net/http/http_status_code.h"
16 #include "net/url_request/test_url_fetcher_factory.h"
17 #include "net/url_request/url_fetcher_delegate.h"
18 #include "net/url_request/url_request_test_util.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 
21 namespace {
22 
23 const char kPrimaryAccountKey[] = "primary_account@example.com";
24 
25 enum TrackingEventType {
26   ADDED,
27   REMOVED,
28   SIGN_IN,
29   SIGN_OUT
30 };
31 
AccountKeyToObfuscatedId(const std::string email)32 std::string AccountKeyToObfuscatedId(const std::string email) {
33   return "obfid-" + email;
34 }
35 
36 class TrackingEvent {
37  public:
TrackingEvent(TrackingEventType type,const std::string & account_key,const std::string & gaia_id)38   TrackingEvent(TrackingEventType type,
39                 const std::string& account_key,
40                 const std::string& gaia_id)
41       : type_(type),
42         account_key_(account_key),
43         gaia_id_(gaia_id) {}
44 
TrackingEvent(TrackingEventType type,const std::string & account_key)45   TrackingEvent(TrackingEventType type,
46                 const std::string& account_key)
47       : type_(type),
48         account_key_(account_key),
49         gaia_id_(AccountKeyToObfuscatedId(account_key)) {}
50 
operator ==(const TrackingEvent & event) const51   bool operator==(const TrackingEvent& event) const {
52     return type_ == event.type_ && account_key_ == event.account_key_ &&
53         gaia_id_ == event.gaia_id_;
54   }
55 
ToString() const56   std::string ToString() const {
57     const char * typestr = "INVALID";
58     switch (type_) {
59       case ADDED:
60         typestr = "ADD";
61         break;
62       case REMOVED:
63         typestr = "REM";
64         break;
65       case SIGN_IN:
66         typestr = " IN";
67         break;
68       case SIGN_OUT:
69         typestr = "OUT";
70         break;
71     }
72     return base::StringPrintf("{ type: %s, email: %s, gaia: %s }",
73                               typestr,
74                               account_key_.c_str(),
75                               gaia_id_.c_str());
76   }
77 
78  private:
79   friend bool CompareByUser(TrackingEvent a, TrackingEvent b);
80 
81   TrackingEventType type_;
82   std::string account_key_;
83   std::string gaia_id_;
84 };
85 
CompareByUser(TrackingEvent a,TrackingEvent b)86 bool CompareByUser(TrackingEvent a, TrackingEvent b) {
87   return a.account_key_ < b.account_key_;
88 }
89 
Str(const std::vector<TrackingEvent> & events)90 std::string Str(const std::vector<TrackingEvent>& events) {
91   std::string str = "[";
92   bool needs_comma = false;
93   for (std::vector<TrackingEvent>::const_iterator it =
94        events.begin(); it != events.end(); ++it) {
95     if (needs_comma)
96       str += ",\n ";
97     needs_comma = true;
98     str += it->ToString();
99   }
100   str += "]";
101   return str;
102 }
103 
104 }  // namespace
105 
106 namespace gaia {
107 
108 class AccountTrackerObserver : public AccountTracker::Observer {
109  public:
AccountTrackerObserver()110   AccountTrackerObserver() {}
~AccountTrackerObserver()111   virtual ~AccountTrackerObserver() {}
112 
113   testing::AssertionResult CheckEvents();
114   testing::AssertionResult CheckEvents(const TrackingEvent& e1);
115   testing::AssertionResult CheckEvents(const TrackingEvent& e1,
116                                        const TrackingEvent& e2);
117   testing::AssertionResult CheckEvents(const TrackingEvent& e1,
118                                        const TrackingEvent& e2,
119                                        const TrackingEvent& e3);
120   testing::AssertionResult CheckEvents(const TrackingEvent& e1,
121                                        const TrackingEvent& e2,
122                                        const TrackingEvent& e3,
123                                        const TrackingEvent& e4);
124   testing::AssertionResult CheckEvents(const TrackingEvent& e1,
125                                        const TrackingEvent& e2,
126                                        const TrackingEvent& e3,
127                                        const TrackingEvent& e4,
128                                        const TrackingEvent& e5);
129   testing::AssertionResult CheckEvents(const TrackingEvent& e1,
130                                        const TrackingEvent& e2,
131                                        const TrackingEvent& e3,
132                                        const TrackingEvent& e4,
133                                        const TrackingEvent& e5,
134                                        const TrackingEvent& e6);
135   void Clear();
136   void SortEventsByUser();
137 
138   // AccountTracker::Observer implementation
139   virtual void OnAccountAdded(const AccountIds& ids) OVERRIDE;
140   virtual void OnAccountRemoved(const AccountIds& ids) OVERRIDE;
141   virtual void OnAccountSignInChanged(const AccountIds& ids, bool is_signed_in)
142       OVERRIDE;
143 
144  private:
145   testing::AssertionResult CheckEvents(
146       const std::vector<TrackingEvent>& events);
147 
148   std::vector<TrackingEvent> events_;
149 };
150 
OnAccountAdded(const AccountIds & ids)151 void AccountTrackerObserver::OnAccountAdded(const AccountIds& ids) {
152   events_.push_back(TrackingEvent(ADDED, ids.email, ids.gaia));
153 }
154 
OnAccountRemoved(const AccountIds & ids)155 void AccountTrackerObserver::OnAccountRemoved(const AccountIds& ids) {
156   events_.push_back(TrackingEvent(REMOVED, ids.email, ids.gaia));
157 }
158 
OnAccountSignInChanged(const AccountIds & ids,bool is_signed_in)159 void AccountTrackerObserver::OnAccountSignInChanged(const AccountIds& ids,
160                                                     bool is_signed_in) {
161   events_.push_back(
162       TrackingEvent(is_signed_in ? SIGN_IN : SIGN_OUT, ids.email, ids.gaia));
163 }
164 
Clear()165 void AccountTrackerObserver::Clear() {
166   events_.clear();
167 }
168 
SortEventsByUser()169 void AccountTrackerObserver::SortEventsByUser() {
170   std::stable_sort(events_.begin(), events_.end(), CompareByUser);
171 }
172 
CheckEvents()173 testing::AssertionResult AccountTrackerObserver::CheckEvents() {
174   std::vector<TrackingEvent> events;
175   return CheckEvents(events);
176 }
177 
CheckEvents(const TrackingEvent & e1)178 testing::AssertionResult AccountTrackerObserver::CheckEvents(
179     const TrackingEvent& e1) {
180   std::vector<TrackingEvent> events;
181   events.push_back(e1);
182   return CheckEvents(events);
183 }
184 
CheckEvents(const TrackingEvent & e1,const TrackingEvent & e2)185 testing::AssertionResult AccountTrackerObserver::CheckEvents(
186     const TrackingEvent& e1,
187     const TrackingEvent& e2) {
188   std::vector<TrackingEvent> events;
189   events.push_back(e1);
190   events.push_back(e2);
191   return CheckEvents(events);
192 }
193 
CheckEvents(const TrackingEvent & e1,const TrackingEvent & e2,const TrackingEvent & e3)194 testing::AssertionResult AccountTrackerObserver::CheckEvents(
195     const TrackingEvent& e1,
196     const TrackingEvent& e2,
197     const TrackingEvent& e3) {
198   std::vector<TrackingEvent> events;
199   events.push_back(e1);
200   events.push_back(e2);
201   events.push_back(e3);
202   return CheckEvents(events);
203 }
204 
CheckEvents(const TrackingEvent & e1,const TrackingEvent & e2,const TrackingEvent & e3,const TrackingEvent & e4)205 testing::AssertionResult AccountTrackerObserver::CheckEvents(
206     const TrackingEvent& e1,
207     const TrackingEvent& e2,
208     const TrackingEvent& e3,
209     const TrackingEvent& e4) {
210   std::vector<TrackingEvent> events;
211   events.push_back(e1);
212   events.push_back(e2);
213   events.push_back(e3);
214   events.push_back(e4);
215   return CheckEvents(events);
216 }
217 
CheckEvents(const TrackingEvent & e1,const TrackingEvent & e2,const TrackingEvent & e3,const TrackingEvent & e4,const TrackingEvent & e5)218 testing::AssertionResult AccountTrackerObserver::CheckEvents(
219     const TrackingEvent& e1,
220     const TrackingEvent& e2,
221     const TrackingEvent& e3,
222     const TrackingEvent& e4,
223     const TrackingEvent& e5) {
224   std::vector<TrackingEvent> events;
225   events.push_back(e1);
226   events.push_back(e2);
227   events.push_back(e3);
228   events.push_back(e4);
229   events.push_back(e5);
230   return CheckEvents(events);
231 }
232 
CheckEvents(const TrackingEvent & e1,const TrackingEvent & e2,const TrackingEvent & e3,const TrackingEvent & e4,const TrackingEvent & e5,const TrackingEvent & e6)233 testing::AssertionResult AccountTrackerObserver::CheckEvents(
234     const TrackingEvent& e1,
235     const TrackingEvent& e2,
236     const TrackingEvent& e3,
237     const TrackingEvent& e4,
238     const TrackingEvent& e5,
239     const TrackingEvent& e6) {
240   std::vector<TrackingEvent> events;
241   events.push_back(e1);
242   events.push_back(e2);
243   events.push_back(e3);
244   events.push_back(e4);
245   events.push_back(e5);
246   events.push_back(e6);
247   return CheckEvents(events);
248 }
249 
CheckEvents(const std::vector<TrackingEvent> & events)250 testing::AssertionResult AccountTrackerObserver::CheckEvents(
251     const std::vector<TrackingEvent>& events) {
252   std::string maybe_newline = (events.size() + events_.size()) > 2 ? "\n" : "";
253   testing::AssertionResult result(
254       (events_ == events)
255           ? testing::AssertionSuccess()
256           : (testing::AssertionFailure()
257              << "Expected " << maybe_newline << Str(events) << ", "
258              << maybe_newline << "Got " << maybe_newline << Str(events_)));
259   events_.clear();
260   return result;
261 }
262 
263 class IdentityAccountTrackerTest : public testing::Test {
264  public:
IdentityAccountTrackerTest()265   IdentityAccountTrackerTest() {}
266 
~IdentityAccountTrackerTest()267   virtual ~IdentityAccountTrackerTest() {}
268 
SetUp()269   virtual void SetUp() OVERRIDE {
270 
271     fake_oauth2_token_service_.reset(new FakeOAuth2TokenService());
272 
273     fake_identity_provider_.reset(
274         new FakeIdentityProvider(fake_oauth2_token_service_.get()));
275 
276     account_tracker_.reset(
277         new AccountTracker(fake_identity_provider_.get(),
278                            new net::TestURLRequestContextGetter(
279                                message_loop_.message_loop_proxy())));
280     account_tracker_->AddObserver(&observer_);
281   }
282 
TearDown()283   virtual void TearDown() OVERRIDE {
284     account_tracker_->RemoveObserver(&observer_);
285     account_tracker_->Shutdown();
286   }
287 
observer()288   AccountTrackerObserver* observer() {
289     return &observer_;
290   }
291 
account_tracker()292   AccountTracker* account_tracker() {
293     return account_tracker_.get();
294   }
295 
296   // Helpers to pass fake events to the tracker.
297 
NotifyLogin(const std::string account_key)298   void NotifyLogin(const std::string account_key) {
299     identity_provider()->LogIn(account_key);
300   }
301 
NotifyLogout()302   void NotifyLogout() { identity_provider()->LogOut(); }
303 
NotifyTokenAvailable(const std::string & username)304   void NotifyTokenAvailable(const std::string& username) {
305     fake_oauth2_token_service_->AddAccount(username);
306   }
307 
NotifyTokenRevoked(const std::string & username)308   void NotifyTokenRevoked(const std::string& username) {
309     fake_oauth2_token_service_->RemoveAccount(username);
310   }
311 
312   // Helpers to fake access token and user info fetching
IssueAccessToken(const std::string & username)313   void IssueAccessToken(const std::string& username) {
314     fake_oauth2_token_service_->IssueAllTokensForAccount(
315         username, "access_token-" + username, base::Time::Max());
316   }
317 
GetValidTokenInfoResponse(const std::string account_key)318   std::string GetValidTokenInfoResponse(const std::string account_key) {
319     return std::string("{ \"id\": \"") + AccountKeyToObfuscatedId(account_key) +
320            "\" }";
321   }
322 
323   void ReturnOAuthUrlFetchResults(int fetcher_id,
324                                   net::HttpStatusCode response_code,
325                                   const std::string& response_string);
326 
327   void ReturnOAuthUrlFetchSuccess(const std::string& account_key);
328   void ReturnOAuthUrlFetchFailure(const std::string& account_key);
329 
SetupPrimaryLogin()330   void SetupPrimaryLogin() {
331     // Initial setup for tests that start with a signed in profile.
332     NotifyLogin(kPrimaryAccountKey);
333     NotifyTokenAvailable(kPrimaryAccountKey);
334     ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
335     observer()->Clear();
336   }
337 
active_account_id()338   std::string active_account_id() {
339     return identity_provider()->GetActiveAccountId();
340   }
341 
342  private:
identity_provider()343   FakeIdentityProvider* identity_provider() {
344     return static_cast<FakeIdentityProvider*>(
345         account_tracker_->identity_provider());
346   }
347 
348   base::MessageLoopForIO message_loop_;  // net:: stuff needs IO message loop.
349   net::TestURLFetcherFactory test_fetcher_factory_;
350   scoped_ptr<FakeOAuth2TokenService> fake_oauth2_token_service_;
351   scoped_ptr<FakeIdentityProvider> fake_identity_provider_;
352 
353   scoped_ptr<AccountTracker> account_tracker_;
354   AccountTrackerObserver observer_;
355 };
356 
ReturnOAuthUrlFetchResults(int fetcher_id,net::HttpStatusCode response_code,const std::string & response_string)357 void IdentityAccountTrackerTest::ReturnOAuthUrlFetchResults(
358     int fetcher_id,
359     net::HttpStatusCode response_code,
360     const std::string&  response_string) {
361 
362   net::TestURLFetcher* fetcher =
363       test_fetcher_factory_.GetFetcherByID(fetcher_id);
364   ASSERT_TRUE(fetcher);
365   fetcher->set_response_code(response_code);
366   fetcher->SetResponseString(response_string);
367   fetcher->delegate()->OnURLFetchComplete(fetcher);
368 }
369 
ReturnOAuthUrlFetchSuccess(const std::string & account_key)370 void IdentityAccountTrackerTest::ReturnOAuthUrlFetchSuccess(
371     const std::string& account_key) {
372   IssueAccessToken(account_key);
373   ReturnOAuthUrlFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId,
374                              net::HTTP_OK,
375                              GetValidTokenInfoResponse(account_key));
376 }
377 
ReturnOAuthUrlFetchFailure(const std::string & account_key)378 void IdentityAccountTrackerTest::ReturnOAuthUrlFetchFailure(
379     const std::string& account_key) {
380   IssueAccessToken(account_key);
381   ReturnOAuthUrlFetchResults(
382       gaia::GaiaOAuthClient::kUrlFetcherId, net::HTTP_BAD_REQUEST, "");
383 }
384 
385 // Primary tests just involve the Active account
386 
TEST_F(IdentityAccountTrackerTest,PrimaryNoEventsBeforeLogin)387 TEST_F(IdentityAccountTrackerTest, PrimaryNoEventsBeforeLogin) {
388   NotifyTokenAvailable(kPrimaryAccountKey);
389   NotifyTokenRevoked(kPrimaryAccountKey);
390   NotifyLogout();
391   EXPECT_TRUE(observer()->CheckEvents());
392 }
393 
TEST_F(IdentityAccountTrackerTest,PrimaryLoginThenTokenAvailable)394 TEST_F(IdentityAccountTrackerTest, PrimaryLoginThenTokenAvailable) {
395   NotifyLogin(kPrimaryAccountKey);
396   NotifyTokenAvailable(kPrimaryAccountKey);
397   EXPECT_TRUE(observer()->CheckEvents());
398 
399   ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
400   EXPECT_TRUE(
401       observer()->CheckEvents(TrackingEvent(ADDED, kPrimaryAccountKey),
402                               TrackingEvent(SIGN_IN, kPrimaryAccountKey)));
403 }
404 
TEST_F(IdentityAccountTrackerTest,PrimaryTokenAvailableThenLogin)405 TEST_F(IdentityAccountTrackerTest, PrimaryTokenAvailableThenLogin) {
406   NotifyTokenAvailable(kPrimaryAccountKey);
407   EXPECT_TRUE(observer()->CheckEvents());
408 
409   NotifyLogin(kPrimaryAccountKey);
410   ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
411   EXPECT_TRUE(
412       observer()->CheckEvents(TrackingEvent(ADDED, kPrimaryAccountKey),
413                               TrackingEvent(SIGN_IN, kPrimaryAccountKey)));
414 }
415 
TEST_F(IdentityAccountTrackerTest,PrimaryTokenAvailableAndRevokedThenLogin)416 TEST_F(IdentityAccountTrackerTest, PrimaryTokenAvailableAndRevokedThenLogin) {
417   NotifyTokenAvailable(kPrimaryAccountKey);
418   EXPECT_TRUE(observer()->CheckEvents());
419 
420   NotifyLogin(kPrimaryAccountKey);
421   ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
422   EXPECT_TRUE(
423       observer()->CheckEvents(TrackingEvent(ADDED, kPrimaryAccountKey),
424                               TrackingEvent(SIGN_IN, kPrimaryAccountKey)));
425 }
426 
TEST_F(IdentityAccountTrackerTest,PrimaryRevokeThenLogout)427 TEST_F(IdentityAccountTrackerTest, PrimaryRevokeThenLogout) {
428   NotifyLogin(kPrimaryAccountKey);
429   NotifyTokenAvailable(kPrimaryAccountKey);
430   ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
431   observer()->Clear();
432 
433   NotifyTokenRevoked(kPrimaryAccountKey);
434   EXPECT_TRUE(
435       observer()->CheckEvents(TrackingEvent(SIGN_OUT, kPrimaryAccountKey)));
436 
437   NotifyLogout();
438   EXPECT_TRUE(
439       observer()->CheckEvents(TrackingEvent(REMOVED, kPrimaryAccountKey)));
440 }
441 
TEST_F(IdentityAccountTrackerTest,PrimaryRevokeThenLogin)442 TEST_F(IdentityAccountTrackerTest, PrimaryRevokeThenLogin) {
443   NotifyLogin(kPrimaryAccountKey);
444   NotifyTokenAvailable(kPrimaryAccountKey);
445   ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
446   NotifyTokenRevoked(kPrimaryAccountKey);
447   observer()->Clear();
448 
449   NotifyLogin(kPrimaryAccountKey);
450   EXPECT_TRUE(observer()->CheckEvents());
451 }
452 
TEST_F(IdentityAccountTrackerTest,PrimaryRevokeThenTokenAvailable)453 TEST_F(IdentityAccountTrackerTest, PrimaryRevokeThenTokenAvailable) {
454   NotifyLogin(kPrimaryAccountKey);
455   NotifyTokenAvailable(kPrimaryAccountKey);
456   ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
457   NotifyTokenRevoked(kPrimaryAccountKey);
458   observer()->Clear();
459 
460   NotifyTokenAvailable(kPrimaryAccountKey);
461   EXPECT_TRUE(
462       observer()->CheckEvents(TrackingEvent(SIGN_IN, kPrimaryAccountKey)));
463 }
464 
TEST_F(IdentityAccountTrackerTest,PrimaryLogoutThenRevoke)465 TEST_F(IdentityAccountTrackerTest, PrimaryLogoutThenRevoke) {
466   NotifyLogin(kPrimaryAccountKey);
467   NotifyTokenAvailable(kPrimaryAccountKey);
468   ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
469   observer()->Clear();
470 
471   NotifyLogout();
472   EXPECT_TRUE(
473       observer()->CheckEvents(TrackingEvent(SIGN_OUT, kPrimaryAccountKey),
474                               TrackingEvent(REMOVED, kPrimaryAccountKey)));
475 
476   NotifyTokenRevoked(kPrimaryAccountKey);
477   EXPECT_TRUE(observer()->CheckEvents());
478 }
479 
TEST_F(IdentityAccountTrackerTest,PrimaryLogoutFetchCancelAvailable)480 TEST_F(IdentityAccountTrackerTest, PrimaryLogoutFetchCancelAvailable) {
481   NotifyLogin(kPrimaryAccountKey);
482   NotifyTokenAvailable(kPrimaryAccountKey);
483   // TokenAvailable kicks off a fetch. Logout without satisfying it.
484   NotifyLogout();
485   EXPECT_TRUE(observer()->CheckEvents());
486 
487   NotifyLogin(kPrimaryAccountKey);
488   NotifyTokenAvailable(kPrimaryAccountKey);
489   ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
490   EXPECT_TRUE(observer()->CheckEvents(
491       TrackingEvent(ADDED, kPrimaryAccountKey),
492       TrackingEvent(SIGN_IN, kPrimaryAccountKey)));
493 }
494 
495 // Non-primary accounts
496 
TEST_F(IdentityAccountTrackerTest,Available)497 TEST_F(IdentityAccountTrackerTest, Available) {
498   SetupPrimaryLogin();
499 
500   NotifyTokenAvailable("user@example.com");
501   EXPECT_TRUE(observer()->CheckEvents());
502 
503   ReturnOAuthUrlFetchSuccess("user@example.com");
504   EXPECT_TRUE(observer()->CheckEvents(
505       TrackingEvent(ADDED, "user@example.com"),
506       TrackingEvent(SIGN_IN, "user@example.com")));
507 }
508 
TEST_F(IdentityAccountTrackerTest,Revoke)509 TEST_F(IdentityAccountTrackerTest, Revoke) {
510   SetupPrimaryLogin();
511 
512   account_tracker()->OnRefreshTokenRevoked("user@example.com");
513   EXPECT_TRUE(observer()->CheckEvents());
514 }
515 
TEST_F(IdentityAccountTrackerTest,AvailableRevokeAvailable)516 TEST_F(IdentityAccountTrackerTest, AvailableRevokeAvailable) {
517   SetupPrimaryLogin();
518 
519   NotifyTokenAvailable("user@example.com");
520   ReturnOAuthUrlFetchSuccess("user@example.com");
521   NotifyTokenRevoked("user@example.com");
522   EXPECT_TRUE(observer()->CheckEvents(
523       TrackingEvent(ADDED, "user@example.com"),
524       TrackingEvent(SIGN_IN, "user@example.com"),
525       TrackingEvent(SIGN_OUT, "user@example.com")));
526 
527   NotifyTokenAvailable("user@example.com");
528   EXPECT_TRUE(observer()->CheckEvents(
529       TrackingEvent(SIGN_IN, "user@example.com")));
530 }
531 
TEST_F(IdentityAccountTrackerTest,AvailableRevokeAvailableWithPendingFetch)532 TEST_F(IdentityAccountTrackerTest, AvailableRevokeAvailableWithPendingFetch) {
533   SetupPrimaryLogin();
534 
535   NotifyTokenAvailable("user@example.com");
536   NotifyTokenRevoked("user@example.com");
537   EXPECT_TRUE(observer()->CheckEvents());
538 
539   NotifyTokenAvailable("user@example.com");
540   ReturnOAuthUrlFetchSuccess("user@example.com");
541   EXPECT_TRUE(observer()->CheckEvents(
542       TrackingEvent(ADDED, "user@example.com"),
543       TrackingEvent(SIGN_IN, "user@example.com")));
544 }
545 
TEST_F(IdentityAccountTrackerTest,AvailableRevokeRevoke)546 TEST_F(IdentityAccountTrackerTest, AvailableRevokeRevoke) {
547   SetupPrimaryLogin();
548 
549   NotifyTokenAvailable("user@example.com");
550   ReturnOAuthUrlFetchSuccess("user@example.com");
551   NotifyTokenRevoked("user@example.com");
552   EXPECT_TRUE(observer()->CheckEvents(
553       TrackingEvent(ADDED, "user@example.com"),
554       TrackingEvent(SIGN_IN, "user@example.com"),
555       TrackingEvent(SIGN_OUT, "user@example.com")));
556 
557   NotifyTokenRevoked("user@example.com");
558   EXPECT_TRUE(observer()->CheckEvents());
559 }
560 
TEST_F(IdentityAccountTrackerTest,AvailableAvailable)561 TEST_F(IdentityAccountTrackerTest, AvailableAvailable) {
562   SetupPrimaryLogin();
563 
564   NotifyTokenAvailable("user@example.com");
565   ReturnOAuthUrlFetchSuccess("user@example.com");
566   EXPECT_TRUE(observer()->CheckEvents(
567       TrackingEvent(ADDED, "user@example.com"),
568       TrackingEvent(SIGN_IN, "user@example.com")));
569 
570   NotifyTokenAvailable("user@example.com");
571   EXPECT_TRUE(observer()->CheckEvents());
572 }
573 
TEST_F(IdentityAccountTrackerTest,TwoAccounts)574 TEST_F(IdentityAccountTrackerTest, TwoAccounts) {
575   SetupPrimaryLogin();
576 
577   NotifyTokenAvailable("alpha@example.com");
578   ReturnOAuthUrlFetchSuccess("alpha@example.com");
579   EXPECT_TRUE(observer()->CheckEvents(
580       TrackingEvent(ADDED, "alpha@example.com"),
581       TrackingEvent(SIGN_IN, "alpha@example.com")));
582 
583   NotifyTokenAvailable("beta@example.com");
584   ReturnOAuthUrlFetchSuccess("beta@example.com");
585   EXPECT_TRUE(observer()->CheckEvents(
586       TrackingEvent(ADDED, "beta@example.com"),
587       TrackingEvent(SIGN_IN, "beta@example.com")));
588 
589   NotifyTokenRevoked("alpha@example.com");
590   EXPECT_TRUE(
591       observer()->CheckEvents(TrackingEvent(SIGN_OUT, "alpha@example.com")));
592 
593   NotifyTokenRevoked("beta@example.com");
594   EXPECT_TRUE(observer()->CheckEvents(
595       TrackingEvent(SIGN_OUT, "beta@example.com")));
596 }
597 
TEST_F(IdentityAccountTrackerTest,AvailableTokenFetchFailAvailable)598 TEST_F(IdentityAccountTrackerTest, AvailableTokenFetchFailAvailable) {
599   SetupPrimaryLogin();
600 
601   NotifyTokenAvailable("user@example.com");
602   ReturnOAuthUrlFetchFailure("user@example.com");
603   EXPECT_TRUE(observer()->CheckEvents());
604 
605   NotifyTokenAvailable("user@example.com");
606   ReturnOAuthUrlFetchSuccess("user@example.com");
607   EXPECT_TRUE(observer()->CheckEvents(
608       TrackingEvent(ADDED, "user@example.com"),
609       TrackingEvent(SIGN_IN, "user@example.com")));
610 }
611 
TEST_F(IdentityAccountTrackerTest,MultiSignOutSignIn)612 TEST_F(IdentityAccountTrackerTest, MultiSignOutSignIn) {
613   SetupPrimaryLogin();
614 
615   NotifyTokenAvailable("alpha@example.com");
616   ReturnOAuthUrlFetchSuccess("alpha@example.com");
617   NotifyTokenAvailable("beta@example.com");
618   ReturnOAuthUrlFetchSuccess("beta@example.com");
619 
620   observer()->SortEventsByUser();
621   EXPECT_TRUE(observer()->CheckEvents(
622       TrackingEvent(ADDED, "alpha@example.com"),
623       TrackingEvent(SIGN_IN, "alpha@example.com"),
624       TrackingEvent(ADDED, "beta@example.com"),
625       TrackingEvent(SIGN_IN, "beta@example.com")));
626 
627   NotifyLogout();
628   observer()->SortEventsByUser();
629   EXPECT_TRUE(observer()->CheckEvents(
630       TrackingEvent(SIGN_OUT, "alpha@example.com"),
631       TrackingEvent(REMOVED, "alpha@example.com"),
632       TrackingEvent(SIGN_OUT, "beta@example.com"),
633       TrackingEvent(REMOVED, "beta@example.com"),
634       TrackingEvent(SIGN_OUT, kPrimaryAccountKey),
635       TrackingEvent(REMOVED, kPrimaryAccountKey)));
636 
637   // No events fire at all while profile is signed out.
638   NotifyTokenRevoked("alpha@example.com");
639   NotifyTokenAvailable("gamma@example.com");
640   EXPECT_TRUE(observer()->CheckEvents());
641 
642   // Signing the profile in again will resume tracking all accounts.
643   NotifyLogin(kPrimaryAccountKey);
644   NotifyTokenAvailable(kPrimaryAccountKey);
645   ReturnOAuthUrlFetchSuccess("beta@example.com");
646   ReturnOAuthUrlFetchSuccess("gamma@example.com");
647   ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
648   observer()->SortEventsByUser();
649   EXPECT_TRUE(observer()->CheckEvents(
650       TrackingEvent(ADDED, "beta@example.com"),
651       TrackingEvent(SIGN_IN, "beta@example.com"),
652       TrackingEvent(ADDED, "gamma@example.com"),
653       TrackingEvent(SIGN_IN, "gamma@example.com"),
654       TrackingEvent(ADDED, kPrimaryAccountKey),
655       TrackingEvent(SIGN_IN, kPrimaryAccountKey)));
656 
657   // Revoking the primary token does not affect other accounts.
658   NotifyTokenRevoked(kPrimaryAccountKey);
659   EXPECT_TRUE(observer()->CheckEvents(
660       TrackingEvent(SIGN_OUT, kPrimaryAccountKey)));
661 
662   NotifyTokenAvailable(kPrimaryAccountKey);
663   EXPECT_TRUE(observer()->CheckEvents(
664       TrackingEvent(SIGN_IN, kPrimaryAccountKey)));
665 }
666 
667 // Primary/non-primary interactions
668 
TEST_F(IdentityAccountTrackerTest,MultiNoEventsBeforeLogin)669 TEST_F(IdentityAccountTrackerTest, MultiNoEventsBeforeLogin) {
670   NotifyTokenAvailable(kPrimaryAccountKey);
671   NotifyTokenAvailable("user@example.com");
672   NotifyTokenRevoked("user@example.com");
673   NotifyTokenRevoked(kPrimaryAccountKey);
674   NotifyLogout();
675   EXPECT_TRUE(observer()->CheckEvents());
676 }
677 
TEST_F(IdentityAccountTrackerTest,MultiLogoutRemovesAllAccounts)678 TEST_F(IdentityAccountTrackerTest, MultiLogoutRemovesAllAccounts) {
679   NotifyLogin(kPrimaryAccountKey);
680   NotifyTokenAvailable(kPrimaryAccountKey);
681   ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
682   NotifyTokenAvailable("user@example.com");
683   ReturnOAuthUrlFetchSuccess("user@example.com");
684   observer()->Clear();
685 
686   NotifyLogout();
687   observer()->SortEventsByUser();
688   EXPECT_TRUE(
689       observer()->CheckEvents(TrackingEvent(SIGN_OUT, kPrimaryAccountKey),
690                               TrackingEvent(REMOVED, kPrimaryAccountKey),
691                               TrackingEvent(SIGN_OUT, "user@example.com"),
692                               TrackingEvent(REMOVED, "user@example.com")));
693 }
694 
TEST_F(IdentityAccountTrackerTest,MultiRevokePrimaryDoesNotRemoveAllAccounts)695 TEST_F(IdentityAccountTrackerTest, MultiRevokePrimaryDoesNotRemoveAllAccounts) {
696   NotifyLogin(kPrimaryAccountKey);
697   NotifyTokenAvailable(kPrimaryAccountKey);
698   ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey);
699   NotifyTokenAvailable("user@example.com");
700   ReturnOAuthUrlFetchSuccess("user@example.com");
701   observer()->Clear();
702 
703   NotifyTokenRevoked(kPrimaryAccountKey);
704   observer()->SortEventsByUser();
705   EXPECT_TRUE(
706       observer()->CheckEvents(TrackingEvent(SIGN_OUT, kPrimaryAccountKey)));
707 }
708 
TEST_F(IdentityAccountTrackerTest,GetAccountsPrimary)709 TEST_F(IdentityAccountTrackerTest, GetAccountsPrimary) {
710   SetupPrimaryLogin();
711 
712   std::vector<AccountIds> ids = account_tracker()->GetAccounts();
713   EXPECT_EQ(1ul, ids.size());
714   EXPECT_EQ(kPrimaryAccountKey, ids[0].account_key);
715   EXPECT_EQ(AccountKeyToObfuscatedId(kPrimaryAccountKey), ids[0].gaia);
716 }
717 
TEST_F(IdentityAccountTrackerTest,GetAccountsSignedOut)718 TEST_F(IdentityAccountTrackerTest, GetAccountsSignedOut) {
719   std::vector<AccountIds> ids = account_tracker()->GetAccounts();
720   EXPECT_EQ(0ul, ids.size());
721 }
722 
TEST_F(IdentityAccountTrackerTest,GetAccountsOnlyReturnAccountsWithTokens)723 TEST_F(IdentityAccountTrackerTest, GetAccountsOnlyReturnAccountsWithTokens) {
724   SetupPrimaryLogin();
725 
726   NotifyTokenAvailable("alpha@example.com");
727   NotifyTokenAvailable("beta@example.com");
728   ReturnOAuthUrlFetchSuccess("beta@example.com");
729 
730   std::vector<AccountIds> ids = account_tracker()->GetAccounts();
731   EXPECT_EQ(2ul, ids.size());
732   EXPECT_EQ(kPrimaryAccountKey, ids[0].account_key);
733   EXPECT_EQ(AccountKeyToObfuscatedId(kPrimaryAccountKey), ids[0].gaia);
734   EXPECT_EQ("beta@example.com", ids[1].account_key);
735   EXPECT_EQ(AccountKeyToObfuscatedId("beta@example.com"), ids[1].gaia);
736 }
737 
TEST_F(IdentityAccountTrackerTest,GetAccountsSortOrder)738 TEST_F(IdentityAccountTrackerTest, GetAccountsSortOrder) {
739   SetupPrimaryLogin();
740 
741   NotifyTokenAvailable("zeta@example.com");
742   ReturnOAuthUrlFetchSuccess("zeta@example.com");
743   NotifyTokenAvailable("alpha@example.com");
744   ReturnOAuthUrlFetchSuccess("alpha@example.com");
745 
746   // The primary account will be first in the vector. Remaining accounts
747   // will be sorted by gaia ID.
748   std::vector<AccountIds> ids = account_tracker()->GetAccounts();
749   EXPECT_EQ(3ul, ids.size());
750   EXPECT_EQ(kPrimaryAccountKey, ids[0].account_key);
751   EXPECT_EQ(AccountKeyToObfuscatedId(kPrimaryAccountKey), ids[0].gaia);
752   EXPECT_EQ("alpha@example.com", ids[1].account_key);
753   EXPECT_EQ(AccountKeyToObfuscatedId("alpha@example.com"), ids[1].gaia);
754   EXPECT_EQ("zeta@example.com", ids[2].account_key);
755   EXPECT_EQ(AccountKeyToObfuscatedId("zeta@example.com"), ids[2].gaia);
756 }
757 
TEST_F(IdentityAccountTrackerTest,GetAccountsReturnNothingWhenPrimarySignedOut)758 TEST_F(IdentityAccountTrackerTest,
759        GetAccountsReturnNothingWhenPrimarySignedOut) {
760   SetupPrimaryLogin();
761 
762   NotifyTokenAvailable("zeta@example.com");
763   ReturnOAuthUrlFetchSuccess("zeta@example.com");
764   NotifyTokenAvailable("alpha@example.com");
765   ReturnOAuthUrlFetchSuccess("alpha@example.com");
766 
767   NotifyTokenRevoked(kPrimaryAccountKey);
768 
769   std::vector<AccountIds> ids = account_tracker()->GetAccounts();
770   EXPECT_EQ(0ul, ids.size());
771 }
772 
TEST_F(IdentityAccountTrackerTest,FindAccountIdsByGaiaIdPrimary)773 TEST_F(IdentityAccountTrackerTest, FindAccountIdsByGaiaIdPrimary) {
774   SetupPrimaryLogin();
775 
776   AccountIds ids = account_tracker()->FindAccountIdsByGaiaId(
777       AccountKeyToObfuscatedId(kPrimaryAccountKey));
778   EXPECT_EQ(kPrimaryAccountKey, ids.account_key);
779   EXPECT_EQ(kPrimaryAccountKey, ids.email);
780   EXPECT_EQ(AccountKeyToObfuscatedId(kPrimaryAccountKey), ids.gaia);
781 }
782 
TEST_F(IdentityAccountTrackerTest,FindAccountIdsByGaiaIdNotFound)783 TEST_F(IdentityAccountTrackerTest, FindAccountIdsByGaiaIdNotFound) {
784   SetupPrimaryLogin();
785 
786   AccountIds ids = account_tracker()->FindAccountIdsByGaiaId(
787       AccountKeyToObfuscatedId("notfound@example.com"));
788   EXPECT_TRUE(ids.account_key.empty());
789   EXPECT_TRUE(ids.email.empty());
790   EXPECT_TRUE(ids.gaia.empty());
791 }
792 
TEST_F(IdentityAccountTrackerTest,FindAccountIdsByGaiaIdReturnEmptyWhenPrimarySignedOut)793 TEST_F(IdentityAccountTrackerTest,
794        FindAccountIdsByGaiaIdReturnEmptyWhenPrimarySignedOut) {
795   SetupPrimaryLogin();
796 
797   NotifyTokenAvailable("zeta@example.com");
798   ReturnOAuthUrlFetchSuccess("zeta@example.com");
799   NotifyTokenAvailable("alpha@example.com");
800   ReturnOAuthUrlFetchSuccess("alpha@example.com");
801 
802   NotifyTokenRevoked(kPrimaryAccountKey);
803 
804   AccountIds ids =
805       account_tracker()->FindAccountIdsByGaiaId(kPrimaryAccountKey);
806   EXPECT_TRUE(ids.account_key.empty());
807   EXPECT_TRUE(ids.email.empty());
808   EXPECT_TRUE(ids.gaia.empty());
809 
810   ids = account_tracker()->FindAccountIdsByGaiaId("alpha@example.com");
811   EXPECT_TRUE(ids.account_key.empty());
812   EXPECT_TRUE(ids.email.empty());
813   EXPECT_TRUE(ids.gaia.empty());
814 }
815 
816 }  // namespace gaia
817