Bug 1207394 - Make sure web_accessible_resources work with CSP/mixed content blocking, r=kmag

MozReview-Commit-ID: 7UJ1IHwMosh

--HG--
extra : transplant_source : R%A0F%AAOcn%92%2C%10%B3%09%A2%99J%EF%FE%EFy%8C
This commit is contained in:
Bob Silverberg 2016-04-11 18:08:54 -04:00
Родитель 6d15e2b50b
Коммит 12f6f37ec3
5 изменённых файлов: 237 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,14 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div id="test">Sample text</div>
<img id="bad-image" src="http://example.org/tests/toolkit/components/extensions/test/mochitest/file_image_bad.png" />
<script id="bad-script" type="text/javascript" src="http://example.org/tests/toolkit/components/extensions/test/mochitest/file_script_bad.js"></script>
</body>
</html>

Просмотреть файл

@ -0,0 +1 @@
Content-Security-Policy: default-src 'self'

Просмотреть файл

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div id="test">Sample text</div>
<img id="bad-image" src="http://example.com/tests/toolkit/components/extensions/test/mochitest/file_image_bad.png" />
</body>
</html>

Просмотреть файл

@ -2,6 +2,9 @@
skip-if = buildapp == 'mulet' || asan
support-files =
head.js
file_mixed.html
file_csp.html
file_csp.html^headers^
file_WebRequest_page1.html
file_WebRequest_page2.html
file_WebRequest_page3.html

Просмотреть файл

@ -15,6 +15,46 @@
/* eslint-disable mozilla/balanced-listeners */
SimpleTest.registerCleanupFunction(() => {
SpecialPowers.clearUserPref("security.mixed_content.block_display_content");
});
let image = atob("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAA" +
"ACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=");
const IMAGE_ARRAYBUFFER = Uint8Array.from(image, byte => byte.charCodeAt(0)).buffer;
function testImageLoading(src, expectedAction) {
let imageLoadingPromise = new Promise((resolve, reject) => {
let cleanupListeners;
let testImage = document.createElement("img");
testImage.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);
});
imageLoadingPromise.then(success => {
browser.runtime.sendMessage({name: "image-loading", expectedAction, success});
});
}
add_task(function* test_web_accessible_resources() {
function background() {
let gotURL;
@ -140,6 +180,172 @@ add_task(function* test_web_accessible_resources() {
yield extension.unload();
});
add_task(function* test_web_accessible_resources_csp() {
function background() {
browser.runtime.onMessage.addListener((msg, sender) => {
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(event) {
browser.runtime.sendMessage("script-ran");
window.removeEventListener("message", rcv, false);
}, false);
testImageLoading(browser.extension.getURL("image.png"), "loaded");
let testScript = document.createElement("script");
testScript.setAttribute("src", browser.extension.getURL("test_script.js"));
document.head.appendChild(testScript);
browser.runtime.sendMessage("script-loaded");
}
function testScript() {
window.postMessage("test-script-loaded", "*");
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"content_scripts": [{
"matches": ["http://example.com/*/file_csp.html"],
"run_at": "document_start",
"js": ["content_script_helper.js", "content_script.js"],
}],
"web_accessible_resources": [
"image.png",
"test_script.js",
],
},
background: `(${background})()`,
files: {
"content_script_helper.js": `${testImageLoading}`,
"content_script.js": `(${content})()`,
"test_script.js": `(${testScript})()`,
"image.png": IMAGE_ARRAYBUFFER,
},
});
// This is used to watch the blocked data bounce off CSP.
function examiner() {
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
}
let cspEventCount = 0;
examiner.prototype = {
observe: function(subject, topic, data) {
cspEventCount++;
let spec = SpecialPowers.wrap(subject).QueryInterface(SpecialPowers.Ci.nsIURI).spec;
ok(spec.includes("file_image_bad.png") || spec.includes("file_script_bad.js"),
`Expected file: ${spec} rejected by CSP`);
},
// We must eventually call this to remove the listener,
// or mochitests might get borked.
remove: function() {
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
},
};
let observer = new examiner();
yield Promise.all([extension.startup(), extension.awaitMessage("background-ready")]);
let win = window.open("http://example.com/tests/toolkit/components/extensions/test/mochitest/file_csp.html");
yield Promise.all([
extension.awaitMessage("image-loaded"),
extension.awaitMessage("script-loaded"),
extension.awaitMessage("script-ran"),
]);
is(cspEventCount, 2, "Two items were rejected by CSP");
win.close();
observer.remove();
yield extension.unload();
});
add_task(function* test_web_accessible_resources_mixed_content() {
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);
if (msg === "accessible-script-loaded") {
browser.test.notifyPass("mixed-test");
}
}
});
browser.test.sendMessage("background-ready");
}
function content() {
testImageLoading("http://example.com/tests/toolkit/components/extensions/test/mochitest/file_image_bad.png", "blocked");
testImageLoading(browser.extension.getURL("image.png"), "loaded");
let testScript = document.createElement("script");
testScript.setAttribute("src", browser.extension.getURL("test_script.js"));
document.head.appendChild(testScript);
window.addEventListener("message", event => {
browser.runtime.sendMessage(event.data);
});
}
function testScript() {
window.postMessage("accessible-script-loaded", "*");
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"content_scripts": [{
"matches": ["https://example.com/*/file_mixed.html"],
"run_at": "document_start",
"js": ["content_script_helper.js", "content_script.js"],
}],
"web_accessible_resources": [
"image.png",
"test_script.js",
],
},
background: `(${background})()`,
files: {
"content_script_helper.js": `${testImageLoading}`,
"content_script.js": `(${content})()`,
"test_script.js": `(${testScript})()`,
"image.png": IMAGE_ARRAYBUFFER,
},
});
SpecialPowers.setBoolPref("security.mixed_content.block_display_content", true);
yield Promise.all([extension.startup(), extension.awaitMessage("background-ready")]);
let win = window.open("https://example.com/tests/toolkit/components/extensions/test/mochitest/file_mixed.html");
yield Promise.all([
extension.awaitMessage("image-blocked"),
extension.awaitMessage("image-loaded"),
extension.awaitMessage("accessible-script-loaded"),
]);
yield extension.awaitFinish("mixed-test");
win.close();
yield extension.unload();
});
</script>
</body>