chromium/third_party/blink/web_tests/http/tests/media/autoplay/resources/autoplay-test.js

/**
 * Tests autoplay on a page and its subframes.
 */

// Tracks the results and how many active tests we have running.
let testExpectations = {};
let doneCallback;
let resultCallback = (data) => { top.postMessage(data, '*') };
let completedTestResults = [];
let results = {};

function tearDown() {
  // Reset the flag state.
  internals.settings.setAutoplayPolicy('no-user-gesture-required');

  // Ensure that play failed because autoplay was blocked. If playback failed
  // for another reason then we don't care because autoplay is always checked
  // first.
  const canAutoplayMedia = !results.media ||
                           results.media.name != 'NotAllowedError';
  const canAutoplayWebAudio = results.webAudio == 'running';

  // `canAutoplay` must match autoplay for both media element and Web Audio.
  // Special value `undefined` will be propagated otherwise.
  const canAutoplay = canAutoplayMedia == canAutoplayWebAudio ? canAutoplayMedia
                                                              : undefined;

  receivedResult({
    url: window.location.href,
    message: canAutoplay
  });
}

function receivedResult(data) {
  // Forward the result to the top frame.
  if (!doneCallback) {
    top.postMessage(data, '*');
    return;
  }

  completedTestResults.push(data);
  processTestResults();
}

function processTestResults() {
  // Check if we have completed all the tests.
  if (Object.keys(testExpectations).length != completedTestResults.length)
    return;

  completedTestResults.forEach((data) => {
    assert_equals(testExpectations[data.url], data.message);
  });

  doneCallback();
}

function runMediaTest() {
  return new Promise(resolve => {
    const video = document.createElement('video');
    video.src = '/media-resources/content/test.ogv';
    video.play().then(result => results.media = result,
                      result => results.media = result)
                .then(resolve);
  });
}

function runWebAudioTest() {
  const audioContext = new AudioContext();
  results.webAudio = audioContext.state;
}

async function runAutoplayTest() {
  await runMediaTest();
  runWebAudioTest();
  tearDown();
}

function simulateViewportClick(callback) {
  chrome.gpuBenchmarking.pointerActionSequence([
      {"source": "mouse",
       "actions": [
       { "name": "pointerDown", "x": 0, "y": 0 },
       { "name": "pointerUp" } ]}], callback);
}

function simulateFrameClick(callback) {
  const frame = document.getElementsByTagName('iframe')[0];
  const rect = frame.getBoundingClientRect();

  chrome.gpuBenchmarking.pointerActionSequence([
      {"source": "mouse",
       "actions": [
       {
         "name": "pointerDown",
         "x": rect.left + (rect.width / 2),
         "y": rect.top + (rect.height / 2)
       },
       { "name": "pointerUp" } ]}], callback);
}

function simulateNoGesture(callback) {
  callback();
}

function runTest(pointerSequence, expectations) {
  // Setup the global variables.
  expectations.forEach((expectation) => {
    testExpectations[expectation[0]] = expectation[1];
  });

  // Run the test.
  async_test((t) => {
    doneCallback = t.step_func_done();

    // Fire the pointer sequence and then run the video test.
    pointerSequence(t.step_func(() => {
      runAutoplayTest();

      // Navigate the iframe now we have the gesture.
      document.getElementsByTagName('iframe')[0].src =
          expectations[1][0];
    }));

    resultCallback = t.step_func(receivedResult);
  });
}

// Setup the flags before the test is run.
internals.settings.setAutoplayPolicy('document-user-activation-required');
internals.runtimeFlags.autoplayIgnoresWebAudioEnabled = false;

// Setup the event listener to forward messages.
window.addEventListener('message', (e) => { resultCallback(e.data); });

// If we are on an iframe then run the video test automatically.
if (window.self !== window.top)
  runAutoplayTest();