tor-browser

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

test_discardFinishedAnimatedImage.html (4415B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <title>Test that img.decode works on finished, discarded animated images</title>
      5  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      6  <script src="/tests/SimpleTest/WindowSnapshot.js"></script>
      7  <script type="text/javascript" src="imgutils.js"></script>
      8  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
      9 </head>
     10 <body>
     11 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1629490">Mozilla Bug 1629490</a>
     12 <div id="container">
     13  <img id="finitepng" src="finite-apng.png">
     14 </div>
     15 <script class="testbody" type="text/javascript">
     16 
     17 SimpleTest.waitForExplicitFinish();
     18 
     19 window.onload = runTest;
     20 
     21 let discardCallback = undefined;
     22 let frameUpdateCallback = undefined;
     23 
     24 async function runTest() {
     25  const kUsingWebRender = SpecialPowers.DOMWindowUtils.layerManagerType.startsWith("WebRender");
     26 
     27  let img = document.getElementById("finitepng");
     28 
     29  await img.decode();
     30 
     31  while (!isItGreen(img)) {
     32    // We hit an optimized path in WebRender that doesn't cause a repaint on the
     33    // main thread and doesn't seem to send MozAfterPaints.
     34    //
     35    // https://searchfox.org/mozilla-central/rev/b7f3977978922d44c7d92ae01c0d4cc2baca7bc2/layout/style/ImageLoader.cpp#553
     36    await new Promise(resolve => {
     37      if (kUsingWebRender) {
     38        requestAnimationFrame(() => {
     39          requestAnimationFrame(resolve);
     40        });
     41      } else {
     42        window.addEventListener("MozAfterPaint", resolve, { once: true });
     43      }
     44    });
     45  }
     46 
     47  addCallbacks(img);
     48 
     49  let iterationsLeft = 26;
     50  while (iterationsLeft > 0) {
     51 
     52    let discardPromise = new Promise(resolve => {
     53        discardCallback = resolve;
     54    });
     55 
     56    document.getElementById("container").style.display = "none";
     57    document.documentElement.offsetLeft; // force that style to take effect
     58    requestDiscard(img);
     59 
     60    await new Promise(resolve => {requestAnimationFrame(() => { requestAnimationFrame(resolve); }); });
     61 
     62    await discardPromise;
     63    await new Promise(resolve => {requestAnimationFrame(() => { requestAnimationFrame(resolve); }); });
     64 
     65    let waitForFrameUpdate = new Promise(resolve => {
     66        frameUpdateCallback = resolve;
     67    });
     68 
     69    document.getElementById("container").style.display = "";
     70    document.documentElement.offsetLeft; // force that style to take effect
     71 
     72    await img.decode();
     73 
     74    await new Promise(resolve => requestAnimationFrame(resolve));
     75 
     76    await waitForFrameUpdate;
     77 
     78    ok(isItGreen(img), "should be green");
     79 
     80    iterationsLeft--;
     81    await new Promise(resolve => {requestAnimationFrame(() => { requestAnimationFrame(resolve); }); });
     82 
     83  }
     84 
     85  removeObserver(img);
     86  SimpleTest.finish();
     87 }
     88 
     89 function isItGreen(img) {
     90  let rect = img.getBoundingClientRect();
     91  let r = {left: rect.left + 5, top: rect.top + 5, width: 5, height: 5};
     92  let c = SpecialPowers.snapshotWindowWithOptions(window, r);
     93  let d = c.getContext('2d').getImageData(0,0,5,5).data;
     94  let isGreen = true;
     95  for (let i = 0; i < 5*5; i++) {
     96    if (d[4*i] != 0 || d[4*i + 1] != 128 || d[4*i + 2] != 0 || d[4*i + 3] != 255) {
     97      isGreen = false;
     98    }
     99  }
    100  return isGreen;
    101 }
    102 
    103 
    104 let scriptedObserver = undefined;
    105 let imgLoadingContent = undefined;
    106 function addCallbacks(anImage) {
    107  var observer = new ImageDecoderObserverStub();
    108  observer.discard = function () {
    109    if (discardCallback != undefined) {
    110      let localDiscardCallback = discardCallback;
    111      discardCallback = undefined;
    112      setTimeout(localDiscardCallback, 0);
    113    }
    114  };
    115  observer.frameUpdate = function () {
    116    if (frameUpdateCallback != undefined) {
    117      let localFrameUpdateCallback = frameUpdateCallback;
    118      frameUpdateCallback = undefined;
    119      setTimeout(localFrameUpdateCallback, 0);
    120    }
    121  };
    122  observer = SpecialPowers.wrapCallbackObject(observer);
    123 
    124  scriptedObserver = SpecialPowers.Cc["@mozilla.org/image/tools;1"]
    125                           .getService(SpecialPowers.Ci.imgITools)
    126                           .createScriptedObserver(observer);
    127 
    128  imgLoadingContent = SpecialPowers.wrap(anImage);
    129  imgLoadingContent.addObserver(scriptedObserver);
    130 }
    131 
    132 function removeObserver() {
    133  imgLoadingContent.removeObserver(scriptedObserver);
    134 }
    135 
    136 function requestDiscard(anImage) {
    137  var request = SpecialPowers.wrap(anImage)
    138      .getRequest(SpecialPowers.Ci.nsIImageLoadingContent.CURRENT_REQUEST);
    139  setTimeout(() => request.requestDiscard(), 0);
    140 }
    141 
    142 </script>
    143 </body>
    144 </html>