diff options
Diffstat (limited to 'dom/security/test/mixedcontentblocker/file_main.html')
-rw-r--r-- | dom/security/test/mixedcontentblocker/file_main.html | 338 |
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> |