Upstream version 9.37.195.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / signin / account_reconcilor_unittest.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/command_line.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/run_loop.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/time/time.h"
10 #include "build/build_config.h"
11 #include "chrome/browser/prefs/pref_service_syncable.h"
12 #include "chrome/browser/signin/account_reconcilor_factory.h"
13 #include "chrome/browser/signin/chrome_signin_client_factory.h"
14 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
15 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
16 #include "chrome/browser/signin/fake_signin_manager.h"
17 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
18 #include "chrome/browser/signin/signin_manager_factory.h"
19 #include "chrome/browser/signin/test_signin_client_builder.h"
20 #include "chrome/test/base/testing_browser_process.h"
21 #include "chrome/test/base/testing_profile.h"
22 #include "chrome/test/base/testing_profile_manager.h"
23 #include "chrome/test/base/uma_histogram_helper.h"
24 #include "components/signin/core/browser/account_reconcilor.h"
25 #include "components/signin/core/browser/profile_oauth2_token_service.h"
26 #include "components/signin/core/browser/signin_manager.h"
27 #include "components/signin/core/browser/signin_metrics.h"
28 #include "components/signin/core/common/profile_management_switches.h"
29 #include "components/signin/core/common/signin_switches.h"
30 #include "content/public/test/test_browser_thread_bundle.h"
31 #include "google_apis/gaia/gaia_urls.h"
32 #include "net/url_request/test_url_fetcher_factory.h"
33 #include "testing/gmock/include/gmock/gmock.h"
34 #include "testing/gtest/include/gtest/gtest.h"
35
36 namespace {
37
38 const char kTestEmail[] = "user@gmail.com";
39 const char* const kHistogramsToSnapshot[] = {
40     "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
41     "Signin.Reconciler.AddedToCookieJar.FirstRun",
42     "Signin.Reconciler.AddedToChrome.FirstRun",
43     "Signin.Reconciler.DifferentPrimaryAccounts.SubsequentRun",
44     "Signin.Reconciler.AddedToCookieJar.SubsequentRun",
45     "Signin.Reconciler.AddedToChrome.SubsequentRun"};
46
47 class MockAccountReconcilor : public testing::StrictMock<AccountReconcilor> {
48  public:
49   static KeyedService* Build(content::BrowserContext* context);
50
51   MockAccountReconcilor(ProfileOAuth2TokenService* token_service,
52                         SigninManagerBase* signin_manager,
53                         SigninClient* client);
54   virtual ~MockAccountReconcilor() {}
55
56   MOCK_METHOD1(PerformMergeAction, void(const std::string& account_id));
57   MOCK_METHOD1(PerformStartRemoveAction, void(const std::string& account_id));
58   MOCK_METHOD3(
59       PerformFinishRemoveAction,
60       void(const std::string& account_id,
61            const GoogleServiceAuthError& error,
62            const std::vector<std::pair<std::string, bool> >& accounts));
63   MOCK_METHOD2(PerformAddToChromeAction, void(const std::string& account_id,
64                                               int session_index));
65   MOCK_METHOD0(PerformLogoutAllAccountsAction, void());
66 };
67
68 // static
69 KeyedService* MockAccountReconcilor::Build(content::BrowserContext* context) {
70   Profile* profile = Profile::FromBrowserContext(context);
71   AccountReconcilor* reconcilor = new MockAccountReconcilor(
72       ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
73       SigninManagerFactory::GetForProfile(profile),
74       ChromeSigninClientFactory::GetForProfile(profile));
75   reconcilor->Initialize(false /* start_reconcile_if_tokens_available */);
76   return reconcilor;
77 }
78
79 MockAccountReconcilor::MockAccountReconcilor(
80     ProfileOAuth2TokenService* token_service,
81     SigninManagerBase* signin_manager,
82     SigninClient* client)
83     : testing::StrictMock<AccountReconcilor>(token_service,
84                                              signin_manager,
85                                              client) {}
86
87 }  // namespace
88
89 class AccountReconcilorTest : public ::testing::TestWithParam<bool> {
90  public:
91   AccountReconcilorTest();
92   virtual void SetUp() OVERRIDE;
93
94   TestingProfile* profile() { return profile_; }
95   FakeSigninManagerForTesting* signin_manager() { return signin_manager_; }
96   FakeProfileOAuth2TokenService* token_service() { return token_service_; }
97   UMAHistogramHelper* histogram_helper() { return &histogram_helper_; }
98
99   void SetFakeResponse(const std::string& url,
100                        const std::string& data,
101                        net::HttpStatusCode code,
102                        net::URLRequestStatus::Status status) {
103     url_fetcher_factory_.SetFakeResponse(GURL(url), data, code, status);
104   }
105
106   MockAccountReconcilor* GetMockReconcilor();
107
108   void SimulateMergeSessionCompleted(
109       MergeSessionHelper::Observer* observer,
110       const std::string& account_id,
111       const GoogleServiceAuthError& error);
112
113   void SimulateRefreshTokenFetched(
114       AccountReconcilor* reconcilor,
115       const std::string& account_id,
116       const std::string& refresh_token);
117
118  private:
119   content::TestBrowserThreadBundle bundle_;
120   TestingProfile* profile_;
121   FakeSigninManagerForTesting* signin_manager_;
122   FakeProfileOAuth2TokenService* token_service_;
123   MockAccountReconcilor* mock_reconcilor_;
124   net::FakeURLFetcherFactory url_fetcher_factory_;
125   scoped_ptr<TestingProfileManager> testing_profile_manager_;
126   UMAHistogramHelper histogram_helper_;
127
128   DISALLOW_COPY_AND_ASSIGN(AccountReconcilorTest);
129 };
130
131 AccountReconcilorTest::AccountReconcilorTest()
132     : signin_manager_(NULL),
133       token_service_(NULL),
134       mock_reconcilor_(NULL),
135       url_fetcher_factory_(NULL) {}
136
137 void AccountReconcilorTest::SetUp() {
138   // If it's a non-parameterized test, or we have a parameter of true, set flag.
139   if (!::testing::UnitTest::GetInstance()->current_test_info()->value_param() ||
140       GetParam()) {
141     CommandLine::ForCurrentProcess()->AppendSwitch(
142         switches::kEnableNewProfileManagement);
143   }
144
145   testing_profile_manager_.reset(
146       new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
147   ASSERT_TRUE(testing_profile_manager_.get()->SetUp());
148
149   TestingProfile::TestingFactories factories;
150   factories.push_back(std::make_pair(ChromeSigninClientFactory::GetInstance(),
151       signin::BuildTestSigninClient));
152   factories.push_back(std::make_pair(
153       ProfileOAuth2TokenServiceFactory::GetInstance(),
154       BuildFakeProfileOAuth2TokenService));
155   factories.push_back(std::make_pair(SigninManagerFactory::GetInstance(),
156       FakeSigninManagerBase::Build));
157   factories.push_back(std::make_pair(AccountReconcilorFactory::GetInstance(),
158       MockAccountReconcilor::Build));
159
160   profile_ = testing_profile_manager_.get()->CreateTestingProfile("name",
161                               scoped_ptr<PrefServiceSyncable>(),
162                               base::UTF8ToUTF16("name"), 0, std::string(),
163                               factories);
164
165   signin_manager_ =
166       static_cast<FakeSigninManagerForTesting*>(
167           SigninManagerFactory::GetForProfile(profile()));
168
169   token_service_ =
170       static_cast<FakeProfileOAuth2TokenService*>(
171           ProfileOAuth2TokenServiceFactory::GetForProfile(profile()));
172
173   // Take a new snapshot of the concerned histograms before each test
174   histogram_helper_.PrepareSnapshot(kHistogramsToSnapshot,
175                                     arraysize(kHistogramsToSnapshot));
176 }
177
178 MockAccountReconcilor* AccountReconcilorTest::GetMockReconcilor() {
179   if (!mock_reconcilor_) {
180     mock_reconcilor_ =
181         static_cast<MockAccountReconcilor*>(
182             AccountReconcilorFactory::GetForProfile(profile()));
183   }
184
185   return mock_reconcilor_;
186 }
187
188 void AccountReconcilorTest::SimulateMergeSessionCompleted(
189     MergeSessionHelper::Observer* observer,
190     const std::string& account_id,
191     const GoogleServiceAuthError& error) {
192   observer->MergeSessionCompleted(account_id, error);
193 }
194
195 void AccountReconcilorTest::SimulateRefreshTokenFetched(
196     AccountReconcilor* reconcilor,
197     const std::string& account_id,
198     const std::string& refresh_token) {
199   reconcilor->HandleRefreshTokenFetched(account_id, refresh_token);
200 }
201
202 TEST_F(AccountReconcilorTest, Basic) {
203   AccountReconcilor* reconcilor =
204       AccountReconcilorFactory::GetForProfile(profile());
205   ASSERT_TRUE(reconcilor);
206   ASSERT_EQ(token_service(), reconcilor->token_service());
207 }
208
209 #if !defined(OS_CHROMEOS)
210
211 // This method requires the use of the |TestSigninClient| to be created from the
212 // |ChromeSigninClientFactory| because it overrides the |GoogleSigninSucceeded|
213 // method with an empty implementation. On MacOS, the normal implementation
214 // causes the try_bots to time out.
215 TEST_F(AccountReconcilorTest, SigninManagerRegistration) {
216   AccountReconcilor* reconcilor =
217       AccountReconcilorFactory::GetForProfile(profile());
218   ASSERT_TRUE(reconcilor);
219   ASSERT_FALSE(reconcilor->IsRegisteredWithTokenService());
220
221   signin_manager()->set_password("password");
222   signin_manager()->OnExternalSigninCompleted(kTestEmail);
223   ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService());
224
225   EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
226
227   signin_manager()->SignOut(signin_metrics::SIGNOUT_TEST);
228   ASSERT_FALSE(reconcilor->IsRegisteredWithTokenService());
229 }
230
231 // This method requires the use of the |TestSigninClient| to be created from the
232 // |ChromeSigninClientFactory| because it overrides the |GoogleSigninSucceeded|
233 // method with an empty implementation. On MacOS, the normal implementation
234 // causes the try_bots to time out.
235 TEST_F(AccountReconcilorTest, Reauth) {
236   signin_manager()->SetAuthenticatedUsername(kTestEmail);
237   signin_manager()->set_password("password");
238
239   AccountReconcilor* reconcilor =
240       AccountReconcilorFactory::GetForProfile(profile());
241   ASSERT_TRUE(reconcilor);
242   ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService());
243
244   // Simulate reauth.  The state of the reconcilor should not change.
245   signin_manager()->OnExternalSigninCompleted(kTestEmail);
246   ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService());
247 }
248
249 #endif  // !defined(OS_CHROMEOS)
250
251 TEST_F(AccountReconcilorTest, ProfileAlreadyConnected) {
252   signin_manager()->SetAuthenticatedUsername(kTestEmail);
253
254   AccountReconcilor* reconcilor =
255       AccountReconcilorFactory::GetForProfile(profile());
256   ASSERT_TRUE(reconcilor);
257   ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService());
258 }
259
260 TEST_F(AccountReconcilorTest, GetAccountsFromCookieSuccess) {
261   signin_manager()->SetAuthenticatedUsername(kTestEmail);
262   token_service()->UpdateCredentials(kTestEmail, "refresh_token");
263   AccountReconcilor* reconcilor =
264       AccountReconcilorFactory::GetForProfile(profile());
265   ASSERT_TRUE(reconcilor);
266
267   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
268       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 0]]]",
269       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
270
271   reconcilor->StartReconcile();
272   ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
273
274   base::RunLoop().RunUntilIdle();
275   ASSERT_TRUE(reconcilor->AreGaiaAccountsSet());
276   const std::vector<std::pair<std::string, bool> >& accounts =
277       reconcilor->GetGaiaAccountsForTesting();
278   ASSERT_EQ(1u, accounts.size());
279   ASSERT_EQ("user@gmail.com", accounts[0].first);
280 }
281
282 TEST_F(AccountReconcilorTest, GetAccountsFromCookieFailure) {
283   signin_manager()->SetAuthenticatedUsername(kTestEmail);
284   token_service()->UpdateCredentials(kTestEmail, "refresh_token");
285   AccountReconcilor* reconcilor =
286       AccountReconcilorFactory::GetForProfile(profile());
287   ASSERT_TRUE(reconcilor);
288
289   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(), "",
290       net::HTTP_NOT_FOUND, net::URLRequestStatus::SUCCESS);
291
292   reconcilor->StartReconcile();
293   ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
294
295   base::RunLoop().RunUntilIdle();
296   ASSERT_EQ(0u, reconcilor->GetGaiaAccountsForTesting().size());
297 }
298
299 TEST_F(AccountReconcilorTest, ValidateAccountsFromTokens) {
300   signin_manager()->SetAuthenticatedUsername(kTestEmail);
301   token_service()->UpdateCredentials(kTestEmail, "refresh_token");
302
303   AccountReconcilor* reconcilor =
304       AccountReconcilorFactory::GetForProfile(profile());
305   ASSERT_TRUE(reconcilor);
306
307   reconcilor->ValidateAccountsFromTokenService();
308   ASSERT_FALSE(reconcilor->AreAllRefreshTokensChecked());
309
310   SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo",
311       "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS);
312   token_service()->IssueTokenForAllPendingRequests("access_token",
313       base::Time::Now() + base::TimeDelta::FromHours(1));
314
315   base::RunLoop().RunUntilIdle();
316   ASSERT_TRUE(reconcilor->AreAllRefreshTokensChecked());
317   ASSERT_EQ(1u, reconcilor->GetValidChromeAccountsForTesting().size());
318   ASSERT_EQ(0u, reconcilor->GetInvalidChromeAccountsForTesting().size());
319 }
320
321 TEST_F(AccountReconcilorTest, ValidateAccountsFromTokensFailedUserInfo) {
322   signin_manager()->SetAuthenticatedUsername(kTestEmail);
323   token_service()->UpdateCredentials(kTestEmail, "refresh_token");
324
325   AccountReconcilor* reconcilor =
326       AccountReconcilorFactory::GetForProfile(profile());
327   ASSERT_TRUE(reconcilor);
328
329   reconcilor->ValidateAccountsFromTokenService();
330   ASSERT_FALSE(reconcilor->AreAllRefreshTokensChecked());
331
332   SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo",
333       "", net::HTTP_NOT_FOUND, net::URLRequestStatus::SUCCESS);
334   token_service()->IssueTokenForAllPendingRequests("access_token",
335       base::Time::Now() + base::TimeDelta::FromHours(1));
336
337   base::RunLoop().RunUntilIdle();
338   ASSERT_TRUE(reconcilor->AreAllRefreshTokensChecked());
339   ASSERT_EQ(0u, reconcilor->GetValidChromeAccountsForTesting().size());
340   ASSERT_EQ(1u, reconcilor->GetInvalidChromeAccountsForTesting().size());
341 }
342
343 TEST_F(AccountReconcilorTest, ValidateAccountsFromTokensFailedTokenRequest) {
344   signin_manager()->SetAuthenticatedUsername(kTestEmail);
345   token_service()->UpdateCredentials(kTestEmail, "refresh_token");
346
347   AccountReconcilor* reconcilor =
348       AccountReconcilorFactory::GetForProfile(profile());
349   ASSERT_TRUE(reconcilor);
350
351   reconcilor->ValidateAccountsFromTokenService();
352   ASSERT_FALSE(reconcilor->AreAllRefreshTokensChecked());
353
354   token_service()->IssueErrorForAllPendingRequests(
355       GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
356
357   base::RunLoop().RunUntilIdle();
358   ASSERT_TRUE(reconcilor->AreAllRefreshTokensChecked());
359   ASSERT_EQ(0u, reconcilor->GetValidChromeAccountsForTesting().size());
360   ASSERT_EQ(1u, reconcilor->GetInvalidChromeAccountsForTesting().size());
361 }
362
363 TEST_P(AccountReconcilorTest, StartReconcileNoop) {
364   signin_manager()->SetAuthenticatedUsername(kTestEmail);
365   token_service()->UpdateCredentials(kTestEmail, "refresh_token");
366
367   AccountReconcilor* reconcilor =
368       AccountReconcilorFactory::GetForProfile(profile());
369   ASSERT_TRUE(reconcilor);
370
371   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
372       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
373       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
374   SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo",
375       "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS);
376
377   reconcilor->StartReconcile();
378   ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
379   ASSERT_FALSE(reconcilor->AreAllRefreshTokensChecked());
380
381   base::RunLoop().RunUntilIdle();
382   ASSERT_TRUE(reconcilor->AreGaiaAccountsSet());
383   ASSERT_EQ(1u, reconcilor->GetGaiaAccountsForTesting().size());
384   ASSERT_FALSE(reconcilor->AreAllRefreshTokensChecked());
385
386   token_service()->IssueAllTokensForAccount("user@gmail.com", "access_token",
387       base::Time::Now() + base::TimeDelta::FromHours(1));
388
389   base::RunLoop().RunUntilIdle();
390   ASSERT_TRUE(reconcilor->AreAllRefreshTokensChecked());
391   ASSERT_FALSE(reconcilor->is_reconcile_started_);
392
393   histogram_helper()->Fetch();
394   histogram_helper()->ExpectTotalCount(
395       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 1);
396   histogram_helper()->ExpectUniqueSample(
397       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
398       signin_metrics::ACCOUNTS_SAME,
399       1);
400 }
401
402 // This is test is needed until chrome changes to use gaia obfuscated id.
403 // The signin manager and token service use the gaia "email" property, which
404 // preserves dots in usernames and preserves case. gaia::ParseListAccountsData()
405 // however uses gaia "displayEmail" which does not preserve case, and then
406 // passes the string through gaia::CanonicalizeEmail() which removes dots.  This
407 // tests makes sure that an email like "Dot.S@hmail.com", as seen by the
408 // token service, will be considered the same as "dots@gmail.com" as returned
409 // by gaia::ParseListAccountsData().
410 TEST_P(AccountReconcilorTest, StartReconcileNoopWithDots) {
411   signin_manager()->SetAuthenticatedUsername("Dot.S@gmail.com");
412   token_service()->UpdateCredentials("Dot.S@gmail.com", "refresh_token");
413
414   AccountReconcilor* reconcilor =
415       AccountReconcilorFactory::GetForProfile(profile());
416   ASSERT_TRUE(reconcilor);
417
418   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
419       "[\"f\", [[\"b\", 0, \"n\", \"dot.s@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
420       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
421   SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo",
422       "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS);
423
424   reconcilor->StartReconcile();
425   ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
426   ASSERT_FALSE(reconcilor->AreAllRefreshTokensChecked());
427
428   base::RunLoop().RunUntilIdle();
429   ASSERT_TRUE(reconcilor->AreGaiaAccountsSet());
430   ASSERT_EQ(1u, reconcilor->GetGaiaAccountsForTesting().size());
431   ASSERT_STREQ("dots@gmail.com",
432                reconcilor->GetGaiaAccountsForTesting()[0].first.c_str());
433   ASSERT_FALSE(reconcilor->AreAllRefreshTokensChecked());
434
435   token_service()->IssueAllTokensForAccount("Dot.S@gmail.com", "access_token",
436       base::Time::Now() + base::TimeDelta::FromHours(1));
437
438   base::RunLoop().RunUntilIdle();
439   ASSERT_TRUE(reconcilor->AreAllRefreshTokensChecked());
440   ASSERT_FALSE(reconcilor->is_reconcile_started_);
441
442   histogram_helper()->Fetch();
443   histogram_helper()->ExpectUniqueSample(
444       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
445       signin_metrics::ACCOUNTS_SAME,
446       1);
447 }
448
449 TEST_P(AccountReconcilorTest, StartReconcileNoopMultiple) {
450   signin_manager()->SetAuthenticatedUsername("user@gmail.com");
451   token_service()->UpdateCredentials("user@gmail.com", "refresh_token");
452   token_service()->UpdateCredentials("other@gmail.com", "refresh_token");
453
454   AccountReconcilor* reconcilor =
455       AccountReconcilorFactory::GetForProfile(profile());
456   ASSERT_TRUE(reconcilor);
457
458   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
459       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1], "
460                "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
461       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
462   SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo",
463       "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS);
464
465   reconcilor->StartReconcile();
466   ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
467   ASSERT_FALSE(reconcilor->AreAllRefreshTokensChecked());
468
469   base::RunLoop().RunUntilIdle();
470   ASSERT_TRUE(reconcilor->AreGaiaAccountsSet());
471   ASSERT_FALSE(reconcilor->AreAllRefreshTokensChecked());
472   ASSERT_EQ(2u, reconcilor->GetGaiaAccountsForTesting().size());
473
474   token_service()->IssueAllTokensForAccount("other@gmail.com", "access_token",
475       base::Time::Now() + base::TimeDelta::FromHours(1));
476
477   base::RunLoop().RunUntilIdle();
478   ASSERT_FALSE(reconcilor->AreAllRefreshTokensChecked());
479
480   token_service()->IssueAllTokensForAccount("user@gmail.com", "access_token",
481       base::Time::Now() + base::TimeDelta::FromHours(1));
482
483   base::RunLoop().RunUntilIdle();
484   ASSERT_TRUE(reconcilor->AreAllRefreshTokensChecked());
485   ASSERT_FALSE(reconcilor->is_reconcile_started_);
486
487   histogram_helper()->Fetch();
488   histogram_helper()->ExpectTotalCount(
489       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 1);
490   histogram_helper()->ExpectUniqueSample(
491       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
492       signin_metrics::ACCOUNTS_SAME,
493       1);
494 }
495
496 TEST_P(AccountReconcilorTest, StartReconcileAddToCookie) {
497   signin_manager()->SetAuthenticatedUsername("user@gmail.com");
498   token_service()->UpdateCredentials("user@gmail.com", "refresh_token");
499   token_service()->UpdateCredentials("other@gmail.com", "refresh_token");
500
501   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("other@gmail.com"));
502
503   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
504       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
505       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
506   SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo",
507       "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS);
508
509   AccountReconcilor* reconcilor = GetMockReconcilor();
510   reconcilor->StartReconcile();
511   token_service()->IssueAllTokensForAccount("other@gmail.com", "access_token",
512       base::Time::Now() + base::TimeDelta::FromHours(1));
513   token_service()->IssueAllTokensForAccount("user@gmail.com", "access_token",
514       base::Time::Now() + base::TimeDelta::FromHours(1));
515
516   base::RunLoop().RunUntilIdle();
517   ASSERT_TRUE(reconcilor->is_reconcile_started_);
518   SimulateMergeSessionCompleted(reconcilor, "other@gmail.com",
519                                 GoogleServiceAuthError::AuthErrorNone());
520   ASSERT_FALSE(reconcilor->is_reconcile_started_);
521
522   histogram_helper()->Fetch();
523   histogram_helper()->ExpectUniqueSample(
524       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
525       signin_metrics::ACCOUNTS_SAME,
526       1);
527   histogram_helper()->ExpectUniqueSample(
528       "Signin.Reconciler.AddedToCookieJar.FirstRun", 1, 1);
529   histogram_helper()->ExpectUniqueSample(
530       "Signin.Reconciler.AddedToChrome.FirstRun", 0, 1);
531 }
532
533 TEST_P(AccountReconcilorTest, StartReconcileAddToCookieTwice) {
534   signin_manager()->SetAuthenticatedUsername("user@gmail.com");
535   token_service()->UpdateCredentials("user@gmail.com", "refresh_token");
536   token_service()->UpdateCredentials("other@gmail.com", "refresh_token");
537
538   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("other@gmail.com"));
539   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("third@gmail.com"));
540
541   SetFakeResponse(
542       GaiaUrls::GetInstance()->list_accounts_url().spec(),
543       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
544       net::HTTP_OK,
545       net::URLRequestStatus::SUCCESS);
546   SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo",
547                   "{\"id\":\"foo\"}",
548                   net::HTTP_OK,
549                   net::URLRequestStatus::SUCCESS);
550
551   AccountReconcilor* reconcilor = GetMockReconcilor();
552   reconcilor->StartReconcile();
553   token_service()->IssueAllTokensForAccount(
554       "other@gmail.com",
555       "access_token",
556       base::Time::Now() + base::TimeDelta::FromHours(1));
557   token_service()->IssueAllTokensForAccount(
558       "user@gmail.com",
559       "access_token",
560       base::Time::Now() + base::TimeDelta::FromHours(1));
561
562   base::RunLoop().RunUntilIdle();
563   ASSERT_TRUE(reconcilor->is_reconcile_started_);
564   SimulateMergeSessionCompleted(
565       reconcilor, "other@gmail.com", GoogleServiceAuthError::AuthErrorNone());
566   ASSERT_FALSE(reconcilor->is_reconcile_started_);
567
568   histogram_helper()->Fetch();
569   histogram_helper()->ExpectUniqueSample(
570       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
571       signin_metrics::ACCOUNTS_SAME,
572       1);
573   histogram_helper()->ExpectUniqueSample(
574       "Signin.Reconciler.AddedToCookieJar.FirstRun", 1, 1);
575   histogram_helper()->ExpectUniqueSample(
576       "Signin.Reconciler.AddedToChrome.FirstRun", 0, 1);
577
578   // Do another pass after I've added a third account to the token service
579
580   SetFakeResponse(
581       GaiaUrls::GetInstance()->list_accounts_url().spec(),
582       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1], "
583       "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
584       net::HTTP_OK,
585       net::URLRequestStatus::SUCCESS);
586   // This will cause the reconcilor to fire.
587   token_service()->UpdateCredentials("third@gmail.com", "refresh_token");
588
589   token_service()->IssueAllTokensForAccount(
590       "other@gmail.com",
591       "access_token",
592       base::Time::Now() + base::TimeDelta::FromHours(1));
593   token_service()->IssueAllTokensForAccount(
594       "user@gmail.com",
595       "access_token",
596       base::Time::Now() + base::TimeDelta::FromHours(1));
597   token_service()->IssueAllTokensForAccount(
598       "third@gmail.com",
599       "access_token",
600       base::Time::Now() + base::TimeDelta::FromHours(1));
601
602   base::RunLoop().RunUntilIdle();
603
604   ASSERT_TRUE(reconcilor->is_reconcile_started_);
605   SimulateMergeSessionCompleted(
606       reconcilor, "third@gmail.com", GoogleServiceAuthError::AuthErrorNone());
607   ASSERT_FALSE(reconcilor->is_reconcile_started_);
608
609   histogram_helper()->Fetch();
610   histogram_helper()->ExpectUniqueSample(
611       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
612       signin_metrics::ACCOUNTS_SAME,
613       1);
614   histogram_helper()->ExpectUniqueSample(
615       "Signin.Reconciler.AddedToCookieJar.FirstRun", 1, 1);
616   histogram_helper()->ExpectUniqueSample(
617       "Signin.Reconciler.AddedToChrome.FirstRun", 0, 1);
618   histogram_helper()->ExpectUniqueSample(
619       "Signin.Reconciler.DifferentPrimaryAccounts.SubsequentRun",
620       signin_metrics::ACCOUNTS_SAME,
621       1);
622   histogram_helper()->ExpectUniqueSample(
623       "Signin.Reconciler.AddedToCookieJar.SubsequentRun", 1, 1);
624   histogram_helper()->ExpectUniqueSample(
625       "Signin.Reconciler.AddedToChrome.SubsequentRun", 0, 1);
626 }
627
628 TEST_P(AccountReconcilorTest, StartReconcileAddToChrome) {
629   signin_manager()->SetAuthenticatedUsername("user@gmail.com");
630   token_service()->UpdateCredentials("user@gmail.com", "refresh_token");
631
632   EXPECT_CALL(*GetMockReconcilor(),
633               PerformAddToChromeAction("other@gmail.com", 1));
634
635   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
636       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1], "
637                "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
638       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
639   SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo",
640       "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS);
641
642   AccountReconcilor* reconcilor = GetMockReconcilor();
643   reconcilor->StartReconcile();
644   token_service()->IssueAllTokensForAccount("user@gmail.com", "access_token",
645       base::Time::Now() + base::TimeDelta::FromHours(1));
646
647   base::RunLoop().RunUntilIdle();
648   ASSERT_TRUE(reconcilor->is_reconcile_started_);
649   SimulateRefreshTokenFetched(reconcilor, "other@gmail.com", "");
650   ASSERT_FALSE(reconcilor->is_reconcile_started_);
651
652   histogram_helper()->Fetch();
653   histogram_helper()->ExpectUniqueSample(
654       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
655       signin_metrics::ACCOUNTS_SAME,
656       1);
657   histogram_helper()->ExpectUniqueSample(
658       "Signin.Reconciler.AddedToCookieJar.FirstRun", 0, 1);
659   histogram_helper()->ExpectUniqueSample(
660       "Signin.Reconciler.AddedToChrome.FirstRun", 1, 1);
661 }
662
663 TEST_P(AccountReconcilorTest, StartReconcileBadPrimary) {
664   signin_manager()->SetAuthenticatedUsername("user@gmail.com");
665   token_service()->UpdateCredentials("user@gmail.com", "refresh_token");
666   token_service()->UpdateCredentials("other@gmail.com", "refresh_token");
667
668   EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
669   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("user@gmail.com"));
670   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("other@gmail.com"));
671
672   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
673       "[\"f\", [[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1], "
674                "[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
675       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
676   SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo",
677       "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS);
678
679   AccountReconcilor* reconcilor = GetMockReconcilor();
680   reconcilor->StartReconcile();
681   token_service()->IssueAllTokensForAccount("other@gmail.com", "access_token",
682       base::Time::Now() + base::TimeDelta::FromHours(1));
683   token_service()->IssueAllTokensForAccount("user@gmail.com", "access_token",
684       base::Time::Now() + base::TimeDelta::FromHours(1));
685
686   base::RunLoop().RunUntilIdle();
687   ASSERT_TRUE(reconcilor->is_reconcile_started_);
688   SimulateMergeSessionCompleted(reconcilor, "other@gmail.com",
689                                 GoogleServiceAuthError::AuthErrorNone());
690   ASSERT_TRUE(reconcilor->is_reconcile_started_);
691   SimulateMergeSessionCompleted(reconcilor, "user@gmail.com",
692                                 GoogleServiceAuthError::AuthErrorNone());
693   ASSERT_FALSE(reconcilor->is_reconcile_started_);
694
695   histogram_helper()->Fetch();
696   histogram_helper()->ExpectUniqueSample(
697       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
698       signin_metrics::COOKIE_AND_TOKEN_PRIMARIES_DIFFERENT,
699       1);
700   histogram_helper()->ExpectUniqueSample(
701       "Signin.Reconciler.AddedToCookieJar.FirstRun", 2, 1);
702   histogram_helper()->ExpectUniqueSample(
703       "Signin.Reconciler.AddedToChrome.FirstRun", 0, 1);
704 }
705
706 TEST_P(AccountReconcilorTest, StartReconcileOnlyOnce) {
707   signin_manager()->SetAuthenticatedUsername(kTestEmail);
708   token_service()->UpdateCredentials(kTestEmail, "refresh_token");
709
710   AccountReconcilor* reconcilor =
711       AccountReconcilorFactory::GetForProfile(profile());
712   ASSERT_TRUE(reconcilor);
713
714   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
715       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
716       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
717   SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo",
718       "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS);
719
720   ASSERT_FALSE(reconcilor->is_reconcile_started_);
721   reconcilor->StartReconcile();
722   ASSERT_TRUE(reconcilor->is_reconcile_started_);
723
724   token_service()->IssueAllTokensForAccount("user@gmail.com", "access_token",
725       base::Time::Now() + base::TimeDelta::FromHours(1));
726
727   base::RunLoop().RunUntilIdle();
728   ASSERT_FALSE(reconcilor->is_reconcile_started_);
729 }
730
731 TEST_P(AccountReconcilorTest, StartReconcileWithSessionInfoExpiredDefault) {
732   signin_manager()->SetAuthenticatedUsername("user@gmail.com");
733   token_service()->UpdateCredentials("user@gmail.com", "refresh_token");
734   token_service()->UpdateCredentials("other@gmail.com", "refresh_token");
735
736   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("user@gmail.com"));
737
738   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
739       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 0],"
740                "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
741       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
742   SetFakeResponse("https://www.googleapis.com/oauth2/v1/userinfo",
743       "{\"id\":\"foo\"}", net::HTTP_OK, net::URLRequestStatus::SUCCESS);
744
745   AccountReconcilor* reconcilor =
746       AccountReconcilorFactory::GetForProfile(profile());
747   ASSERT_TRUE(reconcilor);
748
749   ASSERT_FALSE(reconcilor->is_reconcile_started_);
750   reconcilor->StartReconcile();
751   ASSERT_TRUE(reconcilor->is_reconcile_started_);
752
753   token_service()->IssueAllTokensForAccount("user@gmail.com", "access_token",
754       base::Time::Now() + base::TimeDelta::FromHours(1));
755   token_service()->IssueAllTokensForAccount("other@gmail.com", "access_token",
756       base::Time::Now() + base::TimeDelta::FromHours(1));
757
758   base::RunLoop().RunUntilIdle();
759   SimulateMergeSessionCompleted(reconcilor, "user@gmail.com",
760                                 GoogleServiceAuthError::AuthErrorNone());
761   ASSERT_FALSE(reconcilor->is_reconcile_started_);
762 }
763
764 INSTANTIATE_TEST_CASE_P(AccountReconcilorMaybeEnabled,
765                         AccountReconcilorTest,
766                         testing::Bool());