tor-browser

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

iframe_sensor_handler.html (3225B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <title>cross-origin iframe sensor tester</title>
      4 <script src="/resources/testdriver.js?feature=bidi"></script>
      5 <script src="/resources/testdriver-vendor.js"></script>
      6 <script src="/generic-sensor/resources/generic-sensor-helpers.js"></script>
      7 <script>
      8  let sensor = null;
      9 
     10  test_driver.set_test_context(window.parent);
     11 
     12  // This function is defined separately so that it is added only once
     13  // regardless of how many times the 'start_sensor' command is received.
     14  function sensorReadingEventHandler() {
     15    window.parent.postMessage(
     16      {
     17        eventName: 'reading',
     18        serializedSensor: serialize_sensor_data(sensor),
     19      }, '*');
     20  }
     21 
     22  async function messageHandler(e) {
     23    switch (e.data.command) {
     24      case 'create_sensor':
     25        if (!sensor) {
     26          const { sensorName, permissionName } = e.data.sensorData;
     27          // TODO(https://github.com/w3c/permissions/issues/419): This does not
     28          // work as expected: due to the set_test_context() call above, this
     29          // call goes through the top-level frame, which has a different
     30          // origin in cross-origin tests, meaning that cross-origin tests only
     31          // really work when permissions are granted by default. This can only
     32          // be fixed by testdriver.js allowing set_permission() to specify a
     33          // different origin.
     34          await test_driver.bidi.permissions.set_permission(
     35              {descriptor: {name: permissionName}, state: 'granted'});
     36          sensor = new self[sensorName]();
     37        }
     38        return Promise.resolve();
     39 
     40      case 'start_sensor':
     41        return new Promise((resolve, reject) => {
     42          // This event listener is different from the ones below, as it is
     43          // supposed to be used together with IframeSensorReadingEventWatcher.
     44          // It sends a message whenever there is an event, and window.parent
     45          // decides whether it was expected or not. It is the only way to have
     46          // something akin to EventWatcher in a cross-origin iframe.
     47          sensor.addEventListener('reading', sensorReadingEventHandler);
     48 
     49          sensor.addEventListener('activate', () => {
     50            resolve();
     51          }, { once: true });
     52          sensor.addEventListener('error', e => {
     53            reject(`${e.error.name}: ${e.error.message}`);
     54          }, { once: true });
     55          sensor.start();
     56        });
     57 
     58      case 'has_reading':
     59        return Promise.resolve(sensor.hasReading);
     60 
     61      case 'stop_sensor':
     62        if (sensor) {
     63          sensor.stop();
     64        }
     65        return Promise.resolve();
     66 
     67      default:
     68        return Promise.reject(`unknown command "${e.data.command}"`);
     69    }
     70  }
     71 
     72  window.onmessage = async (e) => {
     73    // The call to test_driver.set_context() above makes messages other than
     74    // those we are specifically waiting for to be delivered too. Ignore those
     75    // here.
     76    if (!e.data.command) {
     77      return;
     78    }
     79 
     80    try {
     81      test_driver.message_test({
     82        command: e.data.command,
     83        result: await messageHandler(e),
     84      });
     85    } catch (error) {
     86      test_driver.message_test({
     87        command: e.data.command,
     88        error,
     89      });
     90    }
     91  }
     92 </script>