summaryrefslogtreecommitdiffstats
path: root/dom/security/test/mixedcontentblocker/file_main.html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/security/test/mixedcontentblocker/file_main.html')
-rw-r--r--dom/security/test/mixedcontentblocker/file_main.html338
1 files changed, 338 insertions, 0 deletions
diff --git a/dom/security/test/mixedcontentblocker/file_main.html b/dom/security/test/mixedcontentblocker/file_main.html
new file mode 100644
index 0000000000..e4a2d8d08b
--- /dev/null
+++ b/dom/security/test/mixedcontentblocker/file_main.html
@@ -0,0 +1,338 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests for Mixed Content Blocker
+https://bugzilla.mozilla.org/show_bug.cgi?id=62178
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Bug 62178</title>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<div id="testContent"></div>
+
+<!-- types the Mixed Content Blocker can block
+ /*
+ switch (aContentType) {
+ case nsIContentPolicy::TYPE_OBJECT:
+ case nsIContentPolicy::TYPE_SCRIPT:
+ case nsIContentPolicy::TYPE_STYLESHEET:
+ case nsIContentPolicy::TYPE_SUBDOCUMENT:
+ case nsIContentPolicy::TYPE_XMLHTTPREQUEST:
+
+ case nsIContentPolicy::TYPE_FONT: - NO TEST:
+ Load events for external fonts are not detectable by javascript.
+ case nsIContentPolicy::TYPE_WEBSOCKET: - NO TEST:
+ websocket connections over https require an encrypted websocket protocol (wss:)
+
+ case nsIContentPolicy::TYPE_IMAGE:
+ case nsIContentPolicy::TYPE_IMAGESET:
+ case nsIContentPolicy::TYPE_MEDIA:
+ case nsIContentPolicy::TYPE_PING:
+ our ping implementation is off by default and does not comply with the current spec (bug 786347)
+ case nsIContentPolicy::TYPE_BEACON:
+
+ }
+ */
+-->
+
+<script>
+ function ok(a, msg) {
+ parent.postMessage({msg, check: true, status: !!a}, "http://mochi.test:8888");
+ }
+
+ function is(a, b, msg) {
+ ok(a == b, msg);
+ }
+
+ function report(type, msg) {
+ parent.postMessage({test: type, msg}, "http://mochi.test:8888");
+ }
+
+ function uniqueID() {
+ return Math.floor(Math.random() * 100000)
+ }
+ function uniqueIDParam(id) {
+ return "&uniqueID=" + id;
+ }
+
+ async function init() {
+ var baseUrl = "http://example.com/tests/dom/security/test/mixedcontentblocker/file_server.sjs";
+ var checkLastRequestUrl = "https://example.com/tests/dom/security/test/mixedcontentblocker/file_server.sjs?lastRequest=true";
+
+ //For tests that require setTimeout, set the maximum polling time to 100 x 100ms = 10 seconds.
+ var MAX_COUNT = 100;
+ var TIMEOUT_INTERVAL = 100;
+
+ var testContent = document.getElementById("testContent");
+
+ async function checkLastRequest() {
+ const response = await fetch(checkLastRequestUrl);
+ return response.json();
+ }
+
+ /* Part 1: Mixed Script tests */
+
+ // Test 1a: insecure object
+ var object = document.createElement("object");
+ var objectId = uniqueID();
+ object.data = baseUrl + "?type=object" + uniqueIDParam(objectId);
+ object.type = "image/png";
+ object.width = "200";
+ object.height = "200";
+
+ testContent.appendChild(object);
+
+ var objectCount = 0;
+
+ function objectStatus(object) {
+ // Expose our privileged bits on the object. We will match the MIME type to the one
+ // provided by file_server.sjs
+ object = SpecialPowers.wrap(object);
+ var typeIsSet = object.actualType && (object.actualType !== '');
+ var isLoaded = typeIsSet && object.actualType === 'application/x-test-match';
+ if (isLoaded) {
+ //object loaded
+ report("object", "insecure object loaded");
+ }
+ else {
+ if(!typeIsSet && objectCount < MAX_COUNT) {
+ objectCount++;
+ setTimeout(objectStatus, TIMEOUT_INTERVAL, object);
+ }
+ else {
+ //After we have called setTimeout the maximum number of times, assume object is blocked
+ report("object", "insecure object blocked");
+ }
+ }
+ }
+
+ // object does not have onload and onerror events. Hence we need a setTimeout to check the object's status
+ setTimeout(objectStatus, TIMEOUT_INTERVAL, object);
+
+ // Test 1b: insecure script
+ var script = document.createElement("script");
+ var scriptId = uniqueID();
+ var scriptLoad = false;
+ var scriptCount = 0;
+ script.src = baseUrl + "?type=script" + uniqueIDParam(scriptId);
+ script.onload = function(e) {
+ report("script", "insecure script loaded");
+ scriptLoad = true;
+ }
+ testContent.appendChild(script);
+
+ function scriptStatus(script)
+ {
+ if(scriptLoad) {
+ return;
+ }
+ else {
+ if(scriptCount < MAX_COUNT) {
+ scriptCount++;
+ setTimeout(scriptStatus, TIMEOUT_INTERVAL, script);
+ }
+ else {
+ //After we have called setTimeout the maximum number of times, assume script is blocked
+ report("script", "insecure script blocked");
+ }
+ }
+ }
+
+ // scripts blocked by Content Policy's do not have onerror events (see bug 789856). Hence we need a setTimeout to check the script's status
+ setTimeout(scriptStatus, TIMEOUT_INTERVAL, script);
+
+
+ // Test 1c: insecure stylesheet
+ var cssStyleSheet = document.createElement("link");
+ var cssStyleSheetId = uniqueID();
+ cssStyleSheet.rel = "stylesheet";
+ cssStyleSheet.href = baseUrl + "?type=stylesheet" + uniqueIDParam(cssStyleSheetId);
+ cssStyleSheet.type = "text/css";
+ testContent.appendChild(cssStyleSheet);
+
+ var styleCount = 0;
+
+ function styleStatus(cssStyleSheet) {
+ if( cssStyleSheet.sheet || cssStyleSheet.styleSheet || cssStyleSheet.innerHTML ) {
+ report("stylesheet", "insecure stylesheet loaded");
+ }
+ else {
+ if(styleCount < MAX_COUNT) {
+ styleCount++;
+ setTimeout(styleStatus, TIMEOUT_INTERVAL, cssStyleSheet);
+ }
+ else {
+ //After we have called setTimeout the maximum number of times, assume stylesheet is blocked
+ report("stylesheet", "insecure stylesheet blocked");
+ }
+ }
+ }
+
+ // link does not have onload and onerror events. Hence we need a setTimeout to check the link's status
+ window.setTimeout(styleStatus, TIMEOUT_INTERVAL, cssStyleSheet);
+
+ // Test 1d: insecure iframe
+ var iframe = document.createElement("iframe");
+ var iframeId = uniqueID();
+ iframe.src = baseUrl + "?type=iframe" + uniqueIDParam(iframeId);
+ iframe.onload = function() {
+ report("iframe", "insecure iframe loaded");
+ }
+ iframe.onerror = function() {
+ report("iframe", "insecure iframe blocked");
+ };
+ testContent.appendChild(iframe);
+
+
+ // Test 1e: insecure xhr
+ await new Promise((resolve) => {
+ var xhr = new XMLHttpRequest;
+ var xhrId = uniqueID();
+ try {
+ xhr.open("GET", baseUrl + "?type=xhr" + uniqueIDParam(xhrId), true);
+ xhr.send();
+ xhr.onloadend = function (oEvent) {
+ if (xhr.status == 200) {
+ report("xhr", "insecure xhr loaded");
+ resolve();
+ }
+ else {
+ report("xhr", "insecure xhr blocked");
+ resolve();
+ }
+ }
+ } catch(ex) {
+ report("xhr", "insecure xhr blocked");
+ resolve();
+ }
+ });
+
+ /* Part 2: Mixed Display tests */
+
+ // Shorthand for all image test variants
+ async function imgHandlers(img, test, uniqueID) {
+ await new Promise((resolve) => {
+ img.onload = async () => {
+ const lastRequest = await checkLastRequest();
+ is(lastRequest.uniqueID, uniqueID, "UniqueID for the last request matches");
+ let message = "insecure image loaded";
+ if (lastRequest.scheme == "https") {
+ message = "secure image loaded after upgrade";
+ }
+ report(test, message);
+ resolve();
+ }
+ img.onerror = async () => {
+ let message = "insecure image blocked";
+ report(test, message);
+ resolve();
+ }
+ });
+ }
+
+ // Test 2a: insecure image
+ var img = document.createElement("img");
+ var imgId = uniqueID();
+ img.src = baseUrl + "?type=img" + uniqueIDParam(imgId);
+ await imgHandlers(img, "image", imgId);
+ // We don't need to append the image to the document. Doing so causes the image test to run twice.
+
+ // Test 2b: insecure media
+ var media = document.createElement("video");
+ var mediaId = uniqueID();
+ media.src = baseUrl + "?type=media" + uniqueIDParam(mediaId);
+ media.width = "320";
+ media.height = "200";
+ media.type = "video/ogg";
+ await new Promise(res => {
+ media.onloadeddata = async () => {
+ const lastRequest = await checkLastRequest();
+ is(lastRequest.uniqueID, mediaId, "UniqueID for the last request matches");
+ let message = "insecure media loaded";
+ if (lastRequest.scheme == "https") {
+ message = "secure media loaded after upgrade";
+ }
+ report("media", message);
+ res();
+ }
+ media.onerror = function() {
+ report("media", "insecure media blocked");
+ res();
+ }
+ });
+ // We don't need to append the video to the document. Doing so causes the image test to run twice.
+
+ /* Part 3: Mixed Active Tests for Image srcset */
+
+ // Test 3a: image with srcset
+ var imgA = document.createElement("img");
+ var imgAId = uniqueID();
+ imgA.srcset = baseUrl + "?type=img&subtype=imageSrcset" + uniqueIDParam(imgAId);
+ await imgHandlers(imgA, "imageSrcset", imgAId);
+
+ // Test 3b: image with srcset, using fallback from src, should still use imageset policy
+ var imgB = document.createElement("img");
+ var imgBId = uniqueID();
+ imgB.srcset = " ";
+ imgB.src = baseUrl + "?type=img&subtype=imageSrcSetFallback" + uniqueIDParam(imgBId);
+ await imgHandlers(imgB, "imageSrcsetFallback", imgBId);
+
+ // Test 3c: image in <picture>
+ var imgC = document.createElement("img");
+ var pictureC = document.createElement("picture");
+ var sourceC = document.createElement("source");
+ var sourceCId = uniqueID();
+ sourceC.srcset = baseUrl + "?type=img&subtype=imagePicture" + uniqueIDParam(sourceCId);
+ pictureC.appendChild(sourceC);
+ pictureC.appendChild(imgC);
+ await imgHandlers(imgC, "imagePicture", sourceCId);
+
+ // Test 3d: Loaded basic image switching to a <picture>, loading
+ // same source, should still redo the request with new
+ // policy.
+ var imgD = document.createElement("img");
+ var imgDId = uniqueID();
+ var sourceDId = uniqueID();
+ imgD.src = baseUrl + "?type=img&subtype=imageJoinPicture" + uniqueIDParam(imgDId);
+ await new Promise(res => {
+ imgD.onload = imgD.onerror = function() {
+ // Whether or not it loads, we want to now append it to a picture and observe
+ var pictureD = document.createElement("picture");
+ var sourceD = document.createElement("source");
+ sourceD.srcset = baseUrl + "?type=img&subtype=imageJoinPicture2" + uniqueIDParam(sourceDId);
+ pictureD.appendChild(sourceD);
+ pictureD.appendChild(imgD);
+ res();
+ }
+ });
+ await imgHandlers(imgD, "imageJoinPicture", sourceDId);
+
+ // Test 3e: img load from <picture> source reverts to img.src as it
+ // is removed -- the new request should revert to mixed
+ // display policy
+ var imgE = document.createElement("img");
+ var pictureE = document.createElement("picture");
+ var pictureEId = uniqueID();
+ var sourceE = document.createElement("source");
+ var sourceEId = uniqueID();
+ sourceE.srcset = baseUrl + "?type=img&subtype=imageLeavePicture" + uniqueIDParam(sourceEId);
+ pictureE.appendChild(sourceE);
+ pictureE.appendChild(imgE);
+ imgE.src = baseUrl + "?type=img&subtype=imageLeavePicture2" + uniqueIDParam(pictureEId);
+ await new Promise(res => {
+ imgE.onload = imgE.onerror = function() {
+ // Whether or not it loads, remove it from the picture and observe
+ pictureE.removeChild(imgE)
+ res();
+ }
+ });
+ await imgHandlers(imgE, "imageLeavePicture", pictureEId);
+ }
+
+ init();
+
+</script>
+</body>
+</html>