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