1 // Copyright (c) 2012 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.
5 #include "components/signin/core/browser/signin_manager.h"
10 #include "base/bind_helpers.h"
11 #include "base/compiler_specific.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/prefs/testing_pref_service.h"
14 #include "base/run_loop.h"
15 #include "base/strings/stringprintf.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/chrome_notification_types.h"
18 #include "chrome/browser/prefs/browser_prefs.h"
19 #include "chrome/browser/signin/account_tracker_service_factory.h"
20 #include "chrome/browser/signin/chrome_signin_client_factory.h"
21 #include "chrome/browser/signin/fake_account_tracker_service.h"
22 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
23 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
24 #include "chrome/browser/signin/gaia_cookie_manager_service_factory.h"
25 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
26 #include "chrome/browser/signin/signin_manager_factory.h"
27 #include "chrome/browser/signin/test_signin_client_builder.h"
28 #include "chrome/common/pref_names.h"
29 #include "chrome/common/url_constants.h"
30 #include "chrome/test/base/testing_browser_process.h"
31 #include "chrome/test/base/testing_profile.h"
32 #include "components/signin/core/browser/profile_oauth2_token_service.h"
33 #include "components/signin/core/browser/test_signin_client.h"
34 #include "content/public/browser/child_process_security_policy.h"
35 #include "content/public/browser/notification_source.h"
36 #include "content/public/test/test_browser_thread_bundle.h"
37 #include "google_apis/gaia/gaia_constants.h"
38 #include "google_apis/gaia/gaia_urls.h"
39 #include "net/cookies/cookie_monster.h"
40 #include "net/url_request/test_url_fetcher_factory.h"
41 #include "net/url_request/url_request.h"
42 #include "net/url_request/url_request_context_getter.h"
43 #include "net/url_request/url_request_status.h"
45 #include "testing/gmock/include/gmock/gmock.h"
46 #include "testing/gtest/include/gtest/gtest.h"
50 KeyedService
* SigninManagerBuild(content::BrowserContext
* context
) {
51 SigninManager
* service
= NULL
;
52 Profile
* profile
= static_cast<Profile
*>(context
);
53 service
= new SigninManager(
54 ChromeSigninClientFactory::GetInstance()->GetForProfile(profile
),
55 ProfileOAuth2TokenServiceFactory::GetForProfile(profile
),
56 AccountTrackerServiceFactory::GetForProfile(profile
),
57 GaiaCookieManagerServiceFactory::GetForProfile(profile
));
58 service
->Initialize(NULL
);
62 class TestSigninManagerObserver
: public SigninManagerBase::Observer
{
64 TestSigninManagerObserver() : num_failed_signins_(0),
65 num_successful_signins_(0),
69 ~TestSigninManagerObserver() override
{}
71 int num_failed_signins_
;
72 int num_successful_signins_
;
76 // SigninManagerBase::Observer:
77 void GoogleSigninFailed(const GoogleServiceAuthError
& error
) override
{
78 num_failed_signins_
++;
81 void GoogleSigninSucceeded(const std::string
& account_id
,
82 const std::string
& username
,
83 const std::string
& password
) override
{
84 num_successful_signins_
++;
87 void GoogleSignedOut(const std::string
& account_id
,
88 const std::string
& username
) override
{
96 class SigninManagerTest
: public testing::Test
{
98 SigninManagerTest() : manager_(NULL
) {}
99 ~SigninManagerTest() override
{}
101 void SetUp() override
{
103 prefs_
.reset(new TestingPrefServiceSimple
);
104 chrome::RegisterLocalState(prefs_
->registry());
105 TestingBrowserProcess::GetGlobal()->SetLocalState(
107 TestingProfile::Builder builder
;
108 builder
.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
109 BuildFakeProfileOAuth2TokenService
);
110 builder
.AddTestingFactory(ChromeSigninClientFactory::GetInstance(),
111 signin::BuildTestSigninClient
);
112 builder
.AddTestingFactory(SigninManagerFactory::GetInstance(),
114 builder
.AddTestingFactory(AccountTrackerServiceFactory::GetInstance(),
115 FakeAccountTrackerService::Build
);
116 profile_
= builder
.Build();
118 signin_client()->SetURLRequestContext(profile_
->GetRequestContext());
121 void TearDown() override
{
123 manager_
->RemoveObserver(&test_observer_
);
125 // Destroy the SigninManager here, because it relies on profile() which is
126 // freed in the base class.
127 if (naked_manager_
) {
128 naked_manager_
->Shutdown();
129 naked_manager_
.reset(NULL
);
131 TestingBrowserProcess::GetGlobal()->SetLocalState(NULL
);
133 // Manually destroy PrefService and Profile so that they are shutdown
134 // in the correct order. Both need to be destroyed before the
135 // |thread_bundle_| member.
137 prefs_
.reset(); // LocalState needs to outlive the profile.
140 TestingProfile
* profile() { return profile_
.get(); }
142 TestSigninClient
* signin_client() {
143 return static_cast<TestSigninClient
*>(
144 ChromeSigninClientFactory::GetInstance()->GetForProfile(profile()));
147 // Sets up the signin manager as a service if other code will try to get it as
149 void SetUpSigninManagerAsService() {
151 DCHECK(!naked_manager_
);
152 manager_
= static_cast<SigninManager
*>(
153 SigninManagerFactory::GetForProfile(profile()));
154 manager_
->AddObserver(&test_observer_
);
157 // Create a naked signin manager if integration with PKSs is not needed.
158 void CreateNakedSigninManager() {
160 naked_manager_
.reset(new SigninManager(
161 ChromeSigninClientFactory::GetInstance()->GetForProfile(profile()),
162 ProfileOAuth2TokenServiceFactory::GetForProfile(profile()),
163 AccountTrackerServiceFactory::GetForProfile(profile()),
164 GaiaCookieManagerServiceFactory::GetForProfile(profile())));
166 manager_
= naked_manager_
.get();
167 manager_
->AddObserver(&test_observer_
);
170 // Shuts down |manager_|.
171 void ShutDownManager() {
173 manager_
->RemoveObserver(&test_observer_
);
174 manager_
->Shutdown();
176 naked_manager_
.reset(NULL
);
180 void ExpectSignInWithRefreshTokenSuccess() {
181 EXPECT_TRUE(manager_
->IsAuthenticated());
183 ProfileOAuth2TokenService
* token_service
=
184 ProfileOAuth2TokenServiceFactory::GetForProfile(profile());
185 EXPECT_TRUE(token_service
->RefreshTokenIsAvailable(
186 manager_
->GetAuthenticatedUsername()));
188 // Should go into token service and stop.
189 EXPECT_EQ(1, test_observer_
.num_successful_signins_
);
190 EXPECT_EQ(0, test_observer_
.num_failed_signins_
);
193 void CompleteSigninCallback(const std::string
& oauth_token
) {
194 oauth_tokens_fetched_
.push_back(oauth_token
);
195 manager_
->CompletePendingSignin();
198 content::TestBrowserThreadBundle thread_bundle_
;
199 net::TestURLFetcherFactory factory_
;
200 scoped_ptr
<SigninManager
> naked_manager_
;
201 SigninManager
* manager_
;
202 TestSigninManagerObserver test_observer_
;
203 scoped_ptr
<TestingProfile
> profile_
;
204 std::vector
<std::string
> oauth_tokens_fetched_
;
205 scoped_ptr
<TestingPrefServiceSimple
> prefs_
;
206 std::vector
<std::string
> cookies_
;
209 TEST_F(SigninManagerTest
, SignInWithRefreshToken
) {
210 SetUpSigninManagerAsService();
211 EXPECT_FALSE(manager_
->IsAuthenticated());
213 manager_
->StartSignInWithRefreshToken(
217 SigninManager::OAuthTokenFetchedCallback());
219 ExpectSignInWithRefreshTokenSuccess();
221 // Should persist across resets.
223 CreateNakedSigninManager();
224 manager_
->Initialize(NULL
);
225 EXPECT_EQ("user@gmail.com", manager_
->GetAuthenticatedUsername());
228 TEST_F(SigninManagerTest
, SignInWithRefreshTokenCallbackComplete
) {
229 SetUpSigninManagerAsService();
230 EXPECT_FALSE(manager_
->IsAuthenticated());
232 // Since the password is empty, must verify the gaia cookies first.
233 SigninManager::OAuthTokenFetchedCallback callback
=
234 base::Bind(&SigninManagerTest::CompleteSigninCallback
,
235 base::Unretained(this));
236 manager_
->StartSignInWithRefreshToken(
242 ExpectSignInWithRefreshTokenSuccess();
243 ASSERT_EQ(1U, oauth_tokens_fetched_
.size());
244 EXPECT_EQ(oauth_tokens_fetched_
[0], "rt1");
247 TEST_F(SigninManagerTest
, SignInWithRefreshTokenCallsPostSignout
) {
248 SetUpSigninManagerAsService();
249 EXPECT_FALSE(manager_
->IsAuthenticated());
251 std::string gaia_id
= "12345";
252 std::string email
= "user@google.com";
254 FakeAccountTrackerService
* account_tracker_service
=
255 static_cast<FakeAccountTrackerService
*>(
256 AccountTrackerServiceFactory::GetForProfile(profile()));
257 account_tracker_service
->SeedAccountInfo(gaia_id
, email
);
258 account_tracker_service
->EnableNetworkFetches();
259 std::string account_id
= account_tracker_service
->PickAccountIdForAccount(
262 ASSERT_TRUE(signin_client()->get_signed_in_password().empty());
264 manager_
->StartSignInWithRefreshToken(
268 SigninManager::OAuthTokenFetchedCallback());
270 // PostSignedIn is not called until the AccountTrackerService returns.
271 ASSERT_EQ("", signin_client()->get_signed_in_password());
273 account_tracker_service
->FakeUserInfoFetchSuccess(
274 account_id
, email
, gaia_id
, "google.com");
276 // AccountTracker and SigninManager are both done and PostSignedIn was called.
277 ASSERT_EQ("password", signin_client()->get_signed_in_password());
279 ExpectSignInWithRefreshTokenSuccess();
283 TEST_F(SigninManagerTest
, SignOut
) {
284 SetUpSigninManagerAsService();
285 manager_
->StartSignInWithRefreshToken(
289 SigninManager::OAuthTokenFetchedCallback());
290 manager_
->SignOut(signin_metrics::SIGNOUT_TEST
);
291 EXPECT_FALSE(manager_
->IsAuthenticated());
292 // Should not be persisted anymore
294 CreateNakedSigninManager();
295 manager_
->Initialize(NULL
);
296 EXPECT_FALSE(manager_
->IsAuthenticated());
299 TEST_F(SigninManagerTest
, SignOutWhileProhibited
) {
300 SetUpSigninManagerAsService();
301 EXPECT_FALSE(manager_
->IsAuthenticated());
303 manager_
->SetAuthenticatedUsername("user@gmail.com");
304 manager_
->ProhibitSignout(true);
305 manager_
->SignOut(signin_metrics::SIGNOUT_TEST
);
306 EXPECT_TRUE(manager_
->IsAuthenticated());
307 manager_
->ProhibitSignout(false);
308 manager_
->SignOut(signin_metrics::SIGNOUT_TEST
);
309 EXPECT_FALSE(manager_
->IsAuthenticated());
312 TEST_F(SigninManagerTest
, Prohibited
) {
313 g_browser_process
->local_state()->SetString(
314 prefs::kGoogleServicesUsernamePattern
, ".*@google.com");
315 CreateNakedSigninManager();
316 manager_
->Initialize(g_browser_process
->local_state());
317 EXPECT_TRUE(manager_
->IsAllowedUsername("test@google.com"));
318 EXPECT_TRUE(manager_
->IsAllowedUsername("happy@google.com"));
319 EXPECT_FALSE(manager_
->IsAllowedUsername("test@invalid.com"));
320 EXPECT_FALSE(manager_
->IsAllowedUsername("test@notgoogle.com"));
321 EXPECT_FALSE(manager_
->IsAllowedUsername(std::string()));
324 TEST_F(SigninManagerTest
, TestAlternateWildcard
) {
325 // Test to make sure we accept "*@google.com" as a pattern (treat it as if
326 // the admin entered ".*@google.com").
327 g_browser_process
->local_state()->SetString(
328 prefs::kGoogleServicesUsernamePattern
, "*@google.com");
329 CreateNakedSigninManager();
330 manager_
->Initialize(g_browser_process
->local_state());
331 EXPECT_TRUE(manager_
->IsAllowedUsername("test@google.com"));
332 EXPECT_TRUE(manager_
->IsAllowedUsername("happy@google.com"));
333 EXPECT_FALSE(manager_
->IsAllowedUsername("test@invalid.com"));
334 EXPECT_FALSE(manager_
->IsAllowedUsername("test@notgoogle.com"));
335 EXPECT_FALSE(manager_
->IsAllowedUsername(std::string()));
338 TEST_F(SigninManagerTest
, ProhibitedAtStartup
) {
339 profile()->GetPrefs()->SetString(prefs::kGoogleServicesUsername
,
340 "monkey@invalid.com");
341 g_browser_process
->local_state()->SetString(
342 prefs::kGoogleServicesUsernamePattern
, ".*@google.com");
343 CreateNakedSigninManager();
344 manager_
->Initialize(g_browser_process
->local_state());
345 // Currently signed in user is prohibited by policy, so should be signed out.
346 EXPECT_EQ("", manager_
->GetAuthenticatedUsername());
349 TEST_F(SigninManagerTest
, ProhibitedAfterStartup
) {
350 std::string
user("monkey@invalid.com");
351 profile()->GetPrefs()->SetString(prefs::kGoogleServicesUsername
, user
);
352 CreateNakedSigninManager();
353 manager_
->Initialize(g_browser_process
->local_state());
354 EXPECT_EQ(user
, manager_
->GetAuthenticatedUsername());
355 // Update the profile - user should be signed out.
356 g_browser_process
->local_state()->SetString(
357 prefs::kGoogleServicesUsernamePattern
, ".*@google.com");
358 EXPECT_EQ("", manager_
->GetAuthenticatedUsername());
361 TEST_F(SigninManagerTest
, ExternalSignIn
) {
362 CreateNakedSigninManager();
363 manager_
->Initialize(g_browser_process
->local_state());
365 profile()->GetPrefs()->GetString(prefs::kGoogleServicesUsername
));
366 EXPECT_EQ("", manager_
->GetAuthenticatedUsername());
367 EXPECT_EQ(0, test_observer_
.num_successful_signins_
);
369 manager_
->OnExternalSigninCompleted("external@example.com");
370 EXPECT_EQ(1, test_observer_
.num_successful_signins_
);
371 EXPECT_EQ(0, test_observer_
.num_failed_signins_
);
372 EXPECT_EQ("external@example.com",
373 profile()->GetPrefs()->GetString(prefs::kGoogleServicesUsername
));
374 EXPECT_EQ("external@example.com", manager_
->GetAuthenticatedUsername());
377 TEST_F(SigninManagerTest
, SigninNotAllowed
) {
378 std::string
user("user@google.com");
379 profile()->GetPrefs()->SetString(prefs::kGoogleServicesUsername
, user
);
380 profile()->GetPrefs()->SetBoolean(prefs::kSigninAllowed
, false);
381 SetUpSigninManagerAsService();