Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: appname == 'thunderbird' OR os == 'android' OR os == 'mac' && debug OR socketprocess_networking && fission OR os == 'linux' && socketprocess_networking && !fission && debug
- Manifest: toolkit/components/extensions/test/xpcshell/xpcshell-e10s.toml includes toolkit/components/extensions/test/xpcshell/xpcshell-content.toml
- Manifest: toolkit/components/extensions/test/xpcshell/xpcshell-remote.toml includes toolkit/components/extensions/test/xpcshell/xpcshell-content.toml
- Manifest: toolkit/components/extensions/test/xpcshell/xpcshell.toml includes toolkit/components/extensions/test/xpcshell/xpcshell-content.toml
"use strict";
const server = createHttpServer({
hosts: ["green.example.com", "red.example.com"],
});
server.registerDirectory("/data/", do_get_file("data"));
server.registerPathHandler("/pixel.html", (request, response) => {
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Content-Type", "text/html", false);
response.write(`<!DOCTYPE html>
<script>
function readByWeb() {
let ctx = document.querySelector("canvas").getContext("2d");
let {data} = ctx.getImageData(0, 0, 1, 1);
return data.slice(0, 3).join();
}
</script>
`);
});
add_task(async function test_contentscript_canvas_tainting() {
async function contentScript() {
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
function draw(url) {
return new Promise(resolve => {
let img = document.createElement("img");
img.onload = () => {
ctx.drawImage(img, 0, 0, 1, 1);
resolve();
};
img.src = url;
});
}
function readByExt() {
let { data } = ctx.getImageData(0, 0, 1, 1);
return data.slice(0, 3).join();
}
let readByWeb = window.wrappedJSObject.readByWeb;
// Test reading after drawing an image from the same origin as the web page.
browser.test.assertEq(
readByWeb(),
"0,255,0",
"Content can read same-origin image"
);
browser.test.assertEq(
readByExt(),
"0,255,0",
"Extension can read same-origin image"
);
// Test reading after drawing a blue pixel data URI from extension content script.
await draw(
"data:image/gif;base64,R0lGODlhAQABAIABAAAA/wAAACwAAAAAAQABAAACAkQBADs="
);
browser.test.assertThrows(
readByWeb,
/operation is insecure/,
"Content can't read extension's image"
);
browser.test.assertEq(
readByExt(),
"0,0,255",
"Extension can read its own image"
);
// Test after tainting the canvas with an image from a third party domain.
browser.test.assertThrows(
readByWeb,
/operation is insecure/,
"Content can't read third party image"
);
browser.test.assertThrows(
readByExt,
/operation is insecure/,
"Extension can't read fully tainted"
);
// Test canvas is still fully tainted after drawing extension's data: image again.
await draw(
"data:image/gif;base64,R0lGODlhAQABAIABAAAA/wAAACwAAAAAAQABAAACAkQBADs="
);
browser.test.assertThrows(
readByWeb,
/operation is insecure/,
"Canvas still fully tainted for content"
);
browser.test.assertThrows(
readByExt,
/operation is insecure/,
"Canvas still fully tainted for extension"
);
browser.test.sendMessage("done");
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
content_scripts: [
{
js: ["cs.js"],
},
],
},
files: {
"cs.js": contentScript,
},
});
await extension.startup();
let contentPage = await ExtensionTestUtils.loadContentPage(
);
await extension.awaitMessage("done");
await contentPage.close();
await extension.unload();
});