blob: 45fa7dcdc1698542db796298627ff0e1390591e1 [file] [log] [blame]
// Copyright 2022 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/accounts_policy_manager.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "build/buildflag.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/signin/accounts_policy_manager_factory.h"
#include "chrome/browser/signin/chrome_signin_client_factory.h"
#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
#include "chrome/browser/signin/signin_util.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/policy/core/common/features.h"
#include "components/signin/public/base/signin_pref_names.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
namespace {
const char kTestEmail[] = "me@gmail.com";
const char kTestEmail2[] = "me2@gmail.com";
const char kExampleEmail[] = "me@example.com";
} // namespace
#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
class AccountsPolicyManagerTest : public testing::Test {
public:
AccountsPolicyManagerTest()
: profile_manager_(TestingBrowserProcess::GetGlobal()) {}
void SetUp() override {
ASSERT_TRUE(profile_manager_.SetUp());
CreateTestingProfile();
}
void TearDown() override {
if (profile_) {
DestroyProfile();
}
}
~AccountsPolicyManagerTest() override = default;
void CreateTestingProfile() {
DCHECK(!profile_);
profile_ =
profile_manager_
.CreateTestingProfile("accounts_policy_manager_test_profile_path",
IdentityTestEnvironmentProfileAdaptor::
GetIdentityTestEnvironmentFactories())
->GetWeakPtr();
identity_test_env_adaptor_ =
std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile_.get());
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
AccountsPolicyManagerFactory::GetForProfile(GetProfile())
->SetHideUIForTesting(true);
#endif
}
void DestroyProfile() {
identity_test_env_adaptor_.reset();
profile_ = nullptr;
profile_manager_.DeleteTestingProfile(
"accounts_policy_manager_test_profile_path");
}
PrefService* GetLocalState() { return profile_manager_.local_state()->Get(); }
Profile* GetProfile() {
DCHECK(profile_);
return profile_.get();
}
TestingProfileManager* GetProfileManager() { return &profile_manager_; }
signin::IdentityTestEnvironment* GetIdentityTestEnv() {
DCHECK(identity_test_env_adaptor_);
return identity_test_env_adaptor_->identity_test_env();
}
SigninClient* GetSigninSlient(Profile* profile) {
return ChromeSigninClientFactory::GetForProfile(profile);
}
signin::IdentityManager* identity_manager() {
return GetIdentityTestEnv()->identity_manager();
}
private:
content::BrowserTaskEnvironment task_environment_;
TestingProfileManager profile_manager_;
base::WeakPtr<Profile> profile_ = nullptr;
std::unique_ptr<IdentityTestEnvironmentProfileAdaptor>
identity_test_env_adaptor_;
};
#if !BUILDFLAG(IS_CHROMEOS)
// All primary accounts are allowed on ChromeOS and Lacros, so this the
// AccountsPolicyManagerTest does not clear the primary account on
// ChromeOS.
//
// TODO(msarda): Exclude |AccountsPolicyManager| from the ChromeOS
// build.
//
// TODO(msarda): These tests are valid for secondary profiles on Lacros. Enable
// them on Lacros.
TEST_F(AccountsPolicyManagerTest, ClearPrimarySyncAccountWhenSigninNotAllowed) {
GetIdentityTestEnv()->MakePrimaryAccountAvailable(
"test@foo.com", signin::ConsentLevel::kSync);
GetProfile()->GetPrefs()->SetBoolean(prefs::kSigninAllowed, false);
EXPECT_FALSE(GetIdentityTestEnv()->identity_manager()->HasPrimaryAccount(
signin::ConsentLevel::kSync));
EXPECT_FALSE(GetIdentityTestEnv()->identity_manager()->HasPrimaryAccount(
signin::ConsentLevel::kSignin));
}
TEST_F(AccountsPolicyManagerTest,
ClearPrimarySyncAccountWhenPatternNotAllowed) {
GetIdentityTestEnv()->MakePrimaryAccountAvailable(
"test@foo.com", signin::ConsentLevel::kSync);
GetLocalState()->SetString(prefs::kGoogleServicesUsernamePattern,
".*@bar.com");
EXPECT_FALSE(GetIdentityTestEnv()->identity_manager()->HasPrimaryAccount(
signin::ConsentLevel::kSync));
EXPECT_FALSE(GetIdentityTestEnv()->identity_manager()->HasPrimaryAccount(
signin::ConsentLevel::kSignin));
}
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
TEST_F(AccountsPolicyManagerTest, ClearProfileWhenSigninAndSignoutNotAllowed) {
GetIdentityTestEnv()->MakePrimaryAccountAvailable(
"test@foo.com", signin::ConsentLevel::kSync);
// Create a second profile.
GetProfileManager()->CreateTestingProfile(
"accounts_policy_manager_test_profile_path_1",
IdentityTestEnvironmentProfileAdaptor::
GetIdentityTestEnvironmentFactories());
ASSERT_EQ(2u, GetProfileManager()->profile_manager()->GetNumberOfProfiles());
// Disable sign out and sign in. This should result in the initial profile
// being deleted.
GetSigninSlient(GetProfile())
->set_is_clear_primary_account_allowed_for_testing(
SigninClient::SignoutDecision::CLEAR_PRIMARY_ACCOUNT_DISALLOWED);
GetProfile()->GetPrefs()->SetBoolean(prefs::kSigninAllowed, false);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, GetProfileManager()->profile_manager()->GetNumberOfProfiles());
}
TEST_F(AccountsPolicyManagerTest,
ClearProfileWhenSigninAndRevokeSyncNotAllowed) {
GetIdentityTestEnv()->MakePrimaryAccountAvailable(
"test@foo.com", signin::ConsentLevel::kSync);
// Create a second profile.
GetProfileManager()->CreateTestingProfile(
"accounts_policy_manager_test_profile_path_1",
IdentityTestEnvironmentProfileAdaptor::
GetIdentityTestEnvironmentFactories());
ASSERT_EQ(2u, GetProfileManager()->profile_manager()->GetNumberOfProfiles());
// Disable sign out and sign in. This should result in the initial profile
// being deleted.
GetSigninSlient(GetProfile())
->set_is_clear_primary_account_allowed_for_testing(
SigninClient::SignoutDecision::REVOKE_SYNC_DISALLOWED);
GetProfile()->GetPrefs()->SetBoolean(prefs::kSigninAllowed, false);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, GetProfileManager()->profile_manager()->GetNumberOfProfiles());
}
TEST_F(AccountsPolicyManagerTest, ClearProfileUnallowedAccounts) {
base::test::ScopedFeatureList feature_list(
policy::features::kProfileSeparationDomainExceptionListRetroactive);
GetIdentityTestEnv()->SetPrimaryAccount(kTestEmail,
signin::ConsentLevel::kSignin);
GetIdentityTestEnv()->SetRefreshTokenForPrimaryAccount();
auto primary_account_id =
identity_manager()->GetPrimaryAccountId(signin::ConsentLevel::kSignin);
EXPECT_TRUE(
identity_manager()->HasAccountWithRefreshToken(primary_account_id));
AccountInfo account_info2 = GetIdentityTestEnv()->MakeAccountAvailable(
signin::AccountAvailabilityOptionsBuilder().Build(kTestEmail2));
CoreAccountId account_id2 = account_info2.account_id;
GetIdentityTestEnv()->SetRefreshTokenForAccount(account_id2);
EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account_id2));
AccountInfo account_info3 = GetIdentityTestEnv()->MakeAccountAvailable(
signin::AccountAvailabilityOptionsBuilder().Build(kExampleEmail));
CoreAccountId account_id3 = account_info3.account_id;
GetIdentityTestEnv()->SetRefreshTokenForAccount(account_id3);
EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account_id3));
// Set prefs to only allow example.com secondary accounts
base::Value::List profile_separation_domain_exception_list;
profile_separation_domain_exception_list.Append("example.com");
GetProfile()->GetPrefs()->SetList(
prefs::kProfileSeparationDomainExceptionList,
std::move(profile_separation_domain_exception_list));
base::RunLoop run_loop;
run_loop.RunUntilIdle();
// Primary account not removed.
EXPECT_TRUE(
identity_manager()->HasAccountWithRefreshToken(primary_account_id));
// @gmail account removed.
EXPECT_FALSE(identity_manager()->HasAccountWithRefreshToken(account_id2));
// @example.com account not removed.
EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account_id3));
}
TEST_F(AccountsPolicyManagerTest, ClearProfileUnallowedAccountsDisabled) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
policy::features::kProfileSeparationDomainExceptionListRetroactive);
GetIdentityTestEnv()->SetPrimaryAccount(kTestEmail,
signin::ConsentLevel::kSignin);
GetIdentityTestEnv()->SetRefreshTokenForPrimaryAccount();
auto primary_account_id =
identity_manager()->GetPrimaryAccountId(signin::ConsentLevel::kSignin);
EXPECT_TRUE(
identity_manager()->HasAccountWithRefreshToken(primary_account_id));
AccountInfo account_info2 = GetIdentityTestEnv()->MakeAccountAvailable(
signin::AccountAvailabilityOptionsBuilder().Build(kTestEmail2));
CoreAccountId account_id2 = account_info2.account_id;
GetIdentityTestEnv()->SetRefreshTokenForAccount(account_id2);
EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account_id2));
AccountInfo account_info3 = GetIdentityTestEnv()->MakeAccountAvailable(
signin::AccountAvailabilityOptionsBuilder().Build(kExampleEmail));
CoreAccountId account_id3 = account_info3.account_id;
GetIdentityTestEnv()->SetRefreshTokenForAccount(account_id3);
EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account_id3));
// Set prefs to only allow example.com secondary accounts
base::Value::List profile_separation_domain_exception_list;
profile_separation_domain_exception_list.Append("example.com");
GetProfile()->GetPrefs()->SetList(
prefs::kProfileSeparationDomainExceptionList,
std::move(profile_separation_domain_exception_list));
base::RunLoop run_loop;
run_loop.RunUntilIdle();
// No accounts were removed.
EXPECT_TRUE(
identity_manager()->HasAccountWithRefreshToken(primary_account_id));
EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account_id2));
EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(account_id3));
}
#endif // #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
#endif // !BUILDFLAG(IS_CHROMEOS)