summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/test_ext_cors_mozextension.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/extensions/test/xpcshell/test_ext_cors_mozextension.js')
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_cors_mozextension.js220
1 files changed, 220 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_cors_mozextension.js b/toolkit/components/extensions/test/xpcshell/test_ext_cors_mozextension.js
new file mode 100644
index 0000000000..fc50388c77
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_cors_mozextension.js
@@ -0,0 +1,220 @@
+"use strict";
+
+const server = createHttpServer({
+ hosts: ["example.com", "x.example.com"],
+});
+server.registerPathHandler("/dummy", (req, res) => {
+ res.write("dummy");
+});
+server.registerPathHandler("/redir", (req, res) => {
+ res.setStatusLine(req.httpVersion, 302, "Found");
+ res.setHeader("Access-Control-Allow-Origin", "http://example.com");
+ res.setHeader("Access-Control-Allow-Credentials", "true");
+ res.setHeader("Location", new URLSearchParams(req.queryString).get("url"));
+});
+
+add_task(async function load_moz_extension_with_and_without_cors() {
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ web_accessible_resources: ["ok.js"],
+ },
+ files: {
+ "ok.js": "window.status = 'loaded';",
+ "deny.js": "window.status = 'unexpected load'",
+ },
+ });
+ await extension.startup();
+ const EXT_BASE_URL = `moz-extension://${extension.uuid}`;
+ let contentPage = await ExtensionTestUtils.loadContentPage(
+ "http://example.com/dummy"
+ );
+ await contentPage.spawn([EXT_BASE_URL], async EXT_BASE_URL => {
+ const { document, window } = this.content;
+ async function checkScriptLoad({ setupScript, expectLoad, description }) {
+ const scriptElem = document.createElement("script");
+ setupScript(scriptElem);
+ return new Promise(resolve => {
+ window.status = "initial";
+ scriptElem.onload = () => {
+ Assert.equal(window.status, "loaded", "Script executed upon load");
+ Assert.ok(expectLoad, `Script loaded - ${description}`);
+ resolve();
+ };
+ scriptElem.onerror = () => {
+ Assert.equal(window.status, "initial", "not executed upon error");
+ Assert.ok(!expectLoad, `Script not loaded - ${description}`);
+ resolve();
+ };
+ document.head.append(scriptElem);
+ });
+ }
+
+ function sameOriginRedirectUrl(url) {
+ return `http://example.com/redir?url=` + encodeURIComponent(url);
+ }
+ function crossOriginRedirectUrl(url) {
+ return `http://x.example.com/redir?url=` + encodeURIComponent(url);
+ }
+
+ // Direct load of web-accessible extension script.
+ await checkScriptLoad({
+ setupScript(scriptElem) {
+ scriptElem.src = `${EXT_BASE_URL}/ok.js`;
+ },
+ expectLoad: true,
+ description: "web-accessible script, plain load",
+ });
+ await checkScriptLoad({
+ setupScript(scriptElem) {
+ scriptElem.src = `${EXT_BASE_URL}/ok.js`;
+ scriptElem.crossOrigin = "anonymous";
+ },
+ expectLoad: true,
+ description: "web-accessible script, cors",
+ });
+ await checkScriptLoad({
+ setupScript(scriptElem) {
+ scriptElem.src = `${EXT_BASE_URL}/ok.js`;
+ scriptElem.crossOrigin = "use-credentials";
+ },
+ expectLoad: true,
+ description: "web-accessible script, cors+credentials",
+ });
+
+ // Load of web-accessible extension scripts, after same-origin redirect.
+ await checkScriptLoad({
+ setupScript(scriptElem) {
+ scriptElem.src = sameOriginRedirectUrl(`${EXT_BASE_URL}/ok.js`);
+ },
+ expectLoad: true,
+ description: "same-origin redirect to web-accessible script, plain load",
+ });
+ await checkScriptLoad({
+ setupScript(scriptElem) {
+ scriptElem.src = sameOriginRedirectUrl(`${EXT_BASE_URL}/ok.js`);
+ scriptElem.crossOrigin = "anonymous";
+ },
+ expectLoad: true,
+ description: "same-origin redirect to web-accessible script, cors",
+ });
+ await checkScriptLoad({
+ setupScript(scriptElem) {
+ scriptElem.src = sameOriginRedirectUrl(`${EXT_BASE_URL}/ok.js`);
+ scriptElem.crossOrigin = "use-credentials";
+ },
+ expectLoad: true,
+ description:
+ "same-origin redirect to web-accessible script, cors+credentials",
+ });
+
+ // Load of web-accessible extension scripts, after cross-origin redirect.
+ await checkScriptLoad({
+ setupScript(scriptElem) {
+ scriptElem.src = crossOriginRedirectUrl(`${EXT_BASE_URL}/ok.js`);
+ },
+ expectLoad: true,
+ description: "cross-origin redirect to web-accessible script, plain load",
+ });
+ await checkScriptLoad({
+ setupScript(scriptElem) {
+ scriptElem.src = crossOriginRedirectUrl(`${EXT_BASE_URL}/ok.js`);
+ scriptElem.crossOrigin = "anonymous";
+ },
+ expectLoad: true,
+ description: "cross-origin redirect to web-accessible script, cors",
+ });
+ await checkScriptLoad({
+ setupScript(scriptElem) {
+ scriptElem.src = crossOriginRedirectUrl(`${EXT_BASE_URL}/ok.js`);
+ scriptElem.crossOrigin = "use-credentials";
+ },
+ expectLoad: true,
+ description:
+ "cross-origin redirect to web-accessible script, cors+credentials",
+ });
+
+ // Various loads of non-web-accessible extension script.
+ await checkScriptLoad({
+ setupScript(scriptElem) {
+ scriptElem.src = `${EXT_BASE_URL}/deny.js`;
+ },
+ expectLoad: false,
+ description: "non-accessible script, plain load",
+ });
+ await checkScriptLoad({
+ setupScript(scriptElem) {
+ scriptElem.src = `${EXT_BASE_URL}/deny.js`;
+ scriptElem.crossOrigin = "anonymous";
+ },
+ expectLoad: false,
+ description: "non-accessible script, cors",
+ });
+ await checkScriptLoad({
+ setupScript(scriptElem) {
+ scriptElem.src = sameOriginRedirectUrl(`${EXT_BASE_URL}/deny.js`);
+ scriptElem.crossOrigin = "anonymous";
+ },
+ expectLoad: false,
+ description: "same-origin redirect to non-accessible script, cors",
+ });
+ await checkScriptLoad({
+ setupScript(scriptElem) {
+ scriptElem.src = crossOriginRedirectUrl(`${EXT_BASE_URL}/deny.js`);
+ scriptElem.crossOrigin = "anonymous";
+ },
+ expectLoad: false,
+ description: "cross-origin redirect to non-accessible script, cors",
+ });
+
+ // Sub-resource integrity usually requires CORS. Verify that web-accessible
+ // extension resources are still subjected to SRI.
+ const sriHashOkJs = // SRI hash for "window.status = 'loaded';" (=ok.js).
+ "sha384-EAofaAZpgy6JshegITJJHeE3ROzn9ngGw1GAuuzjSJV1c/YS9PLvHMt9oh4RovrI";
+
+ async function testSRI({ integrityMatches }) {
+ const integrity = integrityMatches ? sriHashOkJs : "sha384-bad-sri-hash";
+ const sriDescription = integrityMatches
+ ? "web-accessible script, good sri, "
+ : "web-accessible script, sri not matching, ";
+ await checkScriptLoad({
+ setupScript(scriptElem) {
+ scriptElem.src = `${EXT_BASE_URL}/ok.js`;
+ scriptElem.integrity = integrity;
+ },
+ expectLoad: integrityMatches,
+ description: `${sriDescription} no cors, plain load`,
+ });
+ await checkScriptLoad({
+ setupScript(scriptElem) {
+ scriptElem.src = `${EXT_BASE_URL}/ok.js`;
+ scriptElem.crossOrigin = "anonymous";
+ scriptElem.integrity = integrity;
+ },
+ expectLoad: integrityMatches,
+ description: `${sriDescription} cors, plain load`,
+ });
+ await checkScriptLoad({
+ setupScript(scriptElem) {
+ scriptElem.src = sameOriginRedirectUrl(`${EXT_BASE_URL}/ok.js`);
+ scriptElem.crossOrigin = "anonymous";
+ scriptElem.integrity = integrity;
+ },
+ expectLoad: integrityMatches,
+ description: `${sriDescription} cors, same-origin redirect`,
+ });
+ await checkScriptLoad({
+ setupScript(scriptElem) {
+ scriptElem.src = crossOriginRedirectUrl(`${EXT_BASE_URL}/ok.js`);
+ scriptElem.crossOrigin = "anonymous";
+ scriptElem.integrity = integrity;
+ },
+ expectLoad: integrityMatches,
+ description: `${sriDescription} cors, cross-origin redirect`,
+ });
+ }
+ await testSRI({ integrityMatches: true });
+ await testSRI({ integrityMatches: false });
+ });
+ await contentPage.close();
+ await extension.unload();
+});