blob: a2e5ba8bbc8a8c8378651d6ad3bdc340aaa313ed [file] [log] [blame]
blundell1e21bd32017-05-03 15:25:571// Copyright 2017 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/run_loop.h"
Colin Blundell2c8951de2017-07-07 13:23:456#include "build/build_config.h"
Colin Blundell704d198e2017-06-05 11:27:137#include "components/signin/core/browser/account_info.h"
blundell1e21bd32017-05-03 15:25:578#include "components/signin/core/browser/account_tracker_service.h"
Colin Blundelle89886a2017-06-12 11:26:569#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
blundell1e21bd32017-05-03 15:25:5710#include "components/signin/core/browser/fake_signin_manager.h"
11#include "components/signin/core/browser/test_signin_client.h"
12#include "components/sync_preferences/testing_pref_service_syncable.h"
13#include "mojo/public/cpp/bindings/binding_set.h"
14#include "services/identity/identity_service.h"
Colin Blundell57fb6502017-06-27 12:24:3415#include "services/identity/public/cpp/account_state.h"
Colin Blundelle89886a2017-06-12 11:26:5616#include "services/identity/public/cpp/scope_set.h"
blundell1e21bd32017-05-03 15:25:5717#include "services/identity/public/interfaces/constants.mojom.h"
18#include "services/identity/public/interfaces/identity_manager.mojom.h"
19#include "services/service_manager/public/cpp/binder_registry.h"
20#include "services/service_manager/public/cpp/service_context.h"
21#include "services/service_manager/public/cpp/service_test.h"
22#include "services/service_manager/public/interfaces/service_factory.mojom.h"
23
24namespace identity {
25namespace {
26
Colin Blundell6430f5d2017-07-13 10:17:1327// Delay that is long enough that the Identity Manager will receive and respond
28// to a sent request within this delay *if* the connection is allowed. Local
29// experimentation indicates that 2500 microseconds is long enough to allow this
30// round trip to occur; we double that to give padding. Note that this delay is
31// only ever used in cases where we want to verify that a message wasn't
32// responded to by the Identity Manager. Hence, if this time is ever too short
33// it won't cause tests to hang; it will simply mean that in that case the tests
34// might pass because the connection wasn't made *yet* as opposed to wasn't made
35// *at all*.
36const int kRoundTripMessageTimeInMicroseconds = 5000;
37
Colin Blundell2c8951de2017-07-07 13:23:4538#if defined(OS_CHROMEOS)
39using SigninManagerForTest = FakeSigninManagerBase;
40#else
41using SigninManagerForTest = FakeSigninManager;
42#endif // OS_CHROMEOS
43
blundell1e21bd32017-05-03 15:25:5744const std::string kTestGaiaId = "dummyId";
45const std::string kTestEmail = "[email protected]";
Colin Blundelle89886a2017-06-12 11:26:5646const std::string kTestRefreshToken = "dummy-refresh-token";
47const std::string kTestAccessToken = "access_token";
blundell1e21bd32017-05-03 15:25:5748
49class ServiceTestClient : public service_manager::test::ServiceTestClient,
50 public service_manager::mojom::ServiceFactory {
51 public:
52 ServiceTestClient(service_manager::test::ServiceTest* test,
Colin Blundell2f987fd2017-06-23 10:49:0653 AccountTrackerService* account_tracker,
Colin Blundelle89886a2017-06-12 11:26:5654 SigninManagerBase* signin_manager,
55 ProfileOAuth2TokenService* token_service)
blundell1e21bd32017-05-03 15:25:5756 : service_manager::test::ServiceTestClient(test),
Colin Blundell2f987fd2017-06-23 10:49:0657 account_tracker_(account_tracker),
Colin Blundelle89886a2017-06-12 11:26:5658 signin_manager_(signin_manager),
59 token_service_(token_service) {
blundell1e21bd32017-05-03 15:25:5760 registry_.AddInterface<service_manager::mojom::ServiceFactory>(
61 base::Bind(&ServiceTestClient::Create, base::Unretained(this)));
62 }
63
64 protected:
65 void OnBindInterface(const service_manager::BindSourceInfo& source_info,
66 const std::string& interface_name,
67 mojo::ScopedMessagePipeHandle interface_pipe) override {
Ben Goodger21ada1e2017-07-19 14:53:0168 registry_.BindInterface(interface_name, std::move(interface_pipe));
blundell1e21bd32017-05-03 15:25:5769 }
70
71 void CreateService(service_manager::mojom::ServiceRequest request,
72 const std::string& name) override {
73 if (name == mojom::kServiceName) {
74 identity_service_context_.reset(new service_manager::ServiceContext(
Colin Blundell2f987fd2017-06-23 10:49:0675 base::MakeUnique<IdentityService>(account_tracker_, signin_manager_,
76 token_service_),
blundell1e21bd32017-05-03 15:25:5777 std::move(request)));
78 }
79 }
80
Ben Goodger21ada1e2017-07-19 14:53:0181 void Create(service_manager::mojom::ServiceFactoryRequest request) {
blundell1e21bd32017-05-03 15:25:5782 service_factory_bindings_.AddBinding(this, std::move(request));
83 }
84
85 private:
Colin Blundell2f987fd2017-06-23 10:49:0686 AccountTrackerService* account_tracker_;
blundell1e21bd32017-05-03 15:25:5787 SigninManagerBase* signin_manager_;
Colin Blundelle89886a2017-06-12 11:26:5688 ProfileOAuth2TokenService* token_service_;
blundell1e21bd32017-05-03 15:25:5789 service_manager::BinderRegistry registry_;
90 mojo::BindingSet<service_manager::mojom::ServiceFactory>
91 service_factory_bindings_;
92 std::unique_ptr<service_manager::ServiceContext> identity_service_context_;
93};
94
95class IdentityManagerTest : public service_manager::test::ServiceTest {
96 public:
97 IdentityManagerTest()
98 : ServiceTest("identity_unittests", false),
99 signin_client_(&pref_service_),
Colin Blundell2c8951de2017-07-07 13:23:45100#if defined(OS_CHROMEOS)
blundell1e21bd32017-05-03 15:25:57101 signin_manager_(&signin_client_, &account_tracker_) {
Colin Blundell2c8951de2017-07-07 13:23:45102#else
103 signin_manager_(&signin_client_,
104 &token_service_,
105 &account_tracker_,
106 nullptr) {
107#endif
blundell1e21bd32017-05-03 15:25:57108 AccountTrackerService::RegisterPrefs(pref_service_.registry());
109 SigninManagerBase::RegisterProfilePrefs(pref_service_.registry());
110 SigninManagerBase::RegisterPrefs(pref_service_.registry());
111
112 account_tracker_.Initialize(&signin_client_);
113 }
114
Colin Blundelld829d852017-06-30 11:06:06115 void TearDown() override {
116 // Shut down the SigninManager so that the IdentityManager doesn't end up
117 // outliving it.
118 signin_manager_.Shutdown();
119 ServiceTest::TearDown();
120 }
121
Colin Blundell704d198e2017-06-05 11:27:13122 void OnReceivedPrimaryAccountInfo(
123 base::Closure quit_closure,
Colin Blundell57fb6502017-06-27 12:24:34124 const base::Optional<AccountInfo>& account_info,
125 const AccountState& account_state) {
Colin Blundell704d198e2017-06-05 11:27:13126 primary_account_info_ = account_info;
Colin Blundell57fb6502017-06-27 12:24:34127 primary_account_state_ = account_state;
blundell1e21bd32017-05-03 15:25:57128 quit_closure.Run();
129 }
130
Colin Blundellbdf4642d2017-07-06 07:00:03131 void OnPrimaryAccountAvailable(base::Closure quit_closure,
132 AccountInfo* caller_account_info,
133 AccountState* caller_account_state,
134 const AccountInfo& account_info,
135 const AccountState& account_state) {
136 *caller_account_info = account_info;
137 *caller_account_state = account_state;
138 quit_closure.Run();
139 }
140
Colin Blundell2f987fd2017-06-23 10:49:06141 void OnReceivedAccountInfoFromGaiaId(
142 base::Closure quit_closure,
Colin Blundell57fb6502017-06-27 12:24:34143 const base::Optional<AccountInfo>& account_info,
144 const AccountState& account_state) {
Colin Blundell2f987fd2017-06-23 10:49:06145 account_info_from_gaia_id_ = account_info;
Colin Blundell57fb6502017-06-27 12:24:34146 account_state_from_gaia_id_ = account_state;
Colin Blundell2f987fd2017-06-23 10:49:06147 quit_closure.Run();
148 }
149
Colin Blundelle89886a2017-06-12 11:26:56150 void OnReceivedAccessToken(base::Closure quit_closure,
151 const base::Optional<std::string>& access_token,
152 base::Time expiration_time,
153 const GoogleServiceAuthError& error) {
154 access_token_ = access_token;
155 access_token_error_ = error;
156 quit_closure.Run();
157 }
158
blundell1e21bd32017-05-03 15:25:57159 protected:
Colin Blundell25a80822017-07-13 06:17:52160 void SetUp() override { ServiceTest::SetUp(); }
blundell1e21bd32017-05-03 15:25:57161
Colin Blundell25a80822017-07-13 06:17:52162 mojom::IdentityManager* GetIdentityManager() {
163 if (!identity_manager_)
164 connector()->BindInterface(mojom::kServiceName, &identity_manager_);
165 return identity_manager_.get();
166 }
167
168 void ResetIdentityManager() { identity_manager_.reset(); }
169
170 void FlushIdentityManagerForTesting() {
171 GetIdentityManager();
172 identity_manager_.FlushForTesting();
173 }
174
175 void SetIdentityManagerConnectionErrorHandler(base::Closure handler) {
176 GetIdentityManager();
177 identity_manager_.set_connection_error_handler(handler);
blundell1e21bd32017-05-03 15:25:57178 }
179
180 // service_manager::test::ServiceTest:
181 std::unique_ptr<service_manager::Service> CreateService() override {
Colin Blundell2f987fd2017-06-23 10:49:06182 return base::MakeUnique<ServiceTestClient>(
183 this, &account_tracker_, &signin_manager_, &token_service_);
blundell1e21bd32017-05-03 15:25:57184 }
185
186 mojom::IdentityManagerPtr identity_manager_;
Colin Blundell704d198e2017-06-05 11:27:13187 base::Optional<AccountInfo> primary_account_info_;
Colin Blundell57fb6502017-06-27 12:24:34188 AccountState primary_account_state_;
Colin Blundell2f987fd2017-06-23 10:49:06189 base::Optional<AccountInfo> account_info_from_gaia_id_;
Colin Blundell57fb6502017-06-27 12:24:34190 AccountState account_state_from_gaia_id_;
Colin Blundelle89886a2017-06-12 11:26:56191 base::Optional<std::string> access_token_;
192 GoogleServiceAuthError access_token_error_;
blundell1e21bd32017-05-03 15:25:57193
Colin Blundell2f987fd2017-06-23 10:49:06194 AccountTrackerService* account_tracker() { return &account_tracker_; }
blundell1e21bd32017-05-03 15:25:57195 SigninManagerBase* signin_manager() { return &signin_manager_; }
Colin Blundelle89886a2017-06-12 11:26:56196 FakeProfileOAuth2TokenService* token_service() { return &token_service_; }
blundell1e21bd32017-05-03 15:25:57197
198 private:
199 sync_preferences::TestingPrefServiceSyncable pref_service_;
200 AccountTrackerService account_tracker_;
201 TestSigninClient signin_client_;
Colin Blundell2c8951de2017-07-07 13:23:45202 SigninManagerForTest signin_manager_;
Colin Blundelle89886a2017-06-12 11:26:56203 FakeProfileOAuth2TokenService token_service_;
blundell1e21bd32017-05-03 15:25:57204
205 DISALLOW_COPY_AND_ASSIGN(IdentityManagerTest);
206};
207
Colin Blundell6430f5d2017-07-13 10:17:13208// Tests that the Identity Service delays responding to consumers until its
209// internal state is stable after startup.
210TEST_F(IdentityManagerTest, StartupBeforeInternalStateStable) {
211 EXPECT_FALSE(token_service()->AreAllCredentialsLoaded());
212 AccountInfo sentinel;
213 sentinel.account_id = "sentinel";
214 primary_account_info_ = sentinel;
215
216 // Make a call to the IdentityManager before the Identity Service has reached
217 // an internal stable state, and verify that the IdentityManager does not yet
218 // respond.
219 base::RunLoop run_loop;
220 GetIdentityManager()->GetPrimaryAccountInfo(
221 base::Bind(&IdentityManagerTest::OnReceivedPrimaryAccountInfo,
222 base::Unretained(this), run_loop.QuitClosure()));
223
224 // Spin the run loop long enough for the above request to reach the Identity
225 // Service and for the Identity Manager to process it *if* it were started up
226 // in response. Note that it's not possible to wait on |run_loop| here since
227 // the behavior we're looking to verify is that the above callback is *not*
228 // invoked at this point. It's also not possible to use
229 // FlushIdentityManagerForTesting(), as the Identity Service might not even
230 // bind the IdentityManager request before initialization.
231 base::RunLoop run_loop2;
232 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
233 FROM_HERE, run_loop2.QuitClosure(),
234 base::TimeDelta::FromMicroseconds(kRoundTripMessageTimeInMicroseconds));
235 run_loop2.Run();
236
237 // Verify that the callback to GetPrimaryAccountInfo() was not invoked.
238 EXPECT_TRUE(primary_account_info_);
239 EXPECT_EQ("sentinel", primary_account_info_->account_id);
240
241 // Put the Identity Service in an internal stable state.
242 token_service()->LoadCredentials("sentinel");
243 EXPECT_TRUE(token_service()->AreAllCredentialsLoaded());
244
245 // Verify that the IdentityManager now responds to our earlier call.
246 run_loop.Run();
247 EXPECT_FALSE(primary_account_info_);
248}
249
250// Tests that the Identity Service immediately responds to consumers if first
251// connected to after its internal dependencies have reached a stable state.
252TEST_F(IdentityManagerTest, StartupAfterInternalStateStable) {
253 EXPECT_FALSE(token_service()->AreAllCredentialsLoaded());
254 token_service()->LoadCredentials("sentinel");
255 EXPECT_TRUE(token_service()->AreAllCredentialsLoaded());
256 AccountInfo sentinel;
257 sentinel.account_id = "sentinel";
258 primary_account_info_ = sentinel;
259
260 // Connect to the Identity Manager (causing the Identity Service to be started
261 // up), and verify that the Identity Manager responds immediately.
262 base::RunLoop run_loop;
263 GetIdentityManager()->GetPrimaryAccountInfo(
264 base::Bind(&IdentityManagerTest::OnReceivedPrimaryAccountInfo,
265 base::Unretained(this), run_loop.QuitClosure()));
266 run_loop.Run();
267 EXPECT_FALSE(primary_account_info_);
268}
269
Colin Blundell25a80822017-07-13 06:17:52270// Tests that it is not possible to connect to the Identity Manager if
271// initiated after SigninManager shutdown.
272TEST_F(IdentityManagerTest, SigninManagerShutdownBeforeConnection) {
Colin Blundell6430f5d2017-07-13 10:17:13273 token_service()->LoadCredentials("sentinel");
274
Colin Blundell25a80822017-07-13 06:17:52275 AccountInfo sentinel;
276 sentinel.account_id = "sentinel";
277 primary_account_info_ = sentinel;
278
279 // Ensure that the Identity Service has actually been created before
280 // invoking SigninManagerBase::Shutdown(), since otherwise this test will
281 // spin forever. Then reset the Identity Manager so that the next request
282 // makes a fresh connection.
283 FlushIdentityManagerForTesting();
284 ResetIdentityManager();
285
286 // Make a call to connect to the IdentityManager *after* SigninManager
287 // shutdown; it should get notified of an error when the Identity Service
288 // drops the connection.
289 signin_manager()->Shutdown();
Colin Blundelld829d852017-06-30 11:06:06290 base::RunLoop run_loop;
Colin Blundell25a80822017-07-13 06:17:52291 SetIdentityManagerConnectionErrorHandler(run_loop.QuitClosure());
292
293 GetIdentityManager()->GetPrimaryAccountInfo(
294 base::Bind(&IdentityManagerTest::OnReceivedPrimaryAccountInfo,
295 base::Unretained(this), run_loop.QuitClosure()));
296 run_loop.Run();
297
298 // Verify that the callback to GetPrimaryAccountInfo() was not invoked.
299 EXPECT_TRUE(primary_account_info_);
300 EXPECT_EQ("sentinel", primary_account_info_->account_id);
301}
302
303// Tests that the Identity Manager destroys itself on SigninManager shutdown.
304TEST_F(IdentityManagerTest, SigninManagerShutdownAfterConnection) {
Colin Blundell6430f5d2017-07-13 10:17:13305 token_service()->LoadCredentials("dummy");
306
Colin Blundell25a80822017-07-13 06:17:52307 base::RunLoop run_loop;
308 SetIdentityManagerConnectionErrorHandler(run_loop.QuitClosure());
Colin Blundelld829d852017-06-30 11:06:06309
310 // Ensure that the IdentityManager instance has actually been created before
311 // invoking SigninManagerBase::Shutdown(), since otherwise this test will
312 // spin forever.
Colin Blundell25a80822017-07-13 06:17:52313 FlushIdentityManagerForTesting();
Colin Blundelld829d852017-06-30 11:06:06314 signin_manager()->Shutdown();
315 run_loop.Run();
316}
317
Colin Blundell2f987fd2017-06-23 10:49:06318// Check that the primary account info is null if not signed in.
319TEST_F(IdentityManagerTest, GetPrimaryAccountInfoNotSignedIn) {
Colin Blundell6430f5d2017-07-13 10:17:13320 token_service()->LoadCredentials("dummy");
321
blundell1e21bd32017-05-03 15:25:57322 base::RunLoop run_loop;
Colin Blundell25a80822017-07-13 06:17:52323 GetIdentityManager()->GetPrimaryAccountInfo(
Colin Blundell704d198e2017-06-05 11:27:13324 base::Bind(&IdentityManagerTest::OnReceivedPrimaryAccountInfo,
blundell1e21bd32017-05-03 15:25:57325 base::Unretained(this), run_loop.QuitClosure()));
326 run_loop.Run();
Colin Blundell704d198e2017-06-05 11:27:13327 EXPECT_FALSE(primary_account_info_);
blundell1e21bd32017-05-03 15:25:57328}
329
Colin Blundell57fb6502017-06-27 12:24:34330// Check that the primary account info has expected values if signed in without
331// a refresh token available.
332TEST_F(IdentityManagerTest, GetPrimaryAccountInfoSignedInNoRefreshToken) {
Colin Blundell6430f5d2017-07-13 10:17:13333 token_service()->LoadCredentials("dummy");
334
blundell1e21bd32017-05-03 15:25:57335 signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
336 base::RunLoop run_loop;
Colin Blundell25a80822017-07-13 06:17:52337 GetIdentityManager()->GetPrimaryAccountInfo(
Colin Blundell704d198e2017-06-05 11:27:13338 base::Bind(&IdentityManagerTest::OnReceivedPrimaryAccountInfo,
blundell1e21bd32017-05-03 15:25:57339 base::Unretained(this), run_loop.QuitClosure()));
340 run_loop.Run();
Colin Blundell704d198e2017-06-05 11:27:13341 EXPECT_TRUE(primary_account_info_);
Colin Blundell57fb6502017-06-27 12:24:34342 EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
343 primary_account_info_->account_id);
Colin Blundell704d198e2017-06-05 11:27:13344 EXPECT_EQ(kTestGaiaId, primary_account_info_->gaia);
345 EXPECT_EQ(kTestEmail, primary_account_info_->email);
Colin Blundell57fb6502017-06-27 12:24:34346 EXPECT_FALSE(primary_account_state_.has_refresh_token);
Colin Blundellbdf4642d2017-07-06 07:00:03347 EXPECT_TRUE(primary_account_state_.is_primary_account);
Colin Blundell57fb6502017-06-27 12:24:34348}
349
350// Check that the primary account info has expected values if signed in with a
351// refresh token available.
352TEST_F(IdentityManagerTest, GetPrimaryAccountInfoSignedInRefreshToken) {
Colin Blundell6430f5d2017-07-13 10:17:13353 token_service()->LoadCredentials("dummy");
354
Colin Blundell57fb6502017-06-27 12:24:34355 signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
356 token_service()->UpdateCredentials(
357 signin_manager()->GetAuthenticatedAccountId(), kTestRefreshToken);
358 base::RunLoop run_loop;
Colin Blundell25a80822017-07-13 06:17:52359 GetIdentityManager()->GetPrimaryAccountInfo(
Colin Blundell57fb6502017-06-27 12:24:34360 base::Bind(&IdentityManagerTest::OnReceivedPrimaryAccountInfo,
361 base::Unretained(this), run_loop.QuitClosure()));
362 run_loop.Run();
363 EXPECT_TRUE(primary_account_info_);
364 EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
365 primary_account_info_->account_id);
366 EXPECT_EQ(kTestGaiaId, primary_account_info_->gaia);
367 EXPECT_EQ(kTestEmail, primary_account_info_->email);
368 EXPECT_TRUE(primary_account_state_.has_refresh_token);
Colin Blundellbdf4642d2017-07-06 07:00:03369 EXPECT_TRUE(primary_account_state_.is_primary_account);
370}
371
372// Check that GetPrimaryAccountWhenAvailable() returns immediately in the
373// case where the primary account is available when the call is received.
374TEST_F(IdentityManagerTest, GetPrimaryAccountWhenAvailableSignedIn) {
Colin Blundell6430f5d2017-07-13 10:17:13375 token_service()->LoadCredentials("dummy");
376
Colin Blundellbdf4642d2017-07-06 07:00:03377 signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
378 token_service()->UpdateCredentials(
379 signin_manager()->GetAuthenticatedAccountId(), kTestRefreshToken);
380
381 AccountInfo account_info;
382 AccountState account_state;
383 base::RunLoop run_loop;
Colin Blundell25a80822017-07-13 06:17:52384 GetIdentityManager()->GetPrimaryAccountWhenAvailable(base::Bind(
Colin Blundellbdf4642d2017-07-06 07:00:03385 &IdentityManagerTest::OnPrimaryAccountAvailable, base::Unretained(this),
386 run_loop.QuitClosure(), base::Unretained(&account_info),
387 base::Unretained(&account_state)));
388 run_loop.Run();
389
390 EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
391 account_info.account_id);
392 EXPECT_EQ(kTestGaiaId, account_info.gaia);
393 EXPECT_EQ(kTestEmail, account_info.email);
394 EXPECT_TRUE(account_state.has_refresh_token);
395 EXPECT_TRUE(account_state.is_primary_account);
396}
397
398// Check that GetPrimaryAccountWhenAvailable() returns the expected account
399// info in the case where the primary account is made available *after* the
400// call is received.
401TEST_F(IdentityManagerTest, GetPrimaryAccountWhenAvailableSignInLater) {
Colin Blundell6430f5d2017-07-13 10:17:13402 token_service()->LoadCredentials("dummy");
403
Colin Blundellbdf4642d2017-07-06 07:00:03404 AccountInfo account_info;
405 AccountState account_state;
406
407 base::RunLoop run_loop;
Colin Blundell25a80822017-07-13 06:17:52408 GetIdentityManager()->GetPrimaryAccountWhenAvailable(base::Bind(
Colin Blundellbdf4642d2017-07-06 07:00:03409 &IdentityManagerTest::OnPrimaryAccountAvailable, base::Unretained(this),
410 run_loop.QuitClosure(), base::Unretained(&account_info),
411 base::Unretained(&account_state)));
412
413 // Verify that the primary account info is not currently available (this also
414 // serves to ensure that the preceding call has been received by the Identity
415 // Manager before proceeding).
416 base::RunLoop run_loop2;
Colin Blundell25a80822017-07-13 06:17:52417 GetIdentityManager()->GetPrimaryAccountInfo(
Colin Blundellbdf4642d2017-07-06 07:00:03418 base::Bind(&IdentityManagerTest::OnReceivedPrimaryAccountInfo,
419 base::Unretained(this), run_loop2.QuitClosure()));
420 run_loop2.Run();
421 EXPECT_FALSE(primary_account_info_);
422
423 // Make the primary account available and check that the callback is invoked
424 // as expected.
425 signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
426 token_service()->UpdateCredentials(
427 signin_manager()->GetAuthenticatedAccountId(), kTestRefreshToken);
428 run_loop.Run();
429
430 EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
431 account_info.account_id);
432 EXPECT_EQ(kTestGaiaId, account_info.gaia);
433 EXPECT_EQ(kTestEmail, account_info.email);
434 EXPECT_TRUE(account_state.has_refresh_token);
435 EXPECT_TRUE(account_state.is_primary_account);
436}
437
438// Check that GetPrimaryAccountWhenAvailable() returns the expected account
439// info in the case where signin is done before the call is received but the
440// refresh token is made available only *after* the call is received.
441TEST_F(IdentityManagerTest, GetPrimaryAccountWhenAvailableTokenAvailableLater) {
Colin Blundell6430f5d2017-07-13 10:17:13442 token_service()->LoadCredentials("dummy");
443
Colin Blundellbdf4642d2017-07-06 07:00:03444 AccountInfo account_info;
445 AccountState account_state;
446
447 // Sign in, but don't set the refresh token yet.
448 signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
449 base::RunLoop run_loop;
Colin Blundell25a80822017-07-13 06:17:52450 GetIdentityManager()->GetPrimaryAccountWhenAvailable(base::Bind(
Colin Blundellbdf4642d2017-07-06 07:00:03451 &IdentityManagerTest::OnPrimaryAccountAvailable, base::Unretained(this),
452 run_loop.QuitClosure(), base::Unretained(&account_info),
453 base::Unretained(&account_state)));
454
455 // Verify that the primary account info is present, but that the primary
456 // account is not yet considered available (this also
457 // serves to ensure that the preceding call has been received by the Identity
458 // Manager before proceeding).
459 base::RunLoop run_loop2;
Colin Blundell25a80822017-07-13 06:17:52460 GetIdentityManager()->GetPrimaryAccountInfo(
Colin Blundellbdf4642d2017-07-06 07:00:03461 base::Bind(&IdentityManagerTest::OnReceivedPrimaryAccountInfo,
462 base::Unretained(this), run_loop2.QuitClosure()));
463 run_loop2.Run();
464
465 EXPECT_TRUE(primary_account_info_);
466 EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
467 primary_account_info_->account_id);
468 EXPECT_TRUE(account_info.account_id.empty());
469
470 // Set the refresh token and check that the callback is invoked as expected
471 // (i.e., the primary account is now considered available).
472 token_service()->UpdateCredentials(
473 signin_manager()->GetAuthenticatedAccountId(), kTestRefreshToken);
474 run_loop.Run();
475
476 EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
477 account_info.account_id);
478 EXPECT_EQ(kTestGaiaId, account_info.gaia);
479 EXPECT_EQ(kTestEmail, account_info.email);
480 EXPECT_TRUE(account_state.has_refresh_token);
481 EXPECT_TRUE(account_state.is_primary_account);
482}
483
Colin Blundell2c8951de2017-07-07 13:23:45484// Check that GetPrimaryAccountWhenAvailable() returns the expected account info
485// in the case where the token is available before the call is received but the
486// account is made authenticated only *after* the call is received. This test is
487// relevant only on non-ChromeOS platforms, as the flow being tested here is not
488// possible on ChromeOS.
489#if !defined(OS_CHROMEOS)
490TEST_F(IdentityManagerTest,
491 GetPrimaryAccountWhenAvailableAuthenticationAvailableLater) {
Colin Blundell6430f5d2017-07-13 10:17:13492 token_service()->LoadCredentials("dummy");
493
Colin Blundell2c8951de2017-07-07 13:23:45494 AccountInfo account_info;
495 AccountState account_state;
496
497 // Set the refresh token, but don't sign in yet.
498 std::string account_id_to_use =
499 account_tracker()->SeedAccountInfo(kTestGaiaId, kTestEmail);
500 token_service()->UpdateCredentials(account_id_to_use, kTestRefreshToken);
501 base::RunLoop run_loop;
Colin Blundell25a80822017-07-13 06:17:52502 GetIdentityManager()->GetPrimaryAccountWhenAvailable(base::Bind(
Colin Blundell2c8951de2017-07-07 13:23:45503 &IdentityManagerTest::OnPrimaryAccountAvailable, base::Unretained(this),
504 run_loop.QuitClosure(), base::Unretained(&account_info),
505 base::Unretained(&account_state)));
506
507 // Verify that the account is present and has a refresh token, but that the
508 // primary account is not yet considered available (this also serves to ensure
509 // that the preceding call has been received by the Identity Manager before
510 // proceeding).
511 base::RunLoop run_loop2;
Colin Blundell25a80822017-07-13 06:17:52512 GetIdentityManager()->GetAccountInfoFromGaiaId(
Colin Blundell2c8951de2017-07-07 13:23:45513 kTestGaiaId,
514 base::Bind(&IdentityManagerTest::OnReceivedAccountInfoFromGaiaId,
515 base::Unretained(this), run_loop2.QuitClosure()));
516 run_loop2.Run();
517
518 EXPECT_TRUE(account_info_from_gaia_id_);
519 EXPECT_EQ(account_id_to_use, account_info_from_gaia_id_->account_id);
520 EXPECT_EQ(kTestGaiaId, account_info_from_gaia_id_->gaia);
521 EXPECT_EQ(kTestEmail, account_info_from_gaia_id_->email);
522 EXPECT_TRUE(account_state_from_gaia_id_.has_refresh_token);
523 EXPECT_FALSE(account_state_from_gaia_id_.is_primary_account);
524
525 EXPECT_TRUE(account_info.account_id.empty());
526
527 // Sign the user in and check that the callback is invoked as expected (i.e.,
528 // the primary account is now considered available). Note that it is necessary
529 // to call SignIn() here to ensure that GoogleSigninSucceeded() is fired by
530 // the fake signin manager.
531 static_cast<FakeSigninManager*>(signin_manager())
532 ->SignIn(kTestGaiaId, kTestEmail, "password");
533
534 run_loop.Run();
535
536 EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
537 account_info.account_id);
538 EXPECT_EQ(kTestGaiaId, account_info.gaia);
539 EXPECT_EQ(kTestEmail, account_info.email);
540 EXPECT_TRUE(account_state.has_refresh_token);
541 EXPECT_TRUE(account_state.is_primary_account);
542}
543#endif
544
Colin Blundellbdf4642d2017-07-06 07:00:03545// Check that GetPrimaryAccountWhenAvailable() returns the expected account
546// info to all callers in the case where the primary account is made available
547// after multiple overlapping calls have been received.
548TEST_F(IdentityManagerTest, GetPrimaryAccountWhenAvailableOverlappingCalls) {
Colin Blundell6430f5d2017-07-13 10:17:13549 token_service()->LoadCredentials("dummy");
550
Colin Blundellbdf4642d2017-07-06 07:00:03551 AccountInfo account_info1;
552 AccountState account_state1;
553 base::RunLoop run_loop;
Colin Blundell25a80822017-07-13 06:17:52554 GetIdentityManager()->GetPrimaryAccountWhenAvailable(base::Bind(
Colin Blundellbdf4642d2017-07-06 07:00:03555 &IdentityManagerTest::OnPrimaryAccountAvailable, base::Unretained(this),
556 run_loop.QuitClosure(), base::Unretained(&account_info1),
557 base::Unretained(&account_state1)));
558
559 AccountInfo account_info2;
560 AccountState account_state2;
561 base::RunLoop run_loop2;
Colin Blundell25a80822017-07-13 06:17:52562 GetIdentityManager()->GetPrimaryAccountWhenAvailable(base::Bind(
Colin Blundellbdf4642d2017-07-06 07:00:03563 &IdentityManagerTest::OnPrimaryAccountAvailable, base::Unretained(this),
564 run_loop2.QuitClosure(), base::Unretained(&account_info2),
565 base::Unretained(&account_state2)));
566
567 // Verify that the primary account info is not currently available (this also
568 // serves to ensure that the preceding call has been received by the Identity
569 // Manager before proceeding).
570 base::RunLoop run_loop3;
Colin Blundell25a80822017-07-13 06:17:52571 GetIdentityManager()->GetPrimaryAccountInfo(
Colin Blundellbdf4642d2017-07-06 07:00:03572 base::Bind(&IdentityManagerTest::OnReceivedPrimaryAccountInfo,
573 base::Unretained(this), run_loop3.QuitClosure()));
574 run_loop3.Run();
575 EXPECT_FALSE(primary_account_info_);
576
577 // Make the primary account available and check that the callbacks are invoked
578 // as expected.
579 signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
580 token_service()->UpdateCredentials(
581 signin_manager()->GetAuthenticatedAccountId(), kTestRefreshToken);
582 run_loop.Run();
583 run_loop2.Run();
584
585 EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
586 account_info1.account_id);
587 EXPECT_EQ(kTestGaiaId, account_info1.gaia);
588 EXPECT_EQ(kTestEmail, account_info1.email);
589 EXPECT_TRUE(account_state1.has_refresh_token);
590 EXPECT_TRUE(account_state1.is_primary_account);
591
592 EXPECT_EQ(signin_manager()->GetAuthenticatedAccountId(),
593 account_info2.account_id);
594 EXPECT_EQ(kTestGaiaId, account_info2.gaia);
595 EXPECT_EQ(kTestEmail, account_info2.email);
596 EXPECT_TRUE(account_state2.has_refresh_token);
597 EXPECT_TRUE(account_state2.is_primary_account);
blundell1e21bd32017-05-03 15:25:57598}
599
Colin Blundell2f987fd2017-06-23 10:49:06600// Check that the account info for a given GAIA ID is null if that GAIA ID is
601// unknown.
602TEST_F(IdentityManagerTest, GetAccountInfoForUnknownGaiaID) {
Colin Blundell6430f5d2017-07-13 10:17:13603 token_service()->LoadCredentials("dummy");
604
Colin Blundell2f987fd2017-06-23 10:49:06605 base::RunLoop run_loop;
Colin Blundell25a80822017-07-13 06:17:52606 GetIdentityManager()->GetAccountInfoFromGaiaId(
Colin Blundell2f987fd2017-06-23 10:49:06607 kTestGaiaId,
608 base::Bind(&IdentityManagerTest::OnReceivedAccountInfoFromGaiaId,
609 base::Unretained(this), run_loop.QuitClosure()));
610 run_loop.Run();
611 EXPECT_FALSE(account_info_from_gaia_id_);
612}
613
614// Check that the account info for a given GAIA ID has expected values if that
Colin Blundell57fb6502017-06-27 12:24:34615// GAIA ID is known and there is no refresh token available for it.
616TEST_F(IdentityManagerTest, GetAccountInfoForKnownGaiaIdNoRefreshToken) {
Colin Blundell6430f5d2017-07-13 10:17:13617 token_service()->LoadCredentials("dummy");
618
Colin Blundell57fb6502017-06-27 12:24:34619 std::string account_id =
620 account_tracker()->SeedAccountInfo(kTestGaiaId, kTestEmail);
Colin Blundell2f987fd2017-06-23 10:49:06621 base::RunLoop run_loop;
Colin Blundell25a80822017-07-13 06:17:52622 GetIdentityManager()->GetAccountInfoFromGaiaId(
Colin Blundell2f987fd2017-06-23 10:49:06623 kTestGaiaId,
624 base::Bind(&IdentityManagerTest::OnReceivedAccountInfoFromGaiaId,
625 base::Unretained(this), run_loop.QuitClosure()));
626 run_loop.Run();
627 EXPECT_TRUE(account_info_from_gaia_id_);
Colin Blundell57fb6502017-06-27 12:24:34628 EXPECT_EQ(account_id, account_info_from_gaia_id_->account_id);
Colin Blundell2f987fd2017-06-23 10:49:06629 EXPECT_EQ(kTestGaiaId, account_info_from_gaia_id_->gaia);
630 EXPECT_EQ(kTestEmail, account_info_from_gaia_id_->email);
Colin Blundell57fb6502017-06-27 12:24:34631 EXPECT_FALSE(account_state_from_gaia_id_.has_refresh_token);
Colin Blundellbdf4642d2017-07-06 07:00:03632 EXPECT_FALSE(account_state_from_gaia_id_.is_primary_account);
Colin Blundell57fb6502017-06-27 12:24:34633}
634
635// Check that the account info for a given GAIA ID has expected values if that
636// GAIA ID is known and has a refresh token available.
637TEST_F(IdentityManagerTest, GetAccountInfoForKnownGaiaIdRefreshToken) {
Colin Blundell6430f5d2017-07-13 10:17:13638 token_service()->LoadCredentials("dummy");
639
Colin Blundell57fb6502017-06-27 12:24:34640 std::string account_id =
641 account_tracker()->SeedAccountInfo(kTestGaiaId, kTestEmail);
642 token_service()->UpdateCredentials(account_id, kTestRefreshToken);
643 base::RunLoop run_loop;
Colin Blundell25a80822017-07-13 06:17:52644 GetIdentityManager()->GetAccountInfoFromGaiaId(
Colin Blundell57fb6502017-06-27 12:24:34645 kTestGaiaId,
646 base::Bind(&IdentityManagerTest::OnReceivedAccountInfoFromGaiaId,
647 base::Unretained(this), run_loop.QuitClosure()));
648 run_loop.Run();
649 EXPECT_TRUE(account_info_from_gaia_id_);
650 EXPECT_EQ(account_id, account_info_from_gaia_id_->account_id);
651 EXPECT_EQ(kTestGaiaId, account_info_from_gaia_id_->gaia);
652 EXPECT_EQ(kTestEmail, account_info_from_gaia_id_->email);
653 EXPECT_TRUE(account_state_from_gaia_id_.has_refresh_token);
Colin Blundellbdf4642d2017-07-06 07:00:03654 EXPECT_FALSE(account_state_from_gaia_id_.is_primary_account);
Colin Blundell2f987fd2017-06-23 10:49:06655}
656
Colin Blundelle89886a2017-06-12 11:26:56657// Check that the expected error is received if requesting an access token when
658// not signed in.
659TEST_F(IdentityManagerTest, GetAccessTokenNotSignedIn) {
Colin Blundell6430f5d2017-07-13 10:17:13660 token_service()->LoadCredentials("dummy");
661
Colin Blundelle89886a2017-06-12 11:26:56662 base::RunLoop run_loop;
Colin Blundell25a80822017-07-13 06:17:52663 GetIdentityManager()->GetAccessToken(
Colin Blundelle89886a2017-06-12 11:26:56664 kTestGaiaId, ScopeSet(), "dummy_consumer",
665 base::Bind(&IdentityManagerTest::OnReceivedAccessToken,
666 base::Unretained(this), run_loop.QuitClosure()));
667 run_loop.Run();
668 EXPECT_FALSE(access_token_);
669 EXPECT_EQ(GoogleServiceAuthError::State::USER_NOT_SIGNED_UP,
670 access_token_error_.state());
671}
672
673// Check that the expected access token is received if requesting an access
674// token when signed in.
675TEST_F(IdentityManagerTest, GetAccessTokenSignedIn) {
Colin Blundell6430f5d2017-07-13 10:17:13676 token_service()->LoadCredentials("dummy");
677
Colin Blundelle89886a2017-06-12 11:26:56678 signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
Colin Blundell57fb6502017-06-27 12:24:34679 std::string account_id = signin_manager()->GetAuthenticatedAccountId();
680 token_service()->UpdateCredentials(account_id, kTestRefreshToken);
Colin Blundelle89886a2017-06-12 11:26:56681 token_service()->set_auto_post_fetch_response_on_message_loop(true);
682 base::RunLoop run_loop;
683
Colin Blundell25a80822017-07-13 06:17:52684 GetIdentityManager()->GetAccessToken(
Colin Blundell57fb6502017-06-27 12:24:34685 account_id, ScopeSet(), "dummy_consumer",
Colin Blundelle89886a2017-06-12 11:26:56686 base::Bind(&IdentityManagerTest::OnReceivedAccessToken,
687 base::Unretained(this), run_loop.QuitClosure()));
688 run_loop.Run();
689 EXPECT_TRUE(access_token_);
690 EXPECT_EQ(kTestAccessToken, access_token_.value());
691 EXPECT_EQ(GoogleServiceAuthError::State::NONE, access_token_error_.state());
692}
693
blundell1e21bd32017-05-03 15:25:57694} // namespace
695} // namespace identity