From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../browser_autoplay_policy_web_audio_with_gum.js | 174 +++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 dom/media/autoplay/test/browser/browser_autoplay_policy_web_audio_with_gum.js (limited to 'dom/media/autoplay/test/browser/browser_autoplay_policy_web_audio_with_gum.js') 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); +} -- cgit v1.2.3