<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/html/canvas/resources/canvas-tests.js"></script>
<link rel="help" href="https://html.spec.whatwg.org/#dom-offscreencanvas-converttoblob">
<script id="myWorker" type="text/worker">
function drawCanvas(ctx)
{
    ctx.fillStyle = "red";
    ctx.fillRect(0, 0, 5, 5);
    ctx.fillStyle = "green";
    ctx.fillRect(5, 0, 5, 5);
    ctx.fillStyle = "blue";
    ctx.fillRect(0, 5, 5, 5);
    ctx.fillStyle = "black";
    ctx.fillRect(5, 5, 5, 5);
}

function testConvertToBlob(typeVal, qualityVal) {
    var offscreenCanvas = new OffscreenCanvas(10, 10);
    var oCtx = offscreenCanvas.getContext('2d');
    drawCanvas(oCtx);

    var promise;
    if (typeVal == "empty" && qualityVal == "empty")
        promise = offscreenCanvas.convertToBlob();
    else if (typeVal == "empty" && qualityVal != "empty")
        promise = offscreenCanvas.convertToBlob({quality: qualityVal});
    else if (typeVal != "empty" && qualityVal == "empty")
        promise = offscreenCanvas.convertToBlob({type: typeVal});
    else
        promise = offscreenCanvas.convertToBlob({type: typeVal, quality: qualityVal});
    promise.then(function(blob) {
        self.postMessage(blob);
    });
}

function testConvertToBlobException1()
{
    var offscreenCanvas = new OffscreenCanvas(10, 10);
    self.postMessage({offscreenCanvas}, [offscreenCanvas]);
    offscreenCanvas.convertToBlob().then(function() {
        self.postMessage(false);
    }, function(e) {
        self.postMessage(e instanceof DOMException && e.name == "InvalidStateError");
    });
}

function testConvertToBlobException2()
{
    var offscreenCanvas = new OffscreenCanvas(0, 0);
    offscreenCanvas.convertToBlob().then(function() {
        self.postMessage(false);
    }, function(e) {
        self.postMessage(e instanceof DOMException && e.name == "IndexSizeError");
    });
}

function testConvertToBlobException3(bitmap)
{
    var offscreenCanvas = new OffscreenCanvas(10, 10);
    var ctx = offscreenCanvas.getContext("2d");
    ctx.drawImage(bitmap, 0, 0);
    offscreenCanvas.convertToBlob().then(function() {
        self.postMessage(false);
    }, function(e) {
        self.postMessage(e instanceof DOMException && e.name == "SecurityError");
    });
}

self.onmessage = function(e) {
    if (e.data instanceof ImageBitmap) {
        testConvertToBlobException3(e.data);
        return;
    }

    switch(e.data) {
        case 'test1':
            testConvertToBlob("empty", "empty");
            break;
        case 'test2':
            testConvertToBlob("empty", 1.0);
            break;
        case 'test3':
            testConvertToBlob("empty", 0.2);
            break;
        case 'test4':
            testConvertToBlob("image/png", "empty");
            break;
        case 'test5':
            testConvertToBlob("image/png", 1.0);
            break;
        case 'test6':
            testConvertToBlob("image/png", 0.2);
            break;
        case 'test7':
            testConvertToBlob("image/jpeg", "empty");
            break;
        case 'test8':
            testConvertToBlob("image/jpeg", 1.0);
            break;
        case 'test9':
            testConvertToBlob("image/jpeg", 0.2);
            break;
        case 'test10':
            testConvertToBlob("image/webp", "empty");
            break;
        case 'test11':
            testConvertToBlob("image/webp", 1.0);
            break;
        case 'test12':
            testConvertToBlob("image/webp", 0.2);
            break;
        case 'test13':
            testConvertToBlobException1();
            break;
        case 'test14':
            testConvertToBlobException2();
            break;
    }
};

</script>

<script>
function makeWorker(test) {
    var blob = new Blob([document.getElementById("myWorker").textContent]);
    var worker = new Worker(URL.createObjectURL(blob));
    worker.onerror = test.unreached_func("error");
    return worker;
}

function drawCanvas(ctx)
{
    ctx.fillStyle = "red";
    ctx.fillRect(0, 0, 5, 5);
    ctx.fillStyle = "green";
    ctx.fillRect(5, 0, 5, 5);
    ctx.fillStyle = "blue";
    ctx.fillRect(0, 5, 5, 5);
    ctx.fillStyle = "black";
    ctx.fillRect(5, 5, 5, 5);
}

function compareImages(image1, image2)
{
    var canvas1 = document.createElement('canvas');
    var canvas2 = document.createElement('canvas');
    canvas1.width = canvas1.height = 10;
    canvas2.width = canvas2.height = 10;
    var ctx1 = canvas1.getContext('2d');
    var ctx2 = canvas1.getContext('2d');
    ctx1.drawImage(image1, 0, 0);
    ctx2.drawImage(image2, 0, 0);
    var data1 = ctx1.getImageData(0, 0, 10, 10).data;
    var data2 = ctx2.getImageData(0, 0, 10, 10).data;
    assert_equals(data1.length, data2.length);
    var imageMatched = true;
    for (var i = 0; i < data1.length; i++) {
        if (data1[i] != data2[i]) {
            imageMatched = false;
            break;
        }
    }
    assert_true(imageMatched);
}

function compareWithToBlob(t, typeVal, qualityVal, blob2)
{
    var image1 = new Image();
    var image2 = new Image();
    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');
    drawCanvas(ctx);
    var imageLoadedCounter = 0;

    if (typeVal == "empty" && qualityVal == "empty") {
        canvas.toBlob(function(blob1) {
            image1.src = URL.createObjectURL(blob1);
        });
    } else if (typeVal == "empty" && qualityVal != "empty") {
        canvas.toBlob(function(blob1) {
            image1.src = URL.createObjectURL(blob1);
        }, "image/png", qualityVal);
    } else if (typeVal != "empty" && qualityVal == "empty") {
        canvas.toBlob(function(blob1) {
            image1.src = URL.createObjectURL(blob1);
        }, typeVal, 1.0);
    } else {
        canvas.toBlob(function(blob1) {
            image1.src = URL.createObjectURL(blob1);
        }, typeVal, qualityVal);
    }
    image2.src = URL.createObjectURL(blob2);
    image1.onload = image2.onload = t.step_func(function() {
        imageLoadedCounter++;
        if (imageLoadedCounter == 2) {
            compareImages(image1, image2);
            t.done();
        }
    });
}

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func(function(msg) {
        compareWithToBlob(t, "empty", "empty", msg.data);
    }));
    worker.postMessage('test1');
}, "Test that convertToBlob with default arguments produces correct result in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func(function(msg) {
        compareWithToBlob(t, "empty", 1.0, msg.data);
    }));
    worker.postMessage('test2');
}, "Test that convertToBlob with default type/1.0 quality produces correct result in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func(function(msg) {
        compareWithToBlob(t, "empty", 0.2, msg.data);
    }));
    worker.postMessage('test3');
}, "Test that convertToBlob with default type/0.2 quality produces correct result in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func(function(msg) {
        compareWithToBlob(t, "image/png", "empty", msg.data);
    }));
    worker.postMessage('test4');
}, "Test that convertToBlob with png/default quality produces correct result in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func(function(msg) {
        compareWithToBlob(t, "image/png", 1.0, msg.data);
    }));
    worker.postMessage('test5');
}, "Test that convertToBlob with png/1.0 quality produces correct result in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func(function(msg) {
        compareWithToBlob(t, "image/png", 0.2, msg.data);
    }));
    worker.postMessage('test6');
}, "Test that convertToBlob with png/0.2 quality produces correct result in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func(function(msg) {
        compareWithToBlob(t, "image/jpeg", "empty", msg.data);
    }));
    worker.postMessage('test7');
}, "Test that convertToBlob with jpeg/default quality produces correct result in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func(function(msg) {
        compareWithToBlob(t, "image/jpeg", 1.0, msg.data);
    }));
    worker.postMessage('test8');
}, "Test that convertToBlob with jpeg/1.0 quality produces correct result in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func(function(msg) {
        compareWithToBlob(t, "image/jpeg", 0.2, msg.data);
    }));
    worker.postMessage('test9');
}, "Test that convertToBlob with jpeg/0.2 quality produces correct result in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func(function(msg) {
        compareWithToBlob(t, "image/webp", "empty", msg.data);
    }));
    worker.postMessage('test10');
}, "Test that convertToBlob with webp/default quality produces correct result in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func(function(msg) {
        compareWithToBlob(t, "image/webp", 1.0, msg.data);
    }));
    worker.postMessage('test11');
}, "Test that convertToBlob with webp/1.0 quality produces correct result in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func(function(msg) {
        compareWithToBlob(t, "image/webp", 0.2, msg.data);
    }));
    worker.postMessage('test12');
}, "Test that convertToBlob with webp/0.2 quality produces correct result in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func_done(function(msg) {
        if (msg.data instanceof Object)
            return;
        assert_true(msg.data);
        t.done();
    }));
    worker.postMessage('test13');
}, "Test that call convertToBlob on a detached OffscreenCanvas throws exception in a worker");

async_test(function(t) {
    var worker = makeWorker(t);
    worker.addEventListener('message', t.step_func_done(function(msg) {
        assert_true(msg.data);
        t.done();
    }));
    worker.postMessage('test14');
}, "Test that call convertToBlob on a OffscreenCanvas with size 0 throws exception in a worker");

async_test(function(t) {
    var img = new Image();
    img.src = "/images/green.png";
    img.crossOrigin = "anonymous";
    img.onload = t.step_func_done(() => {
        createImageBitmap(img).then(t.step_func_done(bitmap => {
            var worker = makeWorker(t);
            worker.addEventListener('message', t.step_func_done(function(msg) {
                assert_true(msg.data);
                t.done();
            }));
            worker.postMessage(bitmap);
        }));
    });
}, "Test that call convertToBlob on a OffscreenCanvas with tainted origin throws exception in a worker");

</script>

