• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/test/histogram_tester.h"
10 #include "base/time/time.h"
11 #include "build/build_config.h"
12 #include "chrome/browser/prefs/pref_service_syncable.h"
13 #include "chrome/browser/signin/account_reconcilor_factory.h"
14 #include "chrome/browser/signin/chrome_signin_client_factory.h"
15 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
16 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
17 #include "chrome/browser/signin/fake_signin_manager.h"
18 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
19 #include "chrome/browser/signin/signin_manager_factory.h"
20 #include "chrome/browser/signin/test_signin_client_builder.h"
21 #include "chrome/test/base/testing_browser_process.h"
22 #include "chrome/test/base/testing_profile.h"
23 #include "chrome/test/base/testing_profile_manager.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 
40 class MockAccountReconcilor : public testing::StrictMock<AccountReconcilor> {
41  public:
42   static KeyedService* Build(content::BrowserContext* context);
43 
44   MockAccountReconcilor(ProfileOAuth2TokenService* token_service,
45                         SigninManagerBase* signin_manager,
46                         SigninClient* client);
~MockAccountReconcilor()47   virtual ~MockAccountReconcilor() {}
48 
StartFetchingExternalCcResult()49   virtual void StartFetchingExternalCcResult() OVERRIDE {
50     // Don't do this in tests.
51   }
52 
53   MOCK_METHOD1(PerformMergeAction, void(const std::string& account_id));
54   MOCK_METHOD0(PerformLogoutAllAccountsAction, void());
55 };
56 
57 // static
Build(content::BrowserContext * context)58 KeyedService* MockAccountReconcilor::Build(content::BrowserContext* context) {
59   Profile* profile = Profile::FromBrowserContext(context);
60   AccountReconcilor* reconcilor = new MockAccountReconcilor(
61       ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
62       SigninManagerFactory::GetForProfile(profile),
63       ChromeSigninClientFactory::GetForProfile(profile));
64   reconcilor->Initialize(false /* start_reconcile_if_tokens_available */);
65   return reconcilor;
66 }
67 
MockAccountReconcilor(ProfileOAuth2TokenService * token_service,SigninManagerBase * signin_manager,SigninClient * client)68 MockAccountReconcilor::MockAccountReconcilor(
69     ProfileOAuth2TokenService* token_service,
70     SigninManagerBase* signin_manager,
71     SigninClient* client)
72     : testing::StrictMock<AccountReconcilor>(token_service,
73                                              signin_manager,
74                                              client) {}
75 
76 }  // namespace
77 
78 class AccountReconcilorTest : public ::testing::TestWithParam<bool> {
79  public:
80   AccountReconcilorTest();
81   virtual void SetUp() OVERRIDE;
82 
profile()83   TestingProfile* profile() { return profile_; }
signin_manager()84   FakeSigninManagerForTesting* signin_manager() { return signin_manager_; }
token_service()85   FakeProfileOAuth2TokenService* token_service() { return token_service_; }
histogram_tester()86   base::HistogramTester* histogram_tester() { return &histogram_tester_; }
87 
SetFakeResponse(const std::string & url,const std::string & data,net::HttpStatusCode code,net::URLRequestStatus::Status status)88   void SetFakeResponse(const std::string& url,
89                        const std::string& data,
90                        net::HttpStatusCode code,
91                        net::URLRequestStatus::Status status) {
92     url_fetcher_factory_.SetFakeResponse(GURL(url), data, code, status);
93   }
94 
95   MockAccountReconcilor* GetMockReconcilor();
96 
97   void SimulateMergeSessionCompleted(
98       MergeSessionHelper::Observer* observer,
99       const std::string& account_id,
100       const GoogleServiceAuthError& error);
101 
102  private:
103   content::TestBrowserThreadBundle bundle_;
104   TestingProfile* profile_;
105   FakeSigninManagerForTesting* signin_manager_;
106   FakeProfileOAuth2TokenService* token_service_;
107   MockAccountReconcilor* mock_reconcilor_;
108   net::FakeURLFetcherFactory url_fetcher_factory_;
109   scoped_ptr<TestingProfileManager> testing_profile_manager_;
110   base::HistogramTester histogram_tester_;
111 
112   DISALLOW_COPY_AND_ASSIGN(AccountReconcilorTest);
113 };
114 
AccountReconcilorTest()115 AccountReconcilorTest::AccountReconcilorTest()
116     : signin_manager_(NULL),
117       token_service_(NULL),
118       mock_reconcilor_(NULL),
119       url_fetcher_factory_(NULL) {}
120 
SetUp()121 void AccountReconcilorTest::SetUp() {
122   // If it's a non-parameterized test, or we have a parameter of true, set flag.
123   if (!::testing::UnitTest::GetInstance()->current_test_info()->value_param() ||
124       GetParam()) {
125     CommandLine::ForCurrentProcess()->AppendSwitch(
126         switches::kEnableNewProfileManagement);
127   }
128 
129   testing_profile_manager_.reset(
130       new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
131   ASSERT_TRUE(testing_profile_manager_.get()->SetUp());
132 
133   TestingProfile::TestingFactories factories;
134   factories.push_back(std::make_pair(ChromeSigninClientFactory::GetInstance(),
135       signin::BuildTestSigninClient));
136   factories.push_back(std::make_pair(
137       ProfileOAuth2TokenServiceFactory::GetInstance(),
138       BuildFakeProfileOAuth2TokenService));
139   factories.push_back(std::make_pair(SigninManagerFactory::GetInstance(),
140       FakeSigninManagerBase::Build));
141   factories.push_back(std::make_pair(AccountReconcilorFactory::GetInstance(),
142       MockAccountReconcilor::Build));
143 
144   profile_ = testing_profile_manager_.get()->CreateTestingProfile("name",
145                               scoped_ptr<PrefServiceSyncable>(),
146                               base::UTF8ToUTF16("name"), 0, std::string(),
147                               factories);
148 
149   signin_manager_ =
150       static_cast<FakeSigninManagerForTesting*>(
151           SigninManagerFactory::GetForProfile(profile()));
152 
153   token_service_ =
154       static_cast<FakeProfileOAuth2TokenService*>(
155           ProfileOAuth2TokenServiceFactory::GetForProfile(profile()));
156 }
157 
GetMockReconcilor()158 MockAccountReconcilor* AccountReconcilorTest::GetMockReconcilor() {
159   if (!mock_reconcilor_) {
160     mock_reconcilor_ =
161         static_cast<MockAccountReconcilor*>(
162             AccountReconcilorFactory::GetForProfile(profile()));
163   }
164 
165   return mock_reconcilor_;
166 }
167 
SimulateMergeSessionCompleted(MergeSessionHelper::Observer * observer,const std::string & account_id,const GoogleServiceAuthError & error)168 void AccountReconcilorTest::SimulateMergeSessionCompleted(
169     MergeSessionHelper::Observer* observer,
170     const std::string& account_id,
171     const GoogleServiceAuthError& error) {
172   observer->MergeSessionCompleted(account_id, error);
173 }
174 
TEST_F(AccountReconcilorTest,Basic)175 TEST_F(AccountReconcilorTest, Basic) {
176   AccountReconcilor* reconcilor =
177       AccountReconcilorFactory::GetForProfile(profile());
178   ASSERT_TRUE(reconcilor);
179   ASSERT_EQ(token_service(), reconcilor->token_service());
180 }
181 
182 #if !defined(OS_CHROMEOS)
183 
184 // This method requires the use of the |TestSigninClient| to be created from the
185 // |ChromeSigninClientFactory| because it overrides the |GoogleSigninSucceeded|
186 // method with an empty implementation. On MacOS, the normal implementation
187 // causes the try_bots to time out.
TEST_F(AccountReconcilorTest,SigninManagerRegistration)188 TEST_F(AccountReconcilorTest, SigninManagerRegistration) {
189   AccountReconcilor* reconcilor =
190       AccountReconcilorFactory::GetForProfile(profile());
191   ASSERT_TRUE(reconcilor);
192   ASSERT_FALSE(reconcilor->IsRegisteredWithTokenService());
193 
194   signin_manager()->set_password("password");
195   signin_manager()->OnExternalSigninCompleted(kTestEmail);
196   ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService());
197 
198   EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
199 
200   signin_manager()->SignOut(signin_metrics::SIGNOUT_TEST);
201   ASSERT_FALSE(reconcilor->IsRegisteredWithTokenService());
202 }
203 
204 // This method requires the use of the |TestSigninClient| to be created from the
205 // |ChromeSigninClientFactory| because it overrides the |GoogleSigninSucceeded|
206 // method with an empty implementation. On MacOS, the normal implementation
207 // causes the try_bots to time out.
TEST_F(AccountReconcilorTest,Reauth)208 TEST_F(AccountReconcilorTest, Reauth) {
209   signin_manager()->SetAuthenticatedUsername(kTestEmail);
210   signin_manager()->set_password("password");
211 
212   AccountReconcilor* reconcilor =
213       AccountReconcilorFactory::GetForProfile(profile());
214   ASSERT_TRUE(reconcilor);
215   ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService());
216 
217   // Simulate reauth.  The state of the reconcilor should not change.
218   signin_manager()->OnExternalSigninCompleted(kTestEmail);
219   ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService());
220 }
221 
222 #endif  // !defined(OS_CHROMEOS)
223 
TEST_F(AccountReconcilorTest,ProfileAlreadyConnected)224 TEST_F(AccountReconcilorTest, ProfileAlreadyConnected) {
225   signin_manager()->SetAuthenticatedUsername(kTestEmail);
226 
227   AccountReconcilor* reconcilor =
228       AccountReconcilorFactory::GetForProfile(profile());
229   ASSERT_TRUE(reconcilor);
230   ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService());
231 }
232 
TEST_F(AccountReconcilorTest,GetAccountsFromCookieSuccess)233 TEST_F(AccountReconcilorTest, GetAccountsFromCookieSuccess) {
234   signin_manager()->SetAuthenticatedUsername(kTestEmail);
235   token_service()->UpdateCredentials(kTestEmail, "refresh_token");
236   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(kTestEmail));
237   AccountReconcilor* reconcilor =
238       AccountReconcilorFactory::GetForProfile(profile());
239   ASSERT_TRUE(reconcilor);
240 
241   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
242       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 0]]]",
243       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
244 
245   reconcilor->StartReconcile();
246   ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
247 
248   base::RunLoop().RunUntilIdle();
249   ASSERT_TRUE(reconcilor->AreGaiaAccountsSet());
250   const std::vector<std::pair<std::string, bool> >& accounts =
251       reconcilor->GetGaiaAccountsForTesting();
252   ASSERT_EQ(1u, accounts.size());
253   ASSERT_EQ("user@gmail.com", accounts[0].first);
254 }
255 
TEST_F(AccountReconcilorTest,GetAccountsFromCookieFailure)256 TEST_F(AccountReconcilorTest, GetAccountsFromCookieFailure) {
257   signin_manager()->SetAuthenticatedUsername(kTestEmail);
258   token_service()->UpdateCredentials(kTestEmail, "refresh_token");
259   AccountReconcilor* reconcilor =
260       AccountReconcilorFactory::GetForProfile(profile());
261   ASSERT_TRUE(reconcilor);
262 
263   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(), "",
264       net::HTTP_NOT_FOUND, net::URLRequestStatus::SUCCESS);
265 
266   reconcilor->StartReconcile();
267   ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
268 
269   base::RunLoop().RunUntilIdle();
270   ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
271 }
272 
TEST_P(AccountReconcilorTest,StartReconcileNoop)273 TEST_P(AccountReconcilorTest, StartReconcileNoop) {
274   signin_manager()->SetAuthenticatedUsername(kTestEmail);
275   token_service()->UpdateCredentials(kTestEmail, "refresh_token");
276 
277   AccountReconcilor* reconcilor =
278       AccountReconcilorFactory::GetForProfile(profile());
279   ASSERT_TRUE(reconcilor);
280 
281   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
282       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
283       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
284 
285   reconcilor->StartReconcile();
286   ASSERT_TRUE(reconcilor->is_reconcile_started_);
287   ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
288 
289   base::RunLoop().RunUntilIdle();
290   ASSERT_FALSE(reconcilor->is_reconcile_started_);
291 
292   histogram_tester()->ExpectTotalCount(
293       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 1);
294   histogram_tester()->ExpectUniqueSample(
295       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
296       signin_metrics::ACCOUNTS_SAME,
297       1);
298 }
299 
300 // This is test is needed until chrome changes to use gaia obfuscated id.
301 // The signin manager and token service use the gaia "email" property, which
302 // preserves dots in usernames and preserves case. gaia::ParseListAccountsData()
303 // however uses gaia "displayEmail" which does not preserve case, and then
304 // passes the string through gaia::CanonicalizeEmail() which removes dots.  This
305 // tests makes sure that an email like "Dot.S@hmail.com", as seen by the
306 // token service, will be considered the same as "dots@gmail.com" as returned
307 // by gaia::ParseListAccountsData().
TEST_P(AccountReconcilorTest,StartReconcileNoopWithDots)308 TEST_P(AccountReconcilorTest, StartReconcileNoopWithDots) {
309   signin_manager()->SetAuthenticatedUsername("Dot.S@gmail.com");
310   token_service()->UpdateCredentials("Dot.S@gmail.com", "refresh_token");
311 
312   AccountReconcilor* reconcilor =
313       AccountReconcilorFactory::GetForProfile(profile());
314   ASSERT_TRUE(reconcilor);
315 
316   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
317       "[\"f\", [[\"b\", 0, \"n\", \"dot.s@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
318       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
319 
320   reconcilor->StartReconcile();
321   ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
322 
323   base::RunLoop().RunUntilIdle();
324   ASSERT_FALSE(reconcilor->is_reconcile_started_);
325 
326   histogram_tester()->ExpectUniqueSample(
327       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
328       signin_metrics::ACCOUNTS_SAME,
329       1);
330 }
331 
TEST_P(AccountReconcilorTest,StartReconcileNoopMultiple)332 TEST_P(AccountReconcilorTest, StartReconcileNoopMultiple) {
333   signin_manager()->SetAuthenticatedUsername("user@gmail.com");
334   token_service()->UpdateCredentials("user@gmail.com", "refresh_token");
335   token_service()->UpdateCredentials("other@gmail.com", "refresh_token");
336 
337   AccountReconcilor* reconcilor =
338       AccountReconcilorFactory::GetForProfile(profile());
339   ASSERT_TRUE(reconcilor);
340 
341   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
342       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1], "
343                "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
344       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
345 
346   reconcilor->StartReconcile();
347   ASSERT_FALSE(reconcilor->AreGaiaAccountsSet());
348   base::RunLoop().RunUntilIdle();
349   ASSERT_FALSE(reconcilor->is_reconcile_started_);
350 
351   histogram_tester()->ExpectTotalCount(
352       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun", 1);
353   histogram_tester()->ExpectUniqueSample(
354       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
355       signin_metrics::ACCOUNTS_SAME,
356       1);
357 }
358 
TEST_P(AccountReconcilorTest,StartReconcileAddToCookie)359 TEST_P(AccountReconcilorTest, StartReconcileAddToCookie) {
360   signin_manager()->SetAuthenticatedUsername("user@gmail.com");
361   token_service()->UpdateCredentials("user@gmail.com", "refresh_token");
362   token_service()->UpdateCredentials("other@gmail.com", "refresh_token");
363 
364   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("other@gmail.com"));
365 
366   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
367       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
368       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
369 
370   AccountReconcilor* reconcilor = GetMockReconcilor();
371   reconcilor->StartReconcile();
372 
373   base::RunLoop().RunUntilIdle();
374   ASSERT_TRUE(reconcilor->is_reconcile_started_);
375   SimulateMergeSessionCompleted(reconcilor, "other@gmail.com",
376                                 GoogleServiceAuthError::AuthErrorNone());
377   ASSERT_FALSE(reconcilor->is_reconcile_started_);
378 
379   histogram_tester()->ExpectUniqueSample(
380       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
381       signin_metrics::ACCOUNTS_SAME,
382       1);
383   histogram_tester()->ExpectUniqueSample(
384       "Signin.Reconciler.AddedToCookieJar.FirstRun", 1, 1);
385   histogram_tester()->ExpectUniqueSample(
386       "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1);
387 }
388 
TEST_P(AccountReconcilorTest,StartReconcileRemoveFromCookie)389 TEST_P(AccountReconcilorTest, StartReconcileRemoveFromCookie) {
390   signin_manager()->SetAuthenticatedUsername("user@gmail.com");
391   token_service()->UpdateCredentials("user@gmail.com", "refresh_token");
392 
393   EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
394   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("user@gmail.com"));
395 
396   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
397       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1], "
398                "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
399       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
400 
401   AccountReconcilor* reconcilor = GetMockReconcilor();
402   reconcilor->StartReconcile();
403   ASSERT_TRUE(reconcilor->is_reconcile_started_);
404 
405   base::RunLoop().RunUntilIdle();
406   SimulateMergeSessionCompleted(reconcilor, "user@gmail.com",
407                                 GoogleServiceAuthError::AuthErrorNone());
408   ASSERT_FALSE(reconcilor->is_reconcile_started_);
409 
410   histogram_tester()->ExpectUniqueSample(
411       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
412       signin_metrics::ACCOUNTS_SAME,
413       1);
414   histogram_tester()->ExpectUniqueSample(
415       "Signin.Reconciler.AddedToCookieJar.FirstRun", 0, 1);
416   histogram_tester()->ExpectUniqueSample(
417       "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 1, 1);
418 }
419 
TEST_P(AccountReconcilorTest,StartReconcileAddToCookieTwice)420 TEST_P(AccountReconcilorTest, StartReconcileAddToCookieTwice) {
421   signin_manager()->SetAuthenticatedUsername("user@gmail.com");
422   token_service()->UpdateCredentials("user@gmail.com", "refresh_token");
423   token_service()->UpdateCredentials("other@gmail.com", "refresh_token");
424 
425   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("other@gmail.com"));
426   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("third@gmail.com"));
427 
428   SetFakeResponse(
429       GaiaUrls::GetInstance()->list_accounts_url().spec(),
430       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
431       net::HTTP_OK,
432       net::URLRequestStatus::SUCCESS);
433 
434   AccountReconcilor* reconcilor = GetMockReconcilor();
435   reconcilor->StartReconcile();
436 
437   base::RunLoop().RunUntilIdle();
438   ASSERT_TRUE(reconcilor->is_reconcile_started_);
439   SimulateMergeSessionCompleted(
440       reconcilor, "other@gmail.com", GoogleServiceAuthError::AuthErrorNone());
441   ASSERT_FALSE(reconcilor->is_reconcile_started_);
442 
443   histogram_tester()->ExpectUniqueSample(
444       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
445       signin_metrics::ACCOUNTS_SAME,
446       1);
447   histogram_tester()->ExpectUniqueSample(
448       "Signin.Reconciler.AddedToCookieJar.FirstRun", 1, 1);
449   histogram_tester()->ExpectUniqueSample(
450       "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1);
451 
452   // Do another pass after I've added a third account to the token service
453 
454   SetFakeResponse(
455       GaiaUrls::GetInstance()->list_accounts_url().spec(),
456       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1], "
457       "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
458       net::HTTP_OK,
459       net::URLRequestStatus::SUCCESS);
460   // This will cause the reconcilor to fire.
461   token_service()->UpdateCredentials("third@gmail.com", "refresh_token");
462 
463   base::RunLoop().RunUntilIdle();
464 
465   ASSERT_TRUE(reconcilor->is_reconcile_started_);
466   SimulateMergeSessionCompleted(
467       reconcilor, "third@gmail.com", GoogleServiceAuthError::AuthErrorNone());
468   ASSERT_FALSE(reconcilor->is_reconcile_started_);
469 
470   histogram_tester()->ExpectUniqueSample(
471       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
472       signin_metrics::ACCOUNTS_SAME,
473       1);
474   histogram_tester()->ExpectUniqueSample(
475       "Signin.Reconciler.AddedToCookieJar.FirstRun", 1, 1);
476   histogram_tester()->ExpectUniqueSample(
477       "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1);
478   histogram_tester()->ExpectUniqueSample(
479       "Signin.Reconciler.DifferentPrimaryAccounts.SubsequentRun",
480       signin_metrics::ACCOUNTS_SAME,
481       1);
482   histogram_tester()->ExpectUniqueSample(
483       "Signin.Reconciler.AddedToCookieJar.SubsequentRun", 1, 1);
484   histogram_tester()->ExpectUniqueSample(
485       "Signin.Reconciler.RemovedFromCookieJar.SubsequentRun", 0, 1);
486 }
487 
TEST_P(AccountReconcilorTest,StartReconcileBadPrimary)488 TEST_P(AccountReconcilorTest, StartReconcileBadPrimary) {
489   signin_manager()->SetAuthenticatedUsername("user@gmail.com");
490   token_service()->UpdateCredentials("user@gmail.com", "refresh_token");
491   token_service()->UpdateCredentials("other@gmail.com", "refresh_token");
492 
493   EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
494   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("user@gmail.com"));
495   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("other@gmail.com"));
496 
497   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
498       "[\"f\", [[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1], "
499                "[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
500       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
501 
502   AccountReconcilor* reconcilor = GetMockReconcilor();
503   reconcilor->StartReconcile();
504 
505   base::RunLoop().RunUntilIdle();
506   ASSERT_TRUE(reconcilor->is_reconcile_started_);
507   SimulateMergeSessionCompleted(reconcilor, "other@gmail.com",
508                                 GoogleServiceAuthError::AuthErrorNone());
509   ASSERT_TRUE(reconcilor->is_reconcile_started_);
510   SimulateMergeSessionCompleted(reconcilor, "user@gmail.com",
511                                 GoogleServiceAuthError::AuthErrorNone());
512   ASSERT_FALSE(reconcilor->is_reconcile_started_);
513 
514   histogram_tester()->ExpectUniqueSample(
515       "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
516       signin_metrics::COOKIE_AND_TOKEN_PRIMARIES_DIFFERENT,
517       1);
518   histogram_tester()->ExpectUniqueSample(
519       "Signin.Reconciler.AddedToCookieJar.FirstRun", 0, 1);
520   histogram_tester()->ExpectUniqueSample(
521       "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1);
522 }
523 
TEST_P(AccountReconcilorTest,StartReconcileOnlyOnce)524 TEST_P(AccountReconcilorTest, StartReconcileOnlyOnce) {
525   signin_manager()->SetAuthenticatedUsername(kTestEmail);
526   token_service()->UpdateCredentials(kTestEmail, "refresh_token");
527 
528   AccountReconcilor* reconcilor =
529       AccountReconcilorFactory::GetForProfile(profile());
530   ASSERT_TRUE(reconcilor);
531 
532   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
533       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
534       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
535 
536   ASSERT_FALSE(reconcilor->is_reconcile_started_);
537   reconcilor->StartReconcile();
538   ASSERT_TRUE(reconcilor->is_reconcile_started_);
539 
540   base::RunLoop().RunUntilIdle();
541   ASSERT_FALSE(reconcilor->is_reconcile_started_);
542 }
543 
TEST_P(AccountReconcilorTest,StartReconcileWithSessionInfoExpiredDefault)544 TEST_P(AccountReconcilorTest, StartReconcileWithSessionInfoExpiredDefault) {
545   signin_manager()->SetAuthenticatedUsername("user@gmail.com");
546   token_service()->UpdateCredentials("user@gmail.com", "refresh_token");
547   token_service()->UpdateCredentials("other@gmail.com", "refresh_token");
548 
549   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("user@gmail.com"));
550 
551   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
552       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 0],"
553                "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]",
554       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
555 
556   AccountReconcilor* reconcilor =
557       AccountReconcilorFactory::GetForProfile(profile());
558   ASSERT_TRUE(reconcilor);
559 
560   ASSERT_FALSE(reconcilor->is_reconcile_started_);
561   reconcilor->StartReconcile();
562   ASSERT_TRUE(reconcilor->is_reconcile_started_);
563 
564   base::RunLoop().RunUntilIdle();
565   SimulateMergeSessionCompleted(reconcilor, "user@gmail.com",
566                                 GoogleServiceAuthError::AuthErrorNone());
567   ASSERT_FALSE(reconcilor->is_reconcile_started_);
568 }
569 
TEST_F(AccountReconcilorTest,MergeSessionCompletedWithBogusAccount)570 TEST_F(AccountReconcilorTest, MergeSessionCompletedWithBogusAccount) {
571   signin_manager()->SetAuthenticatedUsername("user@gmail.com");
572   token_service()->UpdateCredentials("user@gmail.com", "refresh_token");
573 
574   EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction("user@gmail.com"));
575 
576   SetFakeResponse(GaiaUrls::GetInstance()->list_accounts_url().spec(),
577       "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 0]]]",
578       net::HTTP_OK, net::URLRequestStatus::SUCCESS);
579 
580   AccountReconcilor* reconcilor =
581       AccountReconcilorFactory::GetForProfile(profile());
582   ASSERT_TRUE(reconcilor);
583 
584   ASSERT_FALSE(reconcilor->is_reconcile_started_);
585   reconcilor->StartReconcile();
586   ASSERT_TRUE(reconcilor->is_reconcile_started_);
587 
588   base::RunLoop().RunUntilIdle();
589 
590   // If an unknown account id is sent, it should not upset the state.
591   SimulateMergeSessionCompleted(reconcilor, "bogus@gmail.com",
592                                 GoogleServiceAuthError::AuthErrorNone());
593   ASSERT_TRUE(reconcilor->is_reconcile_started_);
594 
595   SimulateMergeSessionCompleted(reconcilor, "user@gmail.com",
596                                 GoogleServiceAuthError::AuthErrorNone());
597   ASSERT_FALSE(reconcilor->is_reconcile_started_);
598 }
599 
600 INSTANTIATE_TEST_CASE_P(AccountReconcilorMaybeEnabled,
601                         AccountReconcilorTest,
602                         testing::Bool());
603 
604