summaryrefslogtreecommitdiffstats
path: root/dom/media/autoplay/test/mochitest/test_autoplay_policy.html
blob: dae388b21d4b4ae1d95ff0ed028aecafa80c9cab (plain)
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>
/* import-globals-from ../../../test/manifest.js */
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>