tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_mediaStreamAudioSourceNodeNoGC.html (3663B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <meta charset="utf-8">
      4 <head>
      5  <title>Test that MediaStreamAudioSourceNode and its input MediaStream stays alive while there are active tracks</title>
      6  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      7  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
      8 </head>
      9 <body>
     10 <pre id="test">
     11 <script class="testbody" type="text/javascript">
     12 SimpleTest.waitForExplicitFinish();
     13 SimpleTest.requestFlakyTimeout("gUM and WebAudio data is async to main thread. " +
     14                               "We need a timeout to see that something does " +
     15                               "NOT happen to data.");
     16 
     17 let context = new AudioContext();
     18 let analyser = context.createAnalyser();
     19 
     20 function wait(millis, resolveWithThis) {
     21  return new Promise(resolve => setTimeout(() => resolve(resolveWithThis), millis));
     22 }
     23 
     24 function binIndexForFrequency(frequency) {
     25  return 1 + Math.round(frequency * analyser.fftSize / context.sampleRate);
     26 }
     27 
     28 function waitForAudio(analysisFunction, cancelPromise) {
     29  let data = new Uint8Array(analyser.frequencyBinCount);
     30  let cancelled = false;
     31  let cancelledMsg = "";
     32  cancelPromise.then(msg => {
     33    cancelled = true;
     34    cancelledMsg = msg;
     35  });
     36  return new Promise((resolve, reject) => {
     37    let loop = () => {
     38      analyser.getByteFrequencyData(data);
     39      if (cancelled) {
     40        reject(new Error("waitForAudio cancelled: " + cancelledMsg));
     41        return;
     42      }
     43      if (analysisFunction(data)) {
     44        resolve();
     45        return;
     46      }
     47      requestAnimationFrame(loop);
     48    };
     49    loop();
     50  });
     51 }
     52 
     53 async function test() {
     54  try {
     55    await analyser.connect(context.destination);
     56 
     57    ok(true, "Waiting for audio to pass through the analyser")
     58    await waitForAudio(arr => arr[binIndexForFrequency(1000)] > 200,
     59                       wait(60000, "Timeout waiting for audio"));
     60 
     61    ok(true, "Audio was detected by the analyser. Forcing CC.");
     62    SpecialPowers.forceCC();
     63    SpecialPowers.forceGC();
     64    SpecialPowers.forceCC();
     65    SpecialPowers.forceGC();
     66 
     67    info("Checking that GC didn't destroy the stream or source node");
     68    await waitForAudio(arr => arr[binIndexForFrequency(1000)] < 50,
     69                       wait(5000, "Timeout waiting for GC (timeout OK)"))
     70                  .then(() => Promise.reject("Audio stopped unexpectedly"),
     71                        () => Promise.resolve());
     72 
     73    ok(true, "Audio is still flowing");
     74  } catch(e) {
     75    ok(false, "Error executing test: " + e + (e.stack ? "\n" + e.stack : ""));
     76    SimpleTest.finish();
     77  }
     78 }
     79 
     80 (async function() {
     81  try {
     82    await SpecialPowers.pushPrefEnv({
     83      set: [
     84        // This test expects the fake audio device, specifically for the tones
     85        // it outputs. Explicitly disable the audio loopback device and enable
     86        // fake streams.
     87        ['media.audio_loopback_dev', ''],
     88        ['media.navigator.streams.fake', true],
     89        ['media.navigator.permission.disabled', true]
     90      ]
     91    });
     92 
     93    // Test stream source GC
     94    let stream = await navigator.mediaDevices.getUserMedia({audio: true});
     95    let source = context.createMediaStreamSource(stream);
     96    stream = null;
     97    source.connect(analyser);
     98    await test(source);
     99 
    100    // Test track source GC
    101    stream = await navigator.mediaDevices.getUserMedia({audio: true});
    102    source = context.createMediaStreamTrackSource(stream.getAudioTracks()[0]);
    103    stream = null;
    104    source.connect(analyser);
    105    await test(source);
    106  } catch(e) {
    107    ok(false, `Error executing test: ${e}${e.stack ? "\n" + e.stack : ""}`);
    108  } finally {
    109    context.close();
    110    SimpleTest.finish();
    111  }
    112 })();
    113 </script>
    114 </pre>
    115 </body>
    116 </html>