Update V8 to version 4.6.22.
[chromium-blink-merge.git] / chrome / browser / signin / signin_manager_unittest.cc
blob72747d71043534d3ffa02db58b39f2ecd2e71f30
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"
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/compiler_specific.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/prefs/testing_pref_service.h"
15 #include "base/run_loop.h"
16 #include "base/strings/stringprintf.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/chrome_notification_types.h"
19 #include "chrome/browser/prefs/browser_prefs.h"
20 #include "chrome/browser/signin/account_fetcher_service_factory.h"
21 #include "chrome/browser/signin/account_tracker_service_factory.h"
22 #include "chrome/browser/signin/chrome_signin_client_factory.h"
23 #include "chrome/browser/signin/fake_account_fetcher_service.h"
24 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
25 #include "chrome/browser/signin/gaia_cookie_manager_service_factory.h"
26 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
27 #include "chrome/browser/signin/signin_manager_factory.h"
28 #include "chrome/browser/signin/test_signin_client_builder.h"
29 #include "chrome/common/pref_names.h"
30 #include "chrome/common/url_constants.h"
31 #include "chrome/test/base/testing_browser_process.h"
32 #include "chrome/test/base/testing_profile.h"
33 #include "components/signin/core/browser/account_tracker_service.h"
34 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
35 #include "components/signin/core/browser/profile_oauth2_token_service.h"
36 #include "components/signin/core/browser/test_signin_client.h"
37 #include "content/public/browser/child_process_security_policy.h"
38 #include "content/public/browser/notification_source.h"
39 #include "content/public/test/test_browser_thread_bundle.h"
40 #include "google_apis/gaia/gaia_constants.h"
41 #include "google_apis/gaia/gaia_urls.h"
42 #include "net/cookies/cookie_monster.h"
43 #include "net/url_request/test_url_fetcher_factory.h"
44 #include "net/url_request/url_request.h"
45 #include "net/url_request/url_request_context_getter.h"
46 #include "net/url_request/url_request_status.h"
48 #include "testing/gmock/include/gmock/gmock.h"
49 #include "testing/gtest/include/gtest/gtest.h"
51 namespace {
53 scoped_ptr<KeyedService> SigninManagerBuild(content::BrowserContext* context) {
54 Profile* profile = static_cast<Profile*>(context);
55 scoped_ptr<SigninManager> service(new SigninManager(
56 ChromeSigninClientFactory::GetInstance()->GetForProfile(profile),
57 ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
58 AccountTrackerServiceFactory::GetForProfile(profile),
59 GaiaCookieManagerServiceFactory::GetForProfile(profile)));
60 service->Initialize(NULL);
61 return service.Pass();
64 class TestSigninManagerObserver : public SigninManagerBase::Observer {
65 public:
66 TestSigninManagerObserver() : num_failed_signins_(0),
67 num_successful_signins_(0),
68 num_signouts_(0) {
71 ~TestSigninManagerObserver() override {}
73 int num_failed_signins_;
74 int num_successful_signins_;
75 int num_signouts_;
77 private:
78 // SigninManagerBase::Observer:
79 void GoogleSigninFailed(const GoogleServiceAuthError& error) override {
80 num_failed_signins_++;
83 void GoogleSigninSucceeded(const std::string& account_id,
84 const std::string& username,
85 const std::string& password) override {
86 num_successful_signins_++;
89 void GoogleSignedOut(const std::string& account_id,
90 const std::string& username) override {
91 num_signouts_++;
95 } // namespace
98 class SigninManagerTest : public testing::Test {
99 public:
100 SigninManagerTest() : manager_(NULL) {}
101 ~SigninManagerTest() override {}
103 void SetUp() override {
104 manager_ = NULL;
105 prefs_.reset(new TestingPrefServiceSimple);
106 chrome::RegisterLocalState(prefs_->registry());
107 TestingBrowserProcess::GetGlobal()->SetLocalState(
108 prefs_.get());
109 TestingProfile::Builder builder;
110 builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
111 BuildFakeProfileOAuth2TokenService);
112 builder.AddTestingFactory(ChromeSigninClientFactory::GetInstance(),
113 signin::BuildTestSigninClient);
114 builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
115 SigninManagerBuild);
116 builder.AddTestingFactory(AccountFetcherServiceFactory::GetInstance(),
117 FakeAccountFetcherService::BuildForTests);
118 profile_ = builder.Build();
120 TestSigninClient* client =
121 static_cast<TestSigninClient*>(
122 ChromeSigninClientFactory::GetForProfile(profile()));
123 client->SetURLRequestContext(profile_->GetRequestContext());
126 void TearDown() override {
127 if (manager_)
128 manager_->RemoveObserver(&test_observer_);
130 // Destroy the SigninManager here, because it relies on profile() which is
131 // freed in the base class.
132 if (naked_manager_) {
133 naked_manager_->Shutdown();
134 naked_manager_.reset(NULL);
136 TestingBrowserProcess::GetGlobal()->SetLocalState(NULL);
138 // Manually destroy PrefService and Profile so that they are shutdown
139 // in the correct order. Both need to be destroyed before the
140 // |thread_bundle_| member.
141 profile_.reset();
142 prefs_.reset(); // LocalState needs to outlive the profile.
145 TestingProfile* profile() { return profile_.get(); }
147 TestSigninClient* signin_client() {
148 return static_cast<TestSigninClient*>(
149 ChromeSigninClientFactory::GetInstance()->GetForProfile(profile()));
152 // Seed the account tracker with information from logged in user. Normally
153 // this is done by UI code before calling SigninManager. Returns the string
154 // to use as the account_id.
155 std::string AddToAccountTracker(const std::string& gaia_id,
156 const std::string& email) {
157 AccountTrackerService* service =
158 AccountTrackerServiceFactory::GetForProfile(profile());
159 service->SeedAccountInfo(gaia_id, email);
160 return service->PickAccountIdForAccount(gaia_id, email);
163 // Sets up the signin manager as a service if other code will try to get it as
164 // a PKS.
165 void SetUpSigninManagerAsService() {
166 DCHECK(!manager_);
167 DCHECK(!naked_manager_);
168 manager_ = static_cast<SigninManager*>(
169 SigninManagerFactory::GetForProfile(profile()));
170 manager_->AddObserver(&test_observer_);
173 // Create a naked signin manager if integration with PKSs is not needed.
174 void CreateNakedSigninManager() {
175 DCHECK(!manager_);
176 naked_manager_.reset(new SigninManager(
177 ChromeSigninClientFactory::GetInstance()->GetForProfile(profile()),
178 ProfileOAuth2TokenServiceFactory::GetForProfile(profile()),
179 AccountTrackerServiceFactory::GetForProfile(profile()),
180 GaiaCookieManagerServiceFactory::GetForProfile(profile())));
182 manager_ = naked_manager_.get();
183 manager_->AddObserver(&test_observer_);
186 // Shuts down |manager_|.
187 void ShutDownManager() {
188 DCHECK(manager_);
189 manager_->RemoveObserver(&test_observer_);
190 manager_->Shutdown();
191 if (naked_manager_)
192 naked_manager_.reset(NULL);
193 manager_ = NULL;
196 void ExpectSignInWithRefreshTokenSuccess() {
197 EXPECT_TRUE(manager_->IsAuthenticated());
198 EXPECT_FALSE(manager_->GetAuthenticatedAccountId().empty());
199 EXPECT_FALSE(manager_->GetAuthenticatedUsername().empty());
201 ProfileOAuth2TokenService* token_service =
202 ProfileOAuth2TokenServiceFactory::GetForProfile(profile());
203 EXPECT_TRUE(token_service->RefreshTokenIsAvailable(
204 manager_->GetAuthenticatedAccountId()));
206 // Should go into token service and stop.
207 EXPECT_EQ(1, test_observer_.num_successful_signins_);
208 EXPECT_EQ(0, test_observer_.num_failed_signins_);
211 void CompleteSigninCallback(const std::string& oauth_token) {
212 oauth_tokens_fetched_.push_back(oauth_token);
213 manager_->CompletePendingSignin();
216 content::TestBrowserThreadBundle thread_bundle_;
217 net::TestURLFetcherFactory factory_;
218 scoped_ptr<SigninManager> naked_manager_;
219 SigninManager* manager_;
220 TestSigninManagerObserver test_observer_;
221 scoped_ptr<TestingProfile> profile_;
222 std::vector<std::string> oauth_tokens_fetched_;
223 scoped_ptr<TestingPrefServiceSimple> prefs_;
224 std::vector<std::string> cookies_;
227 TEST_F(SigninManagerTest, SignInWithRefreshToken) {
228 SetUpSigninManagerAsService();
229 EXPECT_FALSE(manager_->IsAuthenticated());
231 std::string account_id = AddToAccountTracker("gaia_id", "user@gmail.com");
232 manager_->StartSignInWithRefreshToken(
233 "rt",
234 "gaia_id",
235 "user@gmail.com",
236 "password",
237 SigninManager::OAuthTokenFetchedCallback());
239 ExpectSignInWithRefreshTokenSuccess();
241 // Should persist across resets.
242 ShutDownManager();
243 CreateNakedSigninManager();
244 manager_->Initialize(NULL);
245 EXPECT_EQ(account_id, manager_->GetAuthenticatedAccountId());
248 TEST_F(SigninManagerTest, SignInWithRefreshTokenCallbackComplete) {
249 SetUpSigninManagerAsService();
250 EXPECT_FALSE(manager_->IsAuthenticated());
252 // Since the password is empty, must verify the gaia cookies first.
253 SigninManager::OAuthTokenFetchedCallback callback =
254 base::Bind(&SigninManagerTest::CompleteSigninCallback,
255 base::Unretained(this));
256 manager_->StartSignInWithRefreshToken(
257 "rt",
258 "gaia_id",
259 "user@gmail.com",
260 "password",
261 callback);
263 ExpectSignInWithRefreshTokenSuccess();
264 ASSERT_EQ(1U, oauth_tokens_fetched_.size());
265 EXPECT_EQ(oauth_tokens_fetched_[0], "rt");
268 TEST_F(SigninManagerTest, SignInWithRefreshTokenCallsPostSignout) {
269 SetUpSigninManagerAsService();
270 EXPECT_FALSE(manager_->IsAuthenticated());
272 std::string gaia_id = "12345";
273 std::string email = "user@google.com";
275 AccountTrackerServiceFactory::GetForProfile(profile())->
276 SeedAccountInfo(gaia_id, email);
277 FakeAccountFetcherService* account_fetcher_service =
278 static_cast<FakeAccountFetcherService*>(
279 AccountFetcherServiceFactory::GetForProfile(profile()));
280 account_fetcher_service->EnableNetworkFetches();
282 ASSERT_TRUE(signin_client()->get_signed_in_password().empty());
284 manager_->StartSignInWithRefreshToken(
285 "rt1",
286 gaia_id,
287 email,
288 "password",
289 SigninManager::OAuthTokenFetchedCallback());
291 // PostSignedIn is not called until the AccountTrackerService returns.
292 ASSERT_EQ("", signin_client()->get_signed_in_password());
294 account_fetcher_service->FakeUserInfoFetchSuccess(email,
295 gaia_id,
296 "google.com",
297 "full_name",
298 "given_name",
299 "locale",
300 "http://www.google.com");
302 // AccountTracker and SigninManager are both done and PostSignedIn was called.
303 ASSERT_EQ("password", signin_client()->get_signed_in_password());
305 ExpectSignInWithRefreshTokenSuccess();
309 TEST_F(SigninManagerTest, SignOut) {
310 SetUpSigninManagerAsService();
311 manager_->StartSignInWithRefreshToken(
312 "rt",
313 "gaia_id",
314 "user@gmail.com",
315 "password",
316 SigninManager::OAuthTokenFetchedCallback());
317 manager_->SignOut(signin_metrics::SIGNOUT_TEST);
318 EXPECT_FALSE(manager_->IsAuthenticated());
319 EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
320 EXPECT_TRUE(manager_->GetAuthenticatedAccountId().empty());
321 // Should not be persisted anymore
322 ShutDownManager();
323 CreateNakedSigninManager();
324 manager_->Initialize(NULL);
325 EXPECT_FALSE(manager_->IsAuthenticated());
326 EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
327 EXPECT_TRUE(manager_->GetAuthenticatedAccountId().empty());
330 TEST_F(SigninManagerTest, SignOutWhileProhibited) {
331 SetUpSigninManagerAsService();
332 EXPECT_FALSE(manager_->IsAuthenticated());
333 EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
334 EXPECT_TRUE(manager_->GetAuthenticatedAccountId().empty());
336 manager_->SetAuthenticatedAccountInfo("gaia_id", "user@gmail.com");
337 manager_->ProhibitSignout(true);
338 manager_->SignOut(signin_metrics::SIGNOUT_TEST);
339 EXPECT_TRUE(manager_->IsAuthenticated());
340 manager_->ProhibitSignout(false);
341 manager_->SignOut(signin_metrics::SIGNOUT_TEST);
342 EXPECT_FALSE(manager_->IsAuthenticated());
345 TEST_F(SigninManagerTest, Prohibited) {
346 g_browser_process->local_state()->SetString(
347 prefs::kGoogleServicesUsernamePattern, ".*@google.com");
348 CreateNakedSigninManager();
349 manager_->Initialize(g_browser_process->local_state());
350 EXPECT_TRUE(manager_->IsAllowedUsername("test@google.com"));
351 EXPECT_TRUE(manager_->IsAllowedUsername("happy@google.com"));
352 EXPECT_FALSE(manager_->IsAllowedUsername("test@invalid.com"));
353 EXPECT_FALSE(manager_->IsAllowedUsername("test@notgoogle.com"));
354 EXPECT_FALSE(manager_->IsAllowedUsername(std::string()));
357 TEST_F(SigninManagerTest, TestAlternateWildcard) {
358 // Test to make sure we accept "*@google.com" as a pattern (treat it as if
359 // the admin entered ".*@google.com").
360 g_browser_process->local_state()->SetString(
361 prefs::kGoogleServicesUsernamePattern, "*@google.com");
362 CreateNakedSigninManager();
363 manager_->Initialize(g_browser_process->local_state());
364 EXPECT_TRUE(manager_->IsAllowedUsername("test@google.com"));
365 EXPECT_TRUE(manager_->IsAllowedUsername("happy@google.com"));
366 EXPECT_FALSE(manager_->IsAllowedUsername("test@invalid.com"));
367 EXPECT_FALSE(manager_->IsAllowedUsername("test@notgoogle.com"));
368 EXPECT_FALSE(manager_->IsAllowedUsername(std::string()));
371 TEST_F(SigninManagerTest, ProhibitedAtStartup) {
372 std::string account_id = AddToAccountTracker("gaia_id", "user@gmail.com");
373 profile()->GetPrefs()->SetString(prefs::kGoogleServicesAccountId, account_id);
374 g_browser_process->local_state()->SetString(
375 prefs::kGoogleServicesUsernamePattern, ".*@google.com");
376 CreateNakedSigninManager();
377 manager_->Initialize(g_browser_process->local_state());
378 // Currently signed in user is prohibited by policy, so should be signed out.
379 EXPECT_EQ("", manager_->GetAuthenticatedUsername());
380 EXPECT_EQ("", manager_->GetAuthenticatedAccountId());
383 TEST_F(SigninManagerTest, ProhibitedAfterStartup) {
384 std::string account_id = AddToAccountTracker("gaia_id", "user@gmail.com");
385 profile()->GetPrefs()->SetString(prefs::kGoogleServicesAccountId, account_id);
386 CreateNakedSigninManager();
387 manager_->Initialize(g_browser_process->local_state());
388 EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedUsername());
389 EXPECT_EQ(account_id, manager_->GetAuthenticatedAccountId());
390 // Update the profile - user should be signed out.
391 g_browser_process->local_state()->SetString(
392 prefs::kGoogleServicesUsernamePattern, ".*@google.com");
393 EXPECT_EQ("", manager_->GetAuthenticatedUsername());
394 EXPECT_EQ("", manager_->GetAuthenticatedAccountId());
397 TEST_F(SigninManagerTest, ExternalSignIn) {
398 CreateNakedSigninManager();
399 manager_->Initialize(g_browser_process->local_state());
400 EXPECT_EQ("", manager_->GetAuthenticatedUsername());
401 EXPECT_EQ("", manager_->GetAuthenticatedAccountId());
402 EXPECT_EQ(0, test_observer_.num_successful_signins_);
404 std::string account_id = AddToAccountTracker("gaia_id", "user@gmail.com");
405 manager_->OnExternalSigninCompleted(account_id);
406 EXPECT_EQ(1, test_observer_.num_successful_signins_);
407 EXPECT_EQ(0, test_observer_.num_failed_signins_);
408 EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedUsername());
409 EXPECT_EQ(account_id, manager_->GetAuthenticatedAccountId());
412 TEST_F(SigninManagerTest, SigninNotAllowed) {
413 std::string user("user@google.com");
414 profile()->GetPrefs()->SetString(prefs::kGoogleServicesAccountId, user);
415 profile()->GetPrefs()->SetBoolean(prefs::kSigninAllowed, false);
416 CreateNakedSigninManager();
417 AddToAccountTracker("gaia_id", user);
418 manager_->Initialize(g_browser_process->local_state());
419 // Currently signing in is prohibited by policy, so should be signed out.
420 EXPECT_EQ("", manager_->GetAuthenticatedUsername());
421 EXPECT_EQ("", manager_->GetAuthenticatedAccountId());
424 TEST_F(SigninManagerTest, UpgradeToNewPrefs) {
425 profile()->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
426 "user@gmail.com");
427 profile()->GetPrefs()->SetString(prefs::kGoogleServicesUserAccountId,
428 "account_id");
429 CreateNakedSigninManager();
430 manager_->Initialize(g_browser_process->local_state());
431 EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedUsername());
433 // TODO(rogerta): until the migration to gaia id, the account id will remain
434 // the old username.
435 EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedAccountId());
436 EXPECT_EQ("user@gmail.com",
437 profile()->GetPrefs()->GetString(prefs::kGoogleServicesAccountId));
438 EXPECT_EQ("",
439 profile()->GetPrefs()->GetString(prefs::kGoogleServicesUsername));
441 // Make sure account tracker was updated.
442 AccountTrackerService* service =
443 AccountTrackerServiceFactory::GetForProfile(profile());
444 AccountTrackerService::AccountInfo info = service->GetAccountInfo(
445 manager_->GetAuthenticatedAccountId());
446 EXPECT_EQ("user@gmail.com", info.email);
447 EXPECT_EQ("account_id", info.gaia);
450 TEST_F(SigninManagerTest, CanonicalizesPrefs) {
451 profile()->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
452 "user.C@gmail.com");
453 CreateNakedSigninManager();
454 manager_->Initialize(g_browser_process->local_state());
455 EXPECT_EQ("user.C@gmail.com", manager_->GetAuthenticatedUsername());
457 // TODO(rogerta): until the migration to gaia id, the account id will remain
458 // the old username.
459 EXPECT_EQ("userc@gmail.com", manager_->GetAuthenticatedAccountId());
460 EXPECT_EQ("userc@gmail.com",
461 profile()->GetPrefs()->GetString(prefs::kGoogleServicesAccountId));
462 EXPECT_EQ("",
463 profile()->GetPrefs()->GetString(prefs::kGoogleServicesUsername));
465 // Make sure account tracker has a canonicalized username.
466 AccountTrackerService* service =
467 AccountTrackerServiceFactory::GetForProfile(profile());
468 AccountTrackerService::AccountInfo info = service->GetAccountInfo(
469 manager_->GetAuthenticatedAccountId());
470 EXPECT_EQ("user.C@gmail.com", info.email);
471 EXPECT_EQ("userc@gmail.com", info.account_id);