blob: c04f508b796097a33fa196d254e89ee2c2ea327f [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// 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_util.h"
#include <memory>
#include "build/buildflag.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "components/policy/core/browser/signin/profile_separation_policies.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/testing_pref_service.h"
#include "components/signin/public/base/signin_pref_names.h"
#include "components/signin/public/base/signin_switches.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "content/public/test/browser_task_environment.h"
using signin_util::ProfileSeparationPolicyState;
using signin_util::ProfileSeparationPolicyStateSet;
using signin_util::SignedInState;
namespace {
const char kLegacyPolicyEmpty[] = "";
const char kLegacyPolicyNone[] = "none";
const char kLegacyPolicyPrimaryAccount[] = "primary_account";
const char kLegacyPolicyPrimaryAccountStrict[] = "primary_account_strict";
const char kLegacyPolicyPrimaryAccountStrictKeepExistingData[] =
"primary_account_strict_keep_existing_data";
const char kLegacyPolicyPrimaryAccountKeepExistingData[] =
"primary_account_keep_existing_data";
} // namespace
class SigninUtilTest : public BrowserWithTestWindowTest {
public:
void SetUp() override {
BrowserWithTestWindowTest::SetUp();
signin_util::ResetForceSigninForTesting();
}
void TearDown() override {
signin_util::ResetForceSigninForTesting();
BrowserWithTestWindowTest::TearDown();
}
bool SeparationEnforcedByExistingProfileExpected(
const std::string& local_policy) {
return enforced_by_existing_profile.find(local_policy) !=
enforced_by_existing_profile.end();
}
bool SeparationEnforcedByInterceptedAccountExpected(
const std::string& intercepted_policy) {
return enforced_by_intercepted_account.find(intercepted_policy) !=
enforced_by_intercepted_account.end();
}
bool KeepBrowsingDataExpected(const std::string& local_policy,
const std::string& intercepted_policy) {
return keeps_browsing_data.find(local_policy) !=
keeps_browsing_data.end() &&
keeps_browsing_data.find(intercepted_policy) !=
keeps_browsing_data.end();
}
bool SeparationEnforcedOnMachineLevelExpected(
const std::string& local_policy) {
return enforced_on_machine_level.find(local_policy) !=
enforced_on_machine_level.end();
}
protected:
std::array<std::string, 6> all_policies{
kLegacyPolicyEmpty,
kLegacyPolicyNone,
kLegacyPolicyPrimaryAccount,
kLegacyPolicyPrimaryAccountStrict,
kLegacyPolicyPrimaryAccountStrictKeepExistingData,
kLegacyPolicyPrimaryAccountKeepExistingData,
};
base::flat_set<std::string> enforced_by_existing_profile{
kLegacyPolicyPrimaryAccountStrict,
kLegacyPolicyPrimaryAccountStrictKeepExistingData};
base::flat_set<std::string> enforced_by_intercepted_account{
kLegacyPolicyPrimaryAccount,
kLegacyPolicyPrimaryAccountStrict,
kLegacyPolicyPrimaryAccountStrictKeepExistingData,
kLegacyPolicyPrimaryAccountKeepExistingData,
};
base::flat_set<std::string> keeps_browsing_data{
kLegacyPolicyEmpty,
kLegacyPolicyNone,
kLegacyPolicyPrimaryAccountKeepExistingData,
kLegacyPolicyPrimaryAccountStrictKeepExistingData,
};
base::flat_set<std::string> enforced_on_machine_level{
kLegacyPolicyPrimaryAccount,
kLegacyPolicyPrimaryAccountStrict,
kLegacyPolicyPrimaryAccountStrictKeepExistingData,
kLegacyPolicyPrimaryAccountKeepExistingData,
};
};
TEST_F(SigninUtilTest, GetForceSigninPolicy) {
EXPECT_FALSE(signin_util::IsForceSigninEnabled());
g_browser_process->local_state()->SetBoolean(prefs::kForceBrowserSignin,
true);
signin_util::ResetForceSigninForTesting();
EXPECT_TRUE(signin_util::IsForceSigninEnabled());
g_browser_process->local_state()->SetBoolean(prefs::kForceBrowserSignin,
false);
signin_util::ResetForceSigninForTesting();
EXPECT_FALSE(signin_util::IsForceSigninEnabled());
}
#if !BUILDFLAG(IS_CHROMEOS_LACROS)
TEST_F(SigninUtilTest, IsProfileSeparationEnforcedByProfile) {
std::unique_ptr<TestingProfile> profile = TestingProfile::Builder().Build();
for (const auto& local_policy : all_policies) {
if (local_policy.empty()) {
profile.get()->GetPrefs()->ClearPref(
prefs::kManagedAccountsSigninRestriction);
} else {
profile.get()->GetPrefs()->SetString(
prefs::kManagedAccountsSigninRestriction, local_policy);
}
EXPECT_EQ(signin_util::IsProfileSeparationEnforcedByProfile(
profile.get(), /*intercepted_account_email=*/std::string()),
SeparationEnforcedByExistingProfileExpected(local_policy));
}
// Test profile set a machine level.
profile.get()->GetPrefs()->SetBoolean(
prefs::kManagedAccountsSigninRestrictionScopeMachine, true);
for (const auto& local_policy : all_policies) {
if (local_policy.empty()) {
profile.get()->GetPrefs()->ClearPref(
prefs::kManagedAccountsSigninRestriction);
} else {
profile.get()->GetPrefs()->SetString(
prefs::kManagedAccountsSigninRestriction, local_policy);
}
EXPECT_EQ(signin_util::IsProfileSeparationEnforcedByProfile(
profile.get(), /*intercepted_account_email=*/std::string()),
SeparationEnforcedOnMachineLevelExpected(local_policy));
}
}
TEST_F(SigninUtilTest, IsProfileSeparationEnforcedByPolicies) {
std::unique_ptr<TestingProfile> profile = TestingProfile::Builder().Build();
for (const auto& intercepted_policy : all_policies) {
EXPECT_EQ(
signin_util::IsProfileSeparationEnforcedByPolicies(
policy::ProfileSeparationPolicies(intercepted_policy)),
SeparationEnforcedByInterceptedAccountExpected(intercepted_policy));
}
}
TEST_F(
SigninUtilTest,
ProfileSeparationAllowsKeepingUnmanagedBrowsingDataInManagedProfileLegacy) {
std::unique_ptr<TestingProfile> profile = TestingProfile::Builder().Build();
for (const auto& local_policy : all_policies) {
if (local_policy.empty()) {
profile.get()->GetPrefs()->ClearPref(
prefs::kManagedAccountsSigninRestriction);
} else {
profile.get()->GetPrefs()->SetString(
prefs::kManagedAccountsSigninRestriction, local_policy);
}
for (const auto& intercepted_policy : all_policies) {
EXPECT_EQ(
signin_util::
ProfileSeparationAllowsKeepingUnmanagedBrowsingDataInManagedProfile(
profile.get(),
policy::ProfileSeparationPolicies(intercepted_policy)),
KeepBrowsingDataExpected(local_policy, intercepted_policy));
}
}
}
TEST_F(SigninUtilTest, IsSecondaryAccountAllowed) {
const std::string consumer_email = "bob@gmail.com";
const std::string enterprise_email = "bob@example.com";
const std::string other_enterprise_email = "bob@bob.com";
EXPECT_TRUE(signin_util::IsAccountExemptedFromEnterpriseProfileSeparation(
profile(), consumer_email));
EXPECT_TRUE(signin_util::IsAccountExemptedFromEnterpriseProfileSeparation(
profile(), enterprise_email));
EXPECT_TRUE(signin_util::IsAccountExemptedFromEnterpriseProfileSeparation(
profile(), other_enterprise_email));
{
profile()->GetPrefs()->SetList(prefs::kProfileSeparationDomainExceptionList,
base::Value::List());
EXPECT_FALSE(signin_util::IsAccountExemptedFromEnterpriseProfileSeparation(
profile(), consumer_email));
EXPECT_FALSE(signin_util::IsAccountExemptedFromEnterpriseProfileSeparation(
profile(), enterprise_email));
EXPECT_FALSE(signin_util::IsAccountExemptedFromEnterpriseProfileSeparation(
profile(), other_enterprise_email));
}
{
base::Value::List profile_separation_exception_list;
profile_separation_exception_list.Append(base::Value("bob.com"));
profile()->GetPrefs()->SetList(
prefs::kProfileSeparationDomainExceptionList,
std::move(profile_separation_exception_list));
EXPECT_FALSE(signin_util::IsAccountExemptedFromEnterpriseProfileSeparation(
profile(), consumer_email));
EXPECT_FALSE(signin_util::IsAccountExemptedFromEnterpriseProfileSeparation(
profile(), enterprise_email));
EXPECT_TRUE(signin_util::IsAccountExemptedFromEnterpriseProfileSeparation(
profile(), other_enterprise_email));
}
{
base::Value::List profile_separation_exception_list;
profile_separation_exception_list.Append(base::Value("bob.com"));
profile_separation_exception_list.Append(base::Value("gmail.com"));
profile()->GetPrefs()->SetList(
prefs::kProfileSeparationDomainExceptionList,
std::move(profile_separation_exception_list));
EXPECT_TRUE(signin_util::IsAccountExemptedFromEnterpriseProfileSeparation(
profile(), consumer_email));
EXPECT_FALSE(signin_util::IsAccountExemptedFromEnterpriseProfileSeparation(
profile(), enterprise_email));
EXPECT_TRUE(signin_util::IsAccountExemptedFromEnterpriseProfileSeparation(
profile(), other_enterprise_email));
}
}
TEST_F(SigninUtilTest,
IsProfileSeparationEnforcedByProfileSecondaryAccountNotAllowed) {
const std::string consumer_email = "bob@gmail.com";
const std::string enterprise_email = "bob@example.com";
const std::string other_enterprise_email = "bob@bob.com";
for (const auto& policy : all_policies) {
profile()->GetPrefs()->SetString(prefs::kManagedAccountsSigninRestriction,
policy);
EXPECT_EQ(signin_util::IsProfileSeparationEnforcedByProfile(profile(),
consumer_email),
SeparationEnforcedByExistingProfileExpected(policy))
<< policy;
EXPECT_EQ(signin_util::IsProfileSeparationEnforcedByProfile(
profile(), enterprise_email),
SeparationEnforcedByExistingProfileExpected(policy))
<< policy;
EXPECT_EQ(signin_util::IsProfileSeparationEnforcedByProfile(
profile(), other_enterprise_email),
SeparationEnforcedByExistingProfileExpected(policy))
<< policy;
}
profile()->GetPrefs()->SetList(prefs::kProfileSeparationDomainExceptionList,
base::Value::List());
for (const auto& policy : all_policies) {
profile()->GetPrefs()->SetString(prefs::kManagedAccountsSigninRestriction,
policy);
EXPECT_TRUE(signin_util::IsProfileSeparationEnforcedByProfile(
profile(), consumer_email))
<< policy;
EXPECT_TRUE(signin_util::IsProfileSeparationEnforcedByProfile(
profile(), enterprise_email))
<< policy;
EXPECT_TRUE(signin_util::IsProfileSeparationEnforcedByProfile(
profile(), other_enterprise_email))
<< policy;
}
base::Value::List profile_separation_exception_list;
profile_separation_exception_list.Append(base::Value("example.com"));
profile()->GetPrefs()->SetList(prefs::kProfileSeparationDomainExceptionList,
std::move(profile_separation_exception_list));
for (const auto& policy : all_policies) {
profile()->GetPrefs()->SetString(prefs::kManagedAccountsSigninRestriction,
policy);
EXPECT_TRUE(signin_util::IsProfileSeparationEnforcedByProfile(
profile(), consumer_email))
<< policy;
EXPECT_EQ(signin_util::IsProfileSeparationEnforcedByProfile(
profile(), enterprise_email),
SeparationEnforcedByExistingProfileExpected(policy))
<< policy;
EXPECT_TRUE(signin_util::IsProfileSeparationEnforcedByProfile(
profile(), other_enterprise_email))
<< policy;
}
}
TEST_F(SigninUtilTest, IsProfileSeparationEnforced) {
EXPECT_FALSE(signin_util::IsProfileSeparationEnforcedByPolicies(
policy::ProfileSeparationPolicies(
policy::ProfileSeparationSettings::SUGGESTED, std::nullopt)));
EXPECT_TRUE(signin_util::IsProfileSeparationEnforcedByPolicies(
policy::ProfileSeparationPolicies(
policy::ProfileSeparationSettings::ENFORCED, std::nullopt)));
EXPECT_FALSE(signin_util::IsProfileSeparationEnforcedByPolicies(
policy::ProfileSeparationPolicies(
policy::ProfileSeparationSettings::DISABLED, std::nullopt)));
}
TEST_F(SigninUtilTest,
ProfileSeparationAllowsKeepingUnmanagedBrowsingDataInManagedProfile) {
for (const auto& local_policy : all_policies) {
if (local_policy.empty()) {
profile()->GetPrefs()->ClearPref(
prefs::kManagedAccountsSigninRestriction);
} else {
profile()->GetPrefs()->SetString(prefs::kManagedAccountsSigninRestriction,
local_policy);
}
EXPECT_EQ(
signin_util::
ProfileSeparationAllowsKeepingUnmanagedBrowsingDataInManagedProfile(
profile(), policy::ProfileSeparationPolicies(
policy::ProfileSeparationSettings::ENFORCED,
policy::ProfileSeparationDataMigrationSettings::
USER_OPT_IN)),
KeepBrowsingDataExpected(local_policy, std::string()))
<< local_policy;
EXPECT_EQ(
signin_util::
ProfileSeparationAllowsKeepingUnmanagedBrowsingDataInManagedProfile(
profile(), policy::ProfileSeparationPolicies(
policy::ProfileSeparationSettings::ENFORCED,
policy::ProfileSeparationDataMigrationSettings::
USER_OPT_OUT)),
KeepBrowsingDataExpected(local_policy, std::string()))
<< local_policy;
EXPECT_FALSE(
signin_util::
ProfileSeparationAllowsKeepingUnmanagedBrowsingDataInManagedProfile(
profile(), policy::ProfileSeparationPolicies(
policy::ProfileSeparationSettings::ENFORCED,
policy::ProfileSeparationDataMigrationSettings::
ALWAYS_SEPARATE)))
<< local_policy;
}
}
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
TEST(SignedInStatesTest, SignedInStates) {
base::test::SingleThreadTaskEnvironment task_environment;
signin::IdentityTestEnvironment identity_test_env;
signin::IdentityManager* identity_manager =
identity_test_env.identity_manager();
// No Account present.
EXPECT_EQ(SignedInState::kSignedOut,
signin_util::GetSignedInState(identity_manager));
// Web signed in.
identity_test_env.MakeAccountAvailable("test@email.com",
{.set_cookie = true});
EXPECT_EQ(SignedInState::kWebOnlySignedIn,
signin_util::GetSignedInState(identity_manager));
// Syncing.
AccountInfo info = identity_test_env.MakePrimaryAccountAvailable(
"test@email.com", signin::ConsentLevel::kSync);
EXPECT_EQ(SignedInState::kSyncing,
signin_util::GetSignedInState(identity_manager));
// Sync paused state.
identity_test_env.SetInvalidRefreshTokenForPrimaryAccount();
EXPECT_EQ(SignedInState::kSyncPaused,
signin_util::GetSignedInState(identity_manager));
// Remove account.
identity_test_env.ClearPrimaryAccount();
EXPECT_EQ(SignedInState::kSignedOut,
signin_util::GetSignedInState(identity_manager));
// In incognito mode, there would be no identity manager.
EXPECT_EQ(SignedInState::kSignedOut, signin_util::GetSignedInState(nullptr));
// `kExplicitBrowserSigninUIOnDesktop` enabled
{
base::test::ScopedFeatureList scoped_feature_list{
switches::kExplicitBrowserSigninUIOnDesktop};
// Signed in.
info = identity_test_env.MakePrimaryAccountAvailable(
"test@email.com", signin::ConsentLevel::kSignin);
EXPECT_EQ(SignedInState::kSignedIn,
signin_util::GetSignedInState(identity_manager));
// When explicit browser signin is enabled, being signed in with an invalid
// refresh token is equivalent to the sign in pending state.
identity_test_env.SetInvalidRefreshTokenForPrimaryAccount();
EXPECT_EQ(SignedInState::kSignInPending,
signin_util::GetSignedInState(identity_manager));
}
// `kExplicitBrowserSigninUIOnDesktop` disabled
{
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndDisableFeature(
switches::kExplicitBrowserSigninUIOnDesktop);
// Signed in.
identity_test_env.ClearPrimaryAccount();
info = identity_test_env.MakePrimaryAccountAvailable(
"test@email.com", signin::ConsentLevel::kSignin);
EXPECT_EQ(SignedInState::kSignedIn,
signin_util::GetSignedInState(identity_manager));
// We expect the user to be signed in, and additional checks would be
// necessary to determine that the refresh token is in error.
identity_test_env.SetInvalidRefreshTokenForPrimaryAccount();
EXPECT_EQ(SignedInState::kSignedIn,
signin_util::GetSignedInState(identity_manager));
}
}
#endif // !BUILDFLAG(ENABLE_DICE_SUPPORT)
#endif