summaryrefslogtreecommitdiffstats
path: root/dom/media/autoplay/test/browser/browser_autoplay_policy_web_audio_with_gum.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/autoplay/test/browser/browser_autoplay_policy_web_audio_with_gum.js')
-rw-r--r--dom/media/autoplay/test/browser/browser_autoplay_policy_web_audio_with_gum.js174
1 files changed, 174 insertions, 0 deletions
diff --git a/dom/media/autoplay/test/browser/browser_autoplay_policy_web_audio_with_gum.js b/dom/media/autoplay/test/browser/browser_autoplay_policy_web_audio_with_gum.js
new file mode 100644
index 0000000000..45d5c71a52
--- /dev/null
+++ b/dom/media/autoplay/test/browser/browser_autoplay_policy_web_audio_with_gum.js
@@ -0,0 +1,174 @@
+/* eslint-disable mozilla/no-arbitrary-setTimeout */
+
+/**
+ * This test is used to ensure web audio can be allowed to start when we have
+ * GUM permission.
+ */
+add_task(async function startTestingWebAudioWithGUM() {
+ info("- setup test preference -");
+ await setupTestPreferences();
+
+ info("- test web audio with gUM success -");
+ await testWebAudioWithGUM({
+ constraints: { audio: true },
+ shouldAllowStartingContext: true,
+ });
+ await testWebAudioWithGUM({
+ constraints: { video: true },
+ shouldAllowStartingContext: true,
+ });
+ await testWebAudioWithGUM({
+ constraints: { video: true, audio: true },
+ shouldAllowStartingContext: true,
+ });
+
+ await SpecialPowers.pushPrefEnv({
+ set: [["media.navigator.permission.force", true]],
+ }).then(async function () {
+ info("- test web audio with gUM denied -");
+ await testWebAudioWithGUM({
+ constraints: { video: true },
+ shouldAllowStartingContext: false,
+ });
+ await testWebAudioWithGUM({
+ constraints: { audio: true },
+ shouldAllowStartingContext: false,
+ });
+ await testWebAudioWithGUM({
+ constraints: { video: true, audio: true },
+ shouldAllowStartingContext: false,
+ });
+ });
+});
+
+/**
+ * testing helper functions
+ */
+function setupTestPreferences() {
+ return SpecialPowers.pushPrefEnv({
+ set: [
+ ["media.autoplay.default", SpecialPowers.Ci.nsIAutoplay.BLOCKED],
+ ["media.autoplay.blocking_policy", 0],
+ ["media.autoplay.block-event.enabled", true],
+ ["media.autoplay.block-webaudio", true],
+ ["media.navigator.permission.fake", true],
+ ],
+ });
+}
+
+function createAudioContext() {
+ content.ac = new content.AudioContext();
+ let ac = content.ac;
+ ac.resumePromises = [];
+ ac.stateChangePromise = new Promise(resolve => {
+ ac.addEventListener(
+ "statechange",
+ function () {
+ resolve();
+ },
+ { once: true }
+ );
+ });
+ ac.notAllowedToStart = new Promise(resolve => {
+ ac.addEventListener(
+ "blocked",
+ function () {
+ resolve();
+ },
+ { once: true }
+ );
+ });
+}
+
+async function checkingAudioContextRunningState() {
+ let ac = content.ac;
+ await ac.notAllowedToStart;
+ ok(ac.state === "suspended", `AudioContext is not started yet.`);
+}
+
+function resumeWithoutExpectedSuccess() {
+ let ac = content.ac;
+ let promise = ac.resume();
+ ac.resumePromises.push(promise);
+ return new Promise((resolve, reject) => {
+ content.setTimeout(() => {
+ if (ac.state == "suspended") {
+ ok(true, "audio context is still suspended");
+ resolve();
+ } else {
+ reject("audio context should not be allowed to start");
+ }
+ }, 2000);
+ });
+}
+
+function resumeWithExpectedSuccess() {
+ let ac = content.ac;
+ ac.resumePromises.push(ac.resume());
+ return Promise.all(ac.resumePromises).then(() => {
+ ok(ac.state == "running", "audio context starts running");
+ });
+}
+
+async function callGUM(testParameters) {
+ info("- calling gum with " + JSON.stringify(testParameters.constraints));
+ if (testParameters.shouldAllowStartingContext) {
+ // Because of the prefs we've set and passed, this is going to allow the
+ // window to start an AudioContext synchronously.
+ testParameters.constraints.fake = true;
+ await content.navigator.mediaDevices.getUserMedia(
+ testParameters.constraints
+ );
+ return;
+ }
+
+ // Call gUM, without sucess: we've made it so that only fake requests
+ // succeed without permission, and this is requesting non-fake-devices. Return
+ // a resolved promise so that the test continues, but the getUserMedia Promise
+ // will never be resolved.
+ // We do this to check that it's not merely calling gUM that allows starting
+ // an AudioContext, it's having the Promise it return resolved successfuly,
+ // because of saved permissions for an origin or explicit user consent using
+ // the prompt.
+ content.navigator.mediaDevices.getUserMedia(testParameters.constraints);
+}
+
+async function testWebAudioWithGUM(testParameters) {
+ info("- open new tab -");
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ window.gBrowser,
+ "https://example.com"
+ );
+ info("- create audio context -");
+ await SpecialPowers.spawn(tab.linkedBrowser, [], createAudioContext);
+
+ info("- check whether audio context starts running -");
+ try {
+ await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [],
+ checkingAudioContextRunningState
+ );
+ } catch (error) {
+ ok(false, error.toString());
+ }
+
+ try {
+ await SpecialPowers.spawn(tab.linkedBrowser, [testParameters], callGUM);
+ } catch (error) {
+ ok(false, error.toString());
+ }
+
+ info("- calling resume() again");
+ try {
+ let resumeFunc = testParameters.shouldAllowStartingContext
+ ? resumeWithExpectedSuccess
+ : resumeWithoutExpectedSuccess;
+ await SpecialPowers.spawn(tab.linkedBrowser, [], resumeFunc);
+ } catch (error) {
+ ok(false, error.toString());
+ }
+
+ info("- remove tab -");
+ await BrowserTestUtils.removeTab(tab);
+}