DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (c68fe15a81fc)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174

<!DOCTYPE HTML>
<html>
<head>
  <title>Autoplay policy test</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
  <script type="text/javascript" src="manifest.js"></script>
</head>
<body>
<pre id="test">

<script>

let manager = new MediaTestManager;

gTestPrefs.push(["media.autoplay.default", SpecialPowers.Ci.nsIAutoplay.BLOCKED],
                ["media.autoplay.blocking_policy", 0]);

window.info = function(msg, token) {
  SimpleTest.info(msg + ", token=" + token);
}

window.is = function(valA, valB, msg, token) {
  SimpleTest.is(valA, valB, msg + ", token=" + token);
}

window.ok = function(val, msg, token) {
  SimpleTest.ok(val, msg + ", token=" + token);
}

/**
 * test files and paremeters
 */
var autoplayTests = [
  /* video */
  { name: "gizmo.mp4", type: "video/mp4", hasAudio:true },
  { name: "gizmo-noaudio.mp4", type: "video/mp4", hasAudio:false },
  { name: "gizmo.webm", type: "video/webm", hasAudio:true },
  { name: "gizmo-noaudio.webm", type: "video/webm", hasAudio:false },
  /* audio */
  { name: "small-shot.ogg", type: "audio/ogg", hasAudio:true },
  { name: "small-shot.m4a", type: "audio/mp4", hasAudio:true },
  { name: "small-shot.mp3", type: "audio/mpeg", hasAudio:true },
  { name: "small-shot.flac", type: "audio/flac", hasAudio:true },
];

var autoplayParams = [
  { volume: 1.0, muted: false, preload: "none" },
  { volume: 0.0, muted: false, preload: "none" },
  { volume: 1.0, muted: true, preload: "none" },
  { volume: 0.0, muted: true, preload: "none" },
  { volume: 1.0, muted: false, preload: "metadata" },
  { volume: 0.0, muted: false, preload: "metadata" },
  { volume: 1.0, muted: true, preload: "metadata" },
  { volume: 0.0, muted: true, preload: "metadata" },
];

function createTestArray()
{
  var tests = [];
  for (let test of autoplayTests) {
    for (let param of autoplayParams) {
      tests.push({
        name: test.name,
        type: test.type,
        hasAudio: test.hasAudio,
        volume: param.volume,
        muted: param.muted,
        preload: param.preload,
      });
    }
  }
  return tests;
}

/**
 * Main test function for different autoplay cases without user interaction.
 *
 * When the pref "media.autoplay.default" is 1 and the pref
 * "media.autoplay.blocking_policy" is 0, we only allow
 * audible media to autoplay after the website has been activated by specific
 * user gestures. However, inaudible media won't be restricted.
 *
 * Audible means the volume is not zero, or muted is not true for the video with
 * audio track. For media without loading metadata, we can't know whether it has
 * audio track or not, so we would also regard it as audible media.
 *
 * Inaudible means the volume is zero, or the muted is true, or the video without
 * audio track.
 */
async function runTest(test, token) {
  manager.started(token);

  await testPlay(test, token);
  await testAutoplayKeyword(test, token);

  manager.finished(token);
}

manager.runTests(createTestArray(), runTest);

/**
 * Different test scenarios
 */
async function testPlay(test, token) {
  info("### start testPlay", token);
  info(`volume=${test.volume}, muted=${test.muted}, ` +
       `preload=${test.preload}, hasAudio=${test.hasAudio}`, token);

  let element = document.createElement(getMajorMimeType(test.type));
  element.volume = test.volume;
  element.muted = test.muted;
  element.src = test.name;
  document.body.appendChild(element);

  // Only need to test preload when calling play(), because media with 'autoplay'
  // keyword always starts after loading enough data.
  const preLoadNone = test.preload == "none";
  if (!preLoadNone) {
    info("### wait for loading metadata", token);
    await once(element, "loadedmetadata");
  }

  let isAudible = (preLoadNone || test.hasAudio) &&
                  test.volume != 0.0 &&
                  !test.muted;
  let state = isAudible? "audible" : "non-audible";
  info(`### calling play() for ${state} media`, token);
  let promise = element.play();
  if (isAudible) {
    await promise.catch(function(error) {
      ok(element.paused, `${state} media fail to start via play()`, token);
      is(error.name, "NotAllowedError", "rejected play promise", token);
    });
  } else {
    // since we just want to check the value of 'paused', we don't need to wait
    // resolved play promise. (it's equal to wait for 'playing' event)
    await once(element, "play");
    ok(!element.paused, `${state} media start via play()`, token);
  }

  removeNodeAndSource(element);
}

async function testAutoplayKeyword(test, token) {
  info("### start testAutoplayKeyword", token);
  info(`volume=${test.volume}, muted=${test.muted}, ` +
       `hasAudio=${test.hasAudio}`, token);

  let element = document.createElement(getMajorMimeType(test.type));
  element.autoplay = true;
  element.volume = test.volume;
  element.muted = test.muted;
  element.src = test.name;
  document.body.appendChild(element);

  let isAudible = test.hasAudio &&
                  test.volume != 0.0 &&
                  !test.muted;
  let state = isAudible? "audible" : "non-audible";
  info(`### wait to autoplay for ${state} media`, token);
  if (isAudible) {
    await once(element, "canplay");
    ok(element.paused, `can not start with 'autoplay' keyword for ${state} media`, token);
  } else {
    await once(element, "play");
    ok(!element.paused, `start with 'autoplay' keyword for ${state} media`, token);
  }

  removeNodeAndSource(element);
}

</script>