Bug 1333641 - Part 2: Add a test case to verify the behavior of speechSynthesis API when 'privacy.resistfingerprinting' is true. r?smaug,arthuredelstein draft
authorTim Huang <tihuang@mozilla.com>
Thu, 20 Jul 2017 16:57:03 +0800
changeset 614927 8fc2596fd64e573040357c389a671a3620e02542
parent 614926 e53fe57cadf54d3ecbe59e2c1eb4af8594d6fab5
child 639017 57062ab47f098377ba96aaeab9e479362a46476a
push id70179
push userbmo:tihuang@mozilla.com
push dateTue, 25 Jul 2017 06:56:38 +0000
reviewerssmaug, arthuredelstein
bugs1333641
milestone56.0a1
Bug 1333641 - Part 2: Add a test case to verify the behavior of speechSynthesis API when 'privacy.resistfingerprinting' is true. r?smaug,arthuredelstein This patch adds a test case to verify the speechSynthesis API when fingerprinting resistance is enabled. This test will first make sure the speechSynthesis has been setup correctly and then flip the pref 'privacy.resistFingerprinting'. Then, it will test speechSynthesis.getVoices(), onvoiceschanged event and speechSynthesis.speak(). MozReview-Commit-ID: 33BcZcHPgat
browser/components/resistfingerprinting/test/mochitest/mochitest.ini
browser/components/resistfingerprinting/test/mochitest/test_speech_synthesis.html
--- a/browser/components/resistfingerprinting/test/mochitest/mochitest.ini
+++ b/browser/components/resistfingerprinting/test/mochitest/mochitest.ini
@@ -6,8 +6,9 @@ support-files =
   !/dom/tests/mochitest/geolocation/network_geolocation.sjs
 
 [test_device_sensor_event.html]
 [test_geolocation.html]
 scheme = https
 [test_reduce_time_precision.html]
 [test_hide_gamepad_info.html]
 support-files = test_hide_gamepad_info_iframe.html
+[test_speech_synthesis.html]
new file mode 100644
--- /dev/null
+++ b/browser/components/resistfingerprinting/test/mochitest/test_speech_synthesis.html
@@ -0,0 +1,105 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1333641
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 1333641</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  /** Test for Bug 1333641 **/
+  SimpleTest.waitForExplicitFinish();
+  window.onload = setupSpeechSynthesis;
+
+  // This function setup the speechSynthesis and flip 'privacy.resistFingerprinting'
+  // after it has been setup correctly.
+  function setupSpeechSynthesis() {
+    window.speechSynthesis.addEventListener("voiceschanged", () => {
+      isnot(window.speechSynthesis.getVoices().length, 0, "Voices added");
+      SimpleTest.waitForFocus(() => {
+        SpecialPowers.pushPrefEnv({"set":
+          [["privacy.resistFingerprinting", true]]
+        }, doGetVoicesTest);
+      }, window);
+    }, {once: true});
+
+    is(window.speechSynthesis.getVoices().length, 0, "No voices added initially");
+  }
+
+  function doGetVoicesTest() {
+    is(window.speechSynthesis.getVoices().length, 0,
+       "There should be no voices after fingerprinting resistance is enabled.");
+    doVoiceschangedEventTest();
+  }
+
+  function doVoiceschangedEventTest() {
+    window.speechSynthesis.addEventListener("voiceschanged", () => {
+      ok(false, "The voiceschanged event should not be fired.");
+      doSpeakTestAsync();
+    }, {once: true});
+
+    window.addEventListener("TestEvent", () => {
+      // If we receive this event without receiving a 'voiceschanged' event, this means
+      // the voiceschanged event has been blocked correctly.
+      ok(true, "Got the 'TestEvent' event.");
+      doSpeakTestAsync();
+    }, {once: true});
+
+    // Notify 'synth-voices-changed' for triggering the voiceschanged event.
+    SpecialPowers.Services.obs.notifyObservers(null, "synth-voices-changed");
+    window.dispatchEvent(new CustomEvent("TestEvent"));
+  }
+
+  // This tests Speak() and its asynchronousness.
+  function doSpeakTestAsync() {
+    // For non-e10s, this test will always fail since the event will be triggered immediately
+    // after speak() is called. So, new added events after speak() won't be called. We skip
+    // this test if it is non-e10s.
+    if (SpecialPowers.Services.appinfo.browserTabsRemoteAutostart) {
+      let utterance = new window.SpeechSynthesisUtterance("Hello, world!");
+      window.speechSynthesis.speak(utterance);
+
+      utterance.addEventListener("start", () => {
+        ok(false, "speechSynthesis should not start speaking if fingerprinting resistance is enabled.");
+        doSpeakTestSync();
+      }, {once: true});
+
+      utterance.addEventListener("error", () => {
+        ok(true, "speechSynthesis.speak should fail if fingerprinting resistance is enabled.");
+        doSpeakTestSync();
+      }, {once: true});
+    } else {
+      doSpeakTestSync();
+    }
+  }
+
+  // This tests Speak() and its synchronousness.
+  function doSpeakTestSync() {
+    let utterance = new window.SpeechSynthesisUtterance("Hello, world!");
+    utterance.addEventListener("start", () => {
+      ok(false, "speechSynthesis should not start speaking if fingerprinting resistance is enabled.");
+      SimpleTest.finish();
+    }, {once: true});
+
+    utterance.addEventListener("error", () => {
+      ok(true, "speechSynthesis.speak should fail if fingerprinting resistance is enabled.");
+      SimpleTest.finish();
+    }, {once: true});
+
+    window.speechSynthesis.speak(utterance);
+  }
+
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug </a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test"></pre>
+</body>
+</html>