tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_imagebitmap.html (13040B)


      1 <!DOCTYPE HTML>
      2 <title>Test ImageBitmap</title>
      3 <meta charset="utf-8">
      4 <script src="/tests/SimpleTest/SimpleTest.js"></script>
      5 <link rel="stylesheet" href="/tests/SimpleTest/test.css">
      6 <body>
      7 
      8 <img src="image_anim-gr.gif" id="image" class="resource">
      9 <video width="320" height="240" src="http://example.com/tests/dom/canvas/test/crossorigin/video.sjs?name=tests/dom/canvas/test/320x240.webm&type=video/webm&cors=anonymous" id="video" crossOrigin="anonymous" autoplay></video>
     10 
     11 <canvas id="c1" class="output" width="128" height="128"></canvas>
     12 <canvas id="c2" width="128" height="128"></canvas>
     13 
     14 <script src="imagebitmap_bug1239300.js"></script>
     15 <script src="imagebitmap_bug1239752.js"></script>
     16 <script type="text/javascript">
     17 
     18 SimpleTest.waitForExplicitFinish();
     19 
     20 /**
     21 * [isPixel description]
     22 *
     23 * @param  {[type]}  ctx : canvas context
     24 * @param  {[type]}  x   : pixel x coordinate
     25 * @param  {[type]}  y   : pixel y coordinate
     26 * @param  {[type]}  c   : a rgba color code
     27 * @param  {[type]}  d   : error duration
     28 * @return {Promise}
     29 */
     30 function isPixel(ctx, x, y, c, d) {
     31  var pos = x + "," + y;
     32  var color = c[0] + "," + c[1] + "," + c[2] + "," + c[3];
     33  var pixel = ctx.getImageData(x, y, 1, 1);
     34  var pr = pixel.data[0],
     35      pg = pixel.data[1],
     36      pb = pixel.data[2],
     37      pa = pixel.data[3];
     38  ok(c[0]-d <= pr && pr <= c[0]+d &&
     39     c[1]-d <= pg && pg <= c[1]+d &&
     40     c[2]-d <= pb && pb <= c[2]+d &&
     41     c[3]-d <= pa && pa <= c[3]+d,
     42     "pixel "+pos+" of "+ctx.canvas.id+" is "+pr+","+pg+","+pb+","+pa+"; expected "+color+" +/- "+d);
     43 }
     44 
     45 var TEST_BITMAPS = [
     46    {'rect': [0, 0, 128, 128],        'draw': [0, 0, 64, 64, 0, 0, 64, 64],       'test': [[0,    0,    [255, 0, 0, 255], 5]]},
     47    {'rect': [128, 0, 128, 128],      'draw': [0, 0, 64, 64, 0, 0, 64, 64],       'test': [[0,    0,    [0, 255, 0, 255], 5]]},
     48    {'rect': [230, 230, 128, 128],    'draw': [0, 0, 128, 128, 0, 0, 128, 128],   'test': [[0,    0,    [255, 0, 0, 255], 5],
     49                                                                                           [100,  100,  [0, 0, 0, 0],     5]]},
     50    {'rect': [-64, -64, 512, 512],    'draw': [0, 0, 128, 128, 0, 0, 128, 128],   'test': [[0,    0,    [0, 0, 0, 0],     5],
     51                                                                                           [100,  100,  [255, 0, 0, 255], 5]]},
     52    {'rect': [128, 128, -128, -128],  'draw': [0, 0, 128, 128, 0, 0, 128, 128],   'test': [[0,    0,    [255, 0, 0, 255], 5]]},
     53    {'rect': [0, 0, 256, 256],        'draw': [0, 128, 128, 128, 0, 0, 128, 128], 'test': [[0,    0,    [0, 255, 0, 255], 5]]},
     54 ];
     55 
     56 var canvas, ctx, ctx2, completedImage;
     57 
     58 function failed(ex) {
     59  ok(false, "Promise failure: " + ex);
     60 }
     61 
     62 function testDraw() {
     63  var resolver, bitmaps = [], image = new Image();
     64 
     65  image.src = 'image_rgrg-256x256.png';
     66  var promise = new Promise(function (arg) { resolver = arg; });
     67 
     68  function createBitmap(def) {
     69    return createImageBitmap(image, def.rect[0], def.rect[1], def.rect[2], def.rect[3])
     70      .then(function (bitmap) { def.bitmap = bitmap; }, failed);
     71  };
     72 
     73  image.onload = function() {
     74    completedImage = image;
     75    resolver(Promise.all(TEST_BITMAPS.map(createBitmap)));
     76  };
     77 
     78  function testPixel(test) {
     79    isPixel(ctx, test[0], test[1], test[2], test[3]);
     80  };
     81 
     82  return promise.then(function() {
     83    TEST_BITMAPS.forEach(function (test) {
     84      if (!test.bitmap) { return; }
     85      ctx.clearRect(0, 0, canvas.width, canvas.height);
     86      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]);
     87      test.test.forEach(testPixel);
     88      is(test.bitmap.width, Math.abs(test.rect[2]), "Bitmap has correct width " + test.bitmap.width);
     89      is(test.bitmap.height, Math.abs(test.rect[3]), "Bitmap has correct height " + test.bitmap.height);
     90    });
     91  });
     92 }
     93 
     94 function testSources() {
     95  ctx.fillStyle="#00FF00";
     96  ctx.fillRect(0, 0, 128, 128);
     97 
     98  function check(bitmap) {
     99    ctx2.clearRect(0, 0, 128, 128);
    100    ctx2.drawImage(bitmap, 0, 0);
    101    isPixel(ctx2, 0, 0, [0, 255, 0, 255], 5);
    102  };
    103 
    104  function getPNGBlobBitmapPromise() {
    105    return new Promise(function(resolve, reject) {
    106      canvas.toBlob(function(blob) {
    107        resolve(createImageBitmap(blob));
    108      })
    109    });
    110  }
    111 
    112  function getJPGBlobBitmapPromise() {
    113    return new Promise(function(resolve, reject) {
    114      canvas.toBlob(function(blob) {
    115        resolve(createImageBitmap(blob));
    116      }, "image/jpeg", 0.95)
    117    });
    118  }
    119 
    120  return Promise.all([
    121    createImageBitmap(document.getElementById('image')).then(check, failed),                                         // HTMLImageElement
    122    createImageBitmap(ctx).then(check, failed),                                                                      // CanvasRenderingContext2D
    123    createImageBitmap(canvas).then(check, failed),                                                                   // HTMLCanvasElement
    124    createImageBitmap(ctx).then(function (bitmap) { return createImageBitmap(bitmap).then(check, failed); }, failed), // ImageBitmap
    125    createImageBitmap(document.getElementById('video'), 140, 0, 20, 20).then(check, failed),                         // HTMLVideoElement
    126    createImageBitmap(ctx.getImageData(0, 0, 128, 128)).then(check, failed),                                          // ImageData
    127    getPNGBlobBitmapPromise().then(check, failed),                                                                   // PNG blob
    128    getJPGBlobBitmapPromise().then(check, failed),                                                                   // JPEG blob
    129  ]);
    130 }
    131 
    132 function promiseThrows(p, name) {
    133  var didThrow;
    134  return p.then(function() { didThrow = false; },
    135                function() { didThrow = true; })
    136          .then(function() { ok(didThrow, name); });
    137 }
    138 
    139 function testExceptions() {
    140 
    141  function createImageBitmapWithNeuturedImageData() {
    142    return new Promise(function(resolve, reject) {
    143      var tempImage = document.createElement('img');
    144      tempImage.src = 'image_rgrg-256x256.png';
    145      tempImage.onload = function() {
    146        var tempCanvas = document.createElement('canvas');
    147        var tempCtx = tempCanvas.getContext('2d');
    148        tempCanvas.with = tempImage.naturalWidth;
    149        tempCanvas.height = tempImage.naturalHeight;
    150        tempCtx.drawImage(tempImage, 0, 0);
    151        var tempWorker = new Worker("test_imagebitmap_on_worker.js");
    152        var imageData = tempCtx.getImageData(0, 0, tempImage.naturalWidth, tempImage.naturalHeight);
    153        tempWorker.postMessage(imageData.data.buffer, [imageData.data.buffer]);
    154        tempWorker.terminate();
    155 
    156        ok(!imageData.data.length, "Get a neutured ImageData.");
    157        resolve(createImageBitmap(imageData));
    158      }
    159    });
    160  }
    161 
    162  function createImageBitmapWithCorruptedBlob() {
    163    return new Promise(function(resolve, reject) {
    164      var xhr = new XMLHttpRequest();
    165      xhr.open("GET", "image_error-early.png");
    166      xhr.responseType = "blob";//force the HTTP response, response-type header to be blob
    167      xhr.onload = function()
    168      {
    169        ok(xhr.response, "Get a corrupted blob");
    170        resolve(createImageBitmap(xhr.response));
    171      }
    172      xhr.send();
    173    });
    174  }
    175 
    176  function createImageBitmapWithNonImageFile() {
    177    return new Promise(function(resolve, reject) {
    178      var xhr = new XMLHttpRequest();
    179      xhr.open("GET", "test_imagebitmap_on_worker.js");
    180      xhr.responseType = "blob";//force the HTTP response, response-type header to be blob
    181      xhr.onload = function()
    182      {
    183        ok(xhr.response, "Get a non-image blob");
    184        resolve(createImageBitmap(xhr.response));
    185      }
    186      xhr.send();
    187    });
    188  }
    189 
    190  return Promise.all([
    191    promiseThrows(createImageBitmap(new Image()), 'createImageBitmap should throw with unloaded image'),
    192    promiseThrows(createImageBitmap(completedImage, 0, 0, 0, 0), 'createImageBitmap should throw with 0 width/height'),
    193    promiseThrows(createImageBitmap(null), 'createImageBitmap should throw with null source'),
    194    promiseThrows(createImageBitmapWithNeuturedImageData(), "createImageBitmap should throw with neutured ImageData"),
    195    promiseThrows(createImageBitmapWithCorruptedBlob(), "createImageBitmap should throw with corrupted blob"),
    196    promiseThrows(createImageBitmapWithNonImageFile(), "createImageBitmap should throw with non-image blob"),
    197  ]);
    198 }
    199 
    200 function testSecurityErrors() {
    201 
    202  function getUncleanImagePromise() {
    203    return new Promise(function(resolve, reject) {
    204      var uncleanImage = document.createElement('img');
    205 
    206      uncleanImage.onload = function() {
    207        resolve(createImageBitmap(uncleanImage));
    208      }
    209 
    210      uncleanImage.onerror = function() {
    211        reject();
    212      }
    213 
    214      uncleanImage.src = "http://example.com/tests/dom/canvas/test/crossorigin/image.png";
    215    });
    216  }
    217 
    218  function getUncleanVideoPromise() {
    219    return new Promise(function(resolve, reject) {
    220      var uncleanVideo = document.createElement('video');
    221 
    222      uncleanVideo.onloadeddata = function() {
    223        resolve(createImageBitmap(uncleanVideo));
    224      }
    225 
    226      uncleanVideo.onerror = function() {
    227        reject();
    228      }
    229 
    230      uncleanVideo.src = "http://example.com/tests/dom/canvas/test/crossorigin/video.sjs?name=tests/dom/canvas/test/320x240.webm&type=video/webm";
    231      uncleanVideo.play();
    232    });
    233  }
    234 
    235  function getTaintedCanvasPromise() {
    236    return new Promise(function(resolve, reject) {
    237      var uncleanImage = document.createElement('img');
    238 
    239      uncleanImage.onload = function() {
    240        var taintedCanvas = document.createElement('canvas');
    241        var taintedCtx = taintedCanvas.getContext('2d');
    242        taintedCtx.drawImage(uncleanImage, 0, 0);
    243        resolve(createImageBitmap(taintedCanvas));
    244      }
    245 
    246      uncleanImage.onerror = function() {
    247        reject();
    248      }
    249 
    250      uncleanImage.src = "http://example.com/tests/dom/canvas/test/crossorigin/image.png";
    251    });
    252  }
    253 
    254  function getTaintedCanvasRenderingContex2dPromise() {
    255    return new Promise(function(resolve, reject) {
    256      var uncleanImage = document.createElement('img');
    257 
    258      uncleanImage.onload = function() {
    259        var taintedCanvas = document.createElement('canvas');
    260        var taintedCtx = taintedCanvas.getContext('2d');
    261        taintedCtx.drawImage(uncleanImage, 0, 0);
    262        resolve(createImageBitmap(taintedCtx));
    263      }
    264 
    265      uncleanImage.onerror = function() {
    266        reject();
    267      }
    268 
    269      uncleanImage.src = "http://example.com/tests/dom/canvas/test/crossorigin/image.png";
    270    });
    271  }
    272 
    273  function checkPromiseFailedWithSecurityError(p) {
    274    return p.then(imageBitmap => {
    275      ok(!!imageBitmap, "ImageBitmaps are always created");
    276      const context = document.createElement("canvas").getContext("2d");
    277      context.drawImage(imageBitmap, 0, 0);
    278      try {
    279        context.getImageData(0, 0, 1, 1);
    280        ok(false, "Did not get SecurityError with unclean source. ImageBitmap was created successfully.");
    281      } catch (ex) {
    282        if (ex == "SecurityError: The operation is insecure.") {
    283          ok(true, ex.message);
    284        }
    285        else {
    286          ok(false, "Did not get SecurityError with unclean source. Error Message: " + ex.message);
    287        }
    288      }
    289    });
    290  }
    291 
    292  return Promise.all([
    293    checkPromiseFailedWithSecurityError(getUncleanImagePromise()),
    294    checkPromiseFailedWithSecurityError(getUncleanVideoPromise()),
    295    checkPromiseFailedWithSecurityError(getTaintedCanvasPromise()),
    296    checkPromiseFailedWithSecurityError(getTaintedCanvasRenderingContex2dPromise()),
    297  ]);
    298 }
    299 
    300 function testCreatePattern() {
    301  var resolve;
    302  var promise = new Promise(function (arg) { resolve = arg; });
    303 
    304  var TEST_PATTERN = [
    305    [0,   0,   [255, 0, 0, 255], 1],
    306    [128, 128, [255, 0, 0, 255], 1],
    307    [256, 256, [255, 0, 0, 255], 1],
    308    [384, 0,   [0, 255, 0, 255], 1],
    309    [0,   384, [0, 255, 0, 255], 1],
    310  ];
    311 
    312  var patternCanvas = document.createElement('canvas');
    313  patternCanvas.width = "512";
    314  patternCanvas.height = "512";
    315  var patternCtx = patternCanvas.getContext('2d');
    316 
    317  var image = new Image();
    318  image.src = 'image_rgrg-256x256.png';
    319  image.onload = function() {
    320    var p = createImageBitmap(image);
    321    p.then(function(bitmap) {
    322      patternCtx.rect(0, 0, 512, 512);
    323      patternCtx.fillStyle = patternCtx.createPattern(bitmap, "repeat");
    324      patternCtx.fill();
    325      document.body.appendChild(patternCanvas);
    326    });
    327    resolve(p);
    328  }
    329 
    330  return promise.then(function() {
    331    TEST_PATTERN.forEach(function(test) {
    332      isPixel(patternCtx, test[0], test[1], test[2], test[3]);
    333    });
    334  });
    335 }
    336 
    337 
    338 function runTests() {
    339  canvas = document.getElementById('c1');
    340  ctx = canvas.getContext('2d');
    341  ctx2 = document.getElementById('c2').getContext('2d');
    342 
    343  testDraw()
    344    .then(testCreatePattern)
    345    .then(testSources)
    346    .then(testExceptions)
    347    .then(testSecurityErrors)
    348    .then(testBug1239300)
    349    .then(testBug1239752)
    350    .then(SimpleTest.finish, function(ev) { failed(ev); SimpleTest.finish(); });
    351 }
    352 
    353 addLoadEvent(runTests);
    354 
    355 </script>
    356 </body>