Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

"use strict";
const server = createHttpServer({ hosts: ["example.com", "example.org"] });
server.registerDirectory("/data/", do_get_file("data"));
let image = atob(
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAA" +
"ACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII="
);
const IMAGE_ARRAYBUFFER = Uint8Array.from(image, byte =>
byte.charCodeAt(0)
).buffer;
async function testImageLoading(src, expectedAction) {
let imageLoadingPromise = new Promise(resolve => {
let cleanupListeners;
let testImage = document.createElement("img");
// Set the src via wrappedJSObject so the load is triggered with the
// content page's principal rather than ours.
testImage.wrappedJSObject.setAttribute("src", src);
let loadListener = () => {
cleanupListeners();
resolve(expectedAction === "loaded");
};
let errorListener = () => {
cleanupListeners();
resolve(expectedAction === "blocked");
};
cleanupListeners = () => {
testImage.removeEventListener("load", loadListener);
testImage.removeEventListener("error", errorListener);
};
testImage.addEventListener("load", loadListener);
testImage.addEventListener("error", errorListener);
document.body.appendChild(testImage);
});
let success = await imageLoadingPromise;
browser.runtime.sendMessage({
name: "image-loading",
expectedAction,
success,
});
}
add_task(async function test_web_accessible_resources_csp() {
function background() {
browser.runtime.onMessage.addListener(msg => {
if (msg.name === "image-loading") {
browser.test.assertTrue(msg.success, `Image was ${msg.expectedAction}`);
browser.test.sendMessage(`image-${msg.expectedAction}`);
} else {
browser.test.sendMessage(msg);
}
});
browser.test.sendMessage("background-ready");
}
function content() {
window.addEventListener("message", function rcv() {
browser.runtime.sendMessage("script-ran");
window.removeEventListener("message", rcv);
});
testImageLoading(browser.runtime.getURL("image.png"), "loaded");
let testScriptElement = document.createElement("script");
// Set the src via wrappedJSObject so the load is triggered with the
// content page's principal rather than ours.
testScriptElement.wrappedJSObject.setAttribute(
"src",
browser.runtime.getURL("test_script.js")
);
document.head.appendChild(testScriptElement);
browser.runtime.sendMessage("script-loaded");
}
function testScript() {
window.postMessage("test-script-loaded", "*");
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
content_scripts: [
{
run_at: "document_end",
js: ["content_script_helper.js", "content_script.js"],
},
],
web_accessible_resources: ["image.png", "test_script.js"],
},
background,
files: {
"content_script_helper.js": `${testImageLoading}`,
"content_script.js": content,
"test_script.js": testScript,
"image.png": IMAGE_ARRAYBUFFER,
},
});
await Promise.all([
extension.startup(),
extension.awaitMessage("background-ready"),
]);
let page = await ExtensionTestUtils.loadContentPage(
);
await page.legacySpawn(null, () => {
this.obs = {
events: [],
observe(subject) {
this.events.push(subject.QueryInterface(Ci.nsIURI).spec);
},
done() {
Services.obs.removeObserver(this, "csp-on-violate-policy");
return this.events;
},
};
Services.obs.addObserver(this.obs, "csp-on-violate-policy");
content.location.href = "http://example.com/data/file_csp.html";
});
await Promise.all([
extension.awaitMessage("image-loaded"),
extension.awaitMessage("script-loaded"),
extension.awaitMessage("script-ran"),
]);
let events = await page.legacySpawn(null, () => this.obs.done());
equal(events.length, 2, "Two items were rejected by CSP");
for (let url of events) {
ok(
url.includes("file_image_bad.png") || url.includes("file_script_bad.js"),
`Expected file: ${url} rejected by CSP`
);
}
await page.close();
await extension.unload();
});