Bug 1415478 - part3 : add tests. r=jwwang
☠☠ backed out by e6b2a97752a6 ☠ ☠
authorAlastor Wu <alwu@mozilla.com>
Fri, 24 Nov 2017 16:42:47 +0800
changeset 393570 447d895b350d0c6743bc151355c45ed49b0c58c4
parent 393569 d855c032c8233f9daf0f8beeec1b12321a45b801
child 393571 2981c85f9586b96e62d35d461834c9bbe73d90c1
push id32966
push useraciure@mozilla.com
push dateFri, 24 Nov 2017 22:02:06 +0000
treeherdermozilla-central@f6f7da6085aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwwang
bugs1415478
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1415478 - part3 : add tests. r=jwwang MozReview-Commit-ID: ALFQcKRKk7c
dom/media/test/mochitest.ini
dom/media/test/test_autoplay_policy.html
--- a/dom/media/test/mochitest.ini
+++ b/dom/media/test/mochitest.ini
@@ -674,16 +674,17 @@ skip-if = android_version == '15' || and
 skip-if = android_version == '15' # android(bug 1232305)
 [test_audio1.html]
 [test_audio2.html]
 [test_audioDocumentTitle.html]
 skip-if = true # bug 475110 - disabled since we don't play Wave files standalone
 [test_autoplay.html]
 [test_autoplay_contentEditable.html]
 skip-if = android_version == '15' || android_version == '17' || android_version == '22' # android(bug 1232305, bug 1232318, bug 1372457)
+[test_autoplay_policy.html]
 [test_buffered.html]
 skip-if = android_version == '15' || android_version == '22' # bug 1308388, android(bug 1232305)
 [test_bug448534.html]
 [test_bug463162.xhtml]
 [test_bug465498.html]
 skip-if = toolkit == 'android' # android(bug 1232305)
 [test_bug495145.html]
 skip-if = (os == 'mac' && os_version == '10.6') || (toolkit == 'android')  # bug 1311229, android(bug 1232305)
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_autoplay_policy.html
@@ -0,0 +1,178 @@
+
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Autoplay policy test</title>
+  <script type="text/javascript" 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.enabled", false],
+                ["media.autoplay.enabled.user-gestures-needed", true]);
+
+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: 1.0, muted: false, preload: "metadata" },
+  { volume: 0.0, muted: false, preload: "none" },
+  { volume: 0.0, muted: false, preload: "metadata" },
+  { volume: 1.0, muted: true,  preload: "none"},
+  { volume: 1.0, muted: true,  preload: "metadata" },
+  { volume: 0.0, muted: true,  preload: "none"},
+  { volume: 0.0, muted: true,  preload: "metadata" }
+];
+
+function createTestArray()
+{
+  var tests = [];
+  for (let testIdx = 0; testIdx < autoplayTests.length; testIdx++) {
+    for (let paramIdx = 0; paramIdx < autoplayParams.length; paramIdx++) {
+      let test = autoplayTests[testIdx];
+      let param = autoplayParams[paramIdx];
+      let obj = new Object;
+      obj.name = test.name;
+      obj.type = test.type;
+      obj.hasAudio = test.hasAudio;
+      obj.volume = param.volume;
+      obj.muted = param.muted;
+      obj.preload = param.preload;
+      tests.push(obj);
+    }
+  }
+  return tests;
+}
+
+/**
+ * Main test function for different autoplay cases without user interaction.
+ *
+ * When the pref "media.autoplay.enabled" is false and the pref
+ * "media.autoplay.enabled.user-gestures-needed" is true, we would only allow
+ * audible media to autoplay after the website has been activated by specific
+ * user gestures. However, non-audible 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.
+ *
+ * Non-audible means the volume is zero, the muted is true, or the video without
+ * audio track.
+ */
+async function runTest(test, token) {
+  manager.started(token);
+
+  await testAutoplayKeyword(test, token);
+  await testPlay(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.preload = test.preload;
+  element.volume = test.volume;
+  element.muted = test.muted;
+  element.src = test.name;
+  document.body.appendChild(element);
+
+  let 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);
+  try {
+    await element.play();
+    ok(!isAudible, `${state} media can start via play()`, token);
+    is(element.paused, false, "media is playing", token);
+  } catch(error) {
+    ok(isAudible, `${state} media can't start via play()`, token);
+    is(error.name, "NotAllowedError", "rejected play promise", token);
+  }
+
+  removeNodeAndSource(element);
+}
+
+async function testAutoplayKeyword(test, token) {
+  info("### start testAutoplayKeyword", token);
+  info(`volume=${test.volume}, muted=${test.muted}, ` +
+       `preload=${test.preload}, hasAudio=${test.hasAudio}`, token);
+
+  let element = document.createElement(getMajorMimeType(test.type));
+  element.autoplay = true;
+  element.preload = test.preload;
+  element.volume = test.volume;
+  element.muted = test.muted;
+  element.src = test.name;
+  document.body.appendChild(element);
+
+  let preLoadNone = test.preload == "none";
+  let isAudible = (preLoadNone || test.hasAudio) &&
+                  test.volume != 0.0 &&
+                  !test.muted;
+  let state = isAudible? "audible" : "non-audible";
+  info(`### wait to autoplay for ${state} media`, token);
+  if (isAudible) {
+    if (preLoadNone) {
+      await once(element, "suspend");
+      is(element.readyState, 0 /* HAVE_NOTHING */, "media won't start loading", token);
+    } else {
+      await once(element, "canplaythrough");
+    }
+    is(element.paused, true, `can't start with 'autoplay' keyword for ${state} media`, token);
+  } else {
+    await once(element, "playing");
+    is(element.paused, false, `start with 'autoplay' keyword for ${state} media`, token);
+  }
+
+  removeNodeAndSource(element);
+}
+
+</script>
\ No newline at end of file