summaryrefslogtreecommitdiffstats
path: root/browser/components/resistfingerprinting/test/mochitest/test_pointer_event.html
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/resistfingerprinting/test/mochitest/test_pointer_event.html')
-rw-r--r--browser/components/resistfingerprinting/test/mochitest/test_pointer_event.html242
1 files changed, 242 insertions, 0 deletions
diff --git a/browser/components/resistfingerprinting/test/mochitest/test_pointer_event.html b/browser/components/resistfingerprinting/test/mochitest/test_pointer_event.html
new file mode 100644
index 0000000000..5b8271274e
--- /dev/null
+++ b/browser/components/resistfingerprinting/test/mochitest/test_pointer_event.html
@@ -0,0 +1,242 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1363508
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Pointer Events spoofing</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<div id="target0" style="width: 50px; height: 50px; background: green"></div>
+<div id="target1" style="width: 50px; height: 50px; background: black"></div>
+<script type="application/javascript">
+
+ /** Test for Bug 1363508 */
+ SimpleTest.waitForExplicitFinish();
+
+ var target0 = window.document.getElementById("target0");
+ var target1 = window.document.getElementById("target1");
+ var utils = SpecialPowers.Ci.nsIDOMWindowUtils;
+
+ // A helper function to check that whether the pointer is spoofed correctly.
+ function checkPointerEvent(aEvent) {
+ is(aEvent.pointerId, utils.DEFAULT_MOUSE_POINTER_ID,
+ "The spoofed pointer event should always have the mouse pointer id.");
+ is(aEvent.width, 1, "The spoofed pointer event should always have width as 1.");
+ is(aEvent.height, 1, "The spoofed pointer event should always have width as 1.");
+ if (aEvent.buttons === 0) {
+ is(aEvent.pressure, 0.0,
+ "The spoofed pointer event should have pressure as 0.0 if it is not in a active buttons state.");
+ } else {
+ is(aEvent.pressure, 0.5,
+ "The spoofed pointer event should have pressure as 0.5 if it is in a active buttons state.");
+ }
+ is(aEvent.tangentialPressure, 0, "The spoofed pointer event should always have tangentialPressure as 0.");
+ is(aEvent.tiltX, 0, "The spoofed pointer event should always have tiltX as 0.");
+ is(aEvent.tiltY, 0, "The spoofed pointer event should always have tiltY as 0.");
+ is(aEvent.twist, 0, "The spoofed pointer event should always have twist as 0.");
+ is(aEvent.pointerType, "mouse", "The spoofed pointer event should always has mouse pointerType.");
+ is(aEvent.isPrimary, true, "The spoofed pointer event should only receive primary pointer events.");
+ }
+
+ // A helper function to create a promise for waiting the event.
+ function promiseForEvent(aEventType, aCheckFunc) {
+ return new Promise(resolve => {
+ target0.addEventListener(aEventType, (event) => {
+ is(event.type, aEventType, "receive " + event.type + " on target0");
+ aCheckFunc(event);
+ resolve();
+ }, { once: true });
+ });
+ }
+
+ // A test for pointer events from touch interface.
+ async function doTestForTouchPointerEvent() {
+ let eventPromises = [
+ promiseForEvent("pointerover", checkPointerEvent),
+ promiseForEvent("pointerenter", checkPointerEvent),
+ promiseForEvent("pointerdown", checkPointerEvent),
+ promiseForEvent("pointermove", checkPointerEvent),
+ promiseForEvent("pointerup", checkPointerEvent),
+ promiseForEvent("pointerout", checkPointerEvent),
+ promiseForEvent("pointerleave", checkPointerEvent),
+ ];
+
+ synthesizeMouse(target0, 5, 5, { type: "mousedown", inputSource: MouseEvent.MOZ_SOURCE_TOUCH, pressure: 0.75 });
+ synthesizeMouse(target0, 5, 5, { type: "mousemove", inputSource: MouseEvent.MOZ_SOURCE_TOUCH, pressure: 0.75 });
+ synthesizeMouse(target0, 5, 5, { type: "mouseup", inputSource: MouseEvent.MOZ_SOURCE_TOUCH, pressure: 0.75 });
+
+ await Promise.all(eventPromises);
+ }
+
+ // A test for pointercancel event.
+ async function doTestForTouchPointerCancelEvent() {
+ let eventPromises = [
+ promiseForEvent("pointerover", checkPointerEvent),
+ promiseForEvent("pointerenter", checkPointerEvent),
+ promiseForEvent("pointerdown", checkPointerEvent),
+ promiseForEvent("pointermove", checkPointerEvent),
+ promiseForEvent("pointercancel", checkPointerEvent),
+ promiseForEvent("pointerout", checkPointerEvent),
+ promiseForEvent("pointerleave", checkPointerEvent),
+ ];
+
+ synthesizeTouch(target0, 5, 5, { type: "touchstart" });
+ synthesizeTouch(target0, 6, 6, { type: "touchmove" });
+ synthesizeTouch(target0, 6, 6, { type: "touchcancel" });
+
+ await Promise.all(eventPromises);
+ }
+
+ // A test for pointer events from pen interface.
+ async function doTestForPenPointerEvent() {
+ let eventPromises = [
+ promiseForEvent("pointerover", checkPointerEvent),
+ promiseForEvent("pointerenter", checkPointerEvent),
+ promiseForEvent("pointerdown", checkPointerEvent),
+ promiseForEvent("pointermove", checkPointerEvent),
+ promiseForEvent("pointerup", checkPointerEvent),
+ promiseForEvent("pointerout", checkPointerEvent),
+ promiseForEvent("pointerleave", checkPointerEvent),
+ ];
+
+ synthesizeMouse(target0, 5, 5, { type: "mousedown", inputSource: MouseEvent.MOZ_SOURCE_PEN });
+ synthesizeMouse(target0, 5, 5, { type: "mousemove", inputSource: MouseEvent.MOZ_SOURCE_PEN });
+ synthesizeMouse(target0, 5, 5, { type: "mouseup", inputSource: MouseEvent.MOZ_SOURCE_PEN });
+ synthesizeMouse(target1, 5, 5, { type: "mousemove", inputSource: MouseEvent.MOZ_SOURCE_PEN });
+
+ await Promise.all(eventPromises);
+ }
+
+ // A test for gotpointercapture and lostpointercapture events.
+ // We would also test releasePointerCapture for only accepting spoofed pointer
+ // Id here.
+ async function doTestForPointerCapture() {
+ // We test for both mouse and touch to see whether the capture events are
+ // filed properly. We don't check pen here since it won't file capture
+ // events.
+ let inputSources = [ MouseEvent.MOZ_SOURCE_MOUSE,
+ MouseEvent.MOZ_SOURCE_TOUCH ];
+
+ for (let inputSource of inputSources) {
+ function eventHandler(event) {
+ checkPointerEvent(event);
+ if (event.type === "pointerdown") {
+ target0.setPointerCapture(event.pointerId);
+ } else if (event.type === "pointermove") {
+ if (inputSource === MouseEvent.MOZ_SOURCE_TOUCH) {
+ try {
+ target0.releasePointerCapture(utils.DEFAULT_TOUCH_POINTER_ID);
+ ok(false, "The releasePointerCapture should fail here, but it is not.");
+ } catch (e) {
+ ok(true, "The releasePointerCapture fails properly.");
+ }
+ }
+ target0.releasePointerCapture(event.pointerId);
+ }
+ }
+
+ let eventPromises = [
+ promiseForEvent("pointerover", eventHandler),
+ promiseForEvent("pointerenter", eventHandler),
+ promiseForEvent("pointerdown", eventHandler),
+ promiseForEvent("gotpointercapture", eventHandler),
+ promiseForEvent("pointermove", eventHandler),
+ promiseForEvent("lostpointercapture", eventHandler),
+ promiseForEvent("pointerup", eventHandler),
+ promiseForEvent("pointerout", eventHandler),
+ promiseForEvent("pointerleave", eventHandler),
+ ];
+
+ synthesizeMouse(target0, 5, 5, { type: "mousedown", inputSource });
+ synthesizeMouse(target0, 5, 5, { type: "mousemove", inputSource });
+ synthesizeMouse(target0, 5, 5, { type: "mouseup", inputSource });
+ synthesizeMouse(target1, 5, 5, { type: "mousemove", inputSource });
+
+ await Promise.all(eventPromises);
+ }
+ }
+
+ // A test for setPointerCapture() for only accepting spoofed pointer id.
+ async function doTestForSetPointerCapture() {
+ function eventHandler(event) {
+ checkPointerEvent(event);
+ if (event.type === "pointerdown") {
+ try {
+ target0.setPointerCapture(utils.DEFAULT_TOUCH_POINTER_ID);
+ ok(false, "The setPointerCapture should fail here, but it is not.");
+ } catch (e) {
+ ok(true, "The setPointerCapture fails properly.");
+ }
+ }
+ }
+
+ let eventPromises = [
+ promiseForEvent("pointerover", eventHandler),
+ promiseForEvent("pointerenter", eventHandler),
+ promiseForEvent("pointerdown", eventHandler),
+ promiseForEvent("pointermove", eventHandler),
+ promiseForEvent("pointerup", eventHandler),
+ promiseForEvent("pointerout", eventHandler),
+ promiseForEvent("pointerleave", eventHandler),
+ ];
+
+ synthesizeMouse(target0, 5, 5, { type: "mousedown", inputSource: MouseEvent.MOZ_SOURCE_TOUCH });
+ synthesizeMouse(target0, 5, 5, { type: "mousemove", inputSource: MouseEvent.MOZ_SOURCE_TOUCH });
+ synthesizeMouse(target0, 5, 5, { type: "mouseup", inputSource: MouseEvent.MOZ_SOURCE_TOUCH });
+
+ await Promise.all(eventPromises);
+ }
+
+ // A test for assuring that script generated events won't be spoofed.
+ function doTestNoSpoofingForScriptGeneratedEvent() {
+ return new Promise(resolve => {
+ // Generate a custom pointer event by script.
+ let pointerEventCustom = new PointerEvent("pointerover", {
+ pointerId: utils.DEFAULT_TOUCH_POINTER_ID,
+ pointerType: "touch",
+ width: 5,
+ height: 5,
+ pressure: 0.75,
+ tangentialPressure: 0.5,
+ isPrimary: false,
+ });
+
+ target0.addEventListener("pointerover", (event) => {
+ // Check that script generated event is not spoofed.
+ is(event.pointerType, "touch", "The pointerEvent.pointerType is not spoofed.");
+ is(event.width, 5, "The pointerEvent.width is not spoofed.");
+ is(event.height, 5, "The pointerEvent.height is not spoofed.");
+ is(event.pressure, 0.75, "The pointerEvent.pressure is not spoofed.");
+ is(event.tangentialPressure, 0.5, "The pointerEvent.tangentialPressure is not spoofed.");
+ is(event.isPrimary, false, "The pointerEvent.isPrimary is not spoofed.");
+ resolve();
+ }, { once: true });
+
+ target0.dispatchEvent(pointerEventCustom);
+ });
+ }
+
+ async function doTests() {
+ await doTestForTouchPointerEvent();
+ await doTestForTouchPointerCancelEvent();
+ await doTestForPenPointerEvent();
+ await doTestForPointerCapture();
+ await doTestForSetPointerCapture();
+ await doTestNoSpoofingForScriptGeneratedEvent();
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForFocus(() => {
+ SpecialPowers.pushPrefEnv({"set": [["privacy.resistFingerprinting", true]]},
+ doTests);
+ });
+
+</script>
+</body>
+</html>