tor-browser

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

test_accelerated_canvas_context_loss.html (3832B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <meta charset="utf-8">
      5  <title>Check for contextlost/restored events after GPU process restart</title>
      6  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      7  <link rel="stylesheet" href="/tests/SimpleTest/test.css">
      8 </head>
      9 <body>
     10 <canvas id="c" width="512" height="512"></canvas>
     11 
     12 <script type="application/javascript">
     13 
     14 function waitRAF() {
     15  return new Promise((resolve, reject) => {
     16    window.requestAnimationFrame(resolve);
     17  });
     18 }
     19 
     20 async function restartGPUProcess() {
     21  return await SpecialPowers.spawnChrome([], async () => {
     22    const gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo);
     23 
     24    if (gfxInfo.usingGPUProcess) {
     25      const { TestUtils } = ChromeUtils.importESModule(
     26        "resource://testing-common/TestUtils.sys.mjs"
     27      );
     28      let promise = TestUtils.topicObserved("compositor-reinitialized");
     29 
     30      const acceleratedCanvas = gfxInfo.usingAcceleratedCanvas;
     31      ok(true, "Restarting GPU process, accelerated canvas " + acceleratedCanvas);
     32 
     33      gfxInfo.killGPUProcessForTests();
     34      await promise;
     35 
     36      return acceleratedCanvas;
     37    }
     38 
     39    ok(true, "Not using GPU process");
     40    return false;
     41  });
     42 }
     43 
     44 const canvas = document.getElementById("c");
     45 const context = canvas.getContext("2d");
     46 
     47 let restoredPromiseResolve;
     48 let restoredPromiseReject;
     49 
     50 const restoredPromise = new Promise((resolve, reject) => {
     51  restoredPromiseResolve = resolve;
     52  restoredPromiseReject = reject;
     53 });
     54 
     55 let countLostEvents = 0;
     56 let countRestoredEvents = 0;
     57 
     58 function onContextLost() {
     59  ok(context.isContextLost(), "Canvas context should be lost during contextlost event");
     60 
     61  try {
     62    let transform = context.getTransform();
     63    ok(transform.isIdentity, "Canvas context should return identity transform while context lost");
     64  } catch (e) {}
     65 
     66  countLostEvents += 1;
     67 }
     68 
     69 function onContextRestored() {
     70  ok(!context.isContextLost(), "Canvas context should not be lost during contextrestored event");
     71  countRestoredEvents += 1;
     72 
     73  restoredPromiseResolve(true);
     74 }
     75 
     76 function waitContextRestored() {
     77  let timeoutId = window.setTimeout(restoredPromiseReject, 5000);
     78  return restoredPromise.then(() => {
     79    window.clearTimeout(timeoutId);
     80  });
     81 }
     82 
     83 async function start() {
     84  try {
     85    canvas.addEventListener("contextlost", onContextLost);
     86    canvas.addEventListener("contextrestored", onContextRestored);
     87 
     88    ok(!context.isContextLost(), "Canvas context should not be lost before initial fill");
     89 
     90    context.fillStyle = 'red';
     91    context.fill();
     92    await waitRAF();
     93 
     94    ok(!context.isContextLost(), "Canvas context should not be lost after initial fill");
     95 
     96    let transform = context.getTransform();
     97    ok(transform.isIdentity, "Canvas context should default to identity transform");
     98    context.setTransform(2.0, 3.0, 4.0, 5.0, 6.0, 7.0);
     99    transform = context.getTransform();
    100    ok(!transform.isIdentity, "Canvas context should have non-identity transform");
    101 
    102    const restarted = await restartGPUProcess();
    103    const expectedEvents = restarted ? 1 : 0;
    104 
    105    if (expectedEvents) {
    106      await waitContextRestored();
    107    }
    108    await waitRAF();
    109 
    110    is(countLostEvents, expectedEvents, "Should have fired " + expectedEvents + " contextlost events");
    111    is(countRestoredEvents, expectedEvents, "Should have fired " + expectedEvents + " contextrestored events");
    112    ok(!context.isContextLost(), "Canvas context should not be lost after restoration");
    113 
    114    context.fillStyle = 'green';
    115    context.fill();
    116    await waitRAF();
    117 
    118    ok(!context.isContextLost(), "Canvas context should not be lost at completion");
    119  } catch (err) {
    120    ok(false, "Caught exception " + err);
    121  } finally {
    122    SimpleTest.finish();
    123  }
    124 }
    125 
    126 SimpleTest.waitForExplicitFinish();
    127 SimpleTest.requestFlakyTimeout("Wait for failure condition");
    128 start();
    129 
    130 </script>
    131 </body>
    132 </html>