Bug 1382533 - Add tests for Presentation API fingerprinting resistance. draft
authorChung-Sheng Fu <cfu@mozilla.com>
Thu, 31 Aug 2017 15:04:33 +0800
changeset 657235 ed4ded0f49d68785a7b8e1649a6eb685abf437a6
parent 657234 bdfb69be0fce8fee1bc3b51918840f6454640c4e
child 729396 03f96655bf2db1131abf550625c25d930ffacd20
push id77488
push userbmo:cfu@mozilla.com
push dateFri, 01 Sep 2017 08:33:09 +0000
bugs1382533
milestone57.0a1
Bug 1382533 - Add tests for Presentation API fingerprinting resistance. MozReview-Commit-ID: JfVlBMPR0xW
dom/presentation/tests/mochitest/file_presentation_fingerprinting_resistance_receiver.html
dom/presentation/tests/mochitest/mochitest.ini
dom/presentation/tests/mochitest/test_presentation_fingerprinting_resistance.html
new file mode 100644
--- /dev/null
+++ b/dom/presentation/tests/mochitest/file_presentation_fingerprinting_resistance_receiver.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<script>
+function testReceiver() {
+  alert(!!navigator.presentation.receiver);
+}
+
+testReceiver();
+window.addEventListener('hashchange', testReceiver);
+</script>
--- a/dom/presentation/tests/mochitest/mochitest.ini
+++ b/dom/presentation/tests/mochitest/mochitest.ini
@@ -71,8 +71,11 @@ skip-if = (e10s || toolkit == 'android')
 skip-if = toolkit == 'android'
 [test_presentation_sandboxed_presentation.html]
 skip-if = true # bug 1315867
 [test_presentation_reconnect.html]
 [test_presentation_mixed_security_contexts.html]
 skip-if = toolkit == 'android' # bug 1304934
 [test_presentation_availability.html]
 support-files = test_presentation_availability_iframe.html
+[test_presentation_fingerprinting_resistance.html]
+skip-if = (e10s || toolkit == 'android')
+support-files = file_presentation_fingerprinting_resistance_receiver.html
new file mode 100644
--- /dev/null
+++ b/dom/presentation/tests/mochitest/test_presentation_fingerprinting_resistance.html
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+/* global SimpleTest SpecialPowers */
+
+const gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationSessionChromeScript1UA.js'));
+const kReceiverFile = 'file_presentation_fingerprinting_resistance_receiver.html';
+const kReceiverUrl = SimpleTest.getTestFileURL(kReceiverFile);
+
+let runTests = async () => {
+  await setup();
+  let request = await createRequest();
+  let iframe = await testRequestAndReceiver(request);
+  await enableResistFingerprinting();
+  await testRequestResistFingerprinting(request);
+  await testReceiverResistFingerprinting(iframe);
+  teardown();
+};
+
+let setup = async () => {
+  await SpecialPowers.pushPrefEnv({
+    set: [
+      ['dom.presentation.enabled', true],
+      ['dom.presentation.controller.enabled', true],
+      ['dom.presentation.receiver.enabled', true],
+      ['dom.presentation.test.enabled', true],
+      ['dom.presentation.test.stage', 0],
+      ['dom.mozBrowserFramesEnabled', true],
+      ['network.disable.ipc.security', true]
+    ]
+  });
+
+  gScript.addMessageListener('device-prompt', function devicePromptHandler() {
+    gScript.removeMessageListener('device-prompt', devicePromptHandler);
+    gScript.sendAsyncMessage('trigger-device-prompt-select');
+  });
+
+  gScript.addMessageListener('control-channel-established', function controlChannelEstablishedHandler() {
+    gScript.removeMessageListener('control-channel-established', controlChannelEstablishedHandler);
+    gScript.sendAsyncMessage('trigger-control-channel-open');
+  });
+
+  gScript.addMessageListener('promise-setup-ready', function promiseSetupReadyHandler() {
+    gScript.removeMessageListener('promise-setup-ready', promiseSetupReadyHandler);
+    gScript.sendAsyncMessage('trigger-on-session-request', kReceiverUrl);
+  });
+};
+
+let createRequest = () => new Promise((resolve, reject) => {
+  let request = new PresentationRequest(kReceiverFile);
+  request.getAvailability().then((availability) => {
+    SimpleTest.ok(availability, 'PresentationRequest.getAvailability');
+    availability.onchange = () => {
+      availability.onchange = null;
+      resolve(request);
+    };
+    gScript.sendAsyncMessage('trigger-device-add');
+  }).catch((error) => {
+    SimpleTest.ok(false, 'PresentationRequest.getAvailability: ' + error);
+    teardown();
+    reject(error);
+  });
+});
+
+let testRequestAndReceiver = (request) => new Promise((resolve, reject) => {
+  gScript.addMessageListener('sender-launch', function senderLaunchHandler(url) {
+    // SimpleTest.is(url, kReceiverUrl, 'sender-launch');
+    gScript.removeMessageListener('sender-launch', senderLaunchHandler);
+
+    let iframe = document.createElement('iframe');
+    iframe.setAttribute('src', kReceiverUrl);
+    iframe.setAttribute('mozbrowser', 'true');
+    iframe.setAttribute('mozpresentation', kReceiverUrl);
+    iframe.setAttribute('remote', 'false');
+    iframe.addEventListener('mozbrowsershowmodalprompt', (event) => {
+      SimpleTest.is(event.detail.message, 'true', 'navigator.presentation.receiver');
+      resolve(iframe);
+    }, {once: true});
+
+    let promise = new Promise((resolve) => {
+      document.body.appendChild(iframe);
+      resolve(iframe);
+    });
+
+    let obs = SpecialPowers.Cc["@mozilla.org/observer-service;1"].getService(SpecialPowers.Ci.nsIObserverService);
+    obs.notifyObservers(promise, 'setup-request-promise');
+  });
+
+  request.start().then((connection) => {
+    SimpleTest.ok(connection, 'PresentationRequest.start');
+  }).catch((error) => {
+    SimpleTest.ok(false, 'PresentationRequest.start: ' + error);
+    teardown();
+    reject(error);
+  });
+});
+
+let enableResistFingerprinting = () => {
+  const kPref = 'privacy.resistFingerprinting';
+  SimpleTest.info(kPref + ' = true');
+  return SpecialPowers.pushPrefEnv({
+    set: [
+      [kPref, true]
+    ]
+  });
+};
+
+let testRequestResistFingerprinting = (request) => {
+  return request.getAvailability()
+      .then(() => SimpleTest.ok(false, 'PresentationRequest.getAvailability'))
+      .catch((error) => SimpleTest.is(error.name, 'SecurityError', 'PresentationRequest.getAvailability'))
+      .then(() => request.start())
+      .then(() => SimpleTest.ok(false, 'PresentationRequest.start'))
+      .catch((error) => SimpleTest.is(error.name, 'SecurityError', 'PresentationRequest.start'))
+      .then(() => request.reconnect(kReceiverUrl))
+      .then(() => SimpleTest.ok(false, 'PresentationRequest.reconnect'))
+      .catch((error) => SimpleTest.is(error.name, 'SecurityError', 'PresentationRequest.reconnect'));
+};
+
+let testReceiverResistFingerprinting = (iframe) => new Promise((resolve) => {
+  iframe.addEventListener('mozbrowsershowmodalprompt', (event) => {
+    SimpleTest.is(event.detail.message, 'false', 'navigator.presentation.receiver');
+    resolve();
+  }, {once: true});
+  iframe.setAttribute('src', kReceiverUrl + '#privacy.resistFingerprinting');
+});
+
+let teardown = () => {
+  gScript.addMessageListener('teardown-complete', function teardownCompleteHandler() {
+    gScript.destroy();
+    SimpleTest.finish();
+  });
+
+  gScript.sendAsyncMessage('teardown');
+};
+
+SimpleTest.waitForExplicitFinish();
+document.addEventListener('DOMContentLoaded', () => {
+  SpecialPowers.pushPermissions([
+    {type: 'presentation-device-manage', allow: false, context: document},
+    {type: 'browser', allow: true, context: document},
+  ], runTests);
+});
+</script>