summaryrefslogtreecommitdiffstats
path: root/dom/media/webrtc/tests/mochitests/blacksilence.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/webrtc/tests/mochitests/blacksilence.js')
-rw-r--r--dom/media/webrtc/tests/mochitests/blacksilence.js134
1 files changed, 134 insertions, 0 deletions
diff --git a/dom/media/webrtc/tests/mochitests/blacksilence.js b/dom/media/webrtc/tests/mochitests/blacksilence.js
new file mode 100644
index 0000000000..bb16e4d78e
--- /dev/null
+++ b/dom/media/webrtc/tests/mochitests/blacksilence.js
@@ -0,0 +1,134 @@
+(function(global) {
+ "use strict";
+
+ // an invertible check on the condition.
+ // if the constraint is applied, then the check is direct
+ // if not applied, then the result should be reversed
+ function check(constraintApplied, condition, message) {
+ var good = constraintApplied ? condition : !condition;
+ message =
+ (constraintApplied ? "with" : "without") +
+ " constraint: should " +
+ (constraintApplied ? "" : "not ") +
+ message +
+ " = " +
+ (good ? "OK" : "waiting...");
+ info(message);
+ return good;
+ }
+
+ function mkElement(type) {
+ // This makes an unattached element.
+ // It's not rendered to save the cycles that costs on b2g emulator
+ // and it gets dropped (and GC'd) when the test is done.
+ var e = document.createElement(type);
+ e.width = 32;
+ e.height = 24;
+ document.getElementById("display").appendChild(e);
+ return e;
+ }
+
+ // Runs checkFunc until it reports success.
+ // This is kludgy, but you have to wait for media to start flowing, and it
+ // can't be any old media, it has to include real data, for which we have no
+ // reliable signals to use as a trigger.
+ function periodicCheck(checkFunc) {
+ var resolve;
+ var done = false;
+ // This returns a function so that we create 10 closures in the loop, not
+ // one; and so that the timers don't all start straight away
+ var waitAndCheck = counter => () => {
+ if (done) {
+ return Promise.resolve();
+ }
+ return new Promise(r => setTimeout(r, 200 << counter)).then(() => {
+ if (checkFunc()) {
+ done = true;
+ resolve();
+ }
+ });
+ };
+
+ var chain = Promise.resolve();
+ for (var i = 0; i < 10; ++i) {
+ chain = chain.then(waitAndCheck(i));
+ }
+ return new Promise(r => (resolve = r));
+ }
+
+ function isSilence(audioData) {
+ var silence = true;
+ for (var i = 0; i < audioData.length; ++i) {
+ if (audioData[i] !== 128) {
+ silence = false;
+ }
+ }
+ return silence;
+ }
+
+ function checkAudio(constraintApplied, stream) {
+ var audio = mkElement("audio");
+ audio.srcObject = stream;
+ audio.play();
+
+ var context = new AudioContext();
+ var source = context.createMediaStreamSource(stream);
+ var analyser = context.createAnalyser();
+ source.connect(analyser);
+ analyser.connect(context.destination);
+
+ return periodicCheck(() => {
+ var sampleCount = analyser.frequencyBinCount;
+ info("got some audio samples: " + sampleCount);
+ var buffer = new Uint8Array(sampleCount);
+ analyser.getByteTimeDomainData(buffer);
+
+ var silent = check(
+ constraintApplied,
+ isSilence(buffer),
+ "be silence for audio"
+ );
+ return sampleCount > 0 && silent;
+ }).then(() => {
+ source.disconnect();
+ analyser.disconnect();
+ audio.pause();
+ ok(true, "audio is " + (constraintApplied ? "" : "not ") + "silent");
+ });
+ }
+
+ function checkVideo(constraintApplied, stream) {
+ var video = mkElement("video");
+ video.srcObject = stream;
+ video.play();
+
+ return periodicCheck(() => {
+ try {
+ var canvas = mkElement("canvas");
+ var ctx = canvas.getContext("2d");
+ // Have to guard drawImage with the try as well, due to bug 879717. If
+ // we get an error, this round fails, but that failure is usually just
+ // transitory.
+ ctx.drawImage(video, 0, 0);
+ ctx.getImageData(0, 0, 1, 1);
+ return check(
+ constraintApplied,
+ false,
+ "throw on getImageData for video"
+ );
+ } catch (e) {
+ return check(
+ constraintApplied,
+ e.name === "SecurityError",
+ "get a security error: " + e.name
+ );
+ }
+ }).then(() => {
+ video.pause();
+ ok(true, "video is " + (constraintApplied ? "" : "not ") + "protected");
+ });
+ }
+
+ global.audioIsSilence = checkAudio;
+ global.videoIsBlack = checkVideo;
+})(this);