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. 4 5 #include "base/prefs/pref_service.h" 6 #include "base/prefs/scoped_user_pref_update.h" 7 #include "base/run_loop.h" 8 #include "base/strings/utf_string_conversions.h" 9 #include "base/values.h" 10 #include "chrome/browser/chrome_notification_types.h" 11 #include "chrome/browser/content_settings/cookie_settings.h" 12 #include "chrome/browser/custom_handlers/protocol_handler_registry.h" 13 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/profiles/profile_info_cache.h" 15 #include "chrome/browser/profiles/profile_io_data.h" 16 #include "chrome/browser/profiles/profile_manager.h" 17 #include "chrome/browser/signin/chrome_signin_client.h" 18 #include "chrome/browser/signin/chrome_signin_client_factory.h" 19 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h" 20 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h" 21 #include "chrome/browser/signin/fake_signin_manager.h" 22 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 23 #include "chrome/browser/signin/signin_manager_factory.h" 24 #include "chrome/browser/signin/signin_names_io_thread.h" 25 #include "chrome/browser/signin/signin_promo.h" 26 #include "chrome/browser/sync/profile_sync_service_factory.h" 27 #include "chrome/browser/sync/test_profile_sync_service.h" 28 #include "chrome/browser/ui/sync/one_click_signin_helper.h" 29 #include "chrome/browser/ui/webui/signin/login_ui_service.h" 30 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" 31 #include "chrome/common/pref_names.h" 32 #include "chrome/test/base/chrome_render_view_host_test_harness.h" 33 #include "chrome/test/base/testing_browser_process.h" 34 #include "chrome/test/base/testing_pref_service_syncable.h" 35 #include "chrome/test/base/testing_profile.h" 36 #include "chrome/test/base/testing_profile_manager.h" 37 #include "components/autofill/core/common/password_form.h" 38 #include "components/signin/core/browser/profile_oauth2_token_service.h" 39 #include "components/signin/core/browser/signin_manager.h" 40 #include "components/sync_driver/pref_names.h" 41 #include "content/public/browser/browser_context.h" 42 #include "content/public/browser/navigation_details.h" 43 #include "content/public/browser/navigation_entry.h" 44 #include "content/public/browser/web_contents.h" 45 #include "content/public/browser/web_contents_delegate.h" 46 #include "content/public/common/frame_navigate_params.h" 47 #include "content/public/common/url_constants.h" 48 #include "content/public/test/mock_render_process_host.h" 49 #include "grit/chromium_strings.h" 50 #include "grit/generated_resources.h" 51 #include "testing/gmock/include/gmock/gmock.h" 52 #include "testing/gtest/include/gtest/gtest.h" 53 #include "ui/base/l10n/l10n_util.h" 54 55 using ::testing::_; 56 using ::testing::AtLeast; 57 using ::testing::Return; 58 59 namespace { 60 61 // Used to confirm OneClickSigninHelper does not trigger redirect when there is 62 // a pending navigation. 63 class MockWebContentsDelegate : public content::WebContentsDelegate { 64 public: 65 MOCK_METHOD2(OpenURLFromTab, 66 content::WebContents*(content::WebContents* source, 67 const content::OpenURLParams& params)); 68 }; 69 70 class SigninManagerMock : public FakeSigninManager { 71 public: 72 explicit SigninManagerMock(Profile* profile) : FakeSigninManager(profile) { 73 Initialize(NULL); 74 } 75 MOCK_CONST_METHOD1(IsAllowedUsername, bool(const std::string& username)); 76 }; 77 78 static KeyedService* BuildSigninManagerMock(content::BrowserContext* profile) { 79 return new SigninManagerMock(static_cast<Profile*>(profile)); 80 } 81 82 class TestProfileIOData : public ProfileIOData { 83 public: 84 TestProfileIOData(Profile::ProfileType profile_type, 85 PrefService* pref_service, PrefService* local_state, 86 CookieSettings* cookie_settings) 87 : ProfileIOData(profile_type) { 88 // Initialize the IO members required for these tests, but keep them on 89 // this thread since we don't use a background thread here. 90 google_services_username()->Init(prefs::kGoogleServicesUsername, 91 pref_service); 92 reverse_autologin_enabled()->Init(prefs::kReverseAutologinEnabled, 93 pref_service); 94 one_click_signin_rejected_email_list()->Init( 95 prefs::kReverseAutologinRejectedEmailList, pref_service); 96 97 google_services_username_pattern()->Init( 98 prefs::kGoogleServicesUsernamePattern, local_state); 99 100 sync_disabled()->Init(sync_driver::prefs::kSyncManaged, pref_service); 101 102 signin_allowed()->Init(prefs::kSigninAllowed, pref_service); 103 104 set_signin_names_for_testing(new SigninNamesOnIOThread()); 105 SetCookieSettingsForTesting(cookie_settings); 106 } 107 108 virtual ~TestProfileIOData() { 109 signin_names()->ReleaseResourcesOnUIThread(); 110 } 111 112 // ProfileIOData overrides: 113 virtual void InitializeInternal( 114 ProfileParams* profile_params, 115 content::ProtocolHandlerMap* protocol_handlers, 116 content::URLRequestInterceptorScopedVector request_interceptors) 117 const OVERRIDE { 118 NOTREACHED(); 119 } 120 virtual void InitializeExtensionsRequestContext( 121 ProfileParams* profile_params) const OVERRIDE { 122 NOTREACHED(); 123 } 124 virtual ChromeURLRequestContext* InitializeAppRequestContext( 125 ChromeURLRequestContext* main_context, 126 const StoragePartitionDescriptor& details, 127 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> 128 protocol_handler_interceptor, 129 content::ProtocolHandlerMap* protocol_handlers, 130 content::URLRequestInterceptorScopedVector request_interceptors) 131 const OVERRIDE { 132 NOTREACHED(); 133 return NULL; 134 } 135 virtual ChromeURLRequestContext* InitializeMediaRequestContext( 136 ChromeURLRequestContext* original_context, 137 const StoragePartitionDescriptor& details) const OVERRIDE { 138 NOTREACHED(); 139 return NULL; 140 } 141 virtual ChromeURLRequestContext* 142 AcquireMediaRequestContext() const OVERRIDE { 143 NOTREACHED(); 144 return NULL; 145 } 146 virtual ChromeURLRequestContext* AcquireIsolatedAppRequestContext( 147 ChromeURLRequestContext* main_context, 148 const StoragePartitionDescriptor& partition_descriptor, 149 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> 150 protocol_handler_interceptor, 151 content::ProtocolHandlerMap* protocol_handlers, 152 content::URLRequestInterceptorScopedVector request_interceptors) 153 const OVERRIDE { 154 NOTREACHED(); 155 return NULL; 156 } 157 virtual ChromeURLRequestContext* 158 AcquireIsolatedMediaRequestContext( 159 ChromeURLRequestContext* app_context, 160 const StoragePartitionDescriptor& partition_descriptor) 161 const OVERRIDE { 162 NOTREACHED(); 163 return NULL; 164 } 165 }; 166 167 class TestURLRequest : public base::SupportsUserData { 168 public: 169 TestURLRequest() {} 170 virtual ~TestURLRequest() {} 171 }; 172 173 class OneClickTestProfileSyncService : public TestProfileSyncService { 174 public: 175 virtual ~OneClickTestProfileSyncService() {} 176 177 // Helper routine to be used in conjunction with 178 // BrowserContextKeyedServiceFactory::SetTestingFactory(). 179 static KeyedService* Build(content::BrowserContext* profile) { 180 return new OneClickTestProfileSyncService(static_cast<Profile*>(profile)); 181 } 182 183 // Need to control this for certain tests. 184 virtual bool FirstSetupInProgress() const OVERRIDE { 185 return first_setup_in_progress_; 186 } 187 188 virtual bool sync_initialized() const OVERRIDE { return sync_initialized_; } 189 190 // Controls return value of FirstSetupInProgress. Because some bits 191 // of UI depend on that value, it's useful to control it separately 192 // from the internal work and components that are triggered (such as 193 // ReconfigureDataTypeManager) to facilitate unit tests. 194 void set_first_setup_in_progress(bool in_progress) { 195 first_setup_in_progress_ = in_progress; 196 } 197 198 void set_sync_initialized(bool initialized) { 199 sync_initialized_ = initialized; 200 } 201 202 private: 203 explicit OneClickTestProfileSyncService(Profile* profile) 204 : TestProfileSyncService( 205 NULL, 206 profile, 207 SigninManagerFactory::GetForProfile(profile), 208 ProfileOAuth2TokenServiceFactory::GetForProfile(profile), 209 browser_sync::MANUAL_START), 210 first_setup_in_progress_(false), 211 sync_initialized_(false) {} 212 213 bool first_setup_in_progress_; 214 bool sync_initialized_; 215 }; 216 217 } // namespace 218 219 class OneClickSigninHelperTest : public ChromeRenderViewHostTestHarness { 220 public: 221 OneClickSigninHelperTest(); 222 223 virtual void SetUp() OVERRIDE; 224 virtual void TearDown() OVERRIDE; 225 226 // Sets up the sign-in manager for tests. If |username| is 227 // is not empty, the profile of the mock WebContents will be connected to 228 // the given account. 229 void SetUpSigninManager(const std::string& username); 230 231 // Set the ID of the signin process that the test will assume to be the 232 // only process allowed to sign the user in to Chrome. 233 void SetTrustedSigninProcessID(int id); 234 235 void AddEmailToOneClickRejectedList(const std::string& email); 236 void EnableOneClick(bool enable); 237 void AllowSigninCookies(bool enable); 238 void SetAllowedUsernamePattern(const std::string& pattern); 239 void SubmitGAIAPassword(OneClickSigninHelper* helper); 240 241 SigninManagerMock* signin_manager_; 242 FakeProfileOAuth2TokenService* fake_oauth2_token_service_; 243 244 protected: 245 GoogleServiceAuthError no_error_; 246 247 private: 248 // ChromeRenderViewHostTestHarness overrides: 249 virtual content::BrowserContext* CreateBrowserContext() OVERRIDE; 250 251 // The ID of the signin process the test will assume to be trusted. 252 // By default, set to the test RenderProcessHost's process ID, but 253 // overridden by SetTrustedSigninProcessID. 254 int trusted_signin_process_id_; 255 256 DISALLOW_COPY_AND_ASSIGN(OneClickSigninHelperTest); 257 }; 258 259 OneClickSigninHelperTest::OneClickSigninHelperTest() 260 : signin_manager_(NULL), 261 fake_oauth2_token_service_(NULL), 262 no_error_(GoogleServiceAuthError::NONE), 263 trusted_signin_process_id_(-1) { 264 } 265 266 void OneClickSigninHelperTest::SetUp() { 267 signin::ForceWebBasedSigninFlowForTesting(true); 268 content::RenderViewHostTestHarness::SetUp(); 269 SetTrustedSigninProcessID(process()->GetID()); 270 } 271 272 void OneClickSigninHelperTest::TearDown() { 273 signin::ForceWebBasedSigninFlowForTesting(false); 274 content::RenderViewHostTestHarness::TearDown(); 275 } 276 277 void OneClickSigninHelperTest::SetTrustedSigninProcessID(int id) { 278 trusted_signin_process_id_ = id; 279 } 280 281 void OneClickSigninHelperTest::SetUpSigninManager(const std::string& username) { 282 SigninClient* signin_client = 283 ChromeSigninClientFactory::GetForProfile(profile()); 284 if (signin_client) 285 signin_client->SetSigninProcess(trusted_signin_process_id_); 286 287 signin_manager_ = static_cast<SigninManagerMock*>( 288 SigninManagerFactory::GetForProfile(profile())); 289 if (!username.empty()) { 290 ASSERT_TRUE(signin_manager_); 291 signin_manager_->SetAuthenticatedUsername(username); 292 } 293 } 294 295 void OneClickSigninHelperTest::EnableOneClick(bool enable) { 296 PrefService* pref_service = profile()->GetPrefs(); 297 pref_service->SetBoolean(prefs::kReverseAutologinEnabled, enable); 298 } 299 300 void OneClickSigninHelperTest::AddEmailToOneClickRejectedList( 301 const std::string& email) { 302 PrefService* pref_service = profile()->GetPrefs(); 303 ListPrefUpdate updater(pref_service, 304 prefs::kReverseAutologinRejectedEmailList); 305 updater->AppendIfNotPresent(new base::StringValue(email)); 306 } 307 308 void OneClickSigninHelperTest::AllowSigninCookies(bool enable) { 309 CookieSettings* cookie_settings = 310 CookieSettings::Factory::GetForProfile(profile()).get(); 311 cookie_settings->SetDefaultCookieSetting(enable ? CONTENT_SETTING_ALLOW 312 : CONTENT_SETTING_BLOCK); 313 } 314 315 void OneClickSigninHelperTest::SetAllowedUsernamePattern( 316 const std::string& pattern) { 317 PrefService* local_state = g_browser_process->local_state(); 318 local_state->SetString(prefs::kGoogleServicesUsernamePattern, pattern); 319 } 320 321 void OneClickSigninHelperTest::SubmitGAIAPassword( 322 OneClickSigninHelper* helper) { 323 autofill::PasswordForm password_form; 324 password_form.origin = GURL("https://accounts.google.com"); 325 password_form.signon_realm = "https://accounts.google.com"; 326 password_form.password_value = base::UTF8ToUTF16("password"); 327 helper->PasswordSubmitted(password_form); 328 } 329 330 content::BrowserContext* OneClickSigninHelperTest::CreateBrowserContext() { 331 TestingProfile::Builder builder; 332 builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(), 333 BuildFakeProfileOAuth2TokenService); 334 builder.AddTestingFactory(SigninManagerFactory::GetInstance(), 335 BuildSigninManagerMock); 336 scoped_ptr<TestingProfile> profile = builder.Build(); 337 338 fake_oauth2_token_service_ = 339 static_cast<FakeProfileOAuth2TokenService*>( 340 ProfileOAuth2TokenServiceFactory::GetForProfile(profile.get())); 341 342 return profile.release(); 343 } 344 345 class OneClickSigninHelperIOTest : public OneClickSigninHelperTest { 346 public: 347 OneClickSigninHelperIOTest(); 348 349 virtual void SetUp() OVERRIDE; 350 351 TestProfileIOData* CreateTestProfileIOData(Profile::ProfileType profile_type); 352 353 protected: 354 TestingProfileManager testing_profile_manager_; 355 TestURLRequest request_; 356 const GURL valid_gaia_url_; 357 358 private: 359 DISALLOW_COPY_AND_ASSIGN(OneClickSigninHelperIOTest); 360 }; 361 362 OneClickSigninHelperIOTest::OneClickSigninHelperIOTest() 363 : testing_profile_manager_( 364 TestingBrowserProcess::GetGlobal()), 365 valid_gaia_url_("https://accounts.google.com/") { 366 } 367 368 void OneClickSigninHelperIOTest::SetUp() { 369 OneClickSigninHelperTest::SetUp(); 370 ASSERT_TRUE(testing_profile_manager_.SetUp()); 371 } 372 373 TestProfileIOData* OneClickSigninHelperIOTest::CreateTestProfileIOData( 374 Profile::ProfileType profile_type) { 375 PrefService* pref_service = profile()->GetPrefs(); 376 PrefService* local_state = g_browser_process->local_state(); 377 CookieSettings* cookie_settings = 378 CookieSettings::Factory::GetForProfile(profile()).get(); 379 TestProfileIOData* io_data = new TestProfileIOData( 380 profile_type, pref_service, local_state, cookie_settings); 381 io_data->set_reverse_autologin_pending_email("user (at) gmail.com"); 382 return io_data; 383 } 384 385 class OneClickSigninHelperIncognitoTest : public OneClickSigninHelperTest { 386 protected: 387 // content::RenderViewHostTestHarness. 388 virtual content::BrowserContext* CreateBrowserContext() OVERRIDE; 389 }; 390 391 content::BrowserContext* 392 OneClickSigninHelperIncognitoTest::CreateBrowserContext() { 393 // Builds an incognito profile to run this test. 394 TestingProfile::Builder builder; 395 builder.SetIncognito(); 396 return builder.Build().release(); 397 } 398 399 TEST_F(OneClickSigninHelperTest, CanOfferNoContents) { 400 std::string error_message; 401 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 402 NULL, OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 403 "user (at) gmail.com", &error_message)); 404 EXPECT_EQ("", error_message); 405 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 406 NULL, OneClickSigninHelper::CAN_OFFER_FOR_ALL, 407 "user (at) gmail.com", &error_message)); 408 EXPECT_EQ("", error_message); 409 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 410 NULL, 411 OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 412 std::string(), 413 &error_message)); 414 EXPECT_EQ("", error_message); 415 } 416 417 TEST_F(OneClickSigninHelperTest, CanOffer) { 418 SetUpSigninManager(std::string()); 419 420 EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)). 421 WillRepeatedly(Return(true)); 422 423 EnableOneClick(true); 424 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 425 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 426 "user (at) gmail.com", NULL)); 427 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 428 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL, 429 "user (at) gmail.com", NULL)); 430 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 431 web_contents(), 432 OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 433 std::string(), 434 NULL)); 435 436 EnableOneClick(false); 437 438 std::string error_message; 439 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 440 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 441 "user (at) gmail.com", &error_message)); 442 EXPECT_EQ("", error_message); 443 444 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 445 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL, 446 "user (at) gmail.com", &error_message)); 447 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 448 web_contents(), 449 OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 450 std::string(), 451 &error_message)); 452 EXPECT_EQ("", error_message); 453 } 454 455 TEST_F(OneClickSigninHelperTest, CanOfferFirstSetup) { 456 SetUpSigninManager(std::string()); 457 458 EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)). 459 WillRepeatedly(Return(true)); 460 461 // Invoke OneClickTestProfileSyncService factory function and grab result. 462 OneClickTestProfileSyncService* sync = 463 static_cast<OneClickTestProfileSyncService*>( 464 ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse( 465 profile(), OneClickTestProfileSyncService::Build)); 466 sync->set_sync_initialized(false); 467 sync->Initialize(); 468 sync->set_sync_initialized(true); 469 sync->set_first_setup_in_progress(true); 470 471 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 472 web_contents(), 473 OneClickSigninHelper::CAN_OFFER_FOR_ALL, 474 "foo (at) gmail.com", NULL)); 475 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 476 web_contents(), 477 OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 478 "foo (at) gmail.com", NULL)); 479 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 480 web_contents(), 481 OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 482 std::string(), 483 NULL)); 484 } 485 486 TEST_F(OneClickSigninHelperTest, CanOfferProfileConnected) { 487 SetUpSigninManager("foo (at) gmail.com"); 488 489 EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)). 490 WillRepeatedly(Return(true)); 491 492 std::string error_message; 493 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 494 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 495 "foo (at) gmail.com", &error_message)); 496 EXPECT_EQ("", error_message); 497 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 498 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 499 "foo", &error_message)); 500 EXPECT_EQ("", error_message); 501 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 502 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 503 "user (at) gmail.com", &error_message)); 504 EXPECT_EQ(l10n_util::GetStringFUTF8(IDS_SYNC_WRONG_EMAIL, 505 base::UTF8ToUTF16("foo (at) gmail.com")), 506 error_message); 507 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 508 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL, 509 "foo (at) gmail.com", &error_message)); 510 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 511 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL, 512 "foo", &error_message)); 513 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 514 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL, 515 "user (at) gmail.com", &error_message)); 516 EXPECT_EQ(l10n_util::GetStringFUTF8(IDS_SYNC_WRONG_EMAIL, 517 base::UTF8ToUTF16("foo (at) gmail.com")), 518 error_message); 519 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 520 web_contents(), 521 OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 522 std::string(), 523 &error_message)); 524 } 525 526 TEST_F(OneClickSigninHelperTest, CanOfferUsernameNotAllowed) { 527 SetUpSigninManager(std::string()); 528 529 EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)). 530 WillRepeatedly(Return(false)); 531 532 std::string error_message; 533 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 534 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 535 "foo (at) gmail.com", &error_message)); 536 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_SYNC_LOGIN_NAME_PROHIBITED), 537 error_message); 538 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 539 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL, 540 "foo (at) gmail.com", &error_message)); 541 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_SYNC_LOGIN_NAME_PROHIBITED), 542 error_message); 543 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 544 web_contents(), 545 OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 546 std::string(), 547 &error_message)); 548 } 549 550 TEST_F(OneClickSigninHelperTest, CanOfferWithRejectedEmail) { 551 SetUpSigninManager(std::string()); 552 553 EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)). 554 WillRepeatedly(Return(true)); 555 556 AddEmailToOneClickRejectedList("foo (at) gmail.com"); 557 AddEmailToOneClickRejectedList("user (at) gmail.com"); 558 559 std::string error_message; 560 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 561 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 562 "foo (at) gmail.com", &error_message)); 563 EXPECT_EQ("", error_message); 564 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 565 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 566 "user (at) gmail.com", &error_message)); 567 EXPECT_EQ("", error_message); 568 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 569 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL, 570 "foo (at) gmail.com", &error_message)); 571 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 572 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL, 573 "user (at) gmail.com", &error_message)); 574 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 575 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 576 "john (at) gmail.com", &error_message)); 577 } 578 579 TEST_F(OneClickSigninHelperIncognitoTest, CanOfferIncognito) { 580 SetUpSigninManager(std::string()); 581 582 std::string error_message; 583 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 584 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 585 "user (at) gmail.com", &error_message)); 586 EXPECT_EQ("", error_message); 587 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 588 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL, 589 "user (at) gmail.com", &error_message)); 590 EXPECT_EQ("", error_message); 591 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 592 web_contents(), 593 OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 594 std::string(), 595 &error_message)); 596 EXPECT_EQ("", error_message); 597 } 598 599 TEST_F(OneClickSigninHelperTest, CanOfferNoSigninCookies) { 600 SetUpSigninManager(std::string()); 601 AllowSigninCookies(false); 602 603 EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)). 604 WillRepeatedly(Return(true)); 605 606 std::string error_message; 607 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 608 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 609 "user (at) gmail.com", &error_message)); 610 EXPECT_EQ("", error_message); 611 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 612 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL, 613 "user (at) gmail.com", &error_message)); 614 EXPECT_EQ("", error_message); 615 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 616 web_contents(), 617 OneClickSigninHelper::CAN_OFFER_FOR_INTERSTITAL_ONLY, 618 std::string(), 619 &error_message)); 620 EXPECT_EQ("", error_message); 621 } 622 623 TEST_F(OneClickSigninHelperTest, CanOfferDisabledByPolicy) { 624 SetUpSigninManager(std::string()); 625 626 EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)). 627 WillRepeatedly(Return(true)); 628 629 EnableOneClick(true); 630 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 631 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL, 632 "user (at) gmail.com", NULL)); 633 634 // Simulate a policy disabling signin by writing kSigninAllowed directly. 635 profile()->GetTestingPrefService()->SetManagedPref( 636 prefs::kSigninAllowed, base::Value::CreateBooleanValue(false)); 637 638 EXPECT_FALSE(OneClickSigninHelper::CanOffer( 639 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL, 640 "user (at) gmail.com", NULL)); 641 642 // Reset the preference value to true. 643 profile()->GetTestingPrefService()->SetManagedPref( 644 prefs::kSigninAllowed, base::Value::CreateBooleanValue(true)); 645 646 // Simulate a policy disabling sync by writing kSyncManaged directly. 647 profile()->GetTestingPrefService()->SetManagedPref( 648 sync_driver::prefs::kSyncManaged, base::Value::CreateBooleanValue(true)); 649 650 // Should still offer even if sync is disabled by policy. 651 EXPECT_TRUE(OneClickSigninHelper::CanOffer( 652 web_contents(), OneClickSigninHelper::CAN_OFFER_FOR_ALL, 653 "user (at) gmail.com", NULL)); 654 } 655 656 // Should not crash if a helper instance is not associated with an incognito 657 // web contents. 658 TEST_F(OneClickSigninHelperIncognitoTest, ShowInfoBarUIThreadIncognito) { 659 SetUpSigninManager(std::string()); 660 OneClickSigninHelper* helper = 661 OneClickSigninHelper::FromWebContents(web_contents()); 662 EXPECT_EQ(NULL, helper); 663 664 OneClickSigninHelper::ShowInfoBarUIThread( 665 "session_index", "email", OneClickSigninHelper::AUTO_ACCEPT_ACCEPTED, 666 signin::SOURCE_UNKNOWN, GURL(), process()->GetID(), 667 rvh()->GetRoutingID()); 668 } 669 670 // If Chrome signin is triggered from a webstore install, and user chooses to 671 // config sync, then Chrome should redirect immediately to sync settings page, 672 // and upon successful setup, redirect back to webstore. 673 TEST_F(OneClickSigninHelperTest, SigninFromWebstoreWithConfigSyncfirst) { 674 SetUpSigninManager(std::string()); 675 EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)) 676 .WillRepeatedly(Return(true)); 677 678 OneClickTestProfileSyncService* sync_service = 679 static_cast<OneClickTestProfileSyncService*>( 680 ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse( 681 profile(), OneClickTestProfileSyncService::Build)); 682 sync_service->set_sync_initialized(true); 683 684 content::WebContents* contents = web_contents(); 685 686 OneClickSigninHelper::CreateForWebContentsWithPasswordManager(contents, NULL); 687 OneClickSigninHelper* helper = 688 OneClickSigninHelper::FromWebContents(contents); 689 helper->SetDoNotClearPendingEmailForTesting(); 690 helper->set_do_not_start_sync_for_testing(); 691 692 GURL continueUrl("https://chrome.google.com/webstore?source=5"); 693 OneClickSigninHelper::ShowInfoBarUIThread( 694 "session_index", "user (at) gmail.com", 695 OneClickSigninHelper::AUTO_ACCEPT_EXPLICIT, 696 signin::SOURCE_WEBSTORE_INSTALL, 697 continueUrl, process()->GetID(), rvh()->GetRoutingID()); 698 699 SubmitGAIAPassword(helper); 700 701 NavigateAndCommit(GURL("https://chrome.google.com/webstore?source=3")); 702 helper->DidStopLoading(rvh()); 703 sync_service->NotifyObservers(); 704 EXPECT_EQ(GURL(continueUrl), contents->GetVisibleURL()); 705 } 706 707 // Checks that the state of OneClickSigninHelper is cleaned when there is a 708 // navigation away from the sign in flow that is not triggered by the 709 // web contents. 710 TEST_F(OneClickSigninHelperTest, CleanTransientStateOnNavigate) { 711 content::WebContents* contents = web_contents(); 712 713 OneClickSigninHelper::CreateForWebContentsWithPasswordManager(contents, NULL); 714 OneClickSigninHelper* helper = 715 OneClickSigninHelper::FromWebContents(contents); 716 helper->SetDoNotClearPendingEmailForTesting(); 717 helper->auto_accept_ = OneClickSigninHelper::AUTO_ACCEPT_EXPLICIT; 718 719 content::LoadCommittedDetails details; 720 content::FrameNavigateParams params; 721 params.url = GURL("http://crbug.com"); 722 params.transition = content::PAGE_TRANSITION_TYPED; 723 helper->DidNavigateMainFrame(details, params); 724 725 EXPECT_EQ(OneClickSigninHelper::AUTO_ACCEPT_NONE, helper->auto_accept_); 726 } 727 728 TEST_F(OneClickSigninHelperTest, NoRedirectToNTPWithPendingEntry) { 729 content::NavigationController& controller = web_contents()->GetController(); 730 EXPECT_FALSE(controller.GetPendingEntry()); 731 732 const GURL fooWebUIURL("chrome://foo"); 733 controller.LoadURL(fooWebUIURL, content::Referrer(), 734 content::PAGE_TRANSITION_TYPED, std::string()); 735 EXPECT_EQ(fooWebUIURL, controller.GetPendingEntry()->GetURL()); 736 737 MockWebContentsDelegate delegate; 738 EXPECT_CALL(delegate, OpenURLFromTab(_, _)).Times(0); 739 web_contents()->SetDelegate(&delegate); 740 OneClickSigninHelper::RedirectToNtpOrAppsPage( 741 web_contents(), signin::SOURCE_UNKNOWN); 742 743 EXPECT_EQ(fooWebUIURL, controller.GetPendingEntry()->GetURL()); 744 } 745 746 // I/O thread tests 747 748 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThread) { 749 scoped_ptr<TestProfileIOData> io_data( 750 CreateTestProfileIOData(Profile::REGULAR_PROFILE)); 751 EXPECT_EQ(OneClickSigninHelper::CAN_OFFER, 752 OneClickSigninHelper::CanOfferOnIOThreadImpl( 753 valid_gaia_url_, &request_, io_data.get())); 754 } 755 756 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadIncognito) { 757 scoped_ptr<TestProfileIOData> io_data( 758 CreateTestProfileIOData(Profile::INCOGNITO_PROFILE)); 759 EXPECT_EQ(OneClickSigninHelper::DONT_OFFER, 760 OneClickSigninHelper::CanOfferOnIOThreadImpl( 761 valid_gaia_url_, &request_, io_data.get())); 762 } 763 764 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadNoIOData) { 765 EXPECT_EQ(OneClickSigninHelper::DONT_OFFER, 766 OneClickSigninHelper::CanOfferOnIOThreadImpl( 767 valid_gaia_url_, &request_, NULL)); 768 } 769 770 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadBadURL) { 771 scoped_ptr<TestProfileIOData> io_data( 772 CreateTestProfileIOData(Profile::REGULAR_PROFILE)); 773 EXPECT_EQ( 774 OneClickSigninHelper::IGNORE_REQUEST, 775 OneClickSigninHelper::CanOfferOnIOThreadImpl( 776 GURL("https://foo.com/"), &request_, io_data.get())); 777 EXPECT_EQ(OneClickSigninHelper::IGNORE_REQUEST, 778 OneClickSigninHelper::CanOfferOnIOThreadImpl( 779 GURL("http://accounts.google.com/"), 780 &request_, 781 io_data.get())); 782 } 783 784 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadDisabled) { 785 EnableOneClick(false); 786 scoped_ptr<TestProfileIOData> io_data( 787 CreateTestProfileIOData(Profile::REGULAR_PROFILE)); 788 EXPECT_EQ(OneClickSigninHelper::DONT_OFFER, 789 OneClickSigninHelper::CanOfferOnIOThreadImpl( 790 valid_gaia_url_, &request_, io_data.get())); 791 } 792 793 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadSignedIn) { 794 PrefService* pref_service = profile()->GetPrefs(); 795 pref_service->SetString(prefs::kGoogleServicesUsername, "user (at) gmail.com"); 796 797 scoped_ptr<TestProfileIOData> io_data( 798 CreateTestProfileIOData(Profile::REGULAR_PROFILE)); 799 EXPECT_EQ(OneClickSigninHelper::DONT_OFFER, 800 OneClickSigninHelper::CanOfferOnIOThreadImpl( 801 valid_gaia_url_, &request_, io_data.get())); 802 } 803 804 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadEmailNotAllowed) { 805 SetAllowedUsernamePattern("*@example.com"); 806 scoped_ptr<TestProfileIOData> io_data( 807 CreateTestProfileIOData(Profile::REGULAR_PROFILE)); 808 EXPECT_EQ(OneClickSigninHelper::DONT_OFFER, 809 OneClickSigninHelper::CanOfferOnIOThreadImpl( 810 valid_gaia_url_, &request_, io_data.get())); 811 } 812 813 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadEmailAlreadyUsed) { 814 ProfileInfoCache* cache = testing_profile_manager_.profile_info_cache(); 815 const base::FilePath& user_data_dir = cache->GetUserDataDir(); 816 cache->AddProfileToCache(user_data_dir.Append(FILE_PATH_LITERAL("user")), 817 base::UTF8ToUTF16("user"), 818 base::UTF8ToUTF16("user (at) gmail.com"), 0, 819 std::string()); 820 821 scoped_ptr<TestProfileIOData> io_data( 822 CreateTestProfileIOData(Profile::REGULAR_PROFILE)); 823 EXPECT_EQ(OneClickSigninHelper::DONT_OFFER, 824 OneClickSigninHelper::CanOfferOnIOThreadImpl( 825 valid_gaia_url_, &request_, io_data.get())); 826 } 827 828 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadWithRejectedEmail) { 829 AddEmailToOneClickRejectedList("user (at) gmail.com"); 830 scoped_ptr<TestProfileIOData> io_data( 831 CreateTestProfileIOData(Profile::REGULAR_PROFILE)); 832 EXPECT_EQ(OneClickSigninHelper::DONT_OFFER, 833 OneClickSigninHelper::CanOfferOnIOThreadImpl( 834 valid_gaia_url_, &request_, io_data.get())); 835 } 836 837 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadNoSigninCookies) { 838 AllowSigninCookies(false); 839 scoped_ptr<TestProfileIOData> io_data( 840 CreateTestProfileIOData(Profile::REGULAR_PROFILE)); 841 EXPECT_EQ(OneClickSigninHelper::DONT_OFFER, 842 OneClickSigninHelper::CanOfferOnIOThreadImpl( 843 valid_gaia_url_, &request_, io_data.get())); 844 } 845 846 TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThreadDisabledByPolicy) { 847 scoped_ptr<TestProfileIOData> io_data( 848 CreateTestProfileIOData(Profile::REGULAR_PROFILE)); 849 EXPECT_EQ(OneClickSigninHelper::CAN_OFFER, 850 OneClickSigninHelper::CanOfferOnIOThreadImpl( 851 valid_gaia_url_, &request_, io_data.get())); 852 853 // Simulate a policy disabling signin by writing kSigninAllowed directly. 854 // We should not offer to sign in the browser. 855 profile()->GetTestingPrefService()->SetManagedPref( 856 prefs::kSigninAllowed, base::Value::CreateBooleanValue(false)); 857 EXPECT_EQ(OneClickSigninHelper::DONT_OFFER, 858 OneClickSigninHelper::CanOfferOnIOThreadImpl( 859 valid_gaia_url_, &request_, io_data.get())); 860 861 // Reset the preference. 862 profile()->GetTestingPrefService()->SetManagedPref( 863 prefs::kSigninAllowed, base::Value::CreateBooleanValue(true)); 864 865 // Simulate a policy disabling sync by writing kSyncManaged directly. 866 // We should still offer to sign in the browser. 867 profile()->GetTestingPrefService()->SetManagedPref( 868 sync_driver::prefs::kSyncManaged, base::Value::CreateBooleanValue(true)); 869 EXPECT_EQ(OneClickSigninHelper::CAN_OFFER, 870 OneClickSigninHelper::CanOfferOnIOThreadImpl( 871 valid_gaia_url_, &request_, io_data.get())); 872 } 873 874 875 class MockStarterWrapper 876 : public testing::StrictMock<OneClickSigninHelper::SyncStarterWrapper> { 877 public: 878 MockStarterWrapper( 879 const OneClickSigninHelper::StartSyncArgs& args, 880 OneClickSigninSyncStarter::StartSyncMode start_mode); 881 882 MOCK_METHOD1(DisplayErrorBubble, void(const std::string& error_message)); 883 MOCK_METHOD0(StartSigninOAuthHelper, void()); 884 MOCK_METHOD2(StartOneClickSigninSyncStarter, 885 void(const std::string& email, 886 const std::string& refresh_token)); 887 }; 888 889 MockStarterWrapper::MockStarterWrapper( 890 const OneClickSigninHelper::StartSyncArgs& args, 891 OneClickSigninSyncStarter::StartSyncMode start_mode) 892 : testing::StrictMock<OneClickSigninHelper::SyncStarterWrapper>( 893 args, start_mode) { 894 } 895 896 class OneClickSyncStarterWrapperTest : public testing::Test { 897 public: 898 virtual void SetUp() OVERRIDE { 899 TestingProfile::Builder builder; 900 profile_ = builder.Build(); 901 } 902 903 virtual void TearDown() OVERRIDE { 904 // Let the SyncStarterWrapper delete itself. 905 base::RunLoop().RunUntilIdle(); 906 } 907 908 void SetCookie(const std::string& value) { 909 // Set a valid LSID cookie in the test cookie store. 910 scoped_refptr<net::CookieMonster> cookie_monster = 911 profile()->GetCookieMonster(); 912 net::CookieOptions options; 913 options.set_include_httponly(); 914 cookie_monster->SetCookieWithOptionsAsync( 915 GURL("https://accounts.google.com"), 916 value, options, 917 net::CookieMonster::SetCookiesCallback()); 918 } 919 920 void SimulateRefreshTokenFetched( 921 SigninOAuthHelper::Consumer* consumer, 922 const std::string& email, 923 const std::string& display_email, 924 const std::string& refresh_token) { 925 consumer->OnSigninOAuthInformationAvailable( 926 email, display_email, refresh_token); 927 } 928 929 TestingProfile* profile() { return profile_.get(); } 930 931 private: 932 content::TestBrowserThreadBundle thread_bundle_; 933 scoped_ptr<TestingProfile> profile_; 934 }; 935 936 TEST_F(OneClickSyncStarterWrapperTest, SignInWithRefreshToken) { 937 OneClickSigninHelper::StartSyncArgs args; 938 args.email = "foo (at) gmail.com"; 939 args.password = "password"; 940 args.refresh_token = "refresh_token"; 941 MockStarterWrapper* wrapper = new MockStarterWrapper( 942 args, OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS); 943 944 EXPECT_CALL(*wrapper, 945 StartOneClickSigninSyncStarter("foo (at) gmail.com", 946 "refresh_token")); 947 wrapper->Start(); 948 } 949 950 TEST_F(OneClickSyncStarterWrapperTest, SignInWithPasswordNoRefreshToken) { 951 OneClickSigninHelper::StartSyncArgs args; 952 args.email = "foo (at) gmail.com"; 953 args.password = "password"; 954 MockStarterWrapper* wrapper = new MockStarterWrapper( 955 args, OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS); 956 957 EXPECT_CALL(*wrapper, StartSigninOAuthHelper()); 958 EXPECT_CALL(*wrapper, 959 StartOneClickSigninSyncStarter("foo (at) gmail.com", 960 "refresh_token")); 961 wrapper->Start(); 962 SimulateRefreshTokenFetched(wrapper, "foo (at) gmail.com", "foo (at) gmail.com", 963 "refresh_token"); 964 } 965 966 TEST_F(OneClickSyncStarterWrapperTest, SignInWithWrongEmail) { 967 OneClickSigninHelper::StartSyncArgs args; 968 args.email = "foo (at) gmail.com"; 969 args.password = "password"; 970 MockStarterWrapper* wrapper = new MockStarterWrapper( 971 args, OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS); 972 973 EXPECT_CALL(*wrapper, StartSigninOAuthHelper()); 974 EXPECT_CALL(*wrapper, DisplayErrorBubble(_)); 975 wrapper->Start(); 976 SimulateRefreshTokenFetched(wrapper, "bar (at) gmail.com", "bar (at) gmail.com", 977 "refresh_token"); 978 } 979 980 TEST_F(OneClickSyncStarterWrapperTest, SignInWithEmptyPasswordValidCookie) { 981 OneClickSigninHelper::StartSyncArgs args; 982 args.email = "foo (at) gmail.com"; 983 args.profile = profile(); 984 MockStarterWrapper* wrapper = new MockStarterWrapper( 985 args, OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS); 986 SetCookie("LSID=1234; secure; httponly"); 987 988 EXPECT_CALL(*wrapper, StartSigninOAuthHelper()); 989 EXPECT_CALL(*wrapper, 990 StartOneClickSigninSyncStarter("foo (at) gmail.com", 991 "refresh_token")); 992 wrapper->Start(); 993 base::RunLoop().RunUntilIdle(); 994 SimulateRefreshTokenFetched(wrapper, "foo (at) gmail.com", "foo (at) gmail.com", 995 "refresh_token"); 996 } 997 998 TEST_F(OneClickSyncStarterWrapperTest, SignInWithEmptyPasswordNoCookie) { 999 OneClickSigninHelper::StartSyncArgs args; 1000 args.email = "foo (at) gmail.com"; 1001 args.profile = profile(); 1002 MockStarterWrapper* wrapper = new MockStarterWrapper( 1003 args, OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS); 1004 1005 EXPECT_CALL(*wrapper, DisplayErrorBubble(_)); 1006 wrapper->Start(); 1007 base::RunLoop().RunUntilIdle(); 1008 } 1009 1010 TEST_F(OneClickSyncStarterWrapperTest, SignInWithEmptyPasswordInvalidCookie) { 1011 OneClickSigninHelper::StartSyncArgs args; 1012 args.email = "foo (at) gmail.com"; 1013 args.profile = profile(); 1014 MockStarterWrapper* wrapper = new MockStarterWrapper( 1015 args, OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS); 1016 SetCookie("LSID=1234; domain=google.com; secure; httponly"); 1017 1018 EXPECT_CALL(*wrapper, DisplayErrorBubble(_)); 1019 wrapper->Start(); 1020 base::RunLoop().RunUntilIdle(); 1021 } 1022