test_autoplay_policy_web_audio_createMediaStreamSource.html (3693B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <title>Autoplay policy test : createMediaStreamSource with active stream</title> 5 <script src="/tests/SimpleTest/SimpleTest.js"></script> 6 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 7 <script type="text/javascript" src="manifest.js"></script> 8 </head> 9 <body> 10 <script> 11 12 /** 13 * This test is used to ensure that we would try to start the blocked AudioContext 14 * which is blocked by autoplay policy, when it creates a MediaStreamAudioSourceNode 15 * which has a active input stream. 16 */ 17 18 SimpleTest.waitForExplicitFinish(); 19 20 (async function testStartAudioContextWhenCreatingMediaStreamAudioSourceWithActiveStream() { 21 await setupTestPreferences(); 22 23 info(`- create 2 AudioContext, one is used to generate active stream, another one is used to test whether it would be resumed after starting MediaStreamAudioSource with active stream -`); 24 createAudioContexts(); 25 26 info(`- both AudioContext are not allowed to start in beginning -`); 27 await audioContextsShouldBeBlocked(); 28 29 info(`- using AudioContext2 to create a MediaStreamAudioSourceNode with active stream, which should resume AudioContext2 -`); 30 await createMediaStreamAudioSourceByAudioContext2(); 31 32 endTest(); 33 })(); 34 35 /** 36 * Test utility functions 37 */ 38 39 function setupTestPreferences() { 40 return SpecialPowers.pushPrefEnv({"set": [ 41 ["media.autoplay.default", SpecialPowers.Ci.nsIAutoplay.BLOCKED], 42 ["media.autoplay.blocking_policy", 0], 43 ["media.autoplay.block-event.enabled", true], 44 ]}); 45 } 46 47 function createAudioContexts() { 48 /* global ac1, ac2 */ 49 window.ac1 = new AudioContext(); 50 window.ac2 = new AudioContext(); 51 52 ac1.allowedToStart = new Promise(resolve => { 53 ac1.addEventListener("statechange", function() { 54 if (ac1.state === "running") { 55 resolve(); 56 } 57 }, {once: true}); 58 }); 59 60 ac1.notAllowedToStart = new Promise(resolve => { 61 ac1.addEventListener("blocked", async function() { 62 resolve(); 63 }, {once: true}); 64 }); 65 66 67 ac2.allowedToStart = new Promise(resolve => { 68 ac2.addEventListener("statechange", function() { 69 if (ac2.state === "running") { 70 resolve(); 71 } 72 }, {once: true}); 73 }); 74 75 ac2.notAllowedToStart = new Promise(resolve => { 76 ac2.addEventListener("blocked", async function() { 77 resolve(); 78 }, {once: true}); 79 }); 80 } 81 82 async function audioContextsShouldBeBlocked() { 83 await ac1.notAllowedToStart; 84 await ac2.notAllowedToStart; 85 is(ac1.state, "suspended", `AudioContext1 is blocked.`); 86 is(ac2.state, "suspended", `AudioContext2 is blocked.`); 87 } 88 89 async function startAudioContext1() { 90 // simulate user gesture in order to start video. 91 SpecialPowers.wrap(document).notifyUserGestureActivation(); 92 ok(await ac1.resume().then(() => true, () => false), `resumed AudioContext1.`); 93 await ac1.allowedToStart; 94 is(ac1.state, "running", `AudioContext1 is running.`); 95 } 96 97 async function getActiveStream() { 98 await startAudioContext1(); 99 // As AudioContext1 has been resumed, we can use it to create active stream. 100 return ac1.createMediaStreamDestination().stream; 101 } 102 103 async function createMediaStreamAudioSourceByAudioContext2() { 104 is(ac2.state, "suspended", `AudioContext2 is suspended.`); 105 let source = ac2.createMediaStreamSource(await getActiveStream()); 106 source.connect(ac2.destination); 107 await ac2.allowedToStart; 108 is(ac2.state, "running", `AudioContext2 is running.`); 109 } 110 111 function endTest() { 112 // reset the activation flag in order not to interfere following test in the 113 // verify mode which would run the test using same document couple times. 114 SpecialPowers.wrap(document).clearUserGestureActivation(); 115 SimpleTest.finish(); 116 } 117 118 </script>