diff options
Diffstat (limited to 'dom/canvas/test/crossorigin')
-rw-r--r-- | dom/canvas/test/crossorigin/image-allow-credentials.png | bin | 0 -> 844 bytes | |||
-rw-r--r-- | dom/canvas/test/crossorigin/image-allow-credentials.png^headers^ | 2 | ||||
-rw-r--r-- | dom/canvas/test/crossorigin/image-allow-star.png | bin | 0 -> 844 bytes | |||
-rw-r--r-- | dom/canvas/test/crossorigin/image-allow-star.png^headers^ | 1 | ||||
-rw-r--r-- | dom/canvas/test/crossorigin/image.png | bin | 0 -> 844 bytes | |||
-rw-r--r-- | dom/canvas/test/crossorigin/mochitest.toml | 22 | ||||
-rw-r--r-- | dom/canvas/test/crossorigin/test_canvas2d_crossorigin.html | 212 | ||||
-rw-r--r-- | dom/canvas/test/crossorigin/test_video_crossorigin.html | 219 | ||||
-rw-r--r-- | dom/canvas/test/crossorigin/test_webgl_crossorigin_textures.html | 143 | ||||
-rw-r--r-- | dom/canvas/test/crossorigin/video.sjs | 52 |
10 files changed, 651 insertions, 0 deletions
diff --git a/dom/canvas/test/crossorigin/image-allow-credentials.png b/dom/canvas/test/crossorigin/image-allow-credentials.png Binary files differnew file mode 100644 index 0000000000..df24ac6d34 --- /dev/null +++ b/dom/canvas/test/crossorigin/image-allow-credentials.png diff --git a/dom/canvas/test/crossorigin/image-allow-credentials.png^headers^ b/dom/canvas/test/crossorigin/image-allow-credentials.png^headers^ new file mode 100644 index 0000000000..a03f99a9c0 --- /dev/null +++ b/dom/canvas/test/crossorigin/image-allow-credentials.png^headers^ @@ -0,0 +1,2 @@ +Access-Control-Allow-Origin: http://mochi.test:8888 +Access-Control-Allow-Credentials: true diff --git a/dom/canvas/test/crossorigin/image-allow-star.png b/dom/canvas/test/crossorigin/image-allow-star.png Binary files differnew file mode 100644 index 0000000000..df24ac6d34 --- /dev/null +++ b/dom/canvas/test/crossorigin/image-allow-star.png diff --git a/dom/canvas/test/crossorigin/image-allow-star.png^headers^ b/dom/canvas/test/crossorigin/image-allow-star.png^headers^ new file mode 100644 index 0000000000..cb762eff80 --- /dev/null +++ b/dom/canvas/test/crossorigin/image-allow-star.png^headers^ @@ -0,0 +1 @@ +Access-Control-Allow-Origin: * diff --git a/dom/canvas/test/crossorigin/image.png b/dom/canvas/test/crossorigin/image.png Binary files differnew file mode 100644 index 0000000000..df24ac6d34 --- /dev/null +++ b/dom/canvas/test/crossorigin/image.png diff --git a/dom/canvas/test/crossorigin/mochitest.toml b/dom/canvas/test/crossorigin/mochitest.toml new file mode 100644 index 0000000000..e45b2624cd --- /dev/null +++ b/dom/canvas/test/crossorigin/mochitest.toml @@ -0,0 +1,22 @@ +[DEFAULT] +support-files = [ + "image-allow-credentials.png", + "image-allow-credentials.png^headers^", + "image-allow-star.png", + "image-allow-star.png^headers^", + "image.png", + "video.sjs", +] + +["test_canvas2d_crossorigin.html"] +skip-if = [ + "http3", + "http2", +] + +["test_video_crossorigin.html"] +subsuite = "gpu" + +["test_webgl_crossorigin_textures.html"] +subsuite = "gpu" + diff --git a/dom/canvas/test/crossorigin/test_canvas2d_crossorigin.html b/dom/canvas/test/crossorigin/test_canvas2d_crossorigin.html new file mode 100644 index 0000000000..5c40ea028a --- /dev/null +++ b/dom/canvas/test/crossorigin/test_canvas2d_crossorigin.html @@ -0,0 +1,212 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=685518 +--> +<head> + <title>Test for Bug 685518</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685518">Mozilla Bug 685518</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 685518 **/ + +SimpleTest.waitForExplicitFinish(); + +const BAD_URI_ERR = "NS_ERROR_DOM_BAD_URI_ERR"; +const OK = ""; + +function verifyError(actual_error, expected_error, message) { + ok(actual_error == expected_error, + message + ": expected " + expected_error + ", got " + actual_error); +} + +var number_of_tests_live = 0; + +function testDone() { + number_of_tests_live--; + + if (number_of_tests_live == 0) + SimpleTest.finish(); +} + +function testImage(url, crossOriginAttribute, expected_error) { + ++number_of_tests_live; + var image; + if (crossOriginAttribute == "just-crossOrigin-without-value") { + var div = document.createElement('div'); + div.innerHTML="<img crossOrigin>"; + image = div.children[0]; + } + else { + image = new Image(); + if (crossOriginAttribute != "missing-value-default") { + image.crossOrigin = crossOriginAttribute; + } + } + + image.onload = function() { + var c = document.createElement("canvas"); + c.width = this.width; + c.height = this.height; + var ctx = c.getContext("2d"); + ctx.drawImage(this, 0, 0); + + var data; + var actual_error; + try { + data = ctx.getImageData(0, 0, 1, 1); + actual_error = OK; + } catch (e) { + actual_error = e.name; + } + + verifyError(actual_error, expected_error, + "drawImage then get image data on " + url + + " with crossOrigin=" + this.crossOrigin); + + try { + c.captureStream(0); + actual_error = OK; + } catch (e) { + actual_error = e.name; + } + + verifyError(actual_error, expected_error, + "drawImage then capture stream on " + url + + " with crossOrigin=" + this.crossOrigin); + + // Now test patterns + c = document.createElement("canvas"); + c.width = this.width; + c.height = this.height; + ctx = c.getContext("2d"); + ctx.fillStyle = ctx.createPattern(this, ""); + ctx.fillRect(0, 0, c.width, c.height); + try { + data = ctx.getImageData(0, 0, 1, 1); + actual_error = OK; + } catch (e) { + actual_error = e.name; + } + + verifyError(actual_error, expected_error, + "createPattern+fill then get image data on " + url + + " with crossOrigin=" + this.crossOrigin); + + try { + c.captureStream(0); + actual_error = OK; + } catch (e) { + actual_error = e.name; + } + + verifyError(actual_error, expected_error, + "createPattern+fill then capture stream on " + url + + " with crossOrigin=" + this.crossOrigin); + + testDone(); + }; + + image.onerror = function(event) { + verifyError(BAD_URI_ERR, expected_error, + "image error handler for " + url + + " with crossOrigin=" + this.crossOrigin); + + testDone(); + } + + image.src = url; +} + +// Now kick off the tests. +const testPath = "/tests/dom/canvas/test/crossorigin/" + +// First column is image file, second column is what CORS headers the server sends +const imageFiles = [ + [ "image.png", "none" ], + [ "image-allow-star.png", "allow-all-anon" ], + [ "image-allow-credentials.png", "allow-single-server-creds" ] +]; + +const hostnames = [ + [ "mochi.test:8888", "same-origin" ], + [ "example.com", "cross-origin" ] +]; + +// First column is the value; second column is the expected resulting CORS mode +const attrValues = [ + [ "missing-value-default", "none" ], + [ "", "anonymous" ], + [ "just-crossOrigin-without-value", "anonymous" ], + [ "anonymous", "anonymous" ], + [ "use-credentials", "use-credentials" ], + [ "foobar", "anonymous" ] +]; + +function beginTest() { + for (var imgIdx = 0; imgIdx < imageFiles.length; ++imgIdx) { + for (var hostnameIdx = 0; hostnameIdx < hostnames.length; ++hostnameIdx) { + var hostnameData = hostnames[hostnameIdx]; + var url = "http://" + hostnameData[0] + testPath + imageFiles[imgIdx][0]; + for (var attrValIdx = 0; attrValIdx < attrValues.length; ++attrValIdx) { + var attrValData = attrValues[attrValIdx]; + // Now compute the expected result + var expected_error; + if (hostnameData[1] == "same-origin") { + // Same-origin; these should all Just Work + expected_error = OK; + } else { + // Cross-origin + is(hostnameData[1], "cross-origin", + "what sort of host is " + hostnameData[0]); + var CORSMode = attrValData[1]; + if (CORSMode == "none") { + // Doesn't matter what headers the server sends; we're not + // using CORS on our end. + expected_error = "SecurityError"; + } else { + // Check whether the server will let us talk to them + var CORSHeaders = imageFiles[imgIdx][1]; + // We're going to look for CORS headers from the server + if (CORSHeaders == "none") { + // No CORS headers from server; load will fail. + expected_error = BAD_URI_ERR; + } else if (CORSHeaders == "allow-all-anon") { + // Server only allows anonymous requests + if (CORSMode == "anonymous") { + expected_error = OK; + } else { + is(CORSMode, "use-credentials", + "What other CORS modes are there?"); + // A load with credentials against a server that only + // allows anonymous loads will fail. + expected_error = BAD_URI_ERR; + } + } else { + is(CORSHeaders, "allow-single-server-creds", + "What other CORS headers could there be?"); + // Our server should allow both anonymous and non-anonymous requests + expected_error = OK; + } + } + } + testImage(url, attrValData[0], expected_error); + } + } + } +} + +beginTest(); +</script> +</pre> +</body> +</html> diff --git a/dom/canvas/test/crossorigin/test_video_crossorigin.html b/dom/canvas/test/crossorigin/test_video_crossorigin.html new file mode 100644 index 0000000000..89ca8e4a10 --- /dev/null +++ b/dom/canvas/test/crossorigin/test_video_crossorigin.html @@ -0,0 +1,219 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=682299 +--> +<head> + <title>Test for Bug 682299</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript" src="/tests/dom/media/test/manifest.js"></script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=682299">Mozilla Bug 682299</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 682299 **/ +SimpleTest.requestFlakyTimeout("untriaged"); + +function createCanvas(width, height) { + var c = document.createElement("canvas"); + c.width = width; + c.height = height; + return c; +} + +function checkGetImageData(ctx, v) { + try { + var data = ctx.getImageData(0, 0, 1, 1); + ok(true, "drawImage '" + v.src + "' then getImageData with crossOrigin='" + v.crossOrigin + "' worked"); + } catch(error) { + ok(!v.crossOrigin && error.name === "SecurityError", "drawImage '" + v.src + "' then getImageData with crossOrigin='" + v.crossOrigin + "' failed"); + v.tainted = true; + } +} + +function checkGetImageDataTainted(ctx, v) { + try { + var data = ctx.getImageData(0, 0, 1, 1); + ok(false, "changing the CORS mode should not allow reading data from remote videos"); + } catch (error) { + ok(error.name === "SecurityError", "changing the CORS mode, drawImage '" + v.src + "' then getImageData with crossOrigin='" + v.crossOrigin + "' failed"); + } +} + +function checkCaptureStream(c, v) { + try { + var stream = c.captureStream(0); + ok(true, "drawImage '" + v.src + "' then captureStream with crossOrigin='" + v.crossOrigin + "' worked"); + } catch(error) { + ok(!v.crossOrigin && error.name === "SecurityError", "drawImage '" + v.src + "' then captureStream with crossOrigin='" + v.crossOrigin + "' failed"); + v.tainted = true; + } +} + +function checkCaptureStreamTainted(c, v) { + try { + var stream = c.captureStream(0); + ok(false, "changing the CORS mode should not allow capturing a stream from remote videos"); + } catch (error) { + ok(error.name === "SecurityError", "changing the CORS mode, drawImage '" + v.src + "' then captureStream with crossOrigin='" + v.crossOrigin + "' failed"); + } +} + +function testCanvasDrawImage(v) { + var c = createCanvas(v.width, v.height); + var ctx = c.getContext("2d"); + ctx.drawImage(v, 0, 0); + + checkGetImageData(ctx, v); + checkCaptureStream(c, v); +} + +function testCanvasCreatePattern(v) { + var c = createCanvas(v.width, v.height); + var ctx = c.getContext("2d"); + ctx.fillStyle = ctx.createPattern(v, ""); + ctx.fillRect(0, 0, c.width, c.height); + + checkGetImageData(ctx, v); + checkCaptureStream(c, v); +} + +function testWebGL(gl, v) { + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + + try { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, v); + ok(true, "createTexture from '" + v.src + "' with crossOrigin='" + v.crossOrigin + "' worked"); + } catch (error) { + ok(!v.crossOrigin && error.name === "SecurityError", "createTexture from '" + v.src + "' with crossOrigin='" + v.crossOrigin + "' failed"); + v.tainted = true; + } +} + +function testTaintedCanvas(v) { + var c = createCanvas(v.width, v.height); + var ctx = c.getContext("2d"); + ctx.drawImage(v, 0, 0); + + checkGetImageDataTainted(ctx, v); + checkCaptureStreamTainted(c, v); +} + +function vidDataSuccess(e) { + ok(!e.target.error, "Load '" + e.target.src + "' with crossOrigin='" + e.target.crossOrigin + "'"); + + testCanvasDrawImage(e.target); + testCanvasCreatePattern(e.target); + if (document.gl) { + testWebGL(document.gl, e.target); + } + // If we change the CORS mode after loading the file without CORS it should still throw a security error + if (e.target.tainted) { + e.target.crossOrigin = "anonymous"; + testTaintedCanvas(e.target); + } + + doneTest(e); +} + +function vidLoadFailure(e) { + ok(false, "Load '" + e.target.src + "' with crossOrigin='" + e.target.crossOrigin + "'"); + doneTest(e); +} + +function vidErrorSuccess(e) { + ok(e.target.error.code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED, + "Load '" + e.target.src + "' with crossOrigin='" + e.target.crossOrigin + "'"); + doneTest(e); +} + +function startTest(test, token) { + var v = document.createElement('video'); + if (test.cors === "just-crossOrigin-without-value") { + var div = document.createElement('div'); + div.innerHTML="<video crossOrigin>"; + v = div.children[0]; + } else if (test.cors !== "missing-value-default") { + v.crossOrigin = test.cors; + } + v.token = token; + document.manager.started(token); + v.autoplay = true; + v.preload = "auto"; + v.style.display = "none"; + if (test.nameIntent === test.corsIntent || test.corsIntent === "none" || + (test.nameIntent === "use-credentials" && test.corsIntent === "anonymous")) { + v.addEventListener("loadeddata", vidDataSuccess); + v.addEventListener("error", vidLoadFailure); + } else { + v.addEventListener("loadeddata", vidLoadFailure); + v.addEventListener("error", vidErrorSuccess); + } + v.src = test.name; + document.body.appendChild(v); +} + +function doneTest(e) { + var v = e.target; + v.remove(); + document.manager.finished(v.token); +} + +function beginTest() { + var videoFile = getPlayableVideo(gSmallTests); + if (!videoFile) { + SimpleTest.finish(); + } + videoFile = "?name=tests/dom/media/test/" + videoFile.name + "&type=" + videoFile.type; + + document.manager = new MediaTestManager; + var corsTests = []; + + const host = "http://example.com/tests/dom/canvas/test/crossorigin/video.sjs"; + const serverAttrValues = [ + [ "&cors=none", "none" ], + [ "&cors=anonymous", "anonymous" ], + [ "&cors=use-credentials", "use-credentials" ] + ]; + const clientAttrValues = [ + [ "missing-value-default", "none" ], + [ "", "anonymous" ], + [ "just-crossOrigin-without-value", "anonymous" ], + [ "anonymous", "anonymous" ], + [ "use-credentials", "use-credentials" ], + [ "foobar", "anonymous" ] + ]; + + // Build the video file test array + for (var i = 0; i < serverAttrValues.length; i++) { + for (var n = 0; n < clientAttrValues.length; n++) { + corsTests.push({ + name: host + videoFile + serverAttrValues[i][0], + nameIntent: serverAttrValues[i][1], + cors: clientAttrValues[n][0], + corsIntent: clientAttrValues[n][1] + }); + } + } + try { + document.gl = createCanvas(16, 16).getContext("experimental-webgl"); + } catch (ex) { + // Mac OS X 10.5 doesn't support WebGL, so we won't run the WebGL tests + } + document.manager.runTests(corsTests, startTest); +} + +SimpleTest.waitForExplicitFinish(); +beginTest(); +</script> +</pre> +</body> +</html> diff --git a/dom/canvas/test/crossorigin/test_webgl_crossorigin_textures.html b/dom/canvas/test/crossorigin/test_webgl_crossorigin_textures.html new file mode 100644 index 0000000000..545048a340 --- /dev/null +++ b/dom/canvas/test/crossorigin/test_webgl_crossorigin_textures.html @@ -0,0 +1,143 @@ +<!DOCTYPE HTML> +<title>WebGL cross-origin textures test</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" href="/tests/SimpleTest/test.css"> +<body> +<canvas id="canvas" style="border: none;" width="100" height="100"> + <p class="fallback"> FAIL (fallback content) </p> +</canvas> +<script> + + SimpleTest.waitForExplicitFinish(); + + const OK = ""; + + var gl; + var number_of_tests_live = 0; + var all_tests_started = false; + + function verifyError(actual_error, expected_error, message) { + ok(actual_error == expected_error, + message + ": expected " + expected_error + ", got " + actual_error); + } + + function testTexture(url, crossOriginAttribute, expected_error) { + number_of_tests_live++; + var image = new Image(); + if (crossOriginAttribute == "just-crossOrigin-without-value") { + var div = document.createElement('div'); + div.innerHTML="<img crossOrigin>"; + image = div.children[0]; + } + else if (crossOriginAttribute != "missing-value-default") + image.crossOrigin = crossOriginAttribute; + + + function testDone() { + number_of_tests_live--; + + if (number_of_tests_live == 0 && all_tests_started) + SimpleTest.finish(); + } + + image.onload = function() { + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + var actual_error = OK; + try { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); + } catch(e) { + actual_error = e.name; + } + verifyError(actual_error, expected_error, "texImage2D on " + url + " with crossOrigin=" + image.crossOrigin); + + testDone(); + }; + + image.onerror = function(event) { + ok(expected_error != OK, "Got an error but expected OK!"); + + testDone(); + } + + image.src = url; + } + + addLoadEvent(function () { + var canvas = document.getElementById("canvas"); + gl = canvas.getContext("experimental-webgl"); + if (!gl) { + todo(false, "Canvas WebGL not supported"); + SimpleTest.finish(); + return; + } + + + testTexture("http://mochi.test:8888/tests/dom/canvas/test/crossorigin/image.png", + "missing-value-default", + OK); + testTexture("http://mochi.test:8888/tests/dom/canvas/test/crossorigin/image.png", + "", + OK); + testTexture("http://mochi.test:8888/tests/dom/canvas/test/crossorigin/image.png", + "just-crossOrigin-without-value", + OK); + testTexture("http://example.com/tests/dom/canvas/test/crossorigin/image.png", + "missing-value-default", + "SecurityError"); + testTexture("http://example.com/tests/dom/canvas/test/crossorigin/image.png", + "", + "SecurityError"); + testTexture("http://example.com/tests/dom/canvas/test/crossorigin/image.png", + "just-crossOrigin-without-value", + "SecurityError"); + + testTexture("http://example.com/tests/dom/canvas/test/crossorigin/image-allow-star.png", + "missing-value-default", + "SecurityError"); + testTexture("http://example.com/tests/dom/canvas/test/crossorigin/image-allow-star.png", + "", + OK); + testTexture("http://example.com/tests/dom/canvas/test/crossorigin/image-allow-star.png", + "just-crossOrigin-without-value", + OK); + testTexture("http://example.com/tests/dom/canvas/test/crossorigin/image-allow-star.png", + "anonymous", + OK); + testTexture("http://example.com/tests/dom/canvas/test/crossorigin/image-allow-star.png", + "use-credentials", + "SecurityError"); + + testTexture("http://example.com/tests/dom/canvas/test/crossorigin/image-allow-credentials.png", + "missing-value-default", + "SecurityError"); + testTexture("http://example.com/tests/dom/canvas/test/crossorigin/image-allow-credentials.png", + "", + OK); + testTexture("http://example.com/tests/dom/canvas/test/crossorigin/image-allow-credentials.png", + "just-crossOrigin-without-value", + OK); + testTexture("http://example.com/tests/dom/canvas/test/crossorigin/image-allow-credentials.png", + "anonymous", + OK); + testTexture("http://example.com/tests/dom/canvas/test/crossorigin/image-allow-credentials.png", + "use-credentials", + OK); + + // Test that bad values for crossorigin="..." are interpreted as invalid-value-default which is "anonymous". + testTexture("http://mochi.test:8888/tests/dom/canvas/test/crossorigin/image.png", + "foobar", + OK); + testTexture("http://example.com/tests/dom/canvas/test/crossorigin/image.png", + "foobar", + "SecurityError"); + testTexture("http://example.com/tests/dom/canvas/test/crossorigin/image-allow-star.png", + "foobar", + OK); + testTexture("http://example.com/tests/dom/canvas/test/crossorigin/image-allow-credentials.png", + "foobar", + OK); + + all_tests_started = true; + }); +</script> diff --git a/dom/canvas/test/crossorigin/video.sjs b/dom/canvas/test/crossorigin/video.sjs new file mode 100644 index 0000000000..1101d3c5b3 --- /dev/null +++ b/dom/canvas/test/crossorigin/video.sjs @@ -0,0 +1,52 @@ +function parseQuery(request, key) { + var params = request.queryString.split("&"); + for (var j = 0; j < params.length; ++j) { + var p = params[j]; + if (p == key) { + return true; + } + if (p.indexOf(key + "=") == 0) { + return p.substring(key.length + 1); + } + if (p.indexOf("=") < 0 && key == "") { + return p; + } + } + return false; +} + +function handleRequest(request, response) { + var name = parseQuery(request, "name"); + var type = parseQuery(request, "type"); + var cors = parseQuery(request, "cors"); + var file = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIProperties) + .get("CurWorkD", Ci.nsIFile); + var fis = Cc["@mozilla.org/network/file-input-stream;1"].createInstance( + Ci.nsIFileInputStream + ); + var bis = Cc["@mozilla.org/binaryinputstream;1"].createInstance( + Ci.nsIBinaryInputStream + ); + var split = name.split("/"); + for (var i = 0; i < split.length; ++i) { + file.append(split[i]); + } + fis.init(file, -1, -1, false); + bis.setInputStream(fis); + var bytes = bis.readBytes(bis.available()); + response.setHeader("Content-Length", "" + bytes.length, false); + response.setHeader("Content-Type", type, false); + if (cors == "anonymous") { + response.setHeader("Access-Control-Allow-Origin", "*", false); + } else if (cors == "use-credentials") { + response.setHeader( + "Access-Control-Allow-Origin", + "http://mochi.test:8888", + false + ); + response.setHeader("Access-Control-Allow-Credentials", "true", false); + } + response.write(bytes, bytes.length); + bis.close(); +} |