mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 16:25:38 +00:00
Bug 1588801 - Add test coverage for JS files loaded from XPIs. r=mixedpuppy,robwu
JS files in packed webextensions (XPIs) are loaded via `nsJARChannel`, which checks the content type of a file based on the extension by calling `nsIMIMEService::GetTypeFromExtension()`. We might not be able to guarantee the exact set of JS file extensions because this method also asks the OS but it should still be reliable. We allow `.js`, `.jsm` and `.mjs` (defined in `defaultMimeEntries` and `extraMimeEntries`). Differential Revision: https://phabricator.services.mozilla.com/D104450
This commit is contained in:
parent
da85975c5c
commit
e0091f942e
@ -143,6 +143,7 @@ skip-if = os == 'android' # Bug 1615427
|
|||||||
[test_ext_runtime_connect_twoway.html]
|
[test_ext_runtime_connect_twoway.html]
|
||||||
[test_ext_runtime_connect2.html]
|
[test_ext_runtime_connect2.html]
|
||||||
[test_ext_runtime_disconnect.html]
|
[test_ext_runtime_disconnect.html]
|
||||||
|
[test_ext_script_filenames.html]
|
||||||
[test_ext_sendmessage_doublereply.html]
|
[test_ext_sendmessage_doublereply.html]
|
||||||
[test_ext_sendmessage_frameId.html]
|
[test_ext_sendmessage_frameId.html]
|
||||||
[test_ext_sendmessage_no_receiver.html]
|
[test_ext_sendmessage_no_receiver.html]
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Script Filenames Test</title>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
|
||||||
|
<script type="text/javascript" src="head.js"></script>
|
||||||
|
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
add_task(async function test_tabs_executeScript() {
|
||||||
|
let validFileName = "script.js";
|
||||||
|
let invalidFileName = "script.xyz";
|
||||||
|
|
||||||
|
async function background() {
|
||||||
|
await browser.tabs.executeScript({ file: "script.js" });
|
||||||
|
|
||||||
|
await browser.test.assertRejects(
|
||||||
|
browser.tabs.executeScript({ file: "script.xyz" }),
|
||||||
|
Error,
|
||||||
|
"invalid filename does not execute"
|
||||||
|
);
|
||||||
|
browser.test.notifyPass("execute-script");
|
||||||
|
}
|
||||||
|
|
||||||
|
let extension = ExtensionTestUtils.loadExtension({
|
||||||
|
manifest: {
|
||||||
|
permissions: ["<all_urls>"],
|
||||||
|
},
|
||||||
|
|
||||||
|
background,
|
||||||
|
|
||||||
|
files: {
|
||||||
|
[validFileName]: function contentScript1() {
|
||||||
|
browser.test.sendMessage("content-script-loaded");
|
||||||
|
},
|
||||||
|
[invalidFileName]: function contentScript2() {
|
||||||
|
browser.test.fail("this script should not be loaded");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
let tab = await AppTestDelegate.openNewForegroundTab(
|
||||||
|
window,
|
||||||
|
"http://mochi.test:8888/",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
await extension.startup();
|
||||||
|
|
||||||
|
await extension.awaitMessage("content-script-loaded");
|
||||||
|
await extension.awaitFinish("execute-script");
|
||||||
|
|
||||||
|
await extension.unload();
|
||||||
|
await AppTestDelegate.removeTab(window, tab);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,325 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const server = createHttpServer();
|
||||||
|
server.registerDirectory("/data/", do_get_file("data"));
|
||||||
|
|
||||||
|
const BASE_URL = `http://localhost:${server.identity.primaryPort}/data`;
|
||||||
|
|
||||||
|
// This function represents a dummy content or background script that the test
|
||||||
|
// cases below should attempt to load but it shouldn't be loaded because we
|
||||||
|
// check the extensions of JavaScript files in `nsJARChannel`.
|
||||||
|
function scriptThatShouldNotBeLoaded() {
|
||||||
|
browser.test.fail("this should not be executed");
|
||||||
|
}
|
||||||
|
|
||||||
|
function scriptThatAlwaysRuns() {
|
||||||
|
browser.test.sendMessage("content-script-loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
// We use these variables in combination with `scriptThatAlwaysRuns()` to send a
|
||||||
|
// signal to the extension and avoid the page to be closed too soon.
|
||||||
|
const alwaysRunsFileName = "always_run.js";
|
||||||
|
const alwaysRunsContentScript = {
|
||||||
|
matches: ["<all_urls>"],
|
||||||
|
js: [alwaysRunsFileName],
|
||||||
|
run_at: "document_start",
|
||||||
|
};
|
||||||
|
|
||||||
|
add_task(async function test_content_script_filename_without_extension() {
|
||||||
|
// Filenames without any extension should not be loaded.
|
||||||
|
let invalidFileName = "content_script";
|
||||||
|
let extensionData = {
|
||||||
|
manifest: {
|
||||||
|
content_scripts: [
|
||||||
|
alwaysRunsContentScript,
|
||||||
|
{
|
||||||
|
matches: ["<all_urls>"],
|
||||||
|
js: [invalidFileName],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
[invalidFileName]: scriptThatShouldNotBeLoaded,
|
||||||
|
[alwaysRunsFileName]: scriptThatAlwaysRuns,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let extension = ExtensionTestUtils.loadExtension(extensionData);
|
||||||
|
await extension.startup();
|
||||||
|
|
||||||
|
let contentPage = await ExtensionTestUtils.loadContentPage(
|
||||||
|
`${BASE_URL}/file_sample.html`
|
||||||
|
);
|
||||||
|
|
||||||
|
await extension.awaitMessage("content-script-loaded");
|
||||||
|
|
||||||
|
await contentPage.close();
|
||||||
|
await extension.unload();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_content_script_filename_with_invalid_extension() {
|
||||||
|
let validFileName = "content_script.js";
|
||||||
|
let invalidFileName = "content_script.xyz";
|
||||||
|
let extensionData = {
|
||||||
|
manifest: {
|
||||||
|
content_scripts: [
|
||||||
|
alwaysRunsContentScript,
|
||||||
|
{
|
||||||
|
matches: ["<all_urls>"],
|
||||||
|
js: [validFileName, invalidFileName],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
// This makes sure that, when one of the content scripts fails to load,
|
||||||
|
// none of the content scripts are executed.
|
||||||
|
[validFileName]: scriptThatShouldNotBeLoaded,
|
||||||
|
[invalidFileName]: scriptThatShouldNotBeLoaded,
|
||||||
|
[alwaysRunsFileName]: scriptThatAlwaysRuns,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let extension = ExtensionTestUtils.loadExtension(extensionData);
|
||||||
|
await extension.startup();
|
||||||
|
|
||||||
|
let contentPage = await ExtensionTestUtils.loadContentPage(
|
||||||
|
`${BASE_URL}/file_sample.html`
|
||||||
|
);
|
||||||
|
|
||||||
|
await extension.awaitMessage("content-script-loaded");
|
||||||
|
|
||||||
|
await contentPage.close();
|
||||||
|
await extension.unload();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_bg_script_injects_script_with_invalid_ext() {
|
||||||
|
function backgroundScript() {
|
||||||
|
browser.test.sendMessage("background-script-loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
let validFileName = "background.js";
|
||||||
|
let invalidFileName = "invalid_background.xyz";
|
||||||
|
let extensionData = {
|
||||||
|
background() {
|
||||||
|
const script = document.createElement("script");
|
||||||
|
script.src = "./invalid_background.xyz";
|
||||||
|
document.head.appendChild(script);
|
||||||
|
|
||||||
|
const validScript = document.createElement("script");
|
||||||
|
validScript.src = "./background.js";
|
||||||
|
document.head.appendChild(validScript);
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
[invalidFileName]: scriptThatShouldNotBeLoaded,
|
||||||
|
[validFileName]: backgroundScript,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let extension = ExtensionTestUtils.loadExtension(extensionData);
|
||||||
|
await extension.startup();
|
||||||
|
|
||||||
|
await extension.awaitMessage("background-script-loaded");
|
||||||
|
|
||||||
|
await extension.unload();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_background_scripts() {
|
||||||
|
function backgroundScript() {
|
||||||
|
browser.test.sendMessage("background-script-loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
let validFileName = "background.js";
|
||||||
|
let invalidFileName = "invalid_background.xyz";
|
||||||
|
let extensionData = {
|
||||||
|
manifest: {
|
||||||
|
background: {
|
||||||
|
scripts: [invalidFileName, validFileName],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
[invalidFileName]: scriptThatShouldNotBeLoaded,
|
||||||
|
[validFileName]: backgroundScript,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let extension = ExtensionTestUtils.loadExtension(extensionData);
|
||||||
|
await extension.startup();
|
||||||
|
|
||||||
|
await extension.awaitMessage("background-script-loaded");
|
||||||
|
|
||||||
|
await extension.unload();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_background_page_injects_scripts_inline() {
|
||||||
|
function injectedBackgroundScript() {
|
||||||
|
browser.test.sendMessage("background-script-loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
let backgroundHtmlPage = "background_page.html";
|
||||||
|
let validFileName = "injected_background.js";
|
||||||
|
let invalidFileName = "invalid_background.xyz";
|
||||||
|
// This is needed to "easily" generate a valid CSP script hash because it
|
||||||
|
// generates a one-line JS payload. If the content below is modified, the
|
||||||
|
// hash has to be updated in `content_security_policy` too.
|
||||||
|
let inlineScript = [
|
||||||
|
'const script = document.createElement("script");',
|
||||||
|
'script.src = "./invalid_background.xyz";',
|
||||||
|
"document.head.appendChild(script);",
|
||||||
|
'const validScript = document.createElement("script");',
|
||||||
|
'validScript.src = "./injected_background.js";',
|
||||||
|
"document.head.appendChild(validScript);",
|
||||||
|
].join("");
|
||||||
|
let extensionData = {
|
||||||
|
manifest: {
|
||||||
|
background: { page: backgroundHtmlPage },
|
||||||
|
content_security_policy: [
|
||||||
|
"script-src",
|
||||||
|
"'self'",
|
||||||
|
"'sha256-2xldfE9/s8HWuAO69FOx5nKY4YDuAVQpUH2d7nX9KIM='",
|
||||||
|
";",
|
||||||
|
"object-src",
|
||||||
|
"'self'",
|
||||||
|
].join(" "),
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
[invalidFileName]: scriptThatShouldNotBeLoaded,
|
||||||
|
[validFileName]: injectedBackgroundScript,
|
||||||
|
[backgroundHtmlPage]: `
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"></head>
|
||||||
|
<script>${inlineScript}</script>
|
||||||
|
</head>
|
||||||
|
</html>`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let extension = ExtensionTestUtils.loadExtension(extensionData);
|
||||||
|
await extension.startup();
|
||||||
|
|
||||||
|
await extension.awaitMessage("background-script-loaded");
|
||||||
|
|
||||||
|
await extension.unload();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_background_page_injects_scripts() {
|
||||||
|
// This is the initial background script loaded in the HTML page.
|
||||||
|
function backgroundScript() {
|
||||||
|
const script = document.createElement("script");
|
||||||
|
script.src = "./invalid_background.xyz";
|
||||||
|
document.head.appendChild(script);
|
||||||
|
|
||||||
|
const validScript = document.createElement("script");
|
||||||
|
validScript.src = "./injected_background.js";
|
||||||
|
document.head.appendChild(validScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the script injected by the script defined in `backgroundScript()`.
|
||||||
|
function injectedBackgroundScript() {
|
||||||
|
browser.test.sendMessage("background-script-loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
let backgroundHtmlPage = "background_page.html";
|
||||||
|
let validFileName = "injected_background.js";
|
||||||
|
let invalidFileName = "invalid_background.xyz";
|
||||||
|
let extensionData = {
|
||||||
|
manifest: {
|
||||||
|
background: { page: backgroundHtmlPage },
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
[invalidFileName]: scriptThatShouldNotBeLoaded,
|
||||||
|
[validFileName]: injectedBackgroundScript,
|
||||||
|
[backgroundHtmlPage]: `
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"></head>
|
||||||
|
<script src="./background.js"></script>
|
||||||
|
</head>
|
||||||
|
</html>`,
|
||||||
|
"background.js": backgroundScript,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let extension = ExtensionTestUtils.loadExtension(extensionData);
|
||||||
|
await extension.startup();
|
||||||
|
|
||||||
|
await extension.awaitMessage("background-script-loaded");
|
||||||
|
|
||||||
|
await extension.unload();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_background_script_registers_content_script() {
|
||||||
|
let invalidFileName = "content_script";
|
||||||
|
let extensionData = {
|
||||||
|
manifest: {
|
||||||
|
permissions: ["<all_urls>"],
|
||||||
|
},
|
||||||
|
async background() {
|
||||||
|
await browser.contentScripts.register({
|
||||||
|
js: [{ file: "/content_script" }],
|
||||||
|
matches: ["<all_urls>"],
|
||||||
|
});
|
||||||
|
browser.test.sendMessage("background-script-loaded");
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
[invalidFileName]: scriptThatShouldNotBeLoaded,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let extension = ExtensionTestUtils.loadExtension(extensionData);
|
||||||
|
await extension.startup();
|
||||||
|
|
||||||
|
let contentPage = await ExtensionTestUtils.loadContentPage(
|
||||||
|
`${BASE_URL}/file_sample.html`
|
||||||
|
);
|
||||||
|
|
||||||
|
await extension.awaitMessage("background-script-loaded");
|
||||||
|
|
||||||
|
await contentPage.close();
|
||||||
|
await extension.unload();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_web_accessible_resources() {
|
||||||
|
function contentScript() {
|
||||||
|
const script = document.createElement("script");
|
||||||
|
script.src = browser.runtime.getURL("content_script.css");
|
||||||
|
script.onerror = () => {
|
||||||
|
browser.test.sendMessage("second-content-script-loaded");
|
||||||
|
};
|
||||||
|
|
||||||
|
document.head.appendChild(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
let contentScriptFileName = "content_script.js";
|
||||||
|
let invalidFileName = "content_script.css";
|
||||||
|
let extensionData = {
|
||||||
|
manifest: {
|
||||||
|
web_accessible_resources: [invalidFileName],
|
||||||
|
content_scripts: [
|
||||||
|
alwaysRunsContentScript,
|
||||||
|
{
|
||||||
|
matches: ["<all_urls>"],
|
||||||
|
js: [contentScriptFileName],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
[invalidFileName]: scriptThatShouldNotBeLoaded,
|
||||||
|
[contentScriptFileName]: contentScript,
|
||||||
|
[alwaysRunsFileName]: scriptThatAlwaysRuns,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let extension = ExtensionTestUtils.loadExtension(extensionData);
|
||||||
|
await extension.startup();
|
||||||
|
|
||||||
|
let contentPage = await ExtensionTestUtils.loadContentPage(
|
||||||
|
`${BASE_URL}/file_sample.html`
|
||||||
|
);
|
||||||
|
|
||||||
|
await extension.awaitMessage("content-script-loaded");
|
||||||
|
await extension.awaitMessage("second-content-script-loaded");
|
||||||
|
|
||||||
|
await contentPage.close();
|
||||||
|
await extension.unload();
|
||||||
|
});
|
@ -155,6 +155,7 @@ skip-if = ccov && os == 'linux' # bug 1607581
|
|||||||
[test_ext_sandbox_var.js]
|
[test_ext_sandbox_var.js]
|
||||||
[test_ext_schema.js]
|
[test_ext_schema.js]
|
||||||
skip-if = os == "android" # Android: Bug 1680132
|
skip-if = os == "android" # Android: Bug 1680132
|
||||||
|
[test_ext_script_filenames.js]
|
||||||
[test_ext_shared_workers.js]
|
[test_ext_shared_workers.js]
|
||||||
[test_ext_shutdown_cleanup.js]
|
[test_ext_shutdown_cleanup.js]
|
||||||
[test_ext_simple.js]
|
[test_ext_simple.js]
|
||||||
|
Loading…
Reference in New Issue
Block a user