tor-browser

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

videoFrame-serialization.https.html (9326B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4  <script src='/resources/testharness.js'></script>
      5  <script src='/resources/testharnessreport.js'></script>
      6  <script src='/common/get-host-info.sub.js'></script>
      7  <script src='/webcodecs/utils.js'></script>
      8  <script id='workerCode' type='javascript/worker'>
      9    self.onmessage = (e) => {
     10      let frame = e.data.frame;
     11      if (e.data.transfer) {
     12        postMessage(frame, [frame]);
     13      } else {
     14        postMessage(frame);
     15      }
     16    };
     17  </script>
     18  <script id='sharedWorkerCode' type='javascript/worker'>
     19    const data = new Uint8Array([
     20      1, 2, 3, 4, 5, 6, 7, 8,
     21      9, 10, 11, 12, 13, 14, 15, 16,
     22    ]);
     23    let received = new Map();
     24    self.onconnect = function (event) {
     25      const port = event.ports[0];
     26      port.onmessage = function (e) {
     27        if (e.data == 'create-frame') {
     28          let frameOrError = null;
     29          try {
     30            frameOrError = new VideoFrame(data, {
     31              timestamp: 0,
     32              codedWidth: 2,
     33              codedHeight: 2,
     34              format: 'RGBA',
     35            });
     36          } catch (error) {
     37            frameOrError = error
     38          }
     39          port.postMessage(frameOrError);
     40          return;
     41        }
     42        if (e.data.hasOwnProperty('id')) {
     43          port.postMessage(
     44            received.get(e.data.id) ? 'RECEIVED' : 'NOT_RECEIVED');
     45          return;
     46        }
     47        if (e.data.toString() == '[object VideoFrame]') {
     48          received.set(e.data.timestamp, e.data);
     49        }
     50      };
     51    };
     52  </script>
     53 </head>
     54 <body>
     55 <script>
     56 const HELPER = '/webcodecs/videoFrame-serialization.crossAgentCluster.helper.html';
     57 const SAMEORIGIN_BASE = get_host_info().HTTPS_ORIGIN;
     58 const CROSSORIGIN_BASE = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
     59 const SAMEORIGIN_HELPER = SAMEORIGIN_BASE + HELPER;
     60 const CROSSORIGIN_HELPER = CROSSORIGIN_BASE + HELPER;
     61 const SERVICE_WORKER = 'serialization.crossAgentCluster.serviceworker.js';
     62 
     63 promise_test(async (t) => {
     64  const target = (await appendIframe(SAMEORIGIN_HELPER)).contentWindow;
     65  let frame = createVideoFrame(10);
     66  t.add_cleanup(() => frame.close());
     67  assert_true(await canSerializeVideoFrame(target, frame));
     68 }, 'Verify frames can be passed within the same agent clusters');
     69 
     70 promise_test(async (t) => {
     71  const blob = new Blob([document.querySelector('#workerCode').textContent], {
     72    type: 'text/javascript',
     73  });
     74  const worker = new Worker(window.URL.createObjectURL(blob));
     75  let frame = createVideoFrame(30);
     76  t.add_cleanup(() => frame.close());
     77  worker.postMessage({frame: frame, transfer: false});
     78  const received = await new Promise(resolve => worker.onmessage = e => {
     79    resolve(e.data);
     80  });
     81  assert_equals(received.toString(), '[object VideoFrame]');
     82  assert_equals(received.timestamp, 30);
     83 }, 'Verify frames can be passed back and forth between main and worker');
     84 
     85 promise_test(async (t) => {
     86  const encodedScriptText = btoa("self.onmessage = (e) => { postMessage(e.data);};");
     87  const scriptURL = 'data:text/javascript;base64,' + encodedScriptText;
     88  const worker = new Worker(scriptURL);
     89  let frame = createVideoFrame(40);
     90  t.add_cleanup(() => frame.close());
     91  worker.postMessage(frame);
     92  const received = await new Promise(resolve => worker.onmessage = e => {
     93    resolve(e.data);
     94  });
     95  assert_equals(received.toString(), '[object VideoFrame]');
     96  assert_equals(received.timestamp, 40);
     97 }, 'Verify frames can be passed back and forth between main and data-url worker');
     98 
     99 promise_test(async (t) => {
    100  const blob = new Blob([document.querySelector('#sharedWorkerCode').textContent], {
    101    type: 'text/javascript',
    102  });
    103  const worker = new SharedWorker(window.URL.createObjectURL(blob));
    104  let frame = createVideoFrame(50);
    105  t.add_cleanup(() => frame.close());
    106  worker.port.postMessage(frame);
    107  worker.port.postMessage({'id': 50});
    108  const received = await new Promise(resolve => worker.port.onmessage = e => {
    109    resolve(e.data);
    110  });
    111  assert_equals(received, 'NOT_RECEIVED');
    112 }, 'Verify frames cannot be passed to sharedworker');
    113 
    114 promise_test(async (t) => {
    115  navigator.serviceWorker.register(SERVICE_WORKER);
    116  navigator.serviceWorker.ready.then((registration) => {
    117    let frame = createVideoFrame(60);
    118    t.add_cleanup(() => frame.close());
    119    registration.active.postMessage(frame);
    120    registration.active.postMessage({'videoFrameId': 60});
    121  });
    122  const received = await new Promise(resolve => navigator.serviceWorker.onmessage = (e) => {
    123    resolve(e.data);
    124  });
    125  assert_equals(received, 'NOT_RECEIVED');
    126 }, 'Verify frames cannot be passed to serviceworker');
    127 
    128 promise_test(async (t) => {
    129  const target = (await appendIframe(SAMEORIGIN_HELPER)).contentWindow;
    130  let frame = createVideoFrame(70);
    131  t.add_cleanup(() => frame.close());
    132  assert_true(await canTransferVideoFrame(target, frame));
    133  assert_true(isFrameClosed(frame));
    134 }, 'Verify frames can be transferred within the same agent clusters');
    135 
    136 promise_test(async (t) => {
    137  const blob = new Blob([document.querySelector('#workerCode').textContent], {
    138    type: 'text/javascript',
    139  });
    140  const worker = new Worker(window.URL.createObjectURL(blob));
    141  let frame = createVideoFrame(90);
    142  t.add_cleanup(() => frame.close());
    143  worker.postMessage({frame: frame, transfer: true}, [frame]);
    144  const received = await new Promise(resolve => worker.onmessage = e => {
    145    resolve(e.data);
    146  });
    147  assert_equals(received.toString(), '[object VideoFrame]');
    148  assert_equals(received.timestamp, 90);
    149 }, 'Verify frames can be transferred back and forth between main and worker');
    150 
    151 promise_test(async (t) => {
    152  const encodedScriptText = btoa("self.onmessage = (e) => { let f = e.data; postMessage(f, [f]); };");
    153  const scriptURL = 'data:text/javascript;base64,' + encodedScriptText;
    154  const worker = new Worker(scriptURL);
    155  let frame = createVideoFrame(100);
    156  t.add_cleanup(() => frame.close());
    157  worker.postMessage(frame, [frame]);
    158  const received = await new Promise(resolve => worker.onmessage = e => {
    159    resolve(e.data);
    160  });
    161  assert_equals(received.toString(), '[object VideoFrame]');
    162  assert_equals(received.timestamp, 100);
    163 }, 'Verify frames can be transferred back and forth between main and data-url worker');
    164 
    165 promise_test(async (t) => {
    166  const blob = new Blob([document.querySelector('#sharedWorkerCode').textContent], {
    167    type: 'text/javascript',
    168  });
    169  const worker = new SharedWorker(window.URL.createObjectURL(blob));
    170  let frame = createVideoFrame(110);
    171  t.add_cleanup(() => frame.close());
    172  worker.port.postMessage(frame, [frame]);
    173  worker.port.postMessage({'id': 110});
    174  const received = await new Promise(resolve => worker.port.onmessage = e => {
    175    resolve(e.data);
    176  });
    177  assert_equals(received, 'NOT_RECEIVED');
    178 }, 'Verify frames cannot be transferred to a sharedworker');
    179 
    180 promise_test(async (t) => {
    181  navigator.serviceWorker.register(SERVICE_WORKER);
    182  navigator.serviceWorker.ready.then((registration) => {
    183    let frame = createVideoFrame(120);
    184    t.add_cleanup(() => frame.close());
    185    registration.active.postMessage(frame, [frame]);
    186    registration.active.postMessage({'videoFrameId': 120});
    187  });
    188  const received = await new Promise(resolve => navigator.serviceWorker.onmessage = (e) => {
    189    resolve(e.data);
    190  });
    191  assert_equals(received, 'NOT_RECEIVED');
    192 }, 'Verify frames cannot be transferred to serviceworker');
    193 
    194 promise_test(async () => {
    195  const blob = new Blob([document.querySelector('#sharedWorkerCode').textContent], {
    196    type: 'text/javascript',
    197  });
    198  const worker = new SharedWorker(window.URL.createObjectURL(blob));
    199  worker.port.postMessage('create-frame');
    200  const received = await new Promise(resolve => worker.port.onmessage = e => {
    201    resolve(e.data);
    202  });
    203  assert_true(received instanceof ReferenceError);
    204 }, 'Verify frames is unavailable in sharedworker');
    205 
    206 promise_test(async () => {
    207  navigator.serviceWorker.register(SERVICE_WORKER);
    208  let registration = await navigator.serviceWorker.ready;
    209  registration.active.postMessage('create-VideoFrame');
    210  const received = await new Promise(resolve => navigator.serviceWorker.onmessage = (e) => {
    211    resolve(e.data);
    212  });
    213  assert_true(received instanceof ReferenceError);
    214 }, 'Verify frames is unavailable in serviceworker');
    215 
    216 function appendIframe(src) {
    217  const frame = document.createElement('iframe');
    218  document.body.appendChild(frame);
    219  frame.src = src;
    220  return new Promise(resolve => frame.onload = () => resolve(frame));
    221 };
    222 
    223 function createVideoFrame(ts) {
    224  let data = new Uint8Array([
    225    1, 2, 3, 4, 5, 6, 7, 8,
    226    9, 10, 11, 12, 13, 14, 15, 16,
    227  ]);
    228  return new VideoFrame(data, {
    229    timestamp: ts,
    230    codedWidth: 2,
    231    codedHeight: 2,
    232    format: 'RGBA',
    233  });
    234 }
    235 
    236 function canSerializeVideoFrame(target, vf) {
    237  return canPostVideoFrame(target, vf, false);
    238 };
    239 
    240 function canTransferVideoFrame(target, vf) {
    241  return canPostVideoFrame(target, vf, true);
    242 };
    243 
    244 function canPostVideoFrame(target, vf, transfer) {
    245  if (transfer) {
    246    target.postMessage(vf, '*', [vf]);
    247    assert_true(isFrameClosed(vf));
    248  } else {
    249    target.postMessage(vf, '*');
    250  }
    251  // vf.timestamp doesn't change after vf is closed, so it's fine to use it.
    252  target.postMessage({'id': vf.timestamp}, '*');
    253  return new Promise(resolve => window.onmessage = e => {
    254    resolve(e.data == 'RECEIVED');
    255  });
    256 };
    257 </script>
    258 </body>
    259 </html>