blob: f170ab1ce2cb4981f9ff4ab75da13c0232404bdb [file] [log] [blame]
// Copyright 2023 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/feature_list.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/task/current_thread.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test.pb.h"
#include "base/test/with_feature_override.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
#include "chrome/browser/optimization_guide/model_execution/chrome_on_device_model_service_controller.h"
#include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
#include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/webauthn/sheet_models.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/metrics_services_manager/metrics_services_manager.h"
#include "components/optimization_guide/core/feature_registry/feature_registration.h"
#include "components/optimization_guide/core/feature_registry/mqls_feature_registry.h"
#include "components/optimization_guide/core/model_execution/feature_keys.h"
#include "components/optimization_guide/core/model_execution/model_execution_features.h"
#include "components/optimization_guide/core/model_execution/model_execution_manager.h"
#include "components/optimization_guide/core/model_execution/model_execution_prefs.h"
#include "components/optimization_guide/core/model_execution/on_device_model_adaptation_loader.h"
#include "components/optimization_guide/core/model_execution/on_device_model_service_controller.h"
#include "components/optimization_guide/core/model_execution/optimization_guide_model_execution_error.h"
#include "components/optimization_guide/core/model_execution/test/fake_model_assets.h"
#include "components/optimization_guide/core/model_execution/test/feature_config_builder.h"
#include "components/optimization_guide/core/model_quality/model_execution_logging_wrappers.h"
#include "components/optimization_guide/core/model_quality/model_quality_log_entry.h"
#include "components/optimization_guide/core/optimization_guide_constants.h"
#include "components/optimization_guide/core/optimization_guide_features.h"
#include "components/optimization_guide/core/optimization_guide_logger.h"
#include "components/optimization_guide/core/optimization_guide_model_executor.h"
#include "components/optimization_guide/core/optimization_guide_switches.h"
#include "components/optimization_guide/core/optimization_guide_util.h"
#include "components/optimization_guide/proto/model_quality_service.pb.h"
#include "components/optimization_guide/proto/on_device_model_execution_config.pb.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/policy_constants.h"
#include "components/signin/public/base/signin_switches.h"
#include "components/signin/public/identity_manager/account_capabilities_test_mutator.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "net/dns/mock_host_resolver.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/tflite/buildflags.h"
namespace optimization_guide {
namespace {
enum class ModelExecutionRemoteResponseType {
kSuccessful = 0,
kUnsuccessful = 1,
kMalformed = 2,
kErrorFiltered = 3,
kUnsupportedLanguage = 4,
};
proto::ExecuteResponse BuildComposeResponse(const std::string& output) {
proto::ComposeResponse compose_response;
compose_response.set_output(output);
proto::ExecuteResponse execute_response;
proto::Any* any_metadata = execute_response.mutable_response_metadata();
any_metadata->set_type_url(
base::StrCat({"type.googleapis.com/", compose_response.GetTypeName()}));
compose_response.SerializeToString(any_metadata->mutable_value());
auto response_data = ParsedAnyMetadata<proto::ComposeResponse>(*any_metadata);
EXPECT_TRUE(response_data);
return execute_response;
}
proto::ExecuteResponse BuildTestErrorExecuteResponse(
const proto::ErrorState& state) {
proto::ExecuteResponse execute_response;
execute_response.mutable_error_response()->set_error_state(state);
return execute_response;
}
class ScopedSetMetricsConsent {
public:
// Enables or disables metrics consent based off of |consent|.
explicit ScopedSetMetricsConsent(bool consent) : consent_(consent) {
ChromeMetricsServiceAccessor::SetMetricsAndCrashReportingForTesting(
&consent_);
}
ScopedSetMetricsConsent(const ScopedSetMetricsConsent&) = delete;
ScopedSetMetricsConsent& operator=(const ScopedSetMetricsConsent&) = delete;
~ScopedSetMetricsConsent() {
ChromeMetricsServiceAccessor::SetMetricsAndCrashReportingForTesting(
nullptr);
}
private:
const bool consent_;
};
constexpr float kTestDefaultTemperature = 0.9;
constexpr uint32_t kTestDefaultTopK = 7;
} // namespace
class ModelExecutionBrowserTestBase : public InProcessBrowserTest {
public:
ModelExecutionBrowserTestBase() = default;
~ModelExecutionBrowserTestBase() override = default;
ModelExecutionBrowserTestBase(const ModelExecutionBrowserTestBase&) = delete;
ModelExecutionBrowserTestBase& operator=(
const ModelExecutionBrowserTestBase&) = delete;
void SetUp() override {
InitializeFeatureList();
model_execution_server_ = std::make_unique<net::EmbeddedTestServer>(
net::EmbeddedTestServer::TYPE_HTTPS);
net::EmbeddedTestServer::ServerCertificateConfig cert_config;
cert_config.dns_names = {
GURL(kOptimizationGuideServiceModelExecutionDefaultURL).host(),
};
model_execution_server_->SetSSLConfig(cert_config);
model_execution_server_->RegisterRequestHandler(base::BindRepeating(
&ModelExecutionBrowserTestBase::HandleGetModelExecutionRequest,
base::Unretained(this)));
// Start ModelQualityLogsUploaderService to upload the model quality logs on
// receiving it from model execution.
model_quality_logs_server_ = std::make_unique<net::EmbeddedTestServer>(
net::EmbeddedTestServer::TYPE_HTTPS);
cert_config.dns_names = {
GURL(kOptimizationGuideServiceModelQualtiyDefaultURL).host(),
};
model_quality_logs_server_->SetSSLConfig(cert_config);
model_quality_logs_server_->RegisterRequestHandler(base::BindRepeating(
&ModelExecutionBrowserTestBase::HandleGetModelQualityLogsUploadRequest,
base::Unretained(this)));
num_logs_requests_ = 0;
ASSERT_TRUE(model_execution_server_->Start());
ASSERT_TRUE(model_quality_logs_server_->Start());
InProcessBrowserTest::SetUp();
}
void SetUpCommandLine(base::CommandLine* cmd) override {
cmd->AppendSwitchASCII(
switches::kOptimizationGuideServiceModelExecutionURL,
model_execution_server_
->GetURL(
GURL(kOptimizationGuideServiceModelExecutionDefaultURL).host(),
"/")
.spec());
cmd->AppendSwitchASCII(
switches::kModelQualityServiceURL,
model_quality_logs_server_
->GetURL(
GURL(kOptimizationGuideServiceModelQualtiyDefaultURL).host(),
"/")
.spec());
}
void SetUpBrowserContextKeyedServices(
content::BrowserContext* context) override {
InProcessBrowserTest::SetUpBrowserContextKeyedServices(context);
IdentityTestEnvironmentProfileAdaptor::
SetIdentityTestEnvironmentFactoriesOnBrowserContext(context);
}
void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread();
identity_test_env_adaptor_ =
std::make_unique<IdentityTestEnvironmentProfileAdaptor>(
browser()->profile());
host_resolver()->AddRule("*", "127.0.0.1");
}
void TearDownOnMainThread() override {
EXPECT_TRUE(model_execution_server_->ShutdownAndWaitUntilComplete());
EXPECT_TRUE(model_quality_logs_server_->ShutdownAndWaitUntilComplete());
InProcessBrowserTest::TearDownOnMainThread();
}
void EnableSignin() {
auto account_info =
identity_test_env_adaptor_->identity_test_env()
->MakePrimaryAccountAvailable("user@gmail.com",
signin::ConsentLevel::kSignin);
AccountCapabilitiesTestMutator mutator(&account_info.capabilities);
mutator.set_can_use_model_execution_features(true);
identity_test_env_adaptor_->identity_test_env()
->UpdateAccountInfoForAccount(account_info);
identity_test_env_adaptor_->identity_test_env()
->SetAutomaticIssueOfAccessTokens(true);
}
bool IsSignedIn() const {
return identity_test_env_adaptor_->identity_test_env()
->identity_manager()
->HasPrimaryAccount(signin::ConsentLevel::kSignin);
}
OptimizationGuideKeyedService* GetOptimizationGuideKeyedService(
Profile* profile = nullptr) {
if (!profile) {
profile = browser()->profile();
}
return OptimizationGuideKeyedServiceFactory::GetForProfile(profile);
}
// Executes the model for the feature, waits until the response is received,
// and returns the response.
void ExecuteModel(UserVisibleFeatureKey feature,
const proto::ComposeRequest& request_metadata,
Profile* profile = nullptr) {
if (!profile) {
profile = browser()->profile();
}
base::RunLoop run_loop;
ExecuteModelWithLogging(
GetOptimizationGuideKeyedService(profile),
ToModelBasedCapabilityKey(feature), request_metadata,
/*execution_timeout=*/std::nullopt,
base::BindOnce(&ModelExecutionBrowserTestBase::OnModelExecutionResponse,
base::Unretained(this), run_loop.QuitClosure()));
run_loop.Run();
}
OnDeviceModelEligibilityReason GetOnDeviceModelEligibility(
ModelBasedCapabilityKey feature,
Profile* profile = nullptr) {
return GetOptimizationGuideKeyedService(profile)
->GetOnDeviceModelEligibility(feature);
}
void SetExpectedBearerAccessToken(
const std::string& expected_bearer_access_token) {
expected_bearer_access_token_ = expected_bearer_access_token;
}
void SetResponseType(ModelExecutionRemoteResponseType response_type) {
response_type_ = response_type;
}
void SetMetricsConsent(bool consent) {
scoped_metrics_consent_.emplace(consent);
}
void WaitForModelQualityLogsUpload(int expected_num_logs_requests) {
while (num_logs_requests_ < expected_num_logs_requests) {
base::RunLoop run_loop;
base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), base::Milliseconds(100));
run_loop.Run();
}
EXPECT_EQ(num_logs_requests_, expected_num_logs_requests);
}
protected:
void OnModelExecutionResponse(
base::OnceClosure on_model_execution_closure,
OptimizationGuideModelExecutionResult result,
std::unique_ptr<proto::ComposeLoggingData> logging_data) {
ModelQualityLogsUploaderService* logs_uploader =
GetOptimizationGuideKeyedService()
->GetModelQualityLogsUploaderService();
base::WeakPtr<ModelQualityLogsUploaderService> logs_uploader_weak_ptr;
if (logs_uploader) {
logs_uploader_weak_ptr = logs_uploader->GetWeakPtr();
}
auto log_entry =
std::make_unique<ModelQualityLogEntry>(logs_uploader_weak_ptr);
*log_entry->log_ai_data_request()->mutable_compose() = *logging_data;
if (result.response.has_value() ||
result.response.error().error() ==
OptimizationGuideModelExecutionError::ModelExecutionError::
kFiltered ||
result.response.error().error() ==
OptimizationGuideModelExecutionError::ModelExecutionError::
kUnsupportedLanguage) {
EXPECT_TRUE(logging_data->has_request());
}
if (result.response.has_value()) {
EXPECT_TRUE(logging_data->has_response());
}
model_execution_result_.emplace(std::move(result));
ModelQualityLogEntry::Upload(std::move(log_entry));
std::move(on_model_execution_closure).Run();
}
std::unique_ptr<net::test_server::HttpResponse>
HandleGetModelExecutionRequest(const net::test_server::HttpRequest& request) {
auto response = std::make_unique<net::test_server::BasicHttpResponse>();
EXPECT_EQ(request.method, net::test_server::METHOD_POST);
EXPECT_NE(request.headers.end(), request.headers.find("X-Client-Data"));
// Access token should be set.
EXPECT_TRUE(base::Contains(request.headers,
net::HttpRequestHeaders::kAuthorization));
EXPECT_EQ(expected_bearer_access_token_,
request.headers.at(net::HttpRequestHeaders::kAuthorization));
if (response_type_ == ModelExecutionRemoteResponseType::kSuccessful) {
std::string serialized_response;
proto::ExecuteResponse execute_response =
BuildComposeResponse("foo response");
execute_response.SerializeToString(&serialized_response);
response->set_code(net::HTTP_OK);
response->set_content(serialized_response);
} else if (response_type_ ==
ModelExecutionRemoteResponseType::kUnsuccessful) {
response->set_code(net::HTTP_NOT_FOUND);
} else if (response_type_ == ModelExecutionRemoteResponseType::kMalformed) {
response->set_code(net::HTTP_OK);
response->set_content("Not a proto");
} else if (response_type_ ==
ModelExecutionRemoteResponseType::kErrorFiltered) {
std::string serialized_response;
proto::ExecuteResponse execute_response = BuildTestErrorExecuteResponse(
proto::ErrorState::ERROR_STATE_FILTERED);
execute_response.SerializeToString(&serialized_response);
response->set_code(net::HTTP_OK);
response->set_content(serialized_response);
} else if (response_type_ ==
ModelExecutionRemoteResponseType::kUnsupportedLanguage) {
std::string serialized_response;
proto::ExecuteResponse execute_response = BuildTestErrorExecuteResponse(
proto::ErrorState::ERROR_STATE_UNSUPPORTED_LANGUAGE);
execute_response.SerializeToString(&serialized_response);
response->set_code(net::HTTP_OK);
response->set_content(serialized_response);
} else {
NOTREACHED();
}
return std::move(response);
}
std::unique_ptr<net::test_server::HttpResponse>
HandleGetModelQualityLogsUploadRequest(
const net::test_server::HttpRequest& request) {
auto response = std::make_unique<net::test_server::BasicHttpResponse>();
EXPECT_EQ(request.method, net::test_server::METHOD_POST);
EXPECT_NE(request.headers.end(), request.headers.find("X-Client-Data"));
// Access token should not be set.
EXPECT_FALSE(base::Contains(request.headers,
net::HttpRequestHeaders::kAuthorization));
std::string serialized_response;
response->set_code(net::HTTP_OK);
response->set_content(serialized_response);
num_logs_requests_++;
return std::move(response);
}
// Virtualize for testing different feature configurations.
virtual void InitializeFeatureList() {}
base::test::ScopedFeatureList scoped_feature_list_;
std::unique_ptr<net::EmbeddedTestServer> model_execution_server_;
std::unique_ptr<net::EmbeddedTestServer> model_quality_logs_server_;
base::HistogramTester histogram_tester_;
ModelExecutionRemoteResponseType response_type_ =
ModelExecutionRemoteResponseType::kSuccessful;
// The last model execution response received.
std::optional<OptimizationGuideModelExecutionResult> model_execution_result_;
// Identity test support.
std::unique_ptr<IdentityTestEnvironmentProfileAdaptor>
identity_test_env_adaptor_;
std::optional<ScopedSetMetricsConsent> scoped_metrics_consent_;
// The expected authorization header holding the bearer access token.
std::string expected_bearer_access_token_;
// The number of requests received by the model quality logs server.
std::atomic<int> num_logs_requests_ = 0;
};
class ModelExecutionDisabledBrowserTest : public ModelExecutionBrowserTestBase {
void InitializeFeatureList() override {
scoped_feature_list_.InitAndDisableFeature(
features::kOptimizationGuideModelExecution);
}
};
IN_PROC_BROWSER_TEST_F(ModelExecutionDisabledBrowserTest,
ModelExecutionDisabled) {
proto::ComposeRequest request;
request.mutable_generate_params()->set_user_input("a user typed this");
ExecuteModel(UserVisibleFeatureKey::kCompose, request);
EXPECT_TRUE(model_execution_result_.has_value());
EXPECT_FALSE(model_execution_result_->response.has_value());
EXPECT_EQ(OptimizationGuideModelExecutionError::ModelExecutionError::
kGenericFailure,
model_execution_result_->response.error().error());
EXPECT_TRUE(model_execution_result_->response.error().transient());
}
IN_PROC_BROWSER_TEST_F(ModelExecutionDisabledBrowserTest,
GetOnDeviceModelEligibilityExecutionDisabled) {
EXPECT_EQ(GetOnDeviceModelEligibility(ModelBasedCapabilityKey::kCompose),
OnDeviceModelEligibilityReason::kFeatureNotEnabled);
}
IN_PROC_BROWSER_TEST_F(
ModelExecutionDisabledBrowserTest,
GetOnDeviceModelEligibilityExecutionDisabledNullDebugReason) {
EXPECT_NE(GetOnDeviceModelEligibility(ModelBasedCapabilityKey::kCompose),
OnDeviceModelEligibilityReason::kSuccess);
}
class ModelExecutionEnabledOnDeviceDisabledBrowserTest
: public ModelExecutionBrowserTestBase {
void InitializeFeatureList() override {
scoped_feature_list_.InitWithFeatures(
{features::kOptimizationGuideModelExecution,
features::kModelQualityLogging},
{features::kOptimizationGuideOnDeviceModel});
}
};
IN_PROC_BROWSER_TEST_F(ModelExecutionEnabledOnDeviceDisabledBrowserTest,
GetOnDeviceModelEligibilityOnDeviceDisabled) {
EXPECT_EQ(GetOnDeviceModelEligibility(ModelBasedCapabilityKey::kCompose),
OnDeviceModelEligibilityReason::kFeatureNotEnabled);
}
IN_PROC_BROWSER_TEST_F(
ModelExecutionEnabledOnDeviceDisabledBrowserTest,
GetOnDeviceModelEligibilityExecutionDisabledNullDebugReason) {
EXPECT_NE(GetOnDeviceModelEligibility(ModelBasedCapabilityKey::kCompose),
OnDeviceModelEligibilityReason::kSuccess);
}
class ModelExecutionEnabledBrowserTest : public ModelExecutionBrowserTestBase {
public:
void InitializeFeatureList() override {
scoped_feature_list_.InitWithFeatures(
{features::kOptimizationGuideModelExecution,
features::kModelQualityLogging,
features::kOptimizationGuideOnDeviceModel},
{});
}
OptimizationGuideKeyedService* GetOptGuideKeyedService() {
return OptimizationGuideKeyedServiceFactory::GetForProfile(
browser()->profile());
}
bool IsSettingVisible(UserVisibleFeatureKey feature) {
return GetOptGuideKeyedService()->IsSettingVisible(feature);
}
bool ShouldFeatureBeCurrentlyEnabledForUser(UserVisibleFeatureKey feature) {
return GetOptGuideKeyedService()
->model_execution_features_controller_
->ShouldFeatureBeCurrentlyEnabledForUser(feature);
}
bool ShouldFeatureBeCurrentlyAllowedForLogging(
proto::LogAiDataRequest::FeatureCase feature) {
const MqlsFeatureMetadata* metadata =
MqlsFeatureRegistry::GetInstance().GetFeature(feature);
return GetOptGuideKeyedService()
->model_execution_features_controller_
->ShouldFeatureBeCurrentlyAllowedForLogging(metadata);
}
};
IN_PROC_BROWSER_TEST_F(ModelExecutionEnabledBrowserTest,
ModelExecutionDisabledInIncognito) {
Browser* otr_browser = CreateIncognitoBrowser(browser()->profile());
proto::ComposeRequest request;
request.mutable_generate_params()->set_user_input("a user typed this");
ExecuteModel(UserVisibleFeatureKey::kCompose, request,
otr_browser->profile());
EXPECT_TRUE(model_execution_result_.has_value());
EXPECT_FALSE(model_execution_result_->response.has_value());
EXPECT_EQ(OptimizationGuideModelExecutionError::ModelExecutionError::
kPermissionDenied,
model_execution_result_->response.error().error());
EXPECT_FALSE(model_execution_result_->response.error().transient());
// The logs shouldn't be uploaded because model execution is disabled for
// incognito and we wouldn't be receiving any log entry.
histogram_tester_.ExpectTotalCount(
"OptimizationGuide.ModelQualityLogsUploaderService.UploadStatus", 0);
}
IN_PROC_BROWSER_TEST_F(ModelExecutionEnabledBrowserTest,
ModelExecutionFailsNoUserSignIn) {
proto::ComposeRequest request;
request.mutable_generate_params()->set_user_input("a user typed this");
ExecuteModel(UserVisibleFeatureKey::kCompose, request);
EXPECT_TRUE(model_execution_result_.has_value());
EXPECT_FALSE(model_execution_result_->response.has_value());
EXPECT_EQ(OptimizationGuideModelExecutionError::ModelExecutionError::
kPermissionDenied,
model_execution_result_->response.error().error());
EXPECT_FALSE(model_execution_result_->response.error().transient());
// The logs shouldn't be uploaded because model execution is denied without
// user signin, also model quality logs.
histogram_tester_.ExpectTotalCount(
"OptimizationGuide.ModelQualityLogsUploaderService.UploadStatus", 0);
}
IN_PROC_BROWSER_TEST_F(ModelExecutionEnabledBrowserTest,
ModelExecutionSuccess_WithoutMetricsConsent) {
EnableSignin();
SetMetricsConsent(false);
SetExpectedBearerAccessToken("Bearer access_token");
proto::ComposeRequest request;
request.mutable_generate_params()->set_user_input("a user typed this");
ExecuteModel(UserVisibleFeatureKey::kCompose, request);
EXPECT_TRUE(model_execution_result_.has_value());
EXPECT_TRUE(model_execution_result_->response.has_value());
auto response = ParsedAnyMetadata<proto::ComposeResponse>(
model_execution_result_->response.value());
EXPECT_EQ("foo response", response->output());
// The logs shouldn't be uploaded because there is no metrics consent.
histogram_tester_.ExpectUniqueSample(
"OptimizationGuide.ModelQualityLogsUploaderService.UploadStatus.Compose",
ModelQualityLogsUploadStatus::kMetricsReportingDisabled, 1);
}
IN_PROC_BROWSER_TEST_F(ModelExecutionEnabledBrowserTest,
ModelExecutionSuccess_WithMetricsConsent) {
EnableSignin();
SetMetricsConsent(true);
SetExpectedBearerAccessToken("Bearer access_token");
proto::ComposeRequest request;
request.mutable_generate_params()->set_user_input("a user typed this");
ExecuteModel(UserVisibleFeatureKey::kCompose, request);
EXPECT_TRUE(model_execution_result_.has_value());
EXPECT_TRUE(model_execution_result_->response.has_value());
auto response = ParsedAnyMetadata<proto::ComposeResponse>(
model_execution_result_->response.value());
EXPECT_EQ("foo response", response->output());
WaitForModelQualityLogsUpload(1);
histogram_tester_.ExpectUniqueSample(
"OptimizationGuide.ModelQualityLogsUploaderService.UploadStatus.Compose",
ModelQualityLogsUploadStatus::kUploadSuccessful, 1);
}
IN_PROC_BROWSER_TEST_F(ModelExecutionEnabledBrowserTest,
ModelExecutionFailsForUnsuccessfulResponse) {
EnableSignin();
SetExpectedBearerAccessToken("Bearer access_token");
SetResponseType(ModelExecutionRemoteResponseType::kUnsuccessful);
// Enable metrics consent for logging.
SetMetricsConsent(true);
ASSERT_TRUE(
g_browser_process->GetMetricsServicesManager()->IsMetricsConsentGiven());
proto::ComposeRequest request;
request.mutable_generate_params()->set_user_input("a user typed this");
ExecuteModel(UserVisibleFeatureKey::kCompose, request);
EXPECT_TRUE(model_execution_result_.has_value());
EXPECT_FALSE(model_execution_result_->response.has_value());
EXPECT_EQ(OptimizationGuideModelExecutionError::ModelExecutionError::
kGenericFailure,
model_execution_result_->response.error().error());
EXPECT_TRUE(model_execution_result_->response.error().transient());
// The logs shouldn't be uploaded when model execution fails for unsuccessful
// response.
histogram_tester_.ExpectTotalCount(
"OptimizationGuide.ModelQualityLogsUploaderService.UploadStatus", 0);
}
IN_PROC_BROWSER_TEST_F(ModelExecutionEnabledBrowserTest,
ModelExecutionFailsForMalformedResponse) {
EnableSignin();
SetExpectedBearerAccessToken("Bearer access_token");
SetResponseType(ModelExecutionRemoteResponseType::kMalformed);
proto::ComposeRequest request;
request.mutable_generate_params()->set_user_input("a user typed this");
ExecuteModel(UserVisibleFeatureKey::kCompose, request);
EXPECT_TRUE(model_execution_result_.has_value());
EXPECT_FALSE(model_execution_result_->response.has_value());
EXPECT_EQ(OptimizationGuideModelExecutionError::ModelExecutionError::
kGenericFailure,
model_execution_result_->response.error().error());
EXPECT_TRUE(model_execution_result_->response.error().transient());
}
IN_PROC_BROWSER_TEST_F(ModelExecutionEnabledBrowserTest,
ModelExecutionFailsForErrorFilteredResponse) {
EnableSignin();
SetExpectedBearerAccessToken("Bearer access_token");
SetResponseType(ModelExecutionRemoteResponseType::kErrorFiltered);
proto::ComposeRequest request;
request.mutable_generate_params()->set_user_input("a user typed this");
ExecuteModel(UserVisibleFeatureKey::kCompose, request);
EXPECT_TRUE(model_execution_result_.has_value());
EXPECT_FALSE(model_execution_result_->response.has_value());
EXPECT_EQ(
OptimizationGuideModelExecutionError::ModelExecutionError::kFiltered,
model_execution_result_->response.error().error());
}
IN_PROC_BROWSER_TEST_F(ModelExecutionEnabledBrowserTest,
ModelExecutionFailsForUnsupportedLanguageResponse) {
EnableSignin();
auto* prefs = browser()->profile()->GetPrefs();
prefs->SetInteger(
prefs::GetSettingEnabledPrefName(UserVisibleFeatureKey::kCompose),
static_cast<int>(prefs::FeatureOptInState::kEnabled));
SetExpectedBearerAccessToken("Bearer access_token");
SetResponseType(ModelExecutionRemoteResponseType::kUnsupportedLanguage);
// Enable metrics consent for logging.
SetMetricsConsent(true);
ASSERT_TRUE(
g_browser_process->GetMetricsServicesManager()->IsMetricsConsentGiven());
proto::ComposeRequest request;
request.mutable_generate_params()->set_user_input("a user typed this");
ExecuteModel(UserVisibleFeatureKey::kCompose, request);
EXPECT_TRUE(model_execution_result_.has_value());
EXPECT_FALSE(model_execution_result_->response.has_value());
EXPECT_EQ(OptimizationGuideModelExecutionError::ModelExecutionError::
kUnsupportedLanguage,
model_execution_result_->response.error().error());
// There should be no error-status reports about log uploading (we don't try
// to upload logs in this test, so there's no success report either).
histogram_tester_.ExpectTotalCount(
"OptimizationGuide.ModelQualityLogsUploaderService.UploadStatus.Compose",
0);
}
// TODO(crbug.com/388544208): Flaky on linux-win-cross-rel.
#if BUILDFLAG(IS_WIN)
#define MAYBE_GetOnDeviceModelEligibilityModelNotEligible \
DISABLED_GetOnDeviceModelEligibilityModelNotEligible
#else
#define MAYBE_GetOnDeviceModelEligibilityModelNotEligible \
GetOnDeviceModelEligibilityModelNotEligible
#endif
IN_PROC_BROWSER_TEST_F(ModelExecutionEnabledBrowserTest,
MAYBE_GetOnDeviceModelEligibilityModelNotEligible) {
EXPECT_EQ(GetOnDeviceModelEligibility(ModelBasedCapabilityKey::kCompose),
OnDeviceModelEligibilityReason::kModelNotEligible);
}
IN_PROC_BROWSER_TEST_F(
ModelExecutionEnabledBrowserTest,
GetOnDeviceModelEligibilityExecutionDisabledNullDebugReason) {
EXPECT_NE(GetOnDeviceModelEligibility(ModelBasedCapabilityKey::kCompose),
OnDeviceModelEligibilityReason::kSuccess);
}
class OnDeviceModelExecutionEnabledBrowserTest
: public ModelExecutionEnabledBrowserTest {
public:
void InitializeFeatureList() override {
scoped_feature_list_.InitWithFeaturesAndParameters(
{{features::kOptimizationGuideModelExecution, {}},
{features::kModelQualityLogging, {}},
{features::kOptimizationGuideOnDeviceModel, {}},
{features::kOnDeviceModelPerformanceParams,
{{"compatible_on_device_performance_classes", "*"}}}},
{});
}
void SetUpGlobalAssets() {
model_execution::prefs::RecordFeatureUsage(
g_browser_process->local_state(), ModelBasedCapabilityKey::kCompose);
base_model_asset_.SetReadyIn(
*OnDeviceModelComponentStateManager::GetInstanceForTesting());
}
// Set up assets which are registered per-profile.
void SetUpProfileAssets() {
compose_asset_.SendTo(
*ChromeOnDeviceModelServiceController::GetSingleInstanceMayBeNull());
}
private:
optimization_guide::FakeBaseModelAsset base_model_asset_;
FakeAdaptationAsset compose_asset_{{
.config =
[]() {
proto::OnDeviceModelExecutionFeatureConfig config;
config.set_feature(proto::MODEL_EXECUTION_FEATURE_COMPOSE);
config.set_can_skip_text_safety(true);
auto* params = config.mutable_sampling_params();
params->set_top_k(kTestDefaultTopK);
params->set_temperature(kTestDefaultTemperature);
return config;
}(),
}};
};
IN_PROC_BROWSER_TEST_F(OnDeviceModelExecutionEnabledBrowserTest,
GetOnDeviceModelEligibilityInRegularProfile) {
SetUpGlobalAssets();
SetUpProfileAssets();
ASSERT_TRUE(base::test::RunUntil([&]() {
return GetOnDeviceModelEligibility(ModelBasedCapabilityKey::kCompose,
nullptr) ==
OnDeviceModelEligibilityReason::kSuccess;
})) << "Timeout waiting for model to be marked eligible.";
}
IN_PROC_BROWSER_TEST_F(OnDeviceModelExecutionEnabledBrowserTest,
GetOnDeviceModelEligibilityInIncognito) {
SetUpGlobalAssets();
Browser* otr_browser = CreateIncognitoBrowser();
SetUpProfileAssets();
ASSERT_TRUE(base::test::RunUntil([&]() {
return GetOnDeviceModelEligibility(ModelBasedCapabilityKey::kCompose,
otr_browser->profile()) ==
OnDeviceModelEligibilityReason::kSuccess;
})) << "Timeout waiting for model to be marked eligible.";
}
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
// Guest profile only available in some platforms.
IN_PROC_BROWSER_TEST_F(OnDeviceModelExecutionEnabledBrowserTest,
GetOnDeviceModelEligibilityInGuestProfile) {
SetUpGlobalAssets();
Browser* guest_browser = CreateGuestBrowser();
SetUpProfileAssets();
ASSERT_TRUE(base::test::RunUntil([&]() {
return GetOnDeviceModelEligibility(ModelBasedCapabilityKey::kCompose,
guest_browser->profile()) ==
OnDeviceModelEligibilityReason::kSuccess;
})) << "Timeout waiting for model to be marked eligible.";
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(OnDeviceModelExecutionEnabledBrowserTest,
GetSamplingParamsConfig) {
SetUpGlobalAssets();
SetUpProfileAssets();
ASSERT_TRUE(base::test::RunUntil([&]() {
return GetOnDeviceModelEligibility(ModelBasedCapabilityKey::kCompose,
nullptr) ==
OnDeviceModelEligibilityReason::kSuccess;
})) << "Timeout waiting for model to be marked eligible.";
auto sampling_config =
GetOptimizationGuideKeyedService()->GetSamplingParamsConfig(
ModelBasedCapabilityKey::kCompose);
EXPECT_EQ(sampling_config->default_top_k, kTestDefaultTopK);
EXPECT_EQ(sampling_config->default_temperature, kTestDefaultTemperature);
}
class ModelExecutionInternalsPageBrowserTest
: public ModelExecutionEnabledBrowserTest {
public:
void SetUpCommandLine(base::CommandLine* cmd) override {
ModelExecutionEnabledBrowserTest::SetUpCommandLine(cmd);
cmd->AppendSwitch(switches::kDebugLoggingEnabled);
}
void CheckInternalsLog(std::string_view message) {
auto* logger =
GetOptimizationGuideKeyedService()->GetOptimizationGuideLogger();
EXPECT_THAT(logger->recent_log_messages_,
testing::Contains(testing::Field(
&OptimizationGuideLogger::LogMessage::message,
testing::HasSubstr(message))));
}
};
IN_PROC_BROWSER_TEST_F(ModelExecutionInternalsPageBrowserTest,
LoggedInInternalsPage) {
EnableSignin();
SetExpectedBearerAccessToken("Bearer access_token");
proto::ComposeRequest request;
request.mutable_generate_params()->set_user_input("foo");
ExecuteModel(UserVisibleFeatureKey::kCompose, request);
EXPECT_TRUE(model_execution_result_.has_value());
EXPECT_TRUE(model_execution_result_->response.has_value());
CheckInternalsLog("ExecuteModel");
// CheckInternalsLog("TabOrganization Request");
CheckInternalsLog("OnModelExecutionResponse");
}
class ModelExecutionEnabledBrowserTestWithExplicitBrowserSignin
: public ModelExecutionEnabledBrowserTest {
public:
void InitializeFeatureList() override {
scoped_feature_list_.InitWithFeatures(
{features::internal::kHistorySearchSettingsVisibility},
{features::internal::kTabOrganizationGraduated});
}
};
IN_PROC_BROWSER_TEST_F(
ModelExecutionEnabledBrowserTestWithExplicitBrowserSignin,
PRE_EnableFeatureViaPref) {
EnableSignin();
auto* prefs = browser()->profile()->GetPrefs();
prefs->SetInteger(
prefs::GetSettingEnabledPrefName(UserVisibleFeatureKey::kWallpaperSearch),
static_cast<int>(prefs::FeatureOptInState::kEnabled));
prefs->SetInteger(
prefs::GetSettingEnabledPrefName(UserVisibleFeatureKey::kTabOrganization),
static_cast<int>(prefs::FeatureOptInState::kDisabled));
histogram_tester_.ExpectUniqueSample(
"OptimizationGuide.ModelExecution.FeatureEnabledAtStartup.Compose", false,
1);
histogram_tester_.ExpectUniqueSample(
"OptimizationGuide.ModelExecution.FeatureEnabledAtStartup."
"TabOrganization",
false, 1);
histogram_tester_.ExpectUniqueSample(
"OptimizationGuide.ModelExecution.FeatureEnabledAtStartup."
"WallpaperSearch",
false, 1);
histogram_tester_.ExpectTotalCount(
"OptimizationGuide.ModelExecution.FeatureEnabledAtSettingsChange.Compose",
0);
histogram_tester_.ExpectUniqueSample(
"OptimizationGuide.ModelExecution.FeatureEnabledAtSettingsChange."
"TabOrganization",
false, 1);
histogram_tester_.ExpectUniqueSample(
"OptimizationGuide.ModelExecution.FeatureEnabledAtSettingsChange."
"WallpaperSearch",
true, 1);
}
IN_PROC_BROWSER_TEST_F(
ModelExecutionEnabledBrowserTestWithExplicitBrowserSignin,
EnableFeatureViaPref) {
#if !BUILDFLAG(IS_CHROMEOS)
EXPECT_TRUE(IsSignedIn());
#endif
histogram_tester_.ExpectUniqueSample(
"OptimizationGuide.ModelExecution.FeatureEnabledAtStartup.Compose", false,
1);
histogram_tester_.ExpectUniqueSample(
"OptimizationGuide.ModelExecution.FeatureEnabledAtStartup."
"TabOrganization",
false, 1);
histogram_tester_.ExpectUniqueSample(
"OptimizationGuide.ModelExecution.FeatureEnabledAtStartup."
"WallpaperSearch",
false, 1);
histogram_tester_.ExpectTotalCount(
"OptimizationGuide.ModelExecution.FeatureEnabledAtSettingsChange.Compose",
0);
histogram_tester_.ExpectTotalCount(
"OptimizationGuide.ModelExecution.FeatureEnabledAtSettingsChange."
"TabOrganization",
0);
histogram_tester_.ExpectTotalCount(
"OptimizationGuide.ModelExecution.FeatureEnabledAtSettingsChange."
"WallpaperSearch",
0);
}
IN_PROC_BROWSER_TEST_F(
ModelExecutionEnabledBrowserTestWithExplicitBrowserSignin,
PRE_HistorySearchRecordsSyntheticFieldTrial) {
EnableSignin();
#if BUILDFLAG(BUILD_TFLITE_WITH_XNNPACK)
EXPECT_TRUE(IsSettingVisible(UserVisibleFeatureKey::kHistorySearch));
#else
EXPECT_FALSE(IsSettingVisible(UserVisibleFeatureKey::kHistorySearch));
#endif
browser()->profile()->GetPrefs()->SetInteger(
prefs::GetSettingEnabledPrefName(UserVisibleFeatureKey::kHistorySearch),
static_cast<int>(prefs::FeatureOptInState::kEnabled));
EXPECT_TRUE(variations::IsInSyntheticTrialGroup(
"SyntheticModelExecutionFeatureHistorySearch", "Disabled"));
}
IN_PROC_BROWSER_TEST_F(
ModelExecutionEnabledBrowserTestWithExplicitBrowserSignin,
HistorySearchRecordsSyntheticFieldTrial) {
#if !BUILDFLAG(IS_CHROMEOS)
EXPECT_TRUE(IsSignedIn());
#endif
EXPECT_TRUE(ShouldFeatureBeCurrentlyEnabledForUser(
UserVisibleFeatureKey::kHistorySearch));
EXPECT_TRUE(variations::IsInSyntheticTrialGroup(
"SyntheticModelExecutionFeatureHistorySearch", "Enabled"));
}
class ModelExecutionComposeLoggingDisabledTest
: public ModelExecutionEnabledBrowserTest {
public:
void InitializeFeatureList() override {
scoped_feature_list_.InitWithFeaturesAndParameters(
{{features::kOptimizationGuideModelExecution, {}},
{features::kModelQualityLogging, {}}},
{features::kComposeMqlsLogging});
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_F(ModelExecutionComposeLoggingDisabledTest,
LoggingForFeatureNotEnabled) {
EnableSignin();
SetExpectedBearerAccessToken("Bearer access_token");
// Enable metrics consent for logging.
SetMetricsConsent(true);
ASSERT_TRUE(
g_browser_process->GetMetricsServicesManager()->IsMetricsConsentGiven());
proto::ComposeRequest request;
request.mutable_generate_params()->set_user_input("a user typed this");
ExecuteModel(UserVisibleFeatureKey::kCompose, request);
EXPECT_TRUE(model_execution_result_.has_value());
EXPECT_TRUE(model_execution_result_->response.has_value());
auto response = ParsedAnyMetadata<proto::ComposeResponse>(
model_execution_result_->response.value());
EXPECT_EQ("foo response", response->output());
// The logs shouldn't be uploaded because the feature is not enabled for
// logging.
histogram_tester_.ExpectUniqueSample(
"OptimizationGuide.ModelQualityLogsUploaderService.UploadStatus.Compose",
ModelQualityLogsUploadStatus::kLoggingNotEnabled, 1);
}
class ModelExecutionNewFeaturesEnabledAutomaticallyTest
: public ModelExecutionEnabledBrowserTest {
public:
void InitializeFeatureList() override {
std::vector<base::test::FeatureRefAndParams> enabled_features = {
{features::kOptimizationGuideModelExecution, {}},
{features::internal::kTabOrganizationSettingsVisibility, {}}};
std::vector<base::test::FeatureRef> disabled_features = {
features::internal::kTabOrganizationGraduated,
features::internal::kComposeGraduated};
std::string test_name =
::testing::UnitTest::GetInstance()->current_test_info()->name();
// Make the new feature visible in the second start of the test.
if (!base::StartsWith(test_name, "PRE_")) {
enabled_features.push_back(
{features::internal::kComposeSettingsVisibility, {}});
enabled_features.push_back(
{features::internal::kHistorySearchSettingsVisibility,
{{"enable_feature_when_main_toggle_on", "false"}}});
} else {
disabled_features.push_back(
features::internal::kHistorySearchSettingsVisibility);
}
scoped_feature_list_.InitWithFeaturesAndParameters(enabled_features,
disabled_features);
}
};
#if !BUILDFLAG(IS_ANDROID)
class ModelExecutionEnterprisePolicyBrowserTest
: public ModelExecutionEnabledBrowserTest,
public ::testing::WithParamInterface<bool> {
public:
void SetUp() override {
policy_provider_.SetDefaultReturns(
/*is_initialization_complete_return=*/true,
/*is_first_policy_load_complete_return=*/true);
policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
&policy_provider_);
ModelExecutionEnabledBrowserTest::SetUp();
}
void InitializeFeatureList() override {
std::vector<base::test::FeatureRef> enabled_features = {
features::kOptimizationGuideModelExecution,
features::kModelQualityLogging,
features::internal::kTabOrganizationSettingsVisibility,
features::internal::kWallpaperSearchSettingsVisibility};
std::vector<base::test::FeatureRef> disabled_features = {
features::internal::kComposeGraduated,
features::internal::kComposeSettingsVisibility,
features::internal::kTabOrganizationGraduated,
features::internal::kWallpaperSearchGraduated};
if (ShowEnterpriseDisabledFeatures()) {
enabled_features.push_back(features::kAiSettingsPageEnterpriseDisabledUi);
} else {
disabled_features.push_back(
features::kAiSettingsPageEnterpriseDisabledUi);
}
scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
}
bool ShowEnterpriseDisabledFeatures() { return GetParam(); }
protected:
testing::NiceMock<policy::MockConfigurationPolicyProvider> policy_provider_;
};
IN_PROC_BROWSER_TEST_P(ModelExecutionEnterprisePolicyBrowserTest,
DisableThenEnable) {
EnableSignin();
auto* prefs = browser()->profile()->GetPrefs();
prefs->SetInteger(
prefs::GetSettingEnabledPrefName(UserVisibleFeatureKey::kTabOrganization),
static_cast<int>(prefs::FeatureOptInState::kEnabled));
base::RunLoop().RunUntilIdle();
// Default policy value allows the feature.
EXPECT_TRUE(IsSettingVisible(UserVisibleFeatureKey::kTabOrganization));
EXPECT_TRUE(ShouldFeatureBeCurrentlyEnabledForUser(
UserVisibleFeatureKey::kTabOrganization));
EXPECT_TRUE(ShouldFeatureBeCurrentlyAllowedForLogging(
proto::LogAiDataRequest::FeatureCase::kTabOrganization));
EXPECT_FALSE(IsSettingVisible(UserVisibleFeatureKey::kCompose));
EXPECT_TRUE(ShouldFeatureBeCurrentlyAllowedForLogging(
proto::LogAiDataRequest::FeatureCase::kCompose));
// Disable via the enterprise policy.
policy::PolicyMap policies;
policies.Set(policy::key::kTabOrganizerSettings,
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
policy::POLICY_SOURCE_CLOUD,
base::Value(static_cast<int>(
model_execution::prefs::ModelExecutionEnterprisePolicyValue::
kDisable)),
nullptr);
policy_provider_.UpdateChromePolicy(policies);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(ShowEnterpriseDisabledFeatures(),
IsSettingVisible(UserVisibleFeatureKey::kTabOrganization));
EXPECT_FALSE(ShouldFeatureBeCurrentlyEnabledForUser(
UserVisibleFeatureKey::kTabOrganization));
EXPECT_FALSE(IsSettingVisible(UserVisibleFeatureKey::kCompose));
EXPECT_TRUE(ShouldFeatureBeCurrentlyAllowedForLogging(
proto::LogAiDataRequest::FeatureCase::kCompose));
EXPECT_FALSE(ShouldFeatureBeCurrentlyAllowedForLogging(
proto::LogAiDataRequest::FeatureCase::kTabOrganization));
// Enable via the enterprise policy.
policies.Set(
policy::key::kTabOrganizerSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(static_cast<int>(
model_execution::prefs::ModelExecutionEnterprisePolicyValue::kAllow)),
nullptr);
policy_provider_.UpdateChromePolicy(policies);
prefs->SetInteger(
prefs::GetSettingEnabledPrefName(UserVisibleFeatureKey::kTabOrganization),
static_cast<int>(prefs::FeatureOptInState::kEnabled));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(IsSettingVisible(UserVisibleFeatureKey::kTabOrganization));
EXPECT_TRUE(ShouldFeatureBeCurrentlyEnabledForUser(
UserVisibleFeatureKey::kTabOrganization));
EXPECT_TRUE(ShouldFeatureBeCurrentlyAllowedForLogging(
proto::LogAiDataRequest::FeatureCase::kTabOrganization));
EXPECT_FALSE(IsSettingVisible(UserVisibleFeatureKey::kCompose));
EXPECT_TRUE(ShouldFeatureBeCurrentlyAllowedForLogging(
proto::LogAiDataRequest::FeatureCase::kCompose));
}
IN_PROC_BROWSER_TEST_P(ModelExecutionEnterprisePolicyBrowserTest,
DisableThenEnableCompose) {
EnableSignin();
SetExpectedBearerAccessToken("Bearer access_token");
SetResponseType(ModelExecutionRemoteResponseType::kUnsupportedLanguage);
// Enable metrics consent for logging.
SetMetricsConsent(true);
ASSERT_TRUE(
g_browser_process->GetMetricsServicesManager()->IsMetricsConsentGiven());
auto* prefs = browser()->profile()->GetPrefs();
prefs->SetInteger(
prefs::GetSettingEnabledPrefName(UserVisibleFeatureKey::kCompose),
static_cast<int>(prefs::FeatureOptInState::kEnabled));
base::RunLoop().RunUntilIdle();
// Default policy value allows the feature.
EXPECT_TRUE(IsSettingVisible(UserVisibleFeatureKey::kCompose));
EXPECT_TRUE(
ShouldFeatureBeCurrentlyEnabledForUser(UserVisibleFeatureKey::kCompose));
// Disable via the enterprise policy.
policy::PolicyMap policies;
policies.Set(policy::key::kHelpMeWriteSettings,
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
policy::POLICY_SOURCE_CLOUD,
base::Value(static_cast<int>(
model_execution::prefs::ModelExecutionEnterprisePolicyValue::
kDisable)),
nullptr);
policy_provider_.UpdateChromePolicy(policies);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(IsSettingVisible(UserVisibleFeatureKey::kCompose));
EXPECT_FALSE(
ShouldFeatureBeCurrentlyEnabledForUser(UserVisibleFeatureKey::kCompose));
proto::ComposeRequest request_1;
request_1.mutable_generate_params()->set_user_input("a user typed this");
ExecuteModel(UserVisibleFeatureKey::kCompose, request_1);
// As the feature is fully disabled by enterprise policy, logs should also be
// disabled.
histogram_tester_.ExpectUniqueSample(
"OptimizationGuide.ModelQualityLogsUploaderService.UploadStatus.Compose",
optimization_guide::ModelQualityLogsUploadStatus::
kDisabledDueToEnterprisePolicy,
1);
// Enable via the enterprise policy and check upload.
policies.Set(
policy::key::kHelpMeWriteSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(static_cast<int>(
model_execution::prefs::ModelExecutionEnterprisePolicyValue::kAllow)),
nullptr);
policy_provider_.UpdateChromePolicy(policies);
prefs->SetInteger(
prefs::GetSettingEnabledPrefName(UserVisibleFeatureKey::kCompose),
static_cast<int>(optimization_guide::prefs::FeatureOptInState::kEnabled));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(IsSettingVisible(UserVisibleFeatureKey::kCompose));
EXPECT_TRUE(
ShouldFeatureBeCurrentlyEnabledForUser(UserVisibleFeatureKey::kCompose));
proto::ComposeRequest request_2;
request_2.mutable_generate_params()->set_user_input("a user typed this");
ExecuteModel(UserVisibleFeatureKey::kCompose, request_2);
// No new blocked logs samples should have been recorded.
histogram_tester_.ExpectUniqueSample(
"OptimizationGuide.ModelQualityLogsUploaderService.UploadStatus.Compose",
optimization_guide::ModelQualityLogsUploadStatus::
kDisabledDueToEnterprisePolicy,
1);
}
IN_PROC_BROWSER_TEST_P(ModelExecutionEnterprisePolicyBrowserTest,
EnableComposeWithoutLogging) {
EnableSignin();
SetExpectedBearerAccessToken("Bearer access_token");
SetResponseType(ModelExecutionRemoteResponseType::kUnsupportedLanguage);
// Enable metrics consent for logging.
SetMetricsConsent(true);
ASSERT_TRUE(
g_browser_process->GetMetricsServicesManager()->IsMetricsConsentGiven());
auto* prefs = browser()->profile()->GetPrefs();
prefs->SetInteger(
prefs::GetSettingEnabledPrefName(UserVisibleFeatureKey::kCompose),
static_cast<int>(optimization_guide::prefs::FeatureOptInState::kEnabled));
base::RunLoop().RunUntilIdle();
// Enable without logging via the enterprise policy.
policy::PolicyMap policies;
policies.Set(policy::key::kHelpMeWriteSettings,
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
policy::POLICY_SOURCE_CLOUD,
base::Value(static_cast<int>(
model_execution::prefs::ModelExecutionEnterprisePolicyValue::
kAllowWithoutLogging)),
nullptr);
policy_provider_.UpdateChromePolicy(policies);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(IsSettingVisible(UserVisibleFeatureKey::kCompose));
EXPECT_TRUE(
ShouldFeatureBeCurrentlyEnabledForUser(UserVisibleFeatureKey::kCompose));
proto::ComposeRequest request_1;
request_1.mutable_generate_params()->set_user_input("a user typed this");
ExecuteModel(UserVisibleFeatureKey::kCompose, request_1);
// The logs should be disabled via enterprise policy.
histogram_tester_.ExpectUniqueSample(
"OptimizationGuide.ModelQualityLogsUploaderService.UploadStatus.Compose",
ModelQualityLogsUploadStatus::kDisabledDueToEnterprisePolicy, 1);
// Enable via the enterprise policy and check upload.
policies.Set(
policy::key::kHelpMeWriteSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(static_cast<int>(
model_execution::prefs::ModelExecutionEnterprisePolicyValue::kAllow)),
nullptr);
policy_provider_.UpdateChromePolicy(policies);
prefs->SetInteger(
prefs::GetSettingEnabledPrefName(UserVisibleFeatureKey::kCompose),
static_cast<int>(prefs::FeatureOptInState::kEnabled));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(IsSettingVisible(UserVisibleFeatureKey::kCompose));
EXPECT_TRUE(
ShouldFeatureBeCurrentlyEnabledForUser(UserVisibleFeatureKey::kCompose));
proto::ComposeRequest request_2;
request_2.mutable_generate_params()->set_user_input("a user typed this");
ExecuteModel(UserVisibleFeatureKey::kCompose, request_2);
// No new blocked logs samples should have been recorded.
histogram_tester_.ExpectUniqueSample(
"OptimizationGuide.ModelQualityLogsUploaderService.UploadStatus.Compose",
optimization_guide::ModelQualityLogsUploadStatus::
kDisabledDueToEnterprisePolicy,
1);
}
IN_PROC_BROWSER_TEST_P(ModelExecutionEnterprisePolicyBrowserTest,
DisableThenEnableWallpaperSearch) {
EnableSignin();
auto* prefs = browser()->profile()->GetPrefs();
prefs->SetInteger(
prefs::GetSettingEnabledPrefName(UserVisibleFeatureKey::kWallpaperSearch),
static_cast<int>(prefs::FeatureOptInState::kEnabled));
base::RunLoop().RunUntilIdle();
// Default policy value allows the feature.
EXPECT_TRUE(IsSettingVisible(UserVisibleFeatureKey::kWallpaperSearch));
EXPECT_TRUE(ShouldFeatureBeCurrentlyEnabledForUser(
UserVisibleFeatureKey::kWallpaperSearch));
// Disable via the enterprise policy.
policy::PolicyMap policies;
policies.Set(policy::key::kCreateThemesSettings,
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
policy::POLICY_SOURCE_CLOUD,
base::Value(static_cast<int>(
model_execution::prefs::ModelExecutionEnterprisePolicyValue::
kDisable)),
nullptr);
policy_provider_.UpdateChromePolicy(policies);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(ShowEnterpriseDisabledFeatures(),
IsSettingVisible(UserVisibleFeatureKey::kWallpaperSearch));
EXPECT_FALSE(ShouldFeatureBeCurrentlyEnabledForUser(
UserVisibleFeatureKey::kWallpaperSearch));
// Enable via the enterprise policy.
policies.Set(
policy::key::kCreateThemesSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(static_cast<int>(
model_execution::prefs::ModelExecutionEnterprisePolicyValue::kAllow)),
nullptr);
policy_provider_.UpdateChromePolicy(policies);
prefs->SetInteger(
prefs::GetSettingEnabledPrefName(UserVisibleFeatureKey::kWallpaperSearch),
static_cast<int>(prefs::FeatureOptInState::kEnabled));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(IsSettingVisible(UserVisibleFeatureKey::kWallpaperSearch));
EXPECT_TRUE(ShouldFeatureBeCurrentlyEnabledForUser(
UserVisibleFeatureKey::kWallpaperSearch));
}
IN_PROC_BROWSER_TEST_P(ModelExecutionEnterprisePolicyBrowserTest,
EnableTabOrganizationWithoutLogging) {
EnableSignin();
auto* prefs = browser()->profile()->GetPrefs();
prefs->SetInteger(
prefs::GetSettingEnabledPrefName(UserVisibleFeatureKey::kTabOrganization),
static_cast<int>(prefs::FeatureOptInState::kEnabled));
base::RunLoop().RunUntilIdle();
// EnableWithoutLogging via the enterprise policy.
policy::PolicyMap policies;
policies.Set(policy::key::kTabOrganizerSettings,
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
policy::POLICY_SOURCE_CLOUD,
base::Value(static_cast<int>(
model_execution::prefs::ModelExecutionEnterprisePolicyValue::
kAllowWithoutLogging)),
nullptr);
policy_provider_.UpdateChromePolicy(policies);
prefs->SetInteger(
prefs::GetSettingEnabledPrefName(UserVisibleFeatureKey::kTabOrganization),
static_cast<int>(prefs::FeatureOptInState::kEnabled));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(IsSettingVisible(UserVisibleFeatureKey::kTabOrganization));
EXPECT_TRUE(ShouldFeatureBeCurrentlyEnabledForUser(
UserVisibleFeatureKey::kTabOrganization));
EXPECT_FALSE(ShouldFeatureBeCurrentlyAllowedForLogging(
proto::LogAiDataRequest::FeatureCase::kTabOrganization));
EXPECT_FALSE(IsSettingVisible(UserVisibleFeatureKey::kCompose));
EXPECT_TRUE(ShouldFeatureBeCurrentlyAllowedForLogging(
proto::LogAiDataRequest::FeatureCase::kCompose));
}
INSTANTIATE_TEST_SUITE_P(,
ModelExecutionEnterprisePolicyBrowserTest,
::testing::Bool());
#endif // !BUILDFLAG(IS_ANDROID)
} // namespace optimization_guide