#include <optional>
#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/scripting/scripting_api.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ssl/https_upgrades_util.h"
#include "components/version_info/channel.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/prerender_test_util.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/api_test_utils.h"
#include "extensions/browser/background_script_executor.h"
#include "extensions/browser/disable_reason.h"
#include "extensions/browser/extension_registrar.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/script_executor.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/features/feature_channel.h"
#include "extensions/common/utils/content_script_utils.h"
#include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/result_catcher.h"
#include "extensions/test/test_extension_dir.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "pdf/buildflags.h"
#include "ui/base/window_open_disposition.h"
#include "url/gurl.h"
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/ui_test_utils.h"
#endif
#if BUILDFLAG(ENABLE_PDF)
#include "base/test/scoped_feature_list.h"
#include "pdf/pdf_features.h"
#endif
static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE));
namespace extensions {
namespace {
constexpr const char kSimulatedResourcePath[] = "/simulated-resource.html";
#if BUILDFLAG(ENABLE_EXTENSIONS)
constexpr char kGetDivIds[] =
R"(let childIds = [];
for (const child of document.body.children)
childIds.push(child.id);
JSON.stringify(childIds.sort());)";
#endif
}
class ScriptingAPITest : public ExtensionApiTest {
public:
ScriptingAPITest() = default;
ScriptingAPITest(const ScriptingAPITest&) = delete;
ScriptingAPITest& operator=(const ScriptingAPITest&) = delete;
~ScriptingAPITest() override = default;
void SetUpOnMainThread() override {
ExtensionApiTest::SetUpOnMainThread();
controllable_http_response_.emplace(embedded_test_server(),
kSimulatedResourcePath);
host_resolver()->AddRule("*", "127.0.0.1");
content::SetupCrossSiteRedirector(embedded_test_server());
ASSERT_TRUE(StartEmbeddedTestServer());
}
void OpenURLInCurrentTab(const GURL& url) {
content::WebContents* web_contents = GetActiveWebContents();
ASSERT_TRUE(web_contents);
ASSERT_TRUE(NavigateToURL(web_contents, url));
EXPECT_EQ(url, web_contents->GetLastCommittedURL());
}
void OpenURLInNewTab(const GURL& url) {
content::TestNavigationObserver nav_observer(url);
nav_observer.StartWatchingNewWebContents();
NavigateToURLInNewTab(url);
nav_observer.Wait();
auto* web_contents = GetActiveWebContents();
content::WaitForLoadStop(web_contents);
EXPECT_TRUE(nav_observer.last_navigation_succeeded());
EXPECT_EQ(url, web_contents->GetLastCommittedURL());
}
net::test_server::ControllableHttpResponse& controllable_http_response() {
return *controllable_http_response_;
}
private:
std::optional<net::test_server::ControllableHttpResponse>
controllable_http_response_;
};
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, GetContentScripts) {
ASSERT_TRUE(RunExtensionTest("scripting/get_scripts")) << message_;
}
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, MainFrameTests) {
OpenURLInCurrentTab(embedded_test_server()->GetURL(
"example.com", "/extensions/main_world_script_flag.html"));
OpenURLInNewTab(
embedded_test_server()->GetURL("chromium.org", "/title2.html"));
ASSERT_TRUE(RunExtensionTest("scripting/main_frame", {},
{.ignore_manifest_warnings = true}))
<< message_;
}
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, SubFramesTests) {
OpenURLInCurrentTab(
embedded_test_server()->GetURL("a.com", "/iframe_cross_site.html"));
OpenURLInNewTab(
embedded_test_server()->GetURL("d.com", "/iframe_cross_site.html"));
OpenURLInNewTab(
embedded_test_server()->GetURL("e.com", "/iframe_sandboxed_srcdoc.html"));
OpenURLInNewTab(
embedded_test_server()->GetURL("f.com", "/iframe_blob_url.html"));
ASSERT_TRUE(RunExtensionTest("scripting/sub_frames")) << message_;
}
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, NestedWebContents) {
OpenURLInCurrentTab(
embedded_test_server()->GetURL("a.com", "/iframe_about_blank.html"));
content::RenderFrameHost* iframe_host =
content::ChildFrameAt(GetActiveWebContents(), 0);
ASSERT_TRUE(iframe_host);
content::WebContents* inner_web_contents =
content::CreateAndAttachInnerContents(iframe_host);
EXPECT_TRUE(content::NavigateToURL(
inner_web_contents, embedded_test_server()->GetURL("/title1.html")));
ASSERT_TRUE(RunExtensionTest("scripting/nested_web_contents")) << message_;
}
#if BUILDFLAG(ENABLE_PDF)
class ScriptingAPIOopifPdfTest : public ScriptingAPITest {
public:
ScriptingAPIOopifPdfTest() {
feature_list_.InitAndEnableFeature(chrome_pdf::features::kPdfOopif);
}
private:
base::test::ScopedFeatureList feature_list_;
};
IN_PROC_BROWSER_TEST_F(ScriptingAPIOopifPdfTest, PdfFrames) {
OpenURLInCurrentTab(
embedded_test_server()->GetURL("a.com", "/page_with_embedded_pdf.html"));
ASSERT_TRUE(RunExtensionTest("scripting/pdf")) << message_;
}
#endif
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, CSSInjection) {
OpenURLInCurrentTab(
embedded_test_server()->GetURL("example.com", "/simple.html"));
OpenURLInNewTab(
embedded_test_server()->GetURL("chromium.org", "/title2.html"));
OpenURLInNewTab(embedded_test_server()->GetURL("subframes.example",
"/iframe_cross_site.html"));
OpenURLInNewTab(embedded_test_server()->GetURL(
"subframes-sandboxed.example", "/iframe_sandboxed_srcdoc.html"));
ASSERT_TRUE(RunExtensionTest("scripting/css_injection")) << message_;
}
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, CSSRemoval) {
ASSERT_TRUE(RunExtensionTest("scripting/remove_css")) << message_;
}
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, RegisterContentScripts) {
ASSERT_TRUE(RunExtensionTest("scripting/register_scripts")) << message_;
}
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, UnregisterContentScripts) {
ASSERT_TRUE(RunExtensionTest("scripting/unregister_scripts")) << message_;
}
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, UpdateContentScripts) {
ASSERT_TRUE(RunExtensionTest("scripting/update_scripts")) << message_;
}
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, DynamicContentScriptParameters) {
ScopedCurrentChannel scoped_channel(version_info::Channel::UNKNOWN);
ASSERT_TRUE(RunExtensionTest("scripting/dynamic_script_parameters"))
<< message_;
}
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, DynamicContentScriptsMainWorld) {
ASSERT_TRUE(RunExtensionTest("scripting/dynamic_scripts_main_world"))
<< message_;
}
IN_PROC_BROWSER_TEST_F(ScriptingAPITest,
RapidDynamicContentScriptRegistrationAndUnregistration) {
static constexpr char kManifest[] =
R"({
"name": "test",
"manifest_version": 3,
"version": "0.1",
"background": {"service_worker": "background.js"},
"permissions": ["scripting"],
"host_permissions": ["*://example.com/*"]
})";
static constexpr char kBackgroundJs[] =
R"(chrome.test.runTests([
async function registerScripts() {
const scripts =
[
{
id: 'script_1',
matches: ['http://example.com/*'],
js: ['script1.js'],
runAt: 'document_end',
},
{
id: 'script_2',
matches: ['http://example.com/*'],
js: ['script2.js'],
runAt: 'document_end',
}
];
// Call to register the two scripts, then immediately (before
// registration is complete) unregister script 1.
const registered =
chrome.scripting.registerContentScripts(scripts);
const unregistered =
chrome.scripting.unregisterContentScripts({ids: ['script_1']});
await Promise.allSettled([registered, unregistered]);
// Only script 2 should still be registered.
const registeredScripts =
await chrome.scripting.getRegisteredContentScripts();
chrome.test.assertEq(['script_2'],
registeredScripts.map(script => script.id));
chrome.test.succeed();
}]);)";
static constexpr char kScript1Js[] =
R"(var div = document.createElement('div');
div.id = 'injected_1';
document.body.appendChild(div);)";
static constexpr char kScript2Js[] =
R"(console.warn('injectory');var div = document.createElement('div');
div.id = 'injected_2';
document.body.appendChild(div);)";
TestExtensionDir test_dir;
test_dir.WriteManifest(kManifest);
test_dir.WriteFile(FILE_PATH_LITERAL("background.js"), kBackgroundJs);
test_dir.WriteFile(FILE_PATH_LITERAL("script1.js"), kScript1Js);
test_dir.WriteFile(FILE_PATH_LITERAL("script2.js"), kScript2Js);
ResultCatcher result_catcher;
const Extension* extension = LoadExtension(test_dir.UnpackedPath());
ASSERT_TRUE(extension);
ASSERT_TRUE(result_catcher.GetNextResult()) << result_catcher.message();
auto* web_contents = GetActiveWebContents();
const GURL url =
embedded_test_server()->GetURL("example.com", "/simple.html");
ASSERT_TRUE(NavigateToURL(web_contents, url));
content::RenderFrameHost* new_frame = web_contents->GetPrimaryMainFrame();
static constexpr char kGetInjectedIds[] =
R"(const divs = document.body.getElementsByTagName('div');
JSON.stringify(Array.from(divs).map(div => div.id));)";
EXPECT_EQ(R"(["injected_2"])", content::EvalJs(new_frame, kGetInjectedIds));
}
#if BUILDFLAG(ENABLE_EXTENSIONS)
#if defined(ADDRESS_SANITIZER)
#define MAYBE_RapidLoadUnload DISABLED_RapidLoadUnload
#else
#define MAYBE_RapidLoadUnload RapidLoadUnload
#endif
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, MAYBE_RapidLoadUnload) {
ResultCatcher result_catcher;
const Extension* extension = LoadExtension(
test_data_dir_.AppendASCII("scripting/register_one_script"));
ASSERT_TRUE(extension);
EXPECT_TRUE(result_catcher.GetNextResult()) << result_catcher.message();
DisableExtension(extension->id());
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("content_scripts/css_injection")));
extension_registrar()->EnableExtension(extension->id());
extension_registrar()->DisableExtension(
extension->id(), {disable_reason::DISABLE_USER_ACTION});
OpenURLInCurrentTab(
embedded_test_server()->GetURL("google.com", "/simple.html"));
}
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, DynamicContentScriptsSizeLimits) {
auto single_scripts_limit_reset =
script_parsing::CreateScopedMaxScriptLengthForTesting(700u);
auto extension_scripts_limit_reset =
script_parsing::CreateScopedMaxScriptsLengthPerExtensionForTesting(1200u);
ASSERT_TRUE(RunExtensionTest("scripting/dynamic_scripts_size_limits"))
<< message_;
}
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, ExecuteScriptSizeLimit) {
auto single_scripts_limit_reset =
script_parsing::CreateScopedMaxScriptLengthForTesting(700u);
ASSERT_TRUE(RunExtensionTest("scripting/execute_script_size_limit"))
<< message_;
}
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, ExecuteScriptSpecialCharacters) {
ASSERT_TRUE(RunExtensionTest("scripting/execute_script_special_characters"))
<< message_;
}
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, ExecuteScriptBeforeInitialCommit) {
constexpr char kManifest[] =
R"({
"name": "Scripting API Test",
"manifest_version": 3,
"version": "0.1",
"permissions": ["scripting", "tabs"],
"host_permissions": ["http://example.com/*"]
})";
constexpr char kArgTemplate[] =
R"([{
"target": {"tabId": %d},
"func": "() => {
document.title = 'Modified Title';
return document.title;
}"
}])";
TestExtensionDir test_dir;
test_dir.WriteManifest(kManifest);
{
GURL target_url =
embedded_test_server()->GetURL("example.com", "/simple.html");
auto execute_script_function =
base::MakeRefCounted<ScriptingExecuteScriptFunction>();
const Extension* extension = LoadExtension(test_dir.UnpackedPath());
ASSERT_TRUE(extension);
execute_script_function->set_extension(extension);
execute_script_function->set_has_callback(true);
ui_test_utils::NavigateToURLWithDisposition(
browser(), target_url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
ASSERT_TRUE(web_contents);
EXPECT_TRUE(web_contents->GetLastCommittedURL().is_empty());
EXPECT_EQ(target_url, web_contents->GetVisibleURL());
int tab_id = ExtensionTabUtil::GetTabId(web_contents);
std::string args = base::StringPrintf(kArgTemplate, tab_id);
std::optional<base::Value> result =
api_test_utils::RunFunctionAndReturnSingleResult(
execute_script_function.get(), args, profile());
ASSERT_TRUE(result);
base::Value::List& result_list = result->GetList();
ASSERT_EQ(1u, result_list.size());
const std::string* result_returned =
result_list[0].GetDict().FindString("result");
ASSERT_TRUE(result_returned);
EXPECT_EQ("Modified Title", *result_returned);
EXPECT_EQ(u"Modified Title", web_contents->GetTitle());
EXPECT_TRUE(WaitForLoadStop(web_contents));
EXPECT_EQ(target_url, web_contents->GetLastCommittedURL());
EXPECT_EQ(u"Modified Title", web_contents->GetTitle());
}
{
GURL target_url =
embedded_test_server()->GetURL("noAccess.com", "/simple.html");
auto execute_script_function =
base::MakeRefCounted<ScriptingExecuteScriptFunction>();
const Extension* extension = LoadExtension(test_dir.UnpackedPath());
ASSERT_TRUE(extension);
execute_script_function->set_extension(extension);
execute_script_function->set_has_callback(true);
ui_test_utils::NavigateToURLWithDisposition(
browser(), target_url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
ASSERT_TRUE(web_contents);
EXPECT_TRUE(web_contents->GetLastCommittedURL().is_empty());
EXPECT_EQ(target_url, web_contents->GetVisibleURL());
int tab_id = ExtensionTabUtil::GetTabId(web_contents);
std::string args = base::StringPrintf(kArgTemplate, tab_id);
std::string error(api_test_utils::RunFunctionAndReturnError(
execute_script_function.get(), args, profile()));
std::string expected_error = base::StringPrintf(
"Cannot access contents of url \"%s\". Extension manifest must request "
"permission to access this host.",
target_url.spec().c_str());
EXPECT_EQ(expected_error, error);
EXPECT_EQ(u"", web_contents->GetTitle());
EXPECT_TRUE(WaitForLoadStop(web_contents));
EXPECT_EQ(target_url, web_contents->GetLastCommittedURL());
EXPECT_EQ(u"OK", web_contents->GetTitle());
}
}
IN_PROC_BROWSER_TEST_F(ScriptingAPITest, InjectImmediately) {
static constexpr char kManifest[] =
R"({
"name": "Scripting Extension",
"manifest_version": 3,
"version": "0.1",
"background": {"service_worker": "worker.js"},
"permissions": ["scripting"],
"host_permissions": ["http://example.com/*"]
})";
static constexpr char kWorker[] = "// Intentionally blank";
TestExtensionDir test_dir;
test_dir.WriteManifest(kManifest);
test_dir.WriteFile(FILE_PATH_LITERAL("worker.js"), kWorker);
const Extension* extension = LoadExtension(test_dir.UnpackedPath());
ASSERT_TRUE(extension);
const GURL page_url =
embedded_test_server()->GetURL("example.com", kSimulatedResourcePath);
ui_test_utils::NavigateToURLWithDisposition(
browser(), page_url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
controllable_http_response().WaitForRequest();
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(web_contents->IsLoading());
const int tab_id = ExtensionTabUtil::GetTabId(web_contents);
static constexpr char kInjectScripts[] =
R"(function injectImmediate() {
return 'Immediate: ' + window.location.href;
}
function injectDefault() {
return 'Default: ' + window.location.href;
}
self.defaultResult = 'unset';
self.immediateResult = 'unset';
const target = {tabId: %d};
chrome.scripting.executeScript(
{
target: target,
func: injectDefault,
},
(results) => {
self.defaultResult = results[0].result;
chrome.test.sendMessage('default complete');
});
chrome.scripting.executeScript(
{
target: target,
func: injectImmediate,
injectImmediately: true,
},
(results) => {
self.immediateResult = results[0].result;
chrome.test.sendMessage('immediate complete');
});)";
std::string expected_immediate_result = "Immediate: " + page_url.spec();
std::string expected_default_result = "Default: " + page_url.spec();
auto run_script_in_worker = [this, extension](const std::string& script) {
return BackgroundScriptExecutor::ExecuteScript(
profile(), extension->id(), script,
BackgroundScriptExecutor::ResultCapture::kSendScriptResult);
};
auto get_default_result = [run_script_in_worker]() {
return run_script_in_worker(
"chrome.test.sendScriptResult(self.defaultResult);");
};
auto get_immediate_result = [run_script_in_worker]() {
return run_script_in_worker(
"chrome.test.sendScriptResult(self.immediateResult);");
};
controllable_http_response().Send(net::HTTP_OK, "text/html",
"<html>Hello, World!</html>");
EXPECT_TRUE(web_contents->IsLoading());
ExtensionTestMessageListener immediate_listener("immediate complete");
ExtensionTestMessageListener default_listener("default complete");
BackgroundScriptExecutor::ExecuteScriptAsync(
profile(), extension->id(), base::StringPrintf(kInjectScripts, tab_id));
ASSERT_TRUE(immediate_listener.WaitUntilSatisfied());
EXPECT_TRUE(web_contents->IsLoading());
EXPECT_FALSE(default_listener.was_satisfied());
EXPECT_EQ(base::Value("unset"), get_default_result());
EXPECT_EQ(base::Value(expected_immediate_result), get_immediate_result());
controllable_http_response().Done();
ASSERT_TRUE(content::WaitForLoadStop(web_contents));
ASSERT_TRUE(default_listener.WaitUntilSatisfied());
EXPECT_EQ(base::Value(expected_default_result), get_default_result());
EXPECT_EQ(base::Value(expected_immediate_result), get_immediate_result());
}
#endif
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(ScriptingAPITest,
PRE_DynamicContentScriptsInjectInIncognito) {
ScopedAllowHttpForHostnamesForTesting allow_http({"example.com"},
profile()->GetPrefs());
const Extension* incognito_allowed =
LoadExtension(test_data_dir_.AppendASCII("scripting/incognito_allowed"),
{.allow_in_incognito = true});
const Extension* incognito_disallowed = LoadExtension(
test_data_dir_.AppendASCII("scripting/incognito_disallowed"),
{.allow_in_incognito = false});
ASSERT_TRUE(incognito_allowed);
ASSERT_TRUE(incognito_disallowed);
auto register_scripts = [this](const ExtensionId& extension_id) {
ResultCatcher result_catcher;
BackgroundScriptExecutor::ExecuteScriptAsync(profile(), extension_id,
"registerScript();");
ASSERT_TRUE(result_catcher.GetNextResult()) << result_catcher.message();
};
register_scripts(incognito_allowed->id());
register_scripts(incognito_disallowed->id());
auto* web_contents = GetActiveWebContents();
const GURL page_url =
embedded_test_server()->GetURL("example.com", "/simple.html");
ASSERT_TRUE(NavigateToURL(web_contents, page_url));
content::RenderFrameHost* regular_page = web_contents->GetPrimaryMainFrame();
EXPECT_EQ(R"(["incognito-allowed","incognito-disallowed"])",
content::EvalJs(regular_page, kGetDivIds));
content::WebContents* incognito_web_contents =
PlatformOpenURLOffTheRecord(profile(), page_url);
content::WaitForLoadStop(incognito_web_contents);
EXPECT_EQ(R"(["incognito-allowed"])",
content::EvalJs(incognito_web_contents, kGetDivIds));
}
IN_PROC_BROWSER_TEST_F(ScriptingAPITest,
DynamicContentScriptsInjectInIncognito) {
ScopedAllowHttpForHostnamesForTesting allow_http({"example.com"},
profile()->GetPrefs());
auto* web_contents = GetActiveWebContents();
const GURL page_url =
embedded_test_server()->GetURL("example.com", "/simple.html");
ASSERT_TRUE(NavigateToURL(web_contents, page_url));
content::RenderFrameHost* regular_page = web_contents->GetPrimaryMainFrame();
EXPECT_EQ(R"(["incognito-allowed","incognito-disallowed"])",
content::EvalJs(regular_page, kGetDivIds));
content::WebContents* incognito_web_contents =
PlatformOpenURLOffTheRecord(profile(), page_url);
content::WaitForLoadStop(incognito_web_contents);
EXPECT_EQ(R"(["incognito-allowed"])",
content::EvalJs(incognito_web_contents, kGetDivIds));
}
#endif
#if BUILDFLAG(ENABLE_EXTENSIONS)
class PersistentScriptingAPITest : public ScriptingAPITest {
public:
PersistentScriptingAPITest() = default;
void SetUp() override {
listener_ = std::make_unique<ExtensionTestMessageListener>(
"ready", ReplyBehavior::kWillReply);
ScriptingAPITest::SetUp();
}
void TearDownOnMainThread() override {
listener_.reset();
ScriptingAPITest::TearDownOnMainThread();
}
protected:
ResultCatcher result_catcher_;
std::unique_ptr<ExtensionTestMessageListener> listener_;
};
IN_PROC_BROWSER_TEST_F(PersistentScriptingAPITest,
PRE_PRE_PersistentDynamicContentScripts) {
const Extension* extension = LoadExtension(
test_data_dir_.AppendASCII("scripting/persistent_dynamic_scripts"));
ASSERT_TRUE(extension);
ASSERT_TRUE(listener_->WaitUntilSatisfied());
listener_->Reply(
testing::UnitTest::GetInstance()->current_test_info()->name());
EXPECT_TRUE(result_catcher_.GetNextResult()) << result_catcher_.message();
}
IN_PROC_BROWSER_TEST_F(PersistentScriptingAPITest,
PRE_PersistentDynamicContentScripts) {
ASSERT_TRUE(listener_->WaitUntilSatisfied());
listener_->Reply(
testing::UnitTest::GetInstance()->current_test_info()->name());
EXPECT_TRUE(result_catcher_.GetNextResult()) << result_catcher_.message();
}
IN_PROC_BROWSER_TEST_F(PersistentScriptingAPITest,
PersistentDynamicContentScripts) {
ASSERT_TRUE(listener_->WaitUntilSatisfied());
listener_->Reply(
testing::UnitTest::GetInstance()->current_test_info()->name());
EXPECT_TRUE(result_catcher_.GetNextResult()) << result_catcher_.message();
}
class ScriptingAPIPrerenderingTest : public ScriptingAPITest {
protected:
ScriptingAPIPrerenderingTest() = default;
~ScriptingAPIPrerenderingTest() override = default;
private:
content::test::ScopedPrerenderFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_F(ScriptingAPIPrerenderingTest, DISABLED_Basic) {
ASSERT_TRUE(RunExtensionTest("scripting/prerendering")) << message_;
}
#endif
}