From b577fd2016aa511b6c54e28b8a1873254cc2391e Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Wed, 6 May 2026 07:21:37 +0000 Subject: [PATCH] Bug 2024854 Part 1 - Add content policies for text modules. r=extension-reviewers,dom-worker-reviewers,tschuster,asuth,robwu Differential Revision: https://phabricator.services.mozilla.com/D295486 --- dom/base/nsContentPolicyType.h | 4 +- dom/base/nsContentUtils.h | 4 + dom/base/nsIContentPolicy.idl | 15 +++ dom/cache/DBSchema.cpp | 4 +- .../xpcshell/test_ext_webRequest_type_text.js | 98 +++++++++++++++++++ .../test/xpcshell/xpcshell-common.toml | 6 ++ .../extensions/webrequest/ChannelWrapper.cpp | 1 + tools/@types/generated/lib.gecko.xpcom.d.ts | 3 +- 8 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 toolkit/components/extensions/test/xpcshell/test_ext_webRequest_type_text.js diff --git a/dom/base/nsContentPolicyType.h b/dom/base/nsContentPolicyType.h index 072a74c65f31..fd38c4b67bb4 100644 --- a/dom/base/nsContentPolicyType.h +++ b/dom/base/nsContentPolicyType.h @@ -69,6 +69,8 @@ NAME(TYPE_INTERNAL_XMLHTTPREQUEST_SYNC) \ NAME(TYPE_INTERNAL_EXTERNAL_RESOURCE) \ NAME(TYPE_JSON) \ - NAME(TYPE_INTERNAL_JSON_PRELOAD) + NAME(TYPE_INTERNAL_JSON_PRELOAD) \ + NAME(TYPE_TEXT) \ + NAME(TYPE_INTERNAL_TEXT_PRELOAD) #endif // nsContentPolicyType_h diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index c813119f2ad0..d068b2883c55 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -3870,6 +3870,9 @@ nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType) { case nsIContentPolicy::TYPE_INTERNAL_JSON_PRELOAD: return ExtContentPolicy::TYPE_JSON; + case nsIContentPolicy::TYPE_INTERNAL_TEXT_PRELOAD: + return ExtContentPolicy::TYPE_TEXT; + case nsIContentPolicy::TYPE_INVALID: case nsIContentPolicy::TYPE_OTHER: case nsIContentPolicy::TYPE_SCRIPT: @@ -3897,6 +3900,7 @@ nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType) { case nsIContentPolicy::TYPE_WEB_IDENTITY: case nsIContentPolicy::TYPE_WEB_TRANSPORT: case nsIContentPolicy::TYPE_JSON: + case nsIContentPolicy::TYPE_TEXT: // NOTE: When adding something here make sure the enumerator is defined! return static_cast(aType); diff --git a/dom/base/nsIContentPolicy.idl b/dom/base/nsIContentPolicy.idl index 79a00b2bed2c..985602dab462 100644 --- a/dom/base/nsIContentPolicy.idl +++ b/dom/base/nsIContentPolicy.idl @@ -467,6 +467,20 @@ interface nsIContentPolicy : nsISupports */ TYPE_INTERNAL_IMAGE_NOTIFICATION = 64, + /** + * Indicates a text module loaded through an import statement. + */ + TYPE_TEXT = 65, + + /** + * Same as TYPE_TEXT but indicates an internal constant for a preloaded + * text module loaded through an import statement. + * + * This will be mapped to TYPE_TEXT before being passed to content policy + * implementations. + */ + TYPE_INTERNAL_TEXT_PRELOAD = 66, + /* When adding new content types, please update * nsCSPContext, CSP_ContentTypeToDirective, * DoContentSecurityChecks, all nsIContentPolicy implementations, the @@ -614,6 +628,7 @@ enum class ExtContentPolicyType : uint8_t { TYPE_WEB_IDENTITY = nsIContentPolicy::TYPE_WEB_IDENTITY, TYPE_WEB_TRANSPORT = nsIContentPolicy::TYPE_WEB_TRANSPORT, TYPE_JSON = nsIContentPolicy::TYPE_JSON, + TYPE_TEXT = nsIContentPolicy::TYPE_TEXT, }; typedef ExtContentPolicyType ExtContentPolicy; diff --git a/dom/cache/DBSchema.cpp b/dom/cache/DBSchema.cpp index ede6bb6b6069..0c7d553314a7 100644 --- a/dom/cache/DBSchema.cpp +++ b/dom/cache/DBSchema.cpp @@ -391,7 +391,9 @@ static_assert( nsIContentPolicy::TYPE_INTERNAL_EXTERNAL_RESOURCE == 61 && nsIContentPolicy::TYPE_JSON == 62 && nsIContentPolicy::TYPE_INTERNAL_JSON_PRELOAD == 63 && - nsIContentPolicy::TYPE_INTERNAL_IMAGE_NOTIFICATION == 64, + nsIContentPolicy::TYPE_INTERNAL_IMAGE_NOTIFICATION == 64 && + nsIContentPolicy::TYPE_TEXT == 65 && + nsIContentPolicy::TYPE_INTERNAL_TEXT_PRELOAD == 66, "nsContentPolicyType values are as expected"); namespace { diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_type_text.js b/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_type_text.js new file mode 100644 index 000000000000..5f20fee6d4ba --- /dev/null +++ b/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_type_text.js @@ -0,0 +1,98 @@ +"use strict"; + +const server = createHttpServer({ hosts: ["example.com"] }); + +const staticImportHtml = ` + + + + + + `; + +const dynamicImportHtml = ` + + + + + + `; + +server.registerPathHandler("/static-import.html", (request, response) => { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/html", false); + response.write(staticImportHtml); +}); + +server.registerPathHandler("/dynamic-import.html", (request, response) => { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/html", false); + response.write(dynamicImportHtml); +}); + +server.registerPathHandler("/test.txt", (request, response) => { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/plain", false); + response.write("hello"); +}); + +add_task(async function test_static_import() { + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + permissions: ["webRequest", "webRequestBlocking", ""], + }, + background() { + browser.webRequest.onBeforeRequest.addListener( + async details => { + browser.test.assertEq("other", details.type); + browser.test.notifyPass("webRequest"); + }, + { urls: ["*://example.com/test.txt"] }, + ["blocking"] + ); + }, + }); + await extension.startup(); + + let contentPage = await ExtensionTestUtils.loadContentPage( + "http://example.com/static-import.html" + ); + + await extension.awaitFinish("webRequest"); + + await extension.unload(); + await contentPage.close(); +}); + +add_task(async function test_dynamic_import() { + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + permissions: ["webRequest", "webRequestBlocking", ""], + }, + background() { + browser.webRequest.onBeforeRequest.addListener( + async details => { + browser.test.assertEq("http://example.com/test.txt", details.url); + browser.test.assertEq("other", details.type); + browser.test.notifyPass("webRequest"); + }, + { urls: [""], types: ["other"] }, + ["blocking"] + ); + }, + }); + await extension.startup(); + + let contentPage = await ExtensionTestUtils.loadContentPage( + "http://example.com/dynamic-import.html" + ); + + await extension.awaitFinish("webRequest"); + + await extension.unload(); + await contentPage.close(); +}); diff --git a/toolkit/components/extensions/test/xpcshell/xpcshell-common.toml b/toolkit/components/extensions/test/xpcshell/xpcshell-common.toml index 34b25f35e4fe..fdec6c33f564 100644 --- a/toolkit/components/extensions/test/xpcshell/xpcshell-common.toml +++ b/toolkit/components/extensions/test/xpcshell/xpcshell-common.toml @@ -873,6 +873,12 @@ skip-if = [ ["test_ext_webRequest_type_json.js"] +["test_ext_webRequest_type_text.js"] +prefs = ["javascript.options.experimental.import_text=true"] +skip-if = [ + "!nightly_build", +] + ["test_ext_webRequest_userContextId.js"] ["test_ext_webRequest_viewsource.js"] diff --git a/toolkit/components/extensions/webrequest/ChannelWrapper.cpp b/toolkit/components/extensions/webrequest/ChannelWrapper.cpp index 99d42c9f8061..8e3d710c746c 100644 --- a/toolkit/components/extensions/webrequest/ChannelWrapper.cpp +++ b/toolkit/components/extensions/webrequest/ChannelWrapper.cpp @@ -892,6 +892,7 @@ MozContentPolicyType GetContentPolicyType(ExtContentPolicyType aType) { return MozContentPolicyType::Speculative; case ExtContentPolicy::TYPE_JSON: return MozContentPolicyType::Json; + case ExtContentPolicy::TYPE_TEXT: case ExtContentPolicy::TYPE_PROXIED_WEBRTC_MEDIA: case ExtContentPolicy::TYPE_INVALID: case ExtContentPolicy::TYPE_OTHER: diff --git a/tools/@types/generated/lib.gecko.xpcom.d.ts b/tools/@types/generated/lib.gecko.xpcom.d.ts index 4e651f00476b..dc5c1a1580ce 100644 --- a/tools/@types/generated/lib.gecko.xpcom.d.ts +++ b/tools/@types/generated/lib.gecko.xpcom.d.ts @@ -1951,7 +1951,8 @@ declare enum nsIContentPolicy_nsContentPolicyType { TYPE_JSON = 62, TYPE_INTERNAL_JSON_PRELOAD = 63, TYPE_INTERNAL_IMAGE_NOTIFICATION = 64, - TYPE_END = 65, + TYPE_TEXT = 65, + TYPE_INTERNAL_TEXT_PRELOAD = 66, } declare global {