#include "chrome/browser/compose/compose_enabling.h"
#include <vector>
#include "base/feature_list.h"
#include "base/test/gmock_expected_support.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/about_flags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/compose/chrome_compose_client.h"
#include "chrome/browser/optimization_guide/browser_test_util.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/profiles/profile.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/compose/core/browser/compose_features.h"
#include "components/optimization_guide/core/model_execution/model_execution_features.h"
#include "components/optimization_guide/core/optimization_guide_features.h"
#include "components/optimization_guide/core/optimization_guide_prefs.h"
#include "components/prefs/pref_service.h"
#include "components/signin/public/identity_manager/identity_test_utils.h"
#include "components/unified_consent/pref_names.h"
#include "components/variations/service/variations_service.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/fenced_frame_test_util.h"
#include "content/public/test/test_host_resolver.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "chromeos/constants/chromeos_features.h"
#endif
class ComposeEnablingBrowserTestBase : public InProcessBrowserTest {
public:
ComposeEnablingBrowserTestBase() = default;
void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread();
CHECK(
g_browser_process->variations_service()->OverrideStoredPermanentCountry(
"us"));
}
void TearDownOnMainThread() override {
CHECK(
g_browser_process->variations_service()->OverrideStoredPermanentCountry(
""));
InProcessBrowserTest::TearDownOnMainThread();
}
void EnableComposePreReqs() {
optimization_guide::EnableSigninAndModelExecutionCapability(
browser()->profile());
PrefService* prefs = browser()->profile()->GetPrefs();
prefs->SetBoolean(
unified_consent::prefs::kUrlKeyedAnonymizedDataCollectionEnabled, true);
EXPECT_TRUE(
base::FeatureList::IsEnabled(compose::features::kEnableCompose));
browser()->profile()->GetPrefs()->SetInteger(
optimization_guide::prefs::GetSettingEnabledPrefName(
optimization_guide::UserVisibleFeatureKey::kCompose),
static_cast<int>(
optimization_guide::prefs::FeatureOptInState::kEnabled));
}
ComposeEnabling& GetComposeEnabling() {
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
ChromeComposeClient* compose_client =
ChromeComposeClient::FromWebContents(web_contents);
return compose_client->GetComposeEnabling();
}
OptimizationGuideKeyedService* GetOptimizationGuide() {
return OptimizationGuideKeyedServiceFactory::GetForProfile(
browser()->profile());
}
protected:
base::test::ScopedFeatureList scoped_feature_list_;
};
class ComposeEnablingBrowserTest : public ComposeEnablingBrowserTestBase {
public:
ComposeEnablingBrowserTest() {
scoped_feature_list_.InitWithFeatures(
{
optimization_guide::features::kOptimizationGuideModelExecution,
optimization_guide::features::internal::kComposeSettingsVisibility,
},
{
optimization_guide::features::internal::kComposeGraduated,
#if BUILDFLAG(IS_CHROMEOS)
chromeos::features::kFeatureManagementDisableChromeCompose,
chromeos::features::kOrca,
chromeos::features::kOrcaDogfood,
#endif
});
}
};
IN_PROC_BROWSER_TEST_F(ComposeEnablingBrowserTest,
PRE_EnableComposeViaSettings) {
EnableComposePreReqs();
EXPECT_EQ(base::ok(), GetComposeEnabling().IsEnabled());
EXPECT_TRUE(GetOptimizationGuide()->ShouldFeatureBeCurrentlyEnabledForUser(
optimization_guide::UserVisibleFeatureKey::kCompose));
}
IN_PROC_BROWSER_TEST_F(ComposeEnablingBrowserTest, EnableComposeViaSettings) {
EXPECT_EQ(base::ok(), GetComposeEnabling().IsEnabled());
EXPECT_TRUE(GetOptimizationGuide()->ShouldFeatureBeCurrentlyEnabledForUser(
optimization_guide::UserVisibleFeatureKey::kCompose));
}
class GraduatedComposeEnablingBrowserTest
: public ComposeEnablingBrowserTestBase {
public:
GraduatedComposeEnablingBrowserTest() {
scoped_feature_list_.InitWithFeatures(
{
optimization_guide::features::kOptimizationGuideModelExecution,
optimization_guide::features::internal::kComposeGraduated,
},
{
optimization_guide::features::internal::kComposeSettingsVisibility,
#if BUILDFLAG(IS_CHROMEOS)
chromeos::features::kFeatureManagementDisableChromeCompose,
chromeos::features::kOrca,
chromeos::features::kOrcaDogfood,
#endif
});
}
};
IN_PROC_BROWSER_TEST_F(GraduatedComposeEnablingBrowserTest, GraduatedCompose) {
EnableComposePreReqs();
EXPECT_EQ(base::ok(), GetComposeEnabling().IsEnabled());
EXPECT_TRUE(GetOptimizationGuide()->ShouldFeatureBeCurrentlyEnabledForUser(
optimization_guide::UserVisibleFeatureKey::kCompose));
}
#if BUILDFLAG(IS_CHROMEOS)
class ComposeOnChromeOS : public ComposeEnablingBrowserTestBase {
public:
ComposeOnChromeOS() {
scoped_feature_list_.InitWithFeatures(
{
optimization_guide::features::kOptimizationGuideModelExecution,
optimization_guide::features::internal::kComposeSettingsVisibility,
#if BUILDFLAG(IS_CHROMEOS)
chromeos::features::kFeatureManagementDisableChromeCompose,
#endif
},
{
optimization_guide::features::internal::kComposeGraduated,
chromeos::features::kOrca,
chromeos::features::kOrcaDogfood,
});
}
};
IN_PROC_BROWSER_TEST_F(ComposeOnChromeOS,
PRE_ComposeDisabledOnNonEligibleCrOSDevices) {
EnableComposePreReqs();
EXPECT_EQ(base::unexpected(compose::ComposeShowStatus::kDisabledOnChromeOS),
GetComposeEnabling().IsEnabled());
}
IN_PROC_BROWSER_TEST_F(ComposeOnChromeOS,
ComposeDisabledOnNonEligibleCrOSDevices) {
EXPECT_EQ(base::unexpected(compose::ComposeShowStatus::kDisabledOnChromeOS),
GetComposeEnabling().IsEnabled());
}
class GraduatedComposeOnChromeOS : public ComposeEnablingBrowserTestBase {
public:
GraduatedComposeOnChromeOS() {
scoped_feature_list_.InitWithFeatures(
{
optimization_guide::features::kOptimizationGuideModelExecution,
optimization_guide::features::internal::kComposeGraduated,
#if BUILDFLAG(IS_CHROMEOS)
chromeos::features::kFeatureManagementDisableChromeCompose,
#endif
},
{
optimization_guide::features::internal::kComposeSettingsVisibility,
chromeos::features::kOrca,
chromeos::features::kOrcaDogfood,
});
}
};
IN_PROC_BROWSER_TEST_F(GraduatedComposeOnChromeOS,
GraduatedComposeDisabledOnNonEligibleCrOSDevices) {
EnableComposePreReqs();
EXPECT_EQ(base::unexpected(compose::ComposeShowStatus::kDisabledOnChromeOS),
GetComposeEnabling().IsEnabled());
}
#endif
class ComposeEnablingWithFencedFramesBrowserTest
: public ComposeEnablingBrowserTest {
public:
void SetUpOnMainThread() override {
ComposeEnablingBrowserTest::SetUpOnMainThread();
host_resolver()->AddRule("*", "127.0.0.1");
https_server()->ServeFilesFromSourceDirectory("content/test/data");
https_server()->SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
content::SetupCrossSiteRedirector(https_server());
net::test_server::RegisterDefaultHandlers(https_server());
ASSERT_TRUE(https_server()->Start());
}
protected:
net::EmbeddedTestServer* https_server() { return &https_server_; }
content::test::FencedFrameTestHelper& fenced_frame_test_helper() {
return fenced_frame_test_helper_;
}
private:
content::test::FencedFrameTestHelper fenced_frame_test_helper_;
net::EmbeddedTestServer https_server_{net::EmbeddedTestServer::TYPE_HTTPS};
};
IN_PROC_BROWSER_TEST_F(ComposeEnablingWithFencedFramesBrowserTest,
DisabledInFencedFrames) {
auto scoped_compose_enabled =
ComposeEnabling::ScopedEnableComposeForTesting();
GURL main_url(https_server()->GetURL(
"a.test", "/cross_site_iframe_factory.html?a.test(a.test{fenced})"));
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
content::RenderFrameHost* main_frame = web_contents->GetPrimaryMainFrame();
std::vector<content::RenderFrameHost*> child_frames =
fenced_frame_test_helper().GetChildFencedFrameHosts(main_frame);
ASSERT_EQ(child_frames.size(), 1u);
content::RenderFrameHost* fenced_child1 = child_frames[0];
auto* client = ChromeComposeClient::FromWebContents(web_contents);
content::ContextMenuParams params;
params.is_content_editable_for_autofill = true;
params.frame_origin = fenced_child1->GetLastCommittedOrigin();
EXPECT_FALSE(client->GetComposeEnabling().ShouldTriggerContextMenu(
browser()->profile(), nullptr, fenced_child1, params));
}