async function send_message_to_iframe(iframe, message, reply) { if (reply === undefined) { reply = 'success'; } return new Promise((resolve, reject) => { let messageHandler = e => { if (e.data.command !== message.command) { return; } window.removeEventListener('message', messageHandler); if (e.data.result === reply) { resolve(); } else { reject(); } } window.addEventListener('message', messageHandler); iframe.contentWindow.postMessage(message, '*'); }); } function run_generic_sensor_iframe_tests(sensorName) { const sensorType = self[sensorName]; const featurePolicies = get_feature_policies_for_sensor(sensorName); sensor_test(async t => { assert_true(sensorName in self); const iframe = document.createElement('iframe'); iframe.allow = featurePolicies.join(';') + ';'; iframe.src = 'https://{{domains[www1]}}:{{ports[https][0]}}/generic-sensor/resources/iframe_sensor_handler.html'; // Create sensor inside cross-origin nested browsing context. const iframeLoadWatcher = new EventWatcher(t, iframe, 'load'); document.body.appendChild(iframe); await iframeLoadWatcher.wait_for('load'); await send_message_to_iframe(iframe, {command: 'create_sensor', type: sensorName}); // Focus on the main frame and test that sensor recieves readings. window.focus(); const sensor = new sensorType(); const sensorWatcher = new EventWatcher(t, sensor, ['reading']); sensor.start(); await sensorWatcher.wait_for('reading'); const cachedTimeStamp = sensor.timestamp; // Focus on the cross-origin frame and verify that sensor reading updates in // the top level browsing context are suspended. iframe.contentWindow.focus(); await send_message_to_iframe(iframe, {command: 'start_sensor'}); assert_equals(cachedTimeStamp, sensor.timestamp); // Focus on the main frame, verify that sensor reading updates are resumed. window.focus(); await sensorWatcher.wait_for('reading'); assert_greater_than(sensor.timestamp, cachedTimeStamp); sensor.stop(); // Verify that sensor in cross-origin frame is suspended. await send_message_to_iframe(iframe, {command: 'is_sensor_suspended'}, true); await send_message_to_iframe(iframe, {command: 'reset_sensor_backend'}); // Remove iframe from main document. iframe.parentNode.removeChild(iframe); }, `${sensorName}: sensor is suspended and resumed when focus traverses from\ to cross-origin frame`); sensor_test(async t => { assert_true(sensorName in self); const iframe = document.createElement('iframe'); iframe.allow = featurePolicies.join(';') + ';'; iframe.src = 'https://{{host}}:{{ports[https][0]}}/generic-sensor/resources/iframe_sensor_handler.html'; // Create sensor inside same-origin nested browsing context. const iframeLoadWatcher = new EventWatcher(t, iframe, 'load'); document.body.appendChild(iframe); await iframeLoadWatcher.wait_for('load'); await send_message_to_iframe(iframe, {command: 'create_sensor', type: sensorName}); // Focus on main frame and test that sensor recieves readings. window.focus(); const sensor = new sensorType(); const sensorWatcher = new EventWatcher(t, sensor, ['reading']); sensor.start(); await sensorWatcher.wait_for('reading'); let cachedTimeStamp = sensor.timestamp; // Stop sensor in main frame, so that sensorWatcher would not receive // readings while sensor in iframe is started. Sensors that are active // and belong to the same-origin context are not suspended, therefore, // we might get unexpeted 'reading' event, thus, failing the test. sensor.stop(); iframe.contentWindow.focus(); await send_message_to_iframe(iframe, {command: 'start_sensor'}); // Start sensor on main frame, verify that readings are updated. window.focus(); sensor.start(); await sensorWatcher.wait_for('reading'); assert_greater_than(sensor.timestamp, cachedTimeStamp); cachedTimeStamp = sensor.timestamp; // Verify that sensor in nested browsing context is not suspended. await send_message_to_iframe(iframe, {command: 'is_sensor_suspended'}, false); // Verify that sensor in top level browsing context is receiving readings. iframe.contentWindow.focus(); sensor.start(); await sensorWatcher.wait_for('reading'); assert_greater_than(sensor.timestamp, cachedTimeStamp); sensor.stop(); await send_message_to_iframe(iframe, {command: 'reset_sensor_backend'}); // Remove iframe from main document. iframe.parentNode.removeChild(iframe); }, `${sensorName}: sensor is not suspended when focus traverses from\ to same-origin frame`); }