blob: f03af1414cd8de6dfae8a1eda01a86c4a0390285 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/json/json_writer.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/run_until.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "chrome/browser/enterprise/browser_management/management_service_factory.h"
#include "chrome/browser/glic/glic_pref_names.h"
#include "chrome/browser/glic/glic_user_status_code.h"
#include "chrome/browser/glic/glic_user_status_fetcher.h"
#include "chrome/browser/glic/public/glic_enabling.h"
#include "chrome/browser/glic/public/glic_keyed_service.h"
#include "chrome/browser/glic/public/glic_keyed_service_factory.h"
#include "chrome/browser/glic/test_support/glic_test_environment.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/chrome_signin_client_factory.h"
#include "chrome/browser/signin/chrome_signin_client_test_util.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/testing_profile.h"
#include "components/policy/core/common/management/scoped_management_service_override_for_testing.h"
#include "components/prefs/pref_service.h"
#include "components/signin/public/base/consent_level.h"
#include "components/signin/public/identity_manager/account_capabilities_test_mutator.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "content/public/test/browser_test.h"
#include "google_apis/common/api_error_codes.h"
#include "net/base/net_errors.h"
#include "net/dns/mock_host_resolver.h"
#include "services/network/test/test_url_loader_factory.h"
#include "services/network/test/test_utils.h"
#include "url/gurl.h"
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
#include "chrome/browser/enterprise/util/managed_browser_utils.h"
#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
namespace glic {
namespace {
const char kGlicUserStatusRelativeTestUrl[] = "/userstatus";
// Simple wrapper to serves as a POD for the test accounts.
struct TestAccount {
const std::string email;
const std::string host_domain;
};
TestAccount nonEnterpriseAccount = {"foo@testbar.com", ""};
TestAccount enterpriseAccount = {"foo@testenterprise.com",
"testenterprise.com"};
TestAccount googleDotComAccount = {"foo@google.com", "google.com"};
class GlicUserStatusBrowserTest : public InProcessBrowserTest {
protected:
GlicUserStatusBrowserTest() {
feature_list_.InitWithFeaturesAndParameters(
{{features::kGlic, {}},
{features::kTabstripComboButton, {}},
{features::kGlicRollout, {}},
{features::kGlicUserStatusCheck,
{{features::kGlicUserStatusRequestDelay.name, "200ms"},
{features::kGlicUserStatusRequestDelayJitter.name, "0"}}}},
{/* disabled_features */});
RegisterGeminiSettingsPrefs(pref_service_.registry());
}
void SetUpBrowserContextKeyedServices(
content::BrowserContext* context) override {
IdentityTestEnvironmentProfileAdaptor::
SetIdentityTestEnvironmentFactoriesOnBrowserContext(context);
ChromeSigninClientFactory::GetInstance()->SetTestingFactory(
context, base::BindRepeating(&BuildChromeSigninClientWithURLLoader,
&test_url_loader_factory_));
}
void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread();
adaptor_ =
std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile());
identity_test_env_ = adaptor_->identity_test_env();
identity_test_env_->SetTestURLLoaderFactory(&test_url_loader_factory_);
identity_manager_ = IdentityManagerFactory::GetForProfile(profile());
embedded_test_server()->AddDefaultHandlers(GetChromeTestDataDir());
host_resolver()->AddRule("*", "127.0.0.1");
profile()->GetPrefs()->SetInteger(
::prefs::kGeminiSettings,
static_cast<int>(glic::prefs::SettingsPolicyState::kEnabled));
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
disclaimer_service_resetter_ =
enterprise_util::DisableAutomaticManagementDisclaimerUntilReset(
profile());
#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
}
void TearDownOnMainThread() override {
ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
identity_manager_ = nullptr;
identity_test_env_ = nullptr;
adaptor_.reset();
InProcessBrowserTest::TearDownOnMainThread();
}
void RegisterUserStatusHandler(net::HttpStatusCode status_code,
std::string response_body) {
embedded_test_server()->RegisterRequestHandler(base::BindLambdaForTesting(
[=](const net::test_server::HttpRequest& request)
-> std::unique_ptr<net::test_server::HttpResponse> {
if (request.relative_url != kGlicUserStatusRelativeTestUrl) {
return nullptr;
}
auto response =
std::make_unique<net::test_server::BasicHttpResponse>();
response->set_code(status_code);
response->set_content(response_body);
response->set_content_type("application/json");
return response;
}));
}
// Simulates user signing in and getting a refresh token.
void SimulatePrimaryAccountChangedSignIn(TestAccount* account) {
identity_test_env_->SetAutomaticIssueOfAccessTokens(true);
AccountInfo account_info = identity_test_env_->MakePrimaryAccountAvailable(
account->email, signin::ConsentLevel::kSync);
AccountCapabilitiesTestMutator mutator(&account_info.capabilities);
mutator.set_can_use_model_execution_features(true);
mutator.set_is_subject_to_enterprise_features(
!account->host_domain.empty());
identity_test_env_->UpdateAccountInfoForAccount(account_info);
SimulateSuccessfulFetchOfAccountInfo(account, &account_info);
}
void SimulateSuccessfulFetchOfAccountInfo(const TestAccount* test_account,
const AccountInfo* account_info) {
identity_test_env_->SimulateSuccessfulFetchOfAccountInfo(
account_info->account_id, account_info->email, account_info->gaia,
test_account->host_domain,
base::StrCat({"full_name-", test_account->email}),
base::StrCat({"given_name-", test_account->email}),
base::StrCat({"local-", test_account->email}),
base::StrCat({"full_name-", test_account->email}));
}
void SetGlicUserStatusUrlForTest() {
GlicKeyedServiceFactory::GetGlicKeyedService(browser()->profile())
->enabling()
.SetGlicUserStatusUrlForTest(
embedded_test_server()->GetURL(kGlicUserStatusRelativeTestUrl));
}
// Gets the user status code from the pref.
std::optional<UserStatusCode> GetCachedStatusCode() {
PrefService* prefs = profile()->GetPrefs();
const base::Value::Dict& dict = prefs->GetDict(prefs::kGlicUserStatus);
if (!dict.FindInt(kUserStatus)) {
return std::nullopt;
}
return static_cast<UserStatusCode>(dict.FindInt(kUserStatus).value());
}
std::string GetGaiaIdHashBase64() {
auto* identity_manager = IdentityManagerFactory::GetForProfile(profile());
CoreAccountInfo primary_account =
identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin);
if (primary_account.IsEmpty()) {
return "";
}
return signin::GaiaIdHash::FromGaiaId(primary_account.gaia).ToBase64();
}
void SetGlicUserStatus(UserStatusCode code) {
base::Value::Dict data;
data.Set(kAccountId, GetGaiaIdHashBase64());
data.Set(kUserStatus, code);
data.Set(kUpdatedAt, base::Time::Now().InSecondsFSinceUnixEpoch());
profile()->GetPrefs()->SetDict(glic::prefs::kGlicUserStatus,
std::move(data));
}
// Gets the full user status details from prefs.
std::optional<base::Value::Dict> GetCachedStatusDict() {
PrefService* prefs = profile()->GetPrefs();
const base::Value::Dict& dict = prefs->GetDict(prefs::kGlicUserStatus);
if (dict.empty()) {
return std::nullopt;
}
return dict.Clone();
}
bool IsGlicEnabled() { return GlicEnabling::IsEnabledForProfile(profile()); }
Profile* profile() { return browser()->profile(); }
base::test::ScopedFeatureList feature_list_;
sync_preferences::TestingPrefServiceSyncable pref_service_;
std::unique_ptr<IdentityTestEnvironmentProfileAdaptor> adaptor_;
raw_ptr<signin::IdentityManager> identity_manager_;
raw_ptr<signin::IdentityTestEnvironment> identity_test_env_;
network::TestURLLoaderFactory test_url_loader_factory_;
base::ScopedClosureRunner disclaimer_service_resetter_;
};
IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, EnterpriseSignInEnabled) {
policy::ScopedManagementServiceOverrideForTesting platform_management(
policy::ManagementServiceFactory::GetForProfile(profile()),
policy::EnterpriseManagementAuthority::CLOUD);
RegisterUserStatusHandler(
net::HTTP_OK,
R"({"isGlicEnabled": true, "isAccessDeniedByAdmin": false})");
net::test_server::EmbeddedTestServerHandle test_server_handle;
ASSERT_TRUE(test_server_handle =
embedded_test_server()->StartAndReturnHandle());
SetGlicUserStatusUrlForTest();
SimulatePrimaryAccountChangedSignIn(&enterpriseAccount);
// Verify Prefs
ASSERT_TRUE(base::test::RunUntil(
[&]() { return GetCachedStatusDict().has_value(); }));
std::optional<base::Value::Dict> cached_dict = GetCachedStatusDict();
EXPECT_EQ(cached_dict->FindInt(kUserStatus).value_or(-1),
UserStatusCode::ENABLED);
EXPECT_EQ(*cached_dict->FindString(kAccountId), GetGaiaIdHashBase64());
EXPECT_TRUE(cached_dict->FindDouble(kUpdatedAt).has_value());
// Verify GlicEnabling status (assuming other criteria met)
EXPECT_TRUE(IsGlicEnabled());
}
IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest,
EnterpriseSignInEnabledGeminiSettings) {
policy::ScopedManagementServiceOverrideForTesting platform_management(
policy::ManagementServiceFactory::GetForProfile(profile()),
policy::EnterpriseManagementAuthority::CLOUD);
// Verify request is sent by the non-existence of the Prefs initially and the
// existence of it after sign-in simulation.
ASSERT_FALSE(GetCachedStatusDict().has_value());
bool request_received = false;
embedded_test_server()->RegisterRequestHandler(base::BindLambdaForTesting(
[=, &request_received](const net::test_server::HttpRequest& request)
-> std::unique_ptr<net::test_server::HttpResponse> {
if (request.relative_url != kGlicUserStatusRelativeTestUrl) {
return nullptr;
}
request_received = true;
auto response = std::make_unique<net::test_server::BasicHttpResponse>();
response->set_code(net::HTTP_OK);
response->set_content(
R"({"isGlicEnabled": true, "isAccessDeniedByAdmin": false})");
response->set_content_type("application/json");
return response;
}));
net::test_server::EmbeddedTestServerHandle test_server_handle;
ASSERT_TRUE(test_server_handle =
embedded_test_server()->StartAndReturnHandle());
SetGlicUserStatusUrlForTest();
SimulatePrimaryAccountChangedSignIn(&enterpriseAccount);
// Verify request is sent by the existence of the Prefs and request handler is
// inovked.
ASSERT_TRUE(base::test::RunUntil(
[&]() { return GetCachedStatusDict().has_value(); }));
ASSERT_TRUE(request_received);
// Sign out to clear the Prefs and reset request_received.
identity_test_env_->ClearPrimaryAccount();
ASSERT_TRUE(base::test::RunUntil([&]() {
return profile()->GetPrefs()->GetDict(prefs::kGlicUserStatus).empty();
}));
request_received = false;
// Setting kGeminiSettings to disabled so that no RPC would be sent.
profile()->GetPrefs()->SetInteger(
::prefs::kGeminiSettings,
static_cast<int>(glic::prefs::SettingsPolicyState::kDisabled));
// Sign in again and wait for a while.
SimulatePrimaryAccountChangedSignIn(&enterpriseAccount);
// Verifying the absence of a request by verifying the absence for a time
// period longer than the polling interval.
base::RunLoop run_loop;
base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), base::Milliseconds(300));
run_loop.Run();
// Verify no request is sent.
EXPECT_FALSE(request_received);
ASSERT_FALSE(GetCachedStatusDict().has_value());
// Sign out.
identity_test_env_->ClearPrimaryAccount();
// Make the account enterprise again by setting kGeminiSettings to enabled.
profile()->GetPrefs()->SetInteger(
::prefs::kGeminiSettings,
static_cast<int>(glic::prefs::SettingsPolicyState::kEnabled));
// Sign in again.
SimulatePrimaryAccountChangedSignIn(&enterpriseAccount);
// Verify request is sent again by the existence of the Prefs and request
// handler is inovked.
ASSERT_TRUE(base::test::RunUntil(
[&]() { return GetCachedStatusDict().has_value(); }));
ASSERT_TRUE(request_received);
}
IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest,
EnterpriseGeminiSettingsChangeNoSignedOut) {
policy::ScopedManagementServiceOverrideForTesting platform_management(
policy::ManagementServiceFactory::GetForProfile(profile()),
policy::EnterpriseManagementAuthority::CLOUD);
// Verify request is sent by the non-existence of the Prefs initially and the
// existence of it after sign-in simulation.
ASSERT_FALSE(GetCachedStatusDict().has_value());
bool request_received = false;
embedded_test_server()->RegisterRequestHandler(base::BindLambdaForTesting(
[=, &request_received](const net::test_server::HttpRequest& request)
-> std::unique_ptr<net::test_server::HttpResponse> {
if (request.relative_url != kGlicUserStatusRelativeTestUrl) {
return nullptr;
}
request_received = true;
auto response = std::make_unique<net::test_server::BasicHttpResponse>();
response->set_code(net::HTTP_OK);
response->set_content(
R"({"isGlicEnabled": true, "isAccessDeniedByAdmin": false})");
response->set_content_type("application/json");
return response;
}));
net::test_server::EmbeddedTestServerHandle test_server_handle;
ASSERT_TRUE(test_server_handle =
embedded_test_server()->StartAndReturnHandle());
SetGlicUserStatusUrlForTest();
SimulatePrimaryAccountChangedSignIn(&enterpriseAccount);
// Verify request is sent by the existence of the Prefs and request handler is
// inovked.
ASSERT_TRUE(base::test::RunUntil(
[&]() { return GetCachedStatusDict().has_value(); }));
ASSERT_TRUE(request_received);
// Setting kGeminiSettings to disabled so that no RPC would be sent.
request_received = false;
profile()->GetPrefs()->SetInteger(
::prefs::kGeminiSettings,
static_cast<int>(glic::prefs::SettingsPolicyState::kDisabled));
// Verifying the absence of a request by verifying the absence for a time
// period longer than the polling interval.
base::RunLoop run_loop;
base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), base::Milliseconds(300));
run_loop.Run();
// Verify no request is sent.
EXPECT_FALSE(request_received);
// Make the account enterprise again by setting kGeminiSettings to enabled.
profile()->GetPrefs()->SetInteger(
::prefs::kGeminiSettings,
static_cast<int>(glic::prefs::SettingsPolicyState::kEnabled));
// Verify request handler is inovked.
ASSERT_TRUE(base::test::RunUntil([&]() { return request_received; }));
}
IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest,
EnterpriseSignInDisabledByAdmin) {
policy::ScopedManagementServiceOverrideForTesting platform_management(
policy::ManagementServiceFactory::GetForProfile(profile()),
policy::EnterpriseManagementAuthority::CLOUD);
RegisterUserStatusHandler(
net::HTTP_OK,
R"({"isGlicEnabled": false, "isAccessDeniedByAdmin": true})");
net::test_server::EmbeddedTestServerHandle test_server_handle;
ASSERT_TRUE(test_server_handle =
embedded_test_server()->StartAndReturnHandle());
SetGlicUserStatusUrlForTest();
SimulatePrimaryAccountChangedSignIn(&enterpriseAccount);
// Verify Prefs
ASSERT_TRUE(base::test::RunUntil(
[&]() { return GetCachedStatusDict().has_value(); }));
std::optional<base::Value::Dict> cached_dict = GetCachedStatusDict();
EXPECT_EQ(cached_dict->FindInt(kUserStatus).value_or(-1),
UserStatusCode::DISABLED_BY_ADMIN);
EXPECT_EQ(*cached_dict->FindString(kAccountId), GetGaiaIdHashBase64());
// Verify GlicEnabling status - Should be disabled by this status
EXPECT_FALSE(IsGlicEnabled());
}
IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest,
EnterpriseSignInDisabledOther) {
policy::ScopedManagementServiceOverrideForTesting platform_management(
policy::ManagementServiceFactory::GetForProfile(profile()),
policy::EnterpriseManagementAuthority::CLOUD);
RegisterUserStatusHandler(
net::HTTP_OK,
R"({"isGlicEnabled": false, "isAccessDeniedByAdmin": false})");
net::test_server::EmbeddedTestServerHandle test_server_handle;
ASSERT_TRUE(test_server_handle =
embedded_test_server()->StartAndReturnHandle());
SetGlicUserStatusUrlForTest();
SimulatePrimaryAccountChangedSignIn(&enterpriseAccount);
// Verify Prefs
ASSERT_TRUE(base::test::RunUntil(
[&]() { return GetCachedStatusDict().has_value(); }));
std::optional<base::Value::Dict> cached_dict = GetCachedStatusDict();
EXPECT_EQ(cached_dict->FindInt(kUserStatus).value_or(-1),
UserStatusCode::DISABLED_OTHER);
EXPECT_EQ(*cached_dict->FindString(kAccountId), GetGaiaIdHashBase64());
// Verify GlicEnabling status - Should be disabled by this status
EXPECT_FALSE(IsGlicEnabled());
}
IN_PROC_BROWSER_TEST_F(
GlicUserStatusBrowserTest,
EnterpriseSignInDisabledButManagedStatusNotImmediatelyKnown) {
RegisterUserStatusHandler(
net::HTTP_OK,
R"({"isGlicEnabled": false, "isAccessDeniedByAdmin": true})");
net::test_server::EmbeddedTestServerHandle test_server_handle;
ASSERT_TRUE(test_server_handle =
embedded_test_server()->StartAndReturnHandle());
SetGlicUserStatusUrlForTest();
identity_test_env_->SetAutomaticIssueOfAccessTokens(true);
AccountInfo account_info = identity_test_env_->MakePrimaryAccountAvailable(
enterpriseAccount.email, signin::ConsentLevel::kSync);
enterprise_util::SetUserAcceptedAccountManagement(profile(), true);
AccountCapabilitiesTestMutator mutator(&account_info.capabilities);
mutator.set_can_use_model_execution_features(true);
identity_test_env_->UpdateAccountInfoForAccount(account_info);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(GetCachedStatusDict().has_value());
// Only now, after the fetch would have happened, does the information about
// the account's managed status become available. This should cause an RPC
// to be sent.
SimulateSuccessfulFetchOfAccountInfo(&enterpriseAccount, &account_info);
policy::ScopedManagementServiceOverrideForTesting platform_management(
policy::ManagementServiceFactory::GetForProfile(profile()),
policy::EnterpriseManagementAuthority::CLOUD);
// Verify Prefs
ASSERT_TRUE(base::test::RunUntil(
[&]() { return GetCachedStatusDict().has_value(); }));
std::optional<base::Value::Dict> cached_dict = GetCachedStatusDict();
EXPECT_EQ(cached_dict->FindInt(kUserStatus).value_or(-1),
UserStatusCode::DISABLED_BY_ADMIN);
EXPECT_EQ(*cached_dict->FindString(kAccountId), GetGaiaIdHashBase64());
// Verify GlicEnabling status - Should be disabled by this status
EXPECT_FALSE(IsGlicEnabled());
}
// It happens that google.com accounts are always considered enterprise
// accounts, even before extended account info is available.
IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest,
EnterpriseSignInDisabledByAdminGoogleDotCom) {
policy::ScopedManagementServiceOverrideForTesting platform_management(
policy::ManagementServiceFactory::GetForProfile(profile()),
policy::EnterpriseManagementAuthority::CLOUD);
RegisterUserStatusHandler(
net::HTTP_OK,
R"({"isGlicEnabled": false, "isAccessDeniedByAdmin": true})");
net::test_server::EmbeddedTestServerHandle test_server_handle;
ASSERT_TRUE(test_server_handle =
embedded_test_server()->StartAndReturnHandle());
SetGlicUserStatusUrlForTest();
SimulatePrimaryAccountChangedSignIn(&googleDotComAccount);
// Verify Prefs
ASSERT_TRUE(base::test::RunUntil(
[&]() { return GetCachedStatusDict().has_value(); }));
std::optional<base::Value::Dict> cached_dict = GetCachedStatusDict();
EXPECT_EQ(cached_dict->FindInt(kUserStatus).value_or(-1),
UserStatusCode::DISABLED_BY_ADMIN);
EXPECT_EQ(*cached_dict->FindString(kAccountId), GetGaiaIdHashBase64());
// Verify GlicEnabling status - Should be disabled by this status
EXPECT_FALSE(IsGlicEnabled());
}
// This ensures that the check using the policy management service still works,
// until/unless we need to switch back to it.
class GlicUserStatusBrowserTestWithPolicyManagementService
: public GlicUserStatusBrowserTest {
protected:
GlicUserStatusBrowserTestWithPolicyManagementService() {
scoped_feature_list_.InitAndEnableFeatureWithParameters(
features::kGlicUserStatusCheck,
{{features::kGlicUserStatusEnterpriseCheckStrategy.name, "policy"}});
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTestWithPolicyManagementService,
EnterpriseSignInDisabledByAdmin) {
policy::ScopedManagementServiceOverrideForTesting platform_management(
policy::ManagementServiceFactory::GetForProfile(profile()),
policy::EnterpriseManagementAuthority::CLOUD);
RegisterUserStatusHandler(
net::HTTP_OK,
R"({"isGlicEnabled": false, "isAccessDeniedByAdmin": true})");
net::test_server::EmbeddedTestServerHandle test_server_handle;
ASSERT_TRUE(test_server_handle =
embedded_test_server()->StartAndReturnHandle());
SetGlicUserStatusUrlForTest();
SimulatePrimaryAccountChangedSignIn(&enterpriseAccount);
// Verify Prefs
ASSERT_TRUE(base::test::RunUntil(
[&]() { return GetCachedStatusDict().has_value(); }));
std::optional<base::Value::Dict> cached_dict = GetCachedStatusDict();
EXPECT_EQ(cached_dict->FindInt(kUserStatus).value_or(-1),
UserStatusCode::DISABLED_BY_ADMIN);
EXPECT_EQ(*cached_dict->FindString(kAccountId), GetGaiaIdHashBase64());
// Verify GlicEnabling status - Should be disabled by this status
EXPECT_FALSE(IsGlicEnabled());
}
IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest,
EnterpriseSignInServerUnavailableNoStoredResult) {
policy::ScopedManagementServiceOverrideForTesting platform_management(
policy::ManagementServiceFactory::GetForProfile(profile()),
policy::EnterpriseManagementAuthority::CLOUD);
RegisterUserStatusHandler(
net::HTTP_NOT_FOUND,
R"({"isGlicEnabled": true, "isAccessDeniedByAdmin": false})");
net::test_server::EmbeddedTestServerHandle test_server_handle;
ASSERT_TRUE(test_server_handle =
embedded_test_server()->StartAndReturnHandle());
SetGlicUserStatusUrlForTest();
SimulatePrimaryAccountChangedSignIn(&enterpriseAccount);
// Verify that when the user status code is SERVER_UNAVAILABLE, the glic user
// status result is not stored.
std::optional<base::Value::Dict> cached_dict = GetCachedStatusDict();
EXPECT_FALSE(cached_dict.has_value());
EXPECT_TRUE(IsGlicEnabled());
}
IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest,
EnterpriseSignInServerUnavailableHasStoredResult) {
policy::ScopedManagementServiceOverrideForTesting platform_management(
policy::ManagementServiceFactory::GetForProfile(profile()),
policy::EnterpriseManagementAuthority::CLOUD);
RegisterUserStatusHandler(
net::HTTP_NOT_FOUND,
R"({"isGlicEnabled": true, "isAccessDeniedByAdmin": false})");
net::test_server::EmbeddedTestServerHandle test_server_handle;
ASSERT_TRUE(test_server_handle =
embedded_test_server()->StartAndReturnHandle());
SetGlicUserStatusUrlForTest();
SimulatePrimaryAccountChangedSignIn(&enterpriseAccount);
auto user_status_code = UserStatusCode::DISABLED_BY_ADMIN;
SetGlicUserStatus(user_status_code);
ASSERT_TRUE(base::test::RunUntil(
[&]() { return GetCachedStatusDict().has_value(); }));
// Verify that when the user status code is SERVER_UNAVAILABLE, the previous
// stored pref value is not overwritten.
std::optional<base::Value::Dict> cached_dict = GetCachedStatusDict();
EXPECT_TRUE(cached_dict.has_value());
EXPECT_EQ(cached_dict->FindInt(kUserStatus).value_or(-1), user_status_code);
EXPECT_FALSE(IsGlicEnabled());
}
IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, EnterpriseSignOut) {
policy::ScopedManagementServiceOverrideForTesting platform_management(
policy::ManagementServiceFactory::GetForProfile(profile()),
policy::EnterpriseManagementAuthority::CLOUD);
// Sign in and set user status to enabled.
RegisterUserStatusHandler(
net::HTTP_OK,
R"({"isGlicEnabled": true, "isAccessDeniedByAdmin": false})");
net::test_server::EmbeddedTestServerHandle test_server_handle;
ASSERT_TRUE(test_server_handle =
embedded_test_server()->StartAndReturnHandle());
SetGlicUserStatusUrlForTest();
SimulatePrimaryAccountChangedSignIn(&enterpriseAccount);
ASSERT_TRUE(base::test::RunUntil(
[&]() { return GetCachedStatusDict().has_value(); }));
ASSERT_TRUE(IsGlicEnabled());
// Sign out.
identity_test_env_->ClearPrimaryAccount();
ASSERT_TRUE(base::test::RunUntil([&]() {
return profile()->GetPrefs()->GetDict(prefs::kGlicUserStatus).empty();
}));
// This is false because the IsNonEnterpriseEnabled() will return false if no
// account is signed in. The UserStatusCheck is true when pref is cleared.
EXPECT_FALSE(IsGlicEnabled());
}
IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, NonEnterpriseSignIn) {
bool request_received = false;
embedded_test_server()->RegisterRequestHandler(base::BindLambdaForTesting(
[=, &request_received](const net::test_server::HttpRequest& request)
-> std::unique_ptr<net::test_server::HttpResponse> {
if (request.relative_url != kGlicUserStatusRelativeTestUrl) {
return nullptr;
}
request_received = true;
auto response = std::make_unique<net::test_server::BasicHttpResponse>();
response->set_code(net::HTTP_OK);
response->set_content(
R"({"isGlicEnabled": true, "isAccessDeniedByAdmin": false})");
response->set_content_type("application/json");
return response;
}));
net::test_server::EmbeddedTestServerHandle test_server_handle;
ASSERT_TRUE(test_server_handle =
embedded_test_server()->StartAndReturnHandle());
SetGlicUserStatusUrlForTest();
SimulatePrimaryAccountChangedSignIn(&nonEnterpriseAccount);
// wait for a while.
base::RunLoop run_loop;
base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), base::Milliseconds(300));
run_loop.Run();
ASSERT_FALSE(request_received);
ASSERT_FALSE(GetCachedStatusDict().has_value());
ASSERT_TRUE(IsGlicEnabled());
}
IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest, EnterpriseDataProtection) {
policy::ScopedManagementServiceOverrideForTesting platform_management(
policy::ManagementServiceFactory::GetForProfile(profile()),
policy::EnterpriseManagementAuthority::CLOUD);
RegisterUserStatusHandler(
net::HTTP_OK,
R"({"isGlicEnabled": true, "isAccessDeniedByAdmin": false,
"isEnterpriseAccountDataProtected": true })");
net::test_server::EmbeddedTestServerHandle test_server_handle;
ASSERT_TRUE(test_server_handle =
embedded_test_server()->StartAndReturnHandle());
SetGlicUserStatusUrlForTest();
SimulatePrimaryAccountChangedSignIn(&enterpriseAccount);
ASSERT_TRUE(base::test::RunUntil(
[&]() { return GetCachedStatusDict().has_value(); }));
// Verify the isEnterpriseAccountDataProtected field.
EXPECT_EQ(profile()
->GetPrefs()
->GetDict(prefs::kGlicUserStatus)
.FindBool(kIsEnterpriseAccountDataProtected),
true);
}
IN_PROC_BROWSER_TEST_F(GlicUserStatusBrowserTest,
EnterpriseDataProtectionMissingInServerResponse) {
policy::ScopedManagementServiceOverrideForTesting platform_management(
policy::ManagementServiceFactory::GetForProfile(profile()),
policy::EnterpriseManagementAuthority::CLOUD);
RegisterUserStatusHandler(
net::HTTP_OK,
R"({"isGlicEnabled": true, "isAccessDeniedByAdmin": false})");
net::test_server::EmbeddedTestServerHandle test_server_handle;
ASSERT_TRUE(test_server_handle =
embedded_test_server()->StartAndReturnHandle());
SetGlicUserStatusUrlForTest();
SimulatePrimaryAccountChangedSignIn(&enterpriseAccount);
ASSERT_TRUE(base::test::RunUntil(
[&]() { return GetCachedStatusDict().has_value(); }));
// Verify the isEnterpriseAccountDataProtected field.
EXPECT_EQ(profile()
->GetPrefs()
->GetDict(prefs::kGlicUserStatus)
.FindBool(kIsEnterpriseAccountDataProtected),
false);
}
} // namespace
} // namespace glic