blob: 45e90f4e458013b85e2a6f38420aac4476df72a4 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/signin/signin_ui_util.h"
#include "base/macros.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.h"
#include "build/buildflag.h"
#include "chrome/browser/signin/account_tracker_service_factory.h"
#include "chrome/browser/signin/fake_gaia_cookie_manager_service_builder.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/gaia_cookie_manager_service_factory.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/scoped_account_consistency.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/signin/signin_promo.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "components/signin/core/browser/profile_management_switches.h"
#include "components/signin/core/browser/signin_buildflags.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace signin_ui_util {
class GetAllowedDomainTest : public ::testing::Test {};
TEST_F(GetAllowedDomainTest, WithInvalidPattern) {
EXPECT_EQ(std::string(), GetAllowedDomain("email"));
EXPECT_EQ(std::string(), GetAllowedDomain("email@a@b"));
EXPECT_EQ(std::string(), GetAllowedDomain("email@a[b"));
EXPECT_EQ(std::string(), GetAllowedDomain("@$"));
EXPECT_EQ(std::string(), GetAllowedDomain("@\\E$"));
EXPECT_EQ(std::string(), GetAllowedDomain("@\\E$a"));
EXPECT_EQ(std::string(), GetAllowedDomain("email@"));
EXPECT_EQ(std::string(), GetAllowedDomain("@"));
EXPECT_EQ(std::string(), GetAllowedDomain("example@a.com|example@b.com"));
EXPECT_EQ(std::string(), GetAllowedDomain(""));
}
TEST_F(GetAllowedDomainTest, WithValidPattern) {
EXPECT_EQ("example.com", GetAllowedDomain("email@example.com"));
EXPECT_EQ("example.com", GetAllowedDomain("email@example.com\\E"));
EXPECT_EQ("example.com", GetAllowedDomain("email@example.com$"));
EXPECT_EQ("example.com", GetAllowedDomain("email@example.com\\E$"));
EXPECT_EQ("example.com", GetAllowedDomain("*@example.com\\E$"));
EXPECT_EQ("example.com", GetAllowedDomain(".*@example.com\\E$"));
EXPECT_EQ("example-1.com", GetAllowedDomain("email@example-1.com"));
}
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
namespace {
const char kMainEmail[] = "main_email@example.com";
const char kMainGaiaID[] = "main_gaia_id";
class SigninUiUtilTestBrowserWindow : public TestBrowserWindow {
public:
SigninUiUtilTestBrowserWindow() = default;
~SigninUiUtilTestBrowserWindow() override = default;
void set_browser(Browser* browser) { browser_ = browser; }
void ShowAvatarBubbleFromAvatarButton(
AvatarBubbleMode mode,
const signin::ManageAccountsParams& manage_accounts_params,
signin_metrics::AccessPoint access_point,
bool is_source_keyboard) override {
ASSERT_TRUE(browser_);
// Simulate what |BrowserView| does for a regular Chrome sign-in flow.
browser_->signin_view_controller()->ShowSignin(
profiles::BubbleViewMode::BUBBLE_VIEW_MODE_GAIA_SIGNIN, browser_,
access_point);
}
private:
Browser* browser_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(SigninUiUtilTestBrowserWindow);
};
} // namespace
class DiceSigninUiUtilTest : public BrowserWithTestWindowTest {
public:
DiceSigninUiUtilTest()
: BrowserWithTestWindowTest(
content::TestBrowserThreadBundle::IO_MAINLOOP),
scoped_account_consistency_(signin::AccountConsistencyMethod::kDice) {}
~DiceSigninUiUtilTest() override = default;
struct CreateDiceTurnSyncOnHelperParams {
public:
Profile* profile = nullptr;
Browser* browser = nullptr;
signin_metrics::AccessPoint signin_access_point =
signin_metrics::AccessPoint::ACCESS_POINT_MAX;
signin_metrics::PromoAction signin_promo_action =
signin_metrics::PromoAction::PROMO_ACTION_NO_SIGNIN_PROMO;
signin_metrics::Reason signin_reason = signin_metrics::Reason::REASON_MAX;
std::string account_id;
DiceTurnSyncOnHelper::SigninAbortedMode signin_aborted_mode =
DiceTurnSyncOnHelper::SigninAbortedMode::REMOVE_ACCOUNT;
};
void CreateDiceTurnSyncOnHelper(
Profile* profile,
Browser* browser,
signin_metrics::AccessPoint signin_access_point,
signin_metrics::PromoAction signin_promo_action,
signin_metrics::Reason signin_reason,
const std::string& account_id,
DiceTurnSyncOnHelper::SigninAbortedMode signin_aborted_mode) {
create_dice_turn_sync_on_helper_called_ = true;
create_dice_turn_sync_on_helper_params_.profile = profile;
create_dice_turn_sync_on_helper_params_.browser = browser;
create_dice_turn_sync_on_helper_params_.signin_access_point =
signin_access_point;
create_dice_turn_sync_on_helper_params_.signin_promo_action =
signin_promo_action;
create_dice_turn_sync_on_helper_params_.signin_reason = signin_reason;
create_dice_turn_sync_on_helper_params_.account_id = account_id;
create_dice_turn_sync_on_helper_params_.signin_aborted_mode =
signin_aborted_mode;
}
protected:
// BrowserWithTestWindowTest:
void SetUp() override {
BrowserWithTestWindowTest::SetUp();
static_cast<SigninUiUtilTestBrowserWindow*>(browser()->window())
->set_browser(browser());
}
// BrowserWithTestWindowTest:
TestingProfile::TestingFactories GetTestingFactories() override {
return {{SigninManagerFactory::GetInstance(), BuildFakeSigninManagerBase},
{ProfileOAuth2TokenServiceFactory::GetInstance(),
BuildFakeProfileOAuth2TokenService},
{GaiaCookieManagerServiceFactory::GetInstance(),
BuildFakeGaiaCookieManagerServiceNoFakeUrlFetcher}};
}
// BrowserWithTestWindowTest:
BrowserWindow* CreateBrowserWindow() override {
return new SigninUiUtilTestBrowserWindow();
}
// Returns the token service.
ProfileOAuth2TokenService* GetTokenService() {
return ProfileOAuth2TokenServiceFactory::GetForProfile(profile());
}
// Returns the account tracker service.
AccountTrackerService* GetAccountTrackerService() {
return AccountTrackerServiceFactory::GetForProfile(profile());
}
void EnableSync(const AccountInfo& account_info,
bool is_default_promo_account) {
signin_ui_util::internal::EnableSyncFromPromo(
browser(), account_info, access_point_, is_default_promo_account,
base::BindOnce(&DiceSigninUiUtilTest::CreateDiceTurnSyncOnHelper,
base::Unretained(this)));
}
void ExpectNoSigninStartedHistograms(
const base::HistogramTester& histogram_tester) {
histogram_tester.ExpectTotalCount("Signin.SigninStartedAccessPoint", 0);
histogram_tester.ExpectTotalCount(
"Signin.SigninStartedAccessPoint.WithDefault", 0);
histogram_tester.ExpectTotalCount(
"Signin.SigninStartedAccessPoint.NotDefault", 0);
histogram_tester.ExpectTotalCount(
"Signin.SigninStartedAccessPoint.NewAccount", 0);
}
void ExpectOneSigninStartedHistograms(
const base::HistogramTester& histogram_tester,
signin_metrics::PromoAction expected_promo_action) {
histogram_tester.ExpectUniqueSample("Signin.SigninStartedAccessPoint",
access_point_, 1);
switch (expected_promo_action) {
case signin_metrics::PromoAction::PROMO_ACTION_NO_SIGNIN_PROMO:
histogram_tester.ExpectTotalCount(
"Signin.SigninStartedAccessPoint.NewAccount", 0);
histogram_tester.ExpectTotalCount(
"Signin.SigninStartedAccessPoint.NotDefault", 0);
histogram_tester.ExpectTotalCount(
"Signin.SigninStartedAccessPoint.WithDefault", 0);
break;
case signin_metrics::PromoAction::PROMO_ACTION_WITH_DEFAULT:
histogram_tester.ExpectTotalCount(
"Signin.SigninStartedAccessPoint.NewAccount", 0);
histogram_tester.ExpectTotalCount(
"Signin.SigninStartedAccessPoint.NotDefault", 0);
histogram_tester.ExpectUniqueSample(
"Signin.SigninStartedAccessPoint.WithDefault", access_point_, 1);
break;
case signin_metrics::PromoAction::PROMO_ACTION_NOT_DEFAULT:
histogram_tester.ExpectTotalCount(
"Signin.SigninStartedAccessPoint.NewAccount", 0);
histogram_tester.ExpectTotalCount(
"Signin.SigninStartedAccessPoint.WithDefault", 0);
histogram_tester.ExpectUniqueSample(
"Signin.SigninStartedAccessPoint.NotDefault", access_point_, 1);
break;
case signin_metrics::PromoAction::PROMO_ACTION_NEW_ACCOUNT:
histogram_tester.ExpectTotalCount(
"Signin.SigninStartedAccessPoint.WithDefault", 0);
histogram_tester.ExpectTotalCount(
"Signin.SigninStartedAccessPoint.NotDefault", 0);
histogram_tester.ExpectUniqueSample(
"Signin.SigninStartedAccessPoint.NewAccount", access_point_, 1);
break;
}
}
const ScopedAccountConsistency scoped_account_consistency_;
signin_metrics::AccessPoint access_point_ =
signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE;
bool create_dice_turn_sync_on_helper_called_ = false;
CreateDiceTurnSyncOnHelperParams create_dice_turn_sync_on_helper_params_;
};
TEST_F(DiceSigninUiUtilTest, EnableSyncWithExistingAccount) {
// Add an account.
std::string account_id =
GetAccountTrackerService()->SeedAccountInfo(kMainEmail, kMainGaiaID);
GetTokenService()->UpdateCredentials(account_id, "token");
for (bool is_default_promo_account : {true, false}) {
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
ExpectNoSigninStartedHistograms(histogram_tester);
EXPECT_EQ(0, user_action_tester.GetActionCount(
"Signin_Signin_FromBookmarkBubble"));
EnableSync(GetAccountTrackerService()->GetAccountInfo(account_id),
is_default_promo_account);
signin_metrics::PromoAction expected_promo_action =
is_default_promo_account
? signin_metrics::PromoAction::PROMO_ACTION_WITH_DEFAULT
: signin_metrics::PromoAction::PROMO_ACTION_NOT_DEFAULT;
ASSERT_TRUE(create_dice_turn_sync_on_helper_called_);
ExpectOneSigninStartedHistograms(histogram_tester, expected_promo_action);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Signin_Signin_FromBookmarkBubble"));
if (is_default_promo_account) {
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Signin_SigninWithDefault_FromBookmarkBubble"));
} else {
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Signin_SigninNotDefault_FromBookmarkBubble"));
}
// Verify that the helper to enable sync is created with the expected
// params.
EXPECT_EQ(profile(), create_dice_turn_sync_on_helper_params_.profile);
EXPECT_EQ(browser(), create_dice_turn_sync_on_helper_params_.browser);
EXPECT_EQ(account_id, create_dice_turn_sync_on_helper_params_.account_id);
EXPECT_EQ(signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE,
create_dice_turn_sync_on_helper_params_.signin_access_point);
EXPECT_EQ(expected_promo_action,
create_dice_turn_sync_on_helper_params_.signin_promo_action);
EXPECT_EQ(signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT,
create_dice_turn_sync_on_helper_params_.signin_reason);
EXPECT_EQ(DiceTurnSyncOnHelper::SigninAbortedMode::KEEP_ACCOUNT,
create_dice_turn_sync_on_helper_params_.signin_aborted_mode);
}
}
TEST_F(DiceSigninUiUtilTest, EnableSyncWithAccountThatNeedsReauth) {
AddTab(browser(), GURL("http://example.com"));
// Add an account to the account tracker, but do not add it to the token
// service in order for it to require a reauth before enabling sync.
std::string account_id =
GetAccountTrackerService()->SeedAccountInfo(kMainGaiaID, kMainEmail);
for (bool is_default_promo_account : {true, false}) {
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
ExpectNoSigninStartedHistograms(histogram_tester);
EXPECT_EQ(0, user_action_tester.GetActionCount(
"Signin_Signin_FromBookmarkBubble"));
EnableSync(GetAccountTrackerService()->GetAccountInfo(account_id),
is_default_promo_account);
ASSERT_FALSE(create_dice_turn_sync_on_helper_called_);
ExpectOneSigninStartedHistograms(
histogram_tester,
is_default_promo_account
? signin_metrics::PromoAction::PROMO_ACTION_WITH_DEFAULT
: signin_metrics::PromoAction::PROMO_ACTION_NOT_DEFAULT);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Signin_Signin_FromBookmarkBubble"));
if (is_default_promo_account) {
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Signin_SigninWithDefault_FromBookmarkBubble"));
} else {
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Signin_SigninNotDefault_FromBookmarkBubble"));
}
// Verify that the active tab has the correct DICE sign-in URL.
TabStripModel* tab_strip = browser()->tab_strip_model();
content::WebContents* active_contents = tab_strip->GetActiveWebContents();
ASSERT_TRUE(active_contents);
EXPECT_EQ(signin::GetSigninURLForDice(profile(), kMainEmail),
active_contents->GetVisibleURL());
tab_strip->CloseWebContentsAt(
tab_strip->GetIndexOfWebContents(active_contents),
TabStripModel::CLOSE_USER_GESTURE);
}
}
TEST_F(DiceSigninUiUtilTest, EnableSyncForNewAccountWithNoTab) {
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
ExpectNoSigninStartedHistograms(histogram_tester);
EXPECT_EQ(
0, user_action_tester.GetActionCount("Signin_Signin_FromBookmarkBubble"));
EnableSync(AccountInfo(), false /* is_default_promo_account (not used)*/);
ASSERT_FALSE(create_dice_turn_sync_on_helper_called_);
ExpectOneSigninStartedHistograms(
histogram_tester, signin_metrics::PromoAction::PROMO_ACTION_NEW_ACCOUNT);
EXPECT_EQ(
1, user_action_tester.GetActionCount("Signin_Signin_FromBookmarkBubble"));
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Signin_SigninNewAccount_FromBookmarkBubble"));
// Verify that the active tab has the correct DICE sign-in URL.
content::WebContents* active_contents =
browser()->tab_strip_model()->GetActiveWebContents();
ASSERT_TRUE(active_contents);
EXPECT_EQ(signin::GetSigninURLForDice(profile(), ""),
active_contents->GetVisibleURL());
}
TEST_F(DiceSigninUiUtilTest, EnableSyncForNewAccountWithOneTab) {
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
AddTab(browser(), GURL("http://foo/1"));
ExpectNoSigninStartedHistograms(histogram_tester);
EXPECT_EQ(
0, user_action_tester.GetActionCount("Signin_Signin_FromBookmarkBubble"));
EnableSync(AccountInfo(), false /* is_default_promo_account (not used)*/);
ASSERT_FALSE(create_dice_turn_sync_on_helper_called_);
ExpectOneSigninStartedHistograms(
histogram_tester, signin_metrics::PromoAction::PROMO_ACTION_NEW_ACCOUNT);
EXPECT_EQ(
1, user_action_tester.GetActionCount("Signin_Signin_FromBookmarkBubble"));
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Signin_SigninNewAccount_FromBookmarkBubble"));
// Verify that the active tab has the correct DICE sign-in URL.
content::WebContents* active_contents =
browser()->tab_strip_model()->GetActiveWebContents();
ASSERT_TRUE(active_contents);
EXPECT_EQ(signin::GetSigninURLForDice(profile(), ""),
active_contents->GetVisibleURL());
}
TEST_F(DiceSigninUiUtilTest, GetAccountsForDicePromos) {
// Should start off with no accounts.
std::vector<AccountInfo> accounts = GetAccountsForDicePromos(profile());
EXPECT_TRUE(accounts.empty());
// TODO(tangltom): Flesh out this test.
}
TEST_F(DiceSigninUiUtilTest, MergeDiceSigninTab) {
base::UserActionTester user_action_tester;
EnableSync(AccountInfo(), false);
EXPECT_EQ(
1, user_action_tester.GetActionCount("Signin_Signin_FromBookmarkBubble"));
// Signin tab is reused.
EnableSync(AccountInfo(), false);
EXPECT_EQ(
1, user_action_tester.GetActionCount("Signin_Signin_FromBookmarkBubble"));
// Give focus to a different tab.
TabStripModel* tab_strip = browser()->tab_strip_model();
ASSERT_EQ(0, tab_strip->active_index());
GURL other_url = GURL("http://example.com");
AddTab(browser(), other_url);
tab_strip->ActivateTabAt(0, true);
ASSERT_EQ(other_url, tab_strip->GetActiveWebContents()->GetVisibleURL());
ASSERT_EQ(0, tab_strip->active_index());
// Extensions re-use the tab but do not take focus.
access_point_ = signin_metrics::AccessPoint::ACCESS_POINT_EXTENSIONS;
EnableSync(AccountInfo(), false);
EXPECT_EQ(
1, user_action_tester.GetActionCount("Signin_Signin_FromBookmarkBubble"));
EXPECT_EQ(0, tab_strip->active_index());
// Other access points re-use the tab and take focus.
access_point_ = signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS;
EnableSync(AccountInfo(), false);
EXPECT_EQ(
1, user_action_tester.GetActionCount("Signin_Signin_FromBookmarkBubble"));
EXPECT_EQ(1, tab_strip->active_index());
}
#endif // BUILDFLAG(ENABLE_DICE_SUPPORT)
} // namespace signin_ui_util