blob: cd504a1021848aee7d803ba9222301488eb08361 [file] [log] [blame]
// Copyright 2024 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/ai/ai_data_keyed_service.h"
#include <memory>
#include <string>
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/test_future.h"
#include "build/build_config.h"
#include "chrome/browser/actor/actor_keyed_service.h"
#include "chrome/browser/actor/actor_switches.h"
#include "chrome/browser/actor/actor_test_util.h"
#include "chrome/browser/actor/browser_action_util.h"
#include "chrome/browser/actor/shared_types.h"
#include "chrome/browser/actor/tools/click_tool_request.h"
#include "chrome/browser/actor/tools/navigate_tool_request.h"
#include "chrome/browser/ai/ai_data_keyed_service_factory.h"
#include "chrome/browser/history_embeddings/history_embeddings_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/tabs/public/tab_features.h"
#include "chrome/browser/ui/tabs/tab_group_model.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/web_applications/isolated_web_apps/test/isolated_web_app_builder.h"
#include "chrome/common/buildflags.h"
#include "chrome/common/chrome_features.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
#include "components/autofill/core/browser/foundations/autofill_manager.h"
#include "components/autofill/core/browser/foundations/test_autofill_manager_waiter.h"
#include "components/autofill/core/browser/test_utils/autofill_form_test_utils.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_test_utils.h"
#include "components/autofill/core/common/form_data.h"
#include "components/history_embeddings/mock_answerer.h"
#include "components/history_embeddings/mock_intent_classifier.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/optimization_guide/content/browser/page_content_proto_provider.h"
#include "components/optimization_guide/proto/features/actions_data.pb.h"
#include "components/optimization_guide/proto/features/common_quality_data.pb.h"
#include "components/passage_embeddings/passage_embeddings_test_util.h"
#include "components/tabs/public/tab_group.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.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_frame_navigation_observer.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/request_handler_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
using ::base::test::TestFuture;
using ::optimization_guide::DocumentIdentifierUserData;
using ::optimization_guide::proto::ClickAction;
using ::testing::ReturnRef;
using AiData = AiDataKeyedService::AiData;
using AiDataSpecifier = AiDataKeyedService::AiDataSpecifier;
class AiDataKeyedServiceBrowserTest : public InProcessBrowserTest {
public:
AiDataKeyedServiceBrowserTest() = default;
AiDataKeyedServiceBrowserTest(const AiDataKeyedServiceBrowserTest&) = delete;
AiDataKeyedServiceBrowserTest& operator=(
const AiDataKeyedServiceBrowserTest&) = delete;
~AiDataKeyedServiceBrowserTest() override = default;
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
https_server_->AddDefaultHandlers(GetChromeTestDataDir());
ASSERT_TRUE(https_server_->Start());
HistoryEmbeddingsServiceFactory::GetInstance()->SetTestingFactory(
browser()->profile(),
base::BindLambdaForTesting([this](content::BrowserContext* context) {
return HistoryEmbeddingsServiceFactory::
BuildServiceInstanceForBrowserContextForTesting(
context,
passage_embeddings_test_env_.embedder_metadata_provider(),
passage_embeddings_test_env_.embedder(),
std::make_unique<history_embeddings::MockAnswerer>(),
std::make_unique<history_embeddings::MockIntentClassifier>());
}));
}
AiDataKeyedService& ai_data_service() {
return *AiDataKeyedServiceFactory::GetAiDataKeyedService(
browser()->profile());
}
actor::ActorKeyedService& actor_service() {
return *actor::ActorKeyedService::Get(browser()->profile());
}
content::WebContents* web_contents() {
return browser()->tab_strip_model()->GetActiveWebContents();
}
void LoadPage(const GURL& url) {
content::NavigateToURLBlockUntilNavigationsComplete(web_contents(), url, 1);
content::WaitForCopyableViewInWebContents(
browser()->tab_strip_model()->GetActiveWebContents());
}
void LoadSimplePage() { LoadPage(https_server_->GetURL("/simple.html")); }
AiData QueryAiData() {
base::test::TestFuture<AiData> ai_data;
ai_data_service().GetAiData(1, web_contents(), "", ai_data.GetCallback(),
1);
return ai_data.Get();
}
AiData QueryAiDataWithSpecifier(AiDataSpecifier specifier) {
base::test::TestFuture<AiData> ai_data;
ai_data_service().GetAiDataWithSpecifier(
web_contents(), std::move(specifier), ai_data.GetCallback());
return ai_data.Get();
}
AiData LoadSimplePageAndData() {
LoadSimplePage();
return QueryAiData();
}
AiData LoadSimplePageAndDataWithSpecifier(AiDataSpecifier specifier) {
LoadSimplePage();
return QueryAiDataWithSpecifier(std::move(specifier));
}
net::EmbeddedTestServer* https_server() { return https_server_.get(); }
private:
autofill::test::AutofillBrowserTestEnvironment autofill_test_environment_;
passage_embeddings::TestEnvironment passage_embeddings_test_env_;
std::unique_ptr<net::EmbeddedTestServer> https_server_ =
std::make_unique<net::EmbeddedTestServer>(
net::EmbeddedTestServer::TYPE_HTTPS);
};
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest,
AllowlistedExtensionListData) {
std::vector<std::string> expected_allowlisted_extensions = {
"hpkopmikdojpadgmioifjjodbmnjjjca", "bgbpcgpcobgjpnpiginpidndjpggappi",
"eefninhhiifgcimjkmkongegpoaikmhm", "fjhpgileahdpnmfmaggobehbipojhlce",
"abdciamfdmknaeggbnmafmbdfdmhfgfa", "fiamdfnbelfkjlacoaeiclobkdmckaoa"};
for (const auto& extension_id : expected_allowlisted_extensions) {
EXPECT_TRUE(
AiDataKeyedService::IsExtensionAllowlistedForData(extension_id));
}
}
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest,
AllowlistedExtensionListActions) {
std::vector<std::string> expected_allowlisted_extensions = {};
for (const auto& extension_id : expected_allowlisted_extensions) {
EXPECT_TRUE(
AiDataKeyedService::IsExtensionAllowlistedForActions(extension_id));
}
std::vector<std::string> expected_not_allowlisted_extensions = {
"hpkopmikdojpadgmioifjjodbmnjjjca", "bgbpcgpcobgjpnpiginpidndjpggappi",
"eefninhhiifgcimjkmkongegpoaikmhm", "fjhpgileahdpnmfmaggobehbipojhlce",
"abdciamfdmknaeggbnmafmbdfdmhfgfa", "fiamdfnbelfkjlacoaeiclobkdmckaoa"};
for (const auto& extension_id : expected_not_allowlisted_extensions) {
EXPECT_FALSE(
AiDataKeyedService::IsExtensionAllowlistedForActions(extension_id));
}
}
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest, GetsData) {
EXPECT_TRUE(LoadSimplePageAndData().has_value());
}
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest, InnerText) {
AiData ai_data = LoadSimplePageAndData();
ASSERT_TRUE(ai_data.has_value());
EXPECT_EQ(ai_data->page_context().inner_text(), "Non empty simple page");
}
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest, InnerTextOffset) {
AiData ai_data = LoadSimplePageAndData();
ASSERT_TRUE(ai_data.has_value());
EXPECT_EQ(ai_data->page_context().inner_text_offset(), 0u);
}
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest, Title) {
AiData ai_data = LoadSimplePageAndData();
ASSERT_TRUE(ai_data.has_value());
EXPECT_EQ(ai_data->page_context().title(), "OK");
}
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest, Url) {
AiData ai_data = LoadSimplePageAndData();
ASSERT_TRUE(ai_data.has_value());
EXPECT_NE(ai_data->page_context().url().find("simple"), std::string::npos);
}
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest,
EmptyHistoryResultWithEmptyQueryString) {
AiDataSpecifier specifier;
auto* history_query_specifiers =
specifier.mutable_browser_data_collection_specifier()
->mutable_history_query_specifiers();
history_query_specifiers->add_history_queries()->set_query("");
AiData ai_data = LoadSimplePageAndDataWithSpecifier(std::move(specifier));
ASSERT_TRUE(ai_data.has_value());
EXPECT_TRUE(ai_data->history_query_result().empty());
}
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest, AxTreeUpdate) {
AiData ai_data = LoadSimplePageAndData();
ASSERT_TRUE(ai_data.has_value());
// If there are nodes and the titles is correct, then the AX tree is filled
// out.
EXPECT_GT(ai_data->page_context().ax_tree_data().nodes().size(), 0);
EXPECT_EQ(ai_data->page_context().ax_tree_data().tree_data().title(), "OK");
}
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest, TabData) {
chrome::AddTabAt(browser(), GURL("foo.com"), -1, false);
chrome::AddTabAt(browser(), GURL("bar.com"), -1, false);
auto* tab_group1 = browser()->GetTabStripModel()->group_model()->GetTabGroup(
browser()->GetTabStripModel()->AddToNewGroup({0}));
auto vis_data1 = *tab_group1->visual_data();
vis_data1.SetTitle(u"ok");
browser()->GetTabStripModel()->ChangeTabGroupVisuals(tab_group1->id(),
vis_data1);
auto* tab_group2 = browser()->GetTabStripModel()->group_model()->GetTabGroup(
browser()->GetTabStripModel()->AddToNewGroup({1, 2}));
auto vis_data2 = *tab_group1->visual_data();
vis_data2.SetTitle(u"ok");
browser()->GetTabStripModel()->ChangeTabGroupVisuals(tab_group2->id(),
vis_data2);
AiData ai_data = LoadSimplePageAndData();
ASSERT_TRUE(ai_data.has_value());
EXPECT_EQ(ai_data->active_tab_id(), 0);
EXPECT_EQ(ai_data->tabs().size(), 3);
EXPECT_EQ(ai_data->pre_existing_tab_groups().size(), 2);
}
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest, TabInnerText) {
chrome::AddTabAt(browser(), GURL("foo.com"), -1, false);
chrome::AddTabAt(browser(), GURL("bar.com"), -1, false);
auto* tab_group1 = browser()->GetTabStripModel()->group_model()->GetTabGroup(
browser()->GetTabStripModel()->AddToNewGroup({0}));
auto vis_data1 = *tab_group1->visual_data();
vis_data1.SetTitle(u"ok");
browser()->GetTabStripModel()->ChangeTabGroupVisuals(tab_group1->id(),
vis_data1);
auto* tab_group2 = browser()->GetTabStripModel()->group_model()->GetTabGroup(
browser()->GetTabStripModel()->AddToNewGroup({1, 2}));
auto vis_data2 = *tab_group1->visual_data();
vis_data2.SetTitle(u"ok");
browser()->GetTabStripModel()->ChangeTabGroupVisuals(tab_group2->id(),
vis_data2);
AiData ai_data = LoadSimplePageAndData();
ASSERT_TRUE(ai_data.has_value());
EXPECT_EQ(ai_data->active_tab_id(), 0);
for (const auto& tab_in_proto : ai_data->tabs()) {
if (tab_in_proto.tab_id() == 0) {
EXPECT_EQ(tab_in_proto.title(), "OK");
EXPECT_NE(tab_in_proto.url().find("simple"), std::string::npos);
EXPECT_EQ(tab_in_proto.page_context().inner_text(),
"Non empty simple page");
}
}
}
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest, TabInnerTextLimit) {
LoadSimplePageAndData();
chrome::AddTabAt(browser(), GURL("bar.com"), -1, true);
AiData ai_data = LoadSimplePageAndData();
ASSERT_TRUE(ai_data.has_value());
EXPECT_EQ(ai_data->active_tab_id(), 1);
for (auto& tab : ai_data->tabs()) {
if (tab.tab_id() == 0) {
EXPECT_EQ(tab.page_context().inner_text(), "Non empty simple page");
}
if (tab.tab_id() == 1) {
EXPECT_EQ(tab.page_context().inner_text(), "");
}
}
}
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest, Screenshot) {
AiData ai_data = LoadSimplePageAndData();
ASSERT_TRUE(ai_data.has_value());
content::RequestFrame(web_contents());
EXPECT_NE(ai_data->page_context().tab_screenshot(), "");
}
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest, SiteEngagementScores) {
AiData ai_data = LoadSimplePageAndData();
ASSERT_TRUE(ai_data.has_value());
EXPECT_EQ(ai_data->site_engagement().entries().size(), 1);
EXPECT_NE(ai_data->site_engagement().entries()[0].url(), "");
EXPECT_GE(ai_data->site_engagement().entries()[0].score(), 0);
}
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest, AIPageContent) {
LoadPage(
https_server()->GetURL("/optimization_guide/actionable_elements.html"));
AiData ai_data = QueryAiData();
ASSERT_TRUE(ai_data.has_value());
{
const auto& page_content = ai_data->page_context().annotated_page_content();
EXPECT_EQ(page_content.version(),
optimization_guide::proto::ANNOTATED_PAGE_CONTENT_VERSION_1_0);
const auto& content_attributes =
page_content.root_node().content_attributes();
EXPECT_EQ(content_attributes.attribute_type(),
optimization_guide::proto::CONTENT_ATTRIBUTE_ROOT);
EXPECT_FALSE(content_attributes.has_interaction_info());
EXPECT_EQ(page_content.root_node().children_nodes().size(), 0);
}
{
const auto& page_content = ai_data->action_annotated_page_content();
EXPECT_EQ(page_content.version(),
optimization_guide::proto::
ANNOTATED_PAGE_CONTENT_VERSION_ONLY_ACTIONABLE_ELEMENTS_1_0);
const auto& content_attributes =
page_content.root_node().content_attributes();
EXPECT_EQ(content_attributes.attribute_type(),
optimization_guide::proto::CONTENT_ATTRIBUTE_ROOT);
EXPECT_TRUE(content_attributes.has_interaction_info());
EXPECT_FALSE(content_attributes.interaction_info().is_clickable());
const auto& html = page_content.root_node().children_nodes().at(0);
const auto& body = html.children_nodes().at(0);
ASSERT_EQ(body.children_nodes().size(), 1);
const auto& child = body.children_nodes().at(0);
EXPECT_TRUE(child.content_attributes().has_interaction_info());
EXPECT_TRUE(child.content_attributes().interaction_info().is_clickable());
}
}
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest, SpecifierOn) {
AiDataSpecifier specifier;
auto* browser_specifier =
specifier.mutable_browser_data_collection_specifier();
auto* foreground_tab_specifier =
browser_specifier->mutable_foreground_tab_page_context_specifier();
foreground_tab_specifier->set_inner_text(true);
foreground_tab_specifier->set_tab_screenshot(true);
foreground_tab_specifier->set_ax_tree(true);
foreground_tab_specifier->set_pdf_data(true);
auto* general_tabs_specifier =
browser_specifier->mutable_tabs_context_specifier()
->mutable_general_tab_specifier();
general_tabs_specifier->mutable_page_context_specifier()->set_inner_text(
true);
general_tabs_specifier->set_tab_limit(2);
browser_specifier->set_site_engagement(true);
browser_specifier->set_tab_groups(true);
AiData ai_data = LoadSimplePageAndDataWithSpecifier(std::move(specifier));
ASSERT_TRUE(ai_data.has_value());
EXPECT_NE(ai_data->page_context().tab_screenshot(), "");
const auto& page_content = ai_data->page_context().annotated_page_content();
const auto& content_attributes =
page_content.root_node().content_attributes();
EXPECT_EQ(content_attributes.attribute_type(),
optimization_guide::proto::CONTENT_ATTRIBUTE_ROOT);
EXPECT_EQ(ai_data->site_engagement().entries().size(), 1);
EXPECT_NE(ai_data->site_engagement().entries()[0].url(), "");
EXPECT_GE(ai_data->site_engagement().entries()[0].score(), 0);
}
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest, SpecifierOff) {
AiDataSpecifier specifier;
AiData ai_data = LoadSimplePageAndDataWithSpecifier(std::move(specifier));
ASSERT_TRUE(ai_data.has_value());
EXPECT_EQ(ai_data->page_context().tab_screenshot(), "");
EXPECT_EQ(ai_data->page_context().inner_text(), "");
EXPECT_EQ(ai_data->site_engagement().entries().size(), 0);
EXPECT_TRUE(ai_data->history_query_result().empty());
}
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTest,
GetFormDataByFieldGlobalIdForModelPrototyping) {
// Simulate loading `expected_form`.
LoadSimplePage();
autofill::ContentAutofillDriver* driver =
autofill::ContentAutofillDriver::GetForRenderFrameHost(
web_contents()->GetPrimaryMainFrame());
const autofill::FormData expected_form = autofill::test::GetFormData(
{.fields = {{.label = u"Field 1"}, {.label = u"Field 2"}}});
ASSERT_TRUE(driver);
autofill::TestAutofillManagerSingleEventWaiter wait_for_forms_seen(
driver->GetAutofillManager(),
&autofill::AutofillManager::Observer::OnAfterFormsSeen,
testing::ElementsAre(expected_form.global_id()), testing::IsEmpty());
driver->GetAutofillManager().OnFormsSeen(/*updated_forms=*/{expected_form},
/*removed_forms=*/{});
ASSERT_TRUE(std::move(wait_for_forms_seen).Wait());
// Query the API for `expected_form`'s first field.
AiDataKeyedService::AiDataSpecifier specifier;
auto* global_id = specifier.mutable_browser_data_collection_specifier()
->mutable_foreground_tab_page_context_specifier()
->mutable_field_global_id();
global_id->set_frame_token(
expected_form.fields()[0].global_id().frame_token->ToString());
global_id->set_renderer_id(
expected_form.fields()[0].global_id().renderer_id.value());
AiData ai_data = QueryAiDataWithSpecifier(std::move(specifier));
// Expect that the result matches `expected_form`.
ASSERT_TRUE(ai_data.has_value());
ASSERT_TRUE(ai_data->has_form_data());
const optimization_guide::proto::FormData& actual_form = ai_data->form_data();
ASSERT_EQ(actual_form.fields_size(), 2);
EXPECT_EQ(actual_form.fields(0).field_label(),
base::UTF16ToUTF8(expected_form.fields()[0].label()));
EXPECT_EQ(actual_form.fields(1).field_label(),
base::UTF16ToUTF8(expected_form.fields()[1].label()));
}
#endif
class AiDataKeyedServiceBrowserTestWithBlocklistedExtensions
: public AiDataKeyedServiceBrowserTest {
public:
~AiDataKeyedServiceBrowserTestWithBlocklistedExtensions() override = default;
AiDataKeyedServiceBrowserTestWithBlocklistedExtensions() {
scoped_feature_list_.InitAndEnableFeatureWithParameters(
AiDataKeyedService::GetAllowlistedAiDataExtensionsFeatureForTesting(),
{{"blocked_extension_ids", "hpkopmikdojpadgmioifjjodbmnjjjca"}});
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTestWithBlocklistedExtensions,
BlockedExtensionList) {
std::vector<std::string> expected_allowlisted_extensions = {
"bgbpcgpcobgjpnpiginpidndjpggappi", "eefninhhiifgcimjkmkongegpoaikmhm",
"fjhpgileahdpnmfmaggobehbipojhlce", "abdciamfdmknaeggbnmafmbdfdmhfgfa",
"fiamdfnbelfkjlacoaeiclobkdmckaoa"};
EXPECT_FALSE(AiDataKeyedService::IsExtensionAllowlistedForData(
"hpkopmikdojpadgmioifjjodbmnjjjca"));
for (const auto& extension : expected_allowlisted_extensions) {
EXPECT_TRUE(AiDataKeyedService::IsExtensionAllowlistedForData(extension));
}
}
class AiDataKeyedServiceBrowserTestWithRemotelyAllowlistedExtensions
: public AiDataKeyedServiceBrowserTest {
public:
~AiDataKeyedServiceBrowserTestWithRemotelyAllowlistedExtensions() override =
default;
AiDataKeyedServiceBrowserTestWithRemotelyAllowlistedExtensions() {
scoped_feature_list_.InitAndEnableFeatureWithParameters(
AiDataKeyedService::GetAllowlistedAiDataExtensionsFeatureForTesting(),
{{"allowlisted_extension_ids", "1234"}});
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_F(
AiDataKeyedServiceBrowserTestWithRemotelyAllowlistedExtensions,
RemotelyAllowlistedExtensionList) {
std::vector<std::string> expected_allowlisted_extensions = {
"1234",
"hpkopmikdojpadgmioifjjodbmnjjjca",
"bgbpcgpcobgjpnpiginpidndjpggappi",
"eefninhhiifgcimjkmkongegpoaikmhm",
"fjhpgileahdpnmfmaggobehbipojhlce",
"abdciamfdmknaeggbnmafmbdfdmhfgfa",
"fiamdfnbelfkjlacoaeiclobkdmckaoa"};
for (const auto& extension : expected_allowlisted_extensions) {
EXPECT_TRUE(AiDataKeyedService::IsExtensionAllowlistedForData(extension));
}
}
class AiDataKeyedServiceBrowserTestWithAllowAndBlock
: public AiDataKeyedServiceBrowserTest {
public:
~AiDataKeyedServiceBrowserTestWithAllowAndBlock() override = default;
AiDataKeyedServiceBrowserTestWithAllowAndBlock() {
scoped_feature_list_.InitAndEnableFeatureWithParameters(
AiDataKeyedService::GetAllowlistedAiDataExtensionsFeatureForTesting(),
{{"allowlisted_extension_ids", "1234"},
{"blocked_extension_ids", "1234"}});
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceBrowserTestWithAllowAndBlock,
AllowAndBlock) {
EXPECT_FALSE(AiDataKeyedService::IsExtensionAllowlistedForData("1234"));
}
#if BUILDFLAG(ENABLE_GLIC)
class AiDataKeyedServiceActorBrowserTest
: public AiDataKeyedServiceBrowserTest {
public:
~AiDataKeyedServiceActorBrowserTest() override = default;
AiDataKeyedServiceActorBrowserTest() {
scoped_feature_list_.InitWithFeatures({features::kGlicActor}, {});
}
void SetUpCommandLine(base::CommandLine* command_line) override {
AiDataKeyedServiceBrowserTest::SetUpCommandLine(command_line);
command_line->AppendSwitch(actor::switches::kDisableActorSafetyChecks);
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
// TODO(crbug.com/411462297): Move these actor tests into an actor-specific test
// suite.
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceActorBrowserTest, StartStopTask) {
int id = 1;
actor::TaskId task_id = actor_service().CreateTask();
EXPECT_EQ(task_id.value(), id);
actor_service().StopTask(task_id, /*success=*/true);
id++;
task_id = actor_service().CreateTask();
EXPECT_EQ(task_id.value(), id);
}
// TODO(crbug.com/439247740): Fails on Win ASan.
#if BUILDFLAG(IS_WIN) && defined(ADDRESS_SANITIZER)
#define MAYBE_StartNavigateStopTask DISABLED_StartNavigateStopTask
#else
#define MAYBE_StartNavigateStopTask StartNavigateStopTask
#endif
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceActorBrowserTest,
MAYBE_StartNavigateStopTask) {
int id = 1;
actor::TaskId task_id = actor_service().CreateTask();
EXPECT_EQ(task_id.value(), id);
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
int tab_id = browser()->GetActiveTabInterface()->GetHandle().raw_value();
auto navigate_callback =
[&run_loop, &id,
&tab_id](optimization_guide::proto::BrowserActionResult response) {
EXPECT_EQ(response.task_id(), id);
EXPECT_EQ(response.tab_id(), tab_id);
// TODO(crbug.com/441556978): This test used to check for observations
// but due to JPEGCodec failures (on Linux Wayland, maybe elsewhere),
// this causes observations to be empty.
run_loop->Quit();
};
std::unique_ptr<actor::ToolRequest> action_request =
std::make_unique<actor::NavigateToolRequest>(
tabs::TabHandle(tab_id), GURL("https://www.google.com"));
actor_service().ExecuteAction(
actor::TaskId(id), actor::ToRequestList(action_request),
base::BindLambdaForTesting(std::move(navigate_callback)));
run_loop->Run();
EXPECT_EQ(web_contents()->GetURL(), GURL("https://www.google.com"));
actor_service().StopTask(actor::TaskId(id), /*success=*/true);
id++;
task_id = actor_service().CreateTask();
EXPECT_EQ(task_id.value(), id);
}
// TODO(crbug.com/439247740): Fails on Win ASan.
#if BUILDFLAG(IS_WIN) && defined(ADDRESS_SANITIZER)
#define MAYBE_ForceSameTabNavigation DISABLED_ForceSameTabNavigation
#else
#define MAYBE_ForceSameTabNavigation ForceSameTabNavigation
#endif
// See ExecutionEngineBrowserTest.ForceSameTabNavigation
IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceActorBrowserTest,
MAYBE_ForceSameTabNavigation) {
int id = 1;
actor::TaskId task_id = actor_service().CreateTask();
EXPECT_EQ(task_id.value(), id);
int tab_id = browser()->GetActiveTabInterface()->GetHandle().raw_value();
const GURL url = https_server()->GetURL("/actor/target_blank_links.html");
TestFuture<optimization_guide::proto::BrowserActionResult> navigate_result;
std::unique_ptr<actor::ToolRequest> action_request =
std::make_unique<actor::NavigateToolRequest>(tabs::TabHandle(tab_id),
url);
actor_service().ExecuteAction(actor::TaskId(id),
actor::ToRequestList(action_request),
navigate_result.GetCallback());
auto& navigate_response = navigate_result.Get();
EXPECT_EQ(navigate_response.task_id(), id);
EXPECT_EQ(navigate_response.tab_id(), tab_id);
std::optional<int> anchor_dom_node_id = content::GetDOMNodeId(
*web_contents()->GetPrimaryMainFrame(), "#anchorTarget");
ASSERT_TRUE(anchor_dom_node_id);
TestFuture<optimization_guide::proto::BrowserActionResult> click_result;
actor::PageTarget target = actor::DomNode{
anchor_dom_node_id.value(),
*DocumentIdentifierUserData::GetDocumentIdentifier(
web_contents()->GetPrimaryMainFrame()->GetGlobalFrameToken())};
std::unique_ptr<actor::ToolRequest> click_request =
std::make_unique<actor::ClickToolRequest>(
tabs::TabHandle(tab_id), target, actor::MouseClickType::kLeft,
actor::MouseClickCount::kSingle);
// Check specifically that it's the existing frame that navigates.
content::TestFrameNavigationObserver frame_nav_observer(
web_contents()->GetPrimaryMainFrame());
actor_service().ExecuteAction(actor::TaskId(id),
actor::ToRequestList(click_request),
click_result.GetCallback());
auto& click_response = click_result.Get();
EXPECT_EQ(click_response.task_id(), id);
EXPECT_EQ(click_response.tab_id(), id);
frame_nav_observer.Wait();
}
#endif // BUILDFLAG(ENABLE_GLIC)
} // namespace