diff options
Diffstat (limited to 'dom/canvas/test/test_imagebitmap.html')
-rw-r--r-- | dom/canvas/test/test_imagebitmap.html | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/dom/canvas/test/test_imagebitmap.html b/dom/canvas/test/test_imagebitmap.html new file mode 100644 index 0000000000..7a68db08df --- /dev/null +++ b/dom/canvas/test/test_imagebitmap.html @@ -0,0 +1,355 @@ +<!DOCTYPE HTML> +<title>Test ImageBitmap</title> +<meta charset="utf-8"> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" href="/tests/SimpleTest/test.css"> +<body> + +<img src="image_anim-gr.gif" id="image" class="resource"> +<video width="320" height="240" src="http://example.com/tests/dom/canvas/test/crossorigin/video.sjs?name=tests/dom/canvas/test/320x240.ogv&type=video/ogg&cors=anonymous" id="video" crossOrigin="anonymous" autoplay></video> + +<canvas id="c1" class="output" width="128" height="128"></canvas> +<canvas id="c2" width="128" height="128"></canvas> + +<script src="imagebitmap_bug1239300.js"></script> +<script src="imagebitmap_bug1239752.js"></script> +<script type="text/javascript"> + +SimpleTest.waitForExplicitFinish(); + +/** + * [isPixel description] + * @param {[type]} ctx : canvas context + * @param {[type]} x : pixel x coordinate + * @param {[type]} y : pixel y coordinate + * @param {[type]} c : a rgba color code + * @param {[type]} d : error duration + * @return {Promise} + */ +function isPixel(ctx, x, y, c, d) { + var pos = x + "," + y; + var color = c[0] + "," + c[1] + "," + c[2] + "," + c[3]; + var pixel = ctx.getImageData(x, y, 1, 1); + var pr = pixel.data[0], + pg = pixel.data[1], + pb = pixel.data[2], + pa = pixel.data[3]; + ok(c[0]-d <= pr && pr <= c[0]+d && + c[1]-d <= pg && pg <= c[1]+d && + c[2]-d <= pb && pb <= c[2]+d && + c[3]-d <= pa && pa <= c[3]+d, + "pixel "+pos+" of "+ctx.canvas.id+" is "+pr+","+pg+","+pb+","+pa+"; expected "+color+" +/- "+d); +} + +var TEST_BITMAPS = [ + {'rect': [0, 0, 128, 128], 'draw': [0, 0, 64, 64, 0, 0, 64, 64], 'test': [[0, 0, [255, 0, 0, 255], 5]]}, + {'rect': [128, 0, 128, 128], 'draw': [0, 0, 64, 64, 0, 0, 64, 64], 'test': [[0, 0, [0, 255, 0, 255], 5]]}, + {'rect': [230, 230, 128, 128], 'draw': [0, 0, 128, 128, 0, 0, 128, 128], 'test': [[0, 0, [255, 0, 0, 255], 5], + [100, 100, [0, 0, 0, 0], 5]]}, + {'rect': [-64, -64, 512, 512], 'draw': [0, 0, 128, 128, 0, 0, 128, 128], 'test': [[0, 0, [0, 0, 0, 0], 5], + [100, 100, [255, 0, 0, 255], 5]]}, + {'rect': [128, 128, -128, -128], 'draw': [0, 0, 128, 128, 0, 0, 128, 128], 'test': [[0, 0, [255, 0, 0, 255], 5]]}, + {'rect': [0, 0, 256, 256], 'draw': [0, 128, 128, 128, 0, 0, 128, 128], 'test': [[0, 0, [0, 255, 0, 255], 5]]}, +]; + +var canvas, ctx, ctx2, completedImage; + +function failed(ex) { + ok(false, "Promise failure: " + ex); +} + +function testDraw() { + var resolver, bitmaps = [], image = new Image(); + + image.src = 'image_rgrg-256x256.png'; + var promise = new Promise(function (arg) { resolver = arg; }); + + function createBitmap(def) { + return createImageBitmap(image, def.rect[0], def.rect[1], def.rect[2], def.rect[3]) + .then(function (bitmap) { def.bitmap = bitmap; }, failed); + }; + + image.onload = function() { + completedImage = image; + resolver(Promise.all(TEST_BITMAPS.map(createBitmap))); + }; + + function testPixel(test) { + isPixel(ctx, test[0], test[1], test[2], test[3]); + }; + + return promise.then(function() { + TEST_BITMAPS.forEach(function (test) { + if (!test.bitmap) { return; } + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(test.bitmap, test.draw[0], test.draw[1], test.draw[2], test.draw[3], test.draw[4], test.draw[5], test.draw[6], test.draw[7]); + test.test.forEach(testPixel); + is(test.bitmap.width, Math.abs(test.rect[2]), "Bitmap has correct width " + test.bitmap.width); + is(test.bitmap.height, Math.abs(test.rect[3]), "Bitmap has correct height " + test.bitmap.height); + }); + }); +} + +function testSources() { + ctx.fillStyle="#00FF00"; + ctx.fillRect(0, 0, 128, 128); + + function check(bitmap) { + ctx2.clearRect(0, 0, 128, 128); + ctx2.drawImage(bitmap, 0, 0); + isPixel(ctx2, 0, 0, [0, 255, 0, 255], 5); + }; + + function getPNGBlobBitmapPromise() { + return new Promise(function(resolve, reject) { + canvas.toBlob(function(blob) { + resolve(createImageBitmap(blob)); + }) + }); + } + + function getJPGBlobBitmapPromise() { + return new Promise(function(resolve, reject) { + canvas.toBlob(function(blob) { + resolve(createImageBitmap(blob)); + }, "image/jpeg", 0.95) + }); + } + + return Promise.all([ + createImageBitmap(document.getElementById('image')).then(check, failed), // HTMLImageElement + createImageBitmap(ctx).then(check, failed), // CanvasRenderingContext2D + createImageBitmap(canvas).then(check, failed), // HTMLCanvasElement + createImageBitmap(ctx).then(function (bitmap) { return createImageBitmap(bitmap).then(check, failed); }, failed), // ImageBitmap + createImageBitmap(document.getElementById('video'), 140, 0, 20, 20).then(check, failed), // HTMLVideoElement + createImageBitmap(ctx.getImageData(0, 0, 128, 128)).then(check, failed), // ImageData + getPNGBlobBitmapPromise().then(check, failed), // PNG blob + getJPGBlobBitmapPromise().then(check, failed), // JPEG blob + ]); +} + +function promiseThrows(p, name) { + var didThrow; + return p.then(function() { didThrow = false; }, + function() { didThrow = true; }) + .then(function() { ok(didThrow, name); }); +} + +function testExceptions() { + + function createImageBitmapWithNeuturedImageData() { + return new Promise(function(resolve, reject) { + var tempImage = document.createElement('img'); + tempImage.src = 'image_rgrg-256x256.png'; + tempImage.onload = function() { + var tempCanvas = document.createElement('canvas'); + var tempCtx = tempCanvas.getContext('2d'); + tempCanvas.with = tempImage.naturalWidth; + tempCanvas.height = tempImage.naturalHeight; + tempCtx.drawImage(tempImage, 0, 0); + var tempWorker = new Worker("test_imagebitmap_on_worker.js"); + var imageData = tempCtx.getImageData(0, 0, tempImage.naturalWidth, tempImage.naturalHeight); + tempWorker.postMessage(imageData.data.buffer, [imageData.data.buffer]); + tempWorker.terminate(); + + ok(!imageData.data.length, "Get a neutured ImageData."); + resolve(createImageBitmap(imageData)); + } + }); + } + + function createImageBitmapWithCorruptedBlob() { + return new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", "image_error-early.png"); + xhr.responseType = "blob";//force the HTTP response, response-type header to be blob + xhr.onload = function() + { + ok(xhr.response, "Get a corrupted blob"); + resolve(createImageBitmap(xhr.response)); + } + xhr.send(); + }); + } + + function createImageBitmapWithNonImageFile() { + return new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", "test_imagebitmap_on_worker.js"); + xhr.responseType = "blob";//force the HTTP response, response-type header to be blob + xhr.onload = function() + { + ok(xhr.response, "Get a non-image blob"); + resolve(createImageBitmap(xhr.response)); + } + xhr.send(); + }); + } + + return Promise.all([ + promiseThrows(createImageBitmap(new Image()), 'createImageBitmap should throw with unloaded image'), + promiseThrows(createImageBitmap(completedImage, 0, 0, 0, 0), 'createImageBitmap should throw with 0 width/height'), + promiseThrows(createImageBitmap(null), 'createImageBitmap should throw with null source'), + promiseThrows(createImageBitmapWithNeuturedImageData(), "createImageBitmap should throw with neutured ImageData"), + promiseThrows(createImageBitmapWithCorruptedBlob(), "createImageBitmap should throw with corrupted blob"), + promiseThrows(createImageBitmapWithNonImageFile(), "createImageBitmap should throw with non-image blob"), + ]); +} + +function testSecurityErrors() { + + function getUncleanImagePromise() { + return new Promise(function(resolve, reject) { + var uncleanImage = document.createElement('img'); + + uncleanImage.onload = function() { + resolve(createImageBitmap(uncleanImage)); + } + + uncleanImage.onerror = function() { + reject(); + } + + uncleanImage.src = "http://example.com/tests/dom/canvas/test/crossorigin/image.png"; + }); + } + + function getUncleanVideoPromise() { + return new Promise(function(resolve, reject) { + var uncleanVideo = document.createElement('video'); + + uncleanVideo.onloadeddata = function() { + resolve(createImageBitmap(uncleanVideo)); + } + + uncleanVideo.onerror = function() { + reject(); + } + + uncleanVideo.src = "http://example.com/tests/dom/canvas/test/crossorigin/video.sjs?name=tests/dom/canvas/test/320x240.ogv&type=video/ogg"; + uncleanVideo.play(); + }); + } + + function getTaintedCanvasPromise() { + return new Promise(function(resolve, reject) { + var uncleanImage = document.createElement('img'); + + uncleanImage.onload = function() { + var taintedCanvas = document.createElement('canvas'); + var taintedCtx = taintedCanvas.getContext('2d'); + taintedCtx.drawImage(uncleanImage, 0, 0); + resolve(createImageBitmap(taintedCanvas)); + } + + uncleanImage.onerror = function() { + reject(); + } + + uncleanImage.src = "http://example.com/tests/dom/canvas/test/crossorigin/image.png"; + }); + } + + function getTaintedCanvasRenderingContex2dPromise() { + return new Promise(function(resolve, reject) { + var uncleanImage = document.createElement('img'); + + uncleanImage.onload = function() { + var taintedCanvas = document.createElement('canvas'); + var taintedCtx = taintedCanvas.getContext('2d'); + taintedCtx.drawImage(uncleanImage, 0, 0); + resolve(createImageBitmap(taintedCtx)); + } + + uncleanImage.onerror = function() { + reject(); + } + + uncleanImage.src = "http://example.com/tests/dom/canvas/test/crossorigin/image.png"; + }); + } + + function checkPromiseFailedWithSecurityError(p) { + return p.then(imageBitmap => { + ok(!!imageBitmap, "ImageBitmaps are always created"); + const context = document.createElement("canvas").getContext("2d"); + context.drawImage(imageBitmap, 0, 0); + try { + context.getImageData(0, 0, 1, 1); + ok(false, "Did not get SecurityError with unclean source. ImageBitmap was created successfully."); + } catch (ex) { + if (ex == "SecurityError: The operation is insecure.") { + ok(true, ex.message); + } + else { + ok(false, "Did not get SecurityError with unclean source. Error Message: " + ex.message); + } + } + }); + } + + return Promise.all([ + checkPromiseFailedWithSecurityError(getUncleanImagePromise()), + checkPromiseFailedWithSecurityError(getUncleanVideoPromise()), + checkPromiseFailedWithSecurityError(getTaintedCanvasPromise()), + checkPromiseFailedWithSecurityError(getTaintedCanvasRenderingContex2dPromise()), + ]); +} + +function testCreatePattern() { + var resolve; + var promise = new Promise(function (arg) { resolve = arg; }); + + var TEST_PATTERN = [ + [0, 0, [255, 0, 0, 255], 1], + [128, 128, [255, 0, 0, 255], 1], + [256, 256, [255, 0, 0, 255], 1], + [384, 0, [0, 255, 0, 255], 1], + [0, 384, [0, 255, 0, 255], 1], + ]; + + var patternCanvas = document.createElement('canvas'); + patternCanvas.width = "512"; + patternCanvas.height = "512"; + var patternCtx = patternCanvas.getContext('2d'); + + var image = new Image(); + image.src = 'image_rgrg-256x256.png'; + image.onload = function() { + var p = createImageBitmap(image); + p.then(function(bitmap) { + patternCtx.rect(0, 0, 512, 512); + patternCtx.fillStyle = patternCtx.createPattern(bitmap, "repeat"); + patternCtx.fill(); + document.body.appendChild(patternCanvas); + }); + resolve(p); + } + + return promise.then(function() { + TEST_PATTERN.forEach(function(test) { + isPixel(patternCtx, test[0], test[1], test[2], test[3]); + }); + }); +} + + +function runTests() { + canvas = document.getElementById('c1'); + ctx = canvas.getContext('2d'); + ctx2 = document.getElementById('c2').getContext('2d'); + + testDraw() + .then(testCreatePattern) + .then(testSources) + .then(testExceptions) + .then(testSecurityErrors) + .then(testBug1239300) + .then(testBug1239752) + .then(SimpleTest.finish, function(ev) { failed(ev); SimpleTest.finish(); }); +} + +addLoadEvent(runTests); + +</script> +</body> |