| Index: chrome/browser/ui/webui/signin/inline_login_ui_browsertest.cc
|
| diff --git a/chrome/browser/ui/webui/signin/inline_login_ui_browsertest.cc b/chrome/browser/ui/webui/signin/inline_login_ui_browsertest.cc
|
| index c95a829b348ce9c04134db4be9a1dfc39ea1e6e4..472eb0ee3f926f9f2133fc459987b82265aed214 100644
|
| --- a/chrome/browser/ui/webui/signin/inline_login_ui_browsertest.cc
|
| +++ b/chrome/browser/ui/webui/signin/inline_login_ui_browsertest.cc
|
| @@ -7,6 +7,9 @@
|
| #include "base/prefs/scoped_user_pref_update.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "chrome/browser/content_settings/cookie_settings_factory.h"
|
| +#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
|
| +#include "chrome/browser/signin/fake_signin_manager_builder.h"
|
| +#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
|
| #include "chrome/browser/signin/signin_manager_factory.h"
|
| #include "chrome/browser/signin/signin_promo.h"
|
| #include "chrome/browser/ui/browser.h"
|
| @@ -27,6 +30,8 @@
|
| #include "chrome/test/base/ui_test_utils.h"
|
| #include "components/content_settings/core/browser/cookie_settings.h"
|
| #include "components/guest_view/browser/guest_view_manager.h"
|
| +#include "components/keyed_service/content/browser_context_dependency_manager.h"
|
| +#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
|
| #include "components/signin/core/browser/signin_manager.h"
|
| #include "components/signin/core/common/profile_management_switches.h"
|
| #include "components/signin/core/common/signin_pref_names.h"
|
| @@ -41,10 +46,13 @@
|
| #include "content/public/test/test_navigation_observer.h"
|
| #include "google_apis/gaia/fake_gaia.h"
|
| #include "google_apis/gaia/gaia_switches.h"
|
| +#include "google_apis/gaia/gaia_urls.h"
|
| #include "net/base/url_util.h"
|
| #include "net/test/embedded_test_server/embedded_test_server.h"
|
| #include "net/test/embedded_test_server/http_request.h"
|
| #include "net/test/embedded_test_server/http_response.h"
|
| +#include "net/url_request/test_url_fetcher_factory.h"
|
| +#include "net/url_request/url_request_status.h"
|
| #include "testing/gmock/include/gmock/gmock.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
| #include "ui/base/l10n/l10n_util.h"
|
| @@ -116,6 +124,120 @@ bool AddToSet(std::set<content::WebContents*>* set,
|
| return false;
|
| }
|
|
|
| +// This class is used to mock out virtual methods with side effects so that
|
| +// tests below can ensure they are called without causing side effects.
|
| +class MockInlineSigninHelper : public InlineSigninHelper {
|
| + public:
|
| + MockInlineSigninHelper(
|
| + base::WeakPtr<InlineLoginHandlerImpl> handler,
|
| + net::URLRequestContextGetter* getter,
|
| + Profile* profile,
|
| + const GURL& current_url,
|
| + const std::string& email,
|
| + const std::string& gaia_id,
|
| + const std::string& password,
|
| + const std::string& session_index,
|
| + const std::string& auth_code,
|
| + const std::string& signin_scoped_device_id,
|
| + bool choose_what_to_sync,
|
| + bool confirm_untrusted_signin);
|
| +
|
| + MOCK_METHOD1(OnClientOAuthSuccess, void(const ClientOAuthResult& result));
|
| + MOCK_METHOD1(OnClientOAuthFailure, void(const GoogleServiceAuthError& error));
|
| + MOCK_METHOD6(CreateSyncStarter,
|
| + void(Browser*,
|
| + content::WebContents*,
|
| + const GURL&,
|
| + const std::string&,
|
| + OneClickSigninSyncStarter::StartSyncMode,
|
| + OneClickSigninSyncStarter::ConfirmationRequired));
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(MockInlineSigninHelper);
|
| +};
|
| +
|
| +MockInlineSigninHelper::MockInlineSigninHelper(
|
| + base::WeakPtr<InlineLoginHandlerImpl> handler,
|
| + net::URLRequestContextGetter* getter,
|
| + Profile* profile,
|
| + const GURL& current_url,
|
| + const std::string& email,
|
| + const std::string& gaia_id,
|
| + const std::string& password,
|
| + const std::string& session_index,
|
| + const std::string& auth_code,
|
| + const std::string& signin_scoped_device_id,
|
| + bool choose_what_to_sync,
|
| + bool confirm_untrusted_signin)
|
| + : InlineSigninHelper(handler,
|
| + getter,
|
| + profile,
|
| + current_url,
|
| + email,
|
| + gaia_id,
|
| + password,
|
| + session_index,
|
| + auth_code,
|
| + signin_scoped_device_id,
|
| + choose_what_to_sync,
|
| + confirm_untrusted_signin) {}
|
| +
|
| +// This class is used to mock out virtual methods with side effects so that
|
| +// tests below can ensure they are called without causing side effects.
|
| +class MockSyncStarterInlineSigninHelper : public InlineSigninHelper {
|
| + public:
|
| + MockSyncStarterInlineSigninHelper(
|
| + base::WeakPtr<InlineLoginHandlerImpl> handler,
|
| + net::URLRequestContextGetter* getter,
|
| + Profile* profile,
|
| + const GURL& current_url,
|
| + const std::string& email,
|
| + const std::string& gaia_id,
|
| + const std::string& password,
|
| + const std::string& session_index,
|
| + const std::string& auth_code,
|
| + const std::string& signin_scoped_device_id,
|
| + bool choose_what_to_sync,
|
| + bool confirm_untrusted_signin);
|
| +
|
| + MOCK_METHOD6(CreateSyncStarter,
|
| + void(Browser*,
|
| + content::WebContents*,
|
| + const GURL&,
|
| + const std::string&,
|
| + OneClickSigninSyncStarter::StartSyncMode,
|
| + OneClickSigninSyncStarter::ConfirmationRequired));
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(MockSyncStarterInlineSigninHelper);
|
| +};
|
| +
|
| +MockSyncStarterInlineSigninHelper::MockSyncStarterInlineSigninHelper(
|
| + base::WeakPtr<InlineLoginHandlerImpl> handler,
|
| + net::URLRequestContextGetter* getter,
|
| + Profile* profile,
|
| + const GURL& current_url,
|
| + const std::string& email,
|
| + const std::string& gaia_id,
|
| + const std::string& password,
|
| + const std::string& session_index,
|
| + const std::string& auth_code,
|
| + const std::string& signin_scoped_device_id,
|
| + bool choose_what_to_sync,
|
| + bool confirm_untrusted_signin)
|
| + : InlineSigninHelper(handler,
|
| + getter,
|
| + profile,
|
| + current_url,
|
| + email,
|
| + gaia_id,
|
| + password,
|
| + session_index,
|
| + auth_code,
|
| + signin_scoped_device_id,
|
| + choose_what_to_sync,
|
| + confirm_untrusted_signin) {}
|
| +
|
| } // namespace
|
|
|
| class InlineLoginUIBrowserTest : public InProcessBrowserTest {
|
| @@ -330,6 +452,328 @@ IN_PROC_BROWSER_TEST_F(InlineLoginUIBrowserTest, CanOfferNoSigninCookies) {
|
| EXPECT_EQ("", error_message);
|
| }
|
|
|
| +class InlineLoginHelperBrowserTest : public InProcessBrowserTest {
|
| + public:
|
| + InlineLoginHelperBrowserTest() {}
|
| +
|
| + void SetUpInProcessBrowserTestFixture() override {
|
| + InProcessBrowserTest::SetUpInProcessBrowserTestFixture();
|
| +
|
| + will_create_browser_context_services_subscription_ =
|
| + BrowserContextDependencyManager::GetInstance()
|
| + ->RegisterWillCreateBrowserContextServicesCallbackForTesting(
|
| + base::Bind(&InlineLoginHelperBrowserTest::
|
| + OnWillCreateBrowserContextServices,
|
| + base::Unretained(this)))
|
| + .Pass();
|
| + }
|
| +
|
| + void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
|
| + // Replace the signin manager and token service with fakes. Do this ahead of
|
| + // creating the browser so that a bunch of classes don't register as
|
| + // observers and end up needing to unregister when the fake is substituted.
|
| + SigninManagerFactory::GetInstance()->SetTestingFactory(
|
| + context, &BuildFakeSigninManagerBase);
|
| + ProfileOAuth2TokenServiceFactory::GetInstance()->SetTestingFactory(
|
| + context, &BuildFakeProfileOAuth2TokenService);
|
| + }
|
| +
|
| + void SetUpOnMainThread() override {
|
| + InProcessBrowserTest::SetUpOnMainThread();
|
| +
|
| + // Grab references to the fake signin manager and token service.
|
| + Profile* profile = browser()->profile();
|
| + signin_manager_ = static_cast<FakeSigninManagerForTesting*>(
|
| + SigninManagerFactory::GetInstance()->GetForProfile(profile));
|
| + ASSERT_TRUE(signin_manager_);
|
| + token_service_ = static_cast<FakeProfileOAuth2TokenService*>(
|
| + ProfileOAuth2TokenServiceFactory::GetInstance()->GetForProfile(
|
| + profile));
|
| + ASSERT_TRUE(token_service_);
|
| + }
|
| +
|
| + void SimulateStartCookieForOAuthLoginTokenExchangeSuccess(
|
| + const std::string& cookie_string) {
|
| + net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
|
| + ASSERT_TRUE(fetcher);
|
| + net::ResponseCookies cookies;
|
| + cookies.push_back(cookie_string);
|
| + fetcher->set_status(net::URLRequestStatus());
|
| + fetcher->set_response_code(net::HTTP_OK);
|
| + fetcher->set_cookies(cookies);
|
| + fetcher->delegate()->OnURLFetchComplete(fetcher);
|
| + }
|
| +
|
| + void SimulateStartAuthCodeForOAuth2TokenExchangeSuccess(
|
| + const std::string& json_response) {
|
| + net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
|
| + ASSERT_TRUE(fetcher);
|
| + fetcher->set_status(net::URLRequestStatus());
|
| + fetcher->set_response_code(net::HTTP_OK);
|
| + fetcher->SetResponseString(json_response);
|
| + fetcher->delegate()->OnURLFetchComplete(fetcher);
|
| + }
|
| +
|
| + void SimulateOnClientOAuthSuccess(GaiaAuthConsumer* consumer,
|
| + const std::string& refresh_token) {
|
| + GaiaAuthConsumer::ClientOAuthResult result;
|
| + result.refresh_token = refresh_token;
|
| + consumer->OnClientOAuthSuccess(result);
|
| + }
|
| +
|
| + FakeSigninManagerForTesting* signin_manager() { return signin_manager_; }
|
| + FakeProfileOAuth2TokenService* token_service() { return token_service_; }
|
| +
|
| + private:
|
| + net::TestURLFetcherFactory url_fetcher_factory_;
|
| + FakeSigninManagerForTesting* signin_manager_;
|
| + FakeProfileOAuth2TokenService* token_service_;
|
| + scoped_ptr<base::CallbackList<void(content::BrowserContext*)>::Subscription>
|
| + will_create_browser_context_services_subscription_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(InlineLoginHelperBrowserTest);
|
| +};
|
| +
|
| +// Test signin helper calls correct fetcher methods when called with a
|
| +// session index.
|
| +IN_PROC_BROWSER_TEST_F(InlineLoginHelperBrowserTest, WithSessionIndex) {
|
| + base::WeakPtr<InlineLoginHandlerImpl> handler;
|
| + MockInlineSigninHelper helper(handler,
|
| + browser()->profile()->GetRequestContext(),
|
| + browser()->profile(),
|
| + GURL(),
|
| + "foo@gmail.com",
|
| + "gaiaid-12345",
|
| + "password",
|
| + "0", // session index from above
|
| + std::string(), // auth code
|
| + std::string(),
|
| + false, // choose what to sync
|
| + false); // confirm untrusted signin
|
| + EXPECT_CALL(helper, OnClientOAuthSuccess(_));
|
| +
|
| + SimulateStartCookieForOAuthLoginTokenExchangeSuccess(
|
| + "secure; httponly; oauth_code=code");
|
| + SimulateStartAuthCodeForOAuth2TokenExchangeSuccess(
|
| + "{\"access_token\": \"access_token\", \"expires_in\": 1234567890,"
|
| + " \"refresh_token\": \"refresh_token\"}");
|
| +}
|
| +
|
| +// Test signin helper calls correct fetcher methods when called with an
|
| +// auth code.
|
| +IN_PROC_BROWSER_TEST_F(InlineLoginHelperBrowserTest, WithAuthCode) {
|
| + base::WeakPtr<InlineLoginHandlerImpl> handler;
|
| + MockInlineSigninHelper helper(handler,
|
| + browser()->profile()->GetRequestContext(),
|
| + browser()->profile(),
|
| + GURL(),
|
| + "foo@gmail.com",
|
| + "gaiaid-12345",
|
| + "password",
|
| + "", // session index
|
| + "auth_code", // auth code
|
| + std::string(),
|
| + false, // choose what to sync
|
| + false); // confirm untrusted signin
|
| + EXPECT_CALL(helper, OnClientOAuthSuccess(_));
|
| +
|
| + SimulateStartAuthCodeForOAuth2TokenExchangeSuccess(
|
| + "{\"access_token\": \"access_token\", \"expires_in\": 1234567890,"
|
| + " \"refresh_token\": \"refresh_token\"}");
|
| +}
|
| +
|
| +// Test signin helper creates sync starter with correct confirmation when
|
| +// signing in with default sync options.
|
| +IN_PROC_BROWSER_TEST_F(InlineLoginHelperBrowserTest,
|
| + SigninCreatesSyncStarter1) {
|
| + // See Source enum in components/signin/core/browser/signin_metrics.h for
|
| + // possible values of source=.
|
| + GURL url("chrome://chrome-signin/?source=0");
|
| + base::WeakPtr<InlineLoginHandlerImpl> handler;
|
| + // MockSyncStarterInlineSigninHelper will delete itself when done using
|
| + // base::ThreadTaskRunnerHandle::DeleteSoon(), so need to delete here. But
|
| + // do need the RunUntilIdle() at the end.
|
| + MockSyncStarterInlineSigninHelper* helper =
|
| + new MockSyncStarterInlineSigninHelper(
|
| + handler,
|
| + browser()->profile()->GetRequestContext(),
|
| + browser()->profile(),
|
| + url,
|
| + "foo@gmail.com",
|
| + "gaiaid-12345",
|
| + "password",
|
| + "", // session index
|
| + "auth_code", // auth code
|
| + std::string(),
|
| + false, // choose what to sync
|
| + false); // confirm untrusted signin
|
| + EXPECT_CALL(*helper, CreateSyncStarter(
|
| + _, _, _, "refresh_token",
|
| + OneClickSigninSyncStarter::CONFIRM_SYNC_SETTINGS_FIRST,
|
| + OneClickSigninSyncStarter::CONFIRM_AFTER_SIGNIN));
|
| +
|
| + SimulateOnClientOAuthSuccess(helper, "refresh_token");
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| +}
|
| +
|
| +// Test signin helper creates sync starter with correct confirmation when
|
| +// signing in and choosing what to sync first.
|
| +IN_PROC_BROWSER_TEST_F(InlineLoginHelperBrowserTest,
|
| + SigninCreatesSyncStarter2) {
|
| + // See Source enum in components/signin/core/browser/signin_metrics.h for
|
| + // possible values of source=.
|
| + const GURL url("chrome://chrome-signin/?source=0");
|
| + base::WeakPtr<InlineLoginHandlerImpl> handler;
|
| + // MockSyncStarterInlineSigninHelper will delete itself when done using
|
| + // base::ThreadTaskRunnerHandle::DeleteSoon(), so need to delete here. But
|
| + // do need the RunUntilIdle() at the end.
|
| + MockSyncStarterInlineSigninHelper* helper =
|
| + new MockSyncStarterInlineSigninHelper(
|
| + handler,
|
| + browser()->profile()->GetRequestContext(),
|
| + browser()->profile(),
|
| + url,
|
| + "foo@gmail.com",
|
| + "gaiaid-12345",
|
| + "password",
|
| + "", // session index
|
| + "auth_code", // auth code
|
| + std::string(),
|
| + true, // choose what to sync
|
| + false); // confirm untrusted signin
|
| + EXPECT_CALL(*helper, CreateSyncStarter(
|
| + _, _, _, "refresh_token",
|
| + OneClickSigninSyncStarter::CONFIGURE_SYNC_FIRST,
|
| + OneClickSigninSyncStarter::CONFIRM_AFTER_SIGNIN));
|
| +
|
| + SimulateOnClientOAuthSuccess(helper, "refresh_token");
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| +}
|
| +
|
| +// Test signin helper creates sync starter with correct confirmation when
|
| +// signing in with an untrusted sign occurs.
|
| +IN_PROC_BROWSER_TEST_F(InlineLoginHelperBrowserTest,
|
| + SigninCreatesSyncStarter3) {
|
| + // See Source enum in components/signin/core/browser/signin_metrics.h for
|
| + // possible values of source=.
|
| + GURL url("chrome://chrome-signin/?source=0");
|
| + base::WeakPtr<InlineLoginHandlerImpl> handler;
|
| + // MockSyncStarterInlineSigninHelper will delete itself when done using
|
| + // base::ThreadTaskRunnerHandle::DeleteSoon(), so need to delete here. But
|
| + // do need the RunUntilIdle() at the end.
|
| + MockSyncStarterInlineSigninHelper* helper =
|
| + new MockSyncStarterInlineSigninHelper(
|
| + handler,
|
| + browser()->profile()->GetRequestContext(),
|
| + browser()->profile(),
|
| + url,
|
| + "foo@gmail.com",
|
| + "gaiaid-12345",
|
| + "password",
|
| + "", // session index
|
| + "auth_code", // auth code
|
| + std::string(),
|
| + false, // choose what to sync
|
| + true); // confirm untrusted signin
|
| + EXPECT_CALL(*helper, CreateSyncStarter(
|
| + _, _, _, "refresh_token",
|
| + OneClickSigninSyncStarter::CONFIRM_SYNC_SETTINGS_FIRST,
|
| + OneClickSigninSyncStarter::CONFIRM_UNTRUSTED_SIGNIN));
|
| +
|
| + SimulateOnClientOAuthSuccess(helper, "refresh_token");
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| +}
|
| +
|
| +// Test signin helper creates sync starter with correct confirmation during
|
| +// re-auth.
|
| +IN_PROC_BROWSER_TEST_F(InlineLoginHelperBrowserTest,
|
| + SigninCreatesSyncStarter4) {
|
| + // See Source enum in components/signin/core/browser/signin_metrics.h for
|
| + // possible values of source=.
|
| + const GURL url("chrome://chrome-signin/?source=3");
|
| + base::WeakPtr<InlineLoginHandlerImpl> handler;
|
| + // MockSyncStarterInlineSigninHelper will delete itself when done using
|
| + // base::ThreadTaskRunnerHandle::DeleteSoon(), so need to delete here. But
|
| + // do need the RunUntilIdle() at the end.
|
| + MockSyncStarterInlineSigninHelper* helper =
|
| + new MockSyncStarterInlineSigninHelper(
|
| + handler,
|
| + browser()->profile()->GetRequestContext(),
|
| + browser()->profile(),
|
| + url,
|
| + "foo@gmail.com",
|
| + "gaiaid-12345",
|
| + "password",
|
| + "", // session index
|
| + "auth_code", // auth code
|
| + std::string(),
|
| + false, // choose what to sync
|
| + false); // confirm untrusted signin
|
| +
|
| + // Even though "choose what to sync" is false, the source of the URL is
|
| + // settings, which means the user wants to CONFIGURE_SYNC_FIRST.
|
| + EXPECT_CALL(*helper, CreateSyncStarter(
|
| + _, _, _, "refresh_token",
|
| + OneClickSigninSyncStarter::CONFIGURE_SYNC_FIRST,
|
| + OneClickSigninSyncStarter::CONFIRM_AFTER_SIGNIN));
|
| +
|
| + SimulateOnClientOAuthSuccess(helper, "refresh_token");
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| +}
|
| +
|
| +// Test signin helper does not create sync starter when reauthenticating.
|
| +IN_PROC_BROWSER_TEST_F(InlineLoginHelperBrowserTest,
|
| + ReauthCallsUpdateCredentials) {
|
| + ASSERT_EQ(0ul, token_service()->GetAccounts().size());
|
| +
|
| + // See Source enum in components/signin/core/browser/signin_metrics.h for
|
| + // possible values of source=.
|
| + GURL url("chrome://chrome-signin/?source=11");
|
| + base::WeakPtr<InlineLoginHandlerImpl> handler;
|
| + InlineSigninHelper helper(handler,
|
| + browser()->profile()->GetRequestContext(),
|
| + browser()->profile(),
|
| + url,
|
| + "foo@gmail.com",
|
| + "gaiaid-12345",
|
| + "password",
|
| + "", // session index
|
| + "auth_code", // auth code
|
| + std::string(),
|
| + false, // choose what to sync
|
| + false); // confirm untrusted signin
|
| + SimulateOnClientOAuthSuccess(&helper, "refresh_token");
|
| + ASSERT_EQ(1ul, token_service()->GetAccounts().size());
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| +}
|
| +
|
| +// Test signin helper does not create sync starter when adding another account
|
| +// to profile.
|
| +IN_PROC_BROWSER_TEST_F(InlineLoginHelperBrowserTest,
|
| + AddAccountsCallsUpdateCredentials) {
|
| + ASSERT_EQ(0ul, token_service()->GetAccounts().size());
|
| +
|
| + // See Source enum in components/signin/core/browser/signin_metrics.h for
|
| + // possible values of source=.
|
| + GURL url("chrome://chrome-signin/?source=9");
|
| + base::WeakPtr<InlineLoginHandlerImpl> handler;
|
| + InlineSigninHelper helper(handler,
|
| + browser()->profile()->GetRequestContext(),
|
| + browser()->profile(),
|
| + url,
|
| + "foo@gmail.com",
|
| + "gaiaid-12345",
|
| + "password",
|
| + "", // session index
|
| + "auth_code", // auth code
|
| + std::string(),
|
| + false, // choose what to sync
|
| + false); // confirm untrusted signin
|
| + SimulateOnClientOAuthSuccess(&helper, "refresh_token");
|
| + ASSERT_EQ(1ul, token_service()->GetAccounts().size());
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| +}
|
| +
|
| #endif // OS_CHROMEOS
|
|
|
| class InlineLoginUISafeIframeBrowserTest : public InProcessBrowserTest {
|
|
|