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