Introduce PointerEvent.deviceProperties

This change replaces deviceId on the PointerEvent interface with a new interface, deviceProperties. DeviceProperties contains one member, uniqueId, which functionally behaves the same as the outgoing deviceId.

Spec: https://github.com/w3c/pointerevents/pull/495

Bug: 330760871
Change-Id: I0f1a9f7d5589f790d94f498a38bfdf55b6f51073
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5388651
Reviewed-by: Robert Flack <flackr@chromium.org>
Commit-Queue: Sahir Vellani <sahir.vellani@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#1286827}
diff --git a/pointerevents/deviceproperties/get-device-properties-uniqueid-from-pointer-event.tentative.html b/pointerevents/deviceproperties/get-device-properties-uniqueid-from-pointer-event.tentative.html
new file mode 100644
index 0000000..53b4d2c
--- /dev/null
+++ b/pointerevents/deviceproperties/get-device-properties-uniqueid-from-pointer-event.tentative.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!--
+   Tentative; contingent on merge of:
+   https://github.com/w3c/pointerevents/pull/495
+-->
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<style>
+  div {
+    user-select: none; // Prevents text selection on drag.
+  }
+</style>
+<div id="logger" draggable="false"></div>
+<div id="console"></div>
+<!-- This test verifies that if the PointerEventDeviceId flag is enabled,
+     pointerEvent.deviceProperties.uniqueId is -1. If not, it is undefined. -->
+<script>
+    function CheckDeviceId(event) {
+        eventFired++;
+        assert_equals(event.deviceProperties.uniqueId, -1, "deviceId is -1");
+    }
+
+    window.addEventListener("pointerdown", CheckDeviceId, false);
+    window.addEventListener("pointermove", CheckDeviceId, false);
+
+    promise_test(async () => {
+        if (!window.internals)
+          return;
+        eventFired = 0;
+        let actions = new test_driver.Actions()
+          .addPointer("TestPointer", "pen")
+          .pointerDown()
+          .pointerMove(100, 100)
+          .pointerUp();
+
+        await actions.send();
+
+        assert_true(eventFired == 2);
+    }, 'PointerEvent.deviceProperties.uniqueId');
+</script>
\ No newline at end of file
diff --git a/pointerevents/deviceproperties/pointer-event-has-device-properties-uniqueid-from-pointer-event-init.tentative.html b/pointerevents/deviceproperties/pointer-event-has-device-properties-uniqueid-from-pointer-event-init.tentative.html
new file mode 100644
index 0000000..029edef
--- /dev/null
+++ b/pointerevents/deviceproperties/pointer-event-has-device-properties-uniqueid-from-pointer-event-init.tentative.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<!--
+   Tentative; contingent on merge of:
+   https://github.com/w3c/pointerevents/pull/495
+-->
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="console"></div>
+
+<!-- This test verifies that if the kPointerEventDeviceId flag is enabled,
+     pointerEvent.deviceProperties.uniqueId can be set via PointerEventInit. If not, it is
+     undefined. -->
+<script>
+    const UNIQUE_ID = 1001;
+    const INVALID_UNIQUE_ID = -1;
+
+    function CheckDeviceId(event, uniqueId) {
+        assert_equals(event.deviceProperties.uniqueId, uniqueId, "uniqueId is populated");
+    }
+
+    promise_test(async () => {
+        if (!window.internals)
+          return;
+        var deviceProps = new DeviceProperties({
+          uniqueId: 1001
+        });
+        var downEvent = new PointerEvent("pointerdown",
+          {pointerId: 1,
+            bubbles: true,
+            cancelable: true,
+            pointerType: "pen",
+            width: 100,
+            height: 100,
+            isPrimary: true,
+            deviceProperties: deviceProps
+          });
+        CheckDeviceId(downEvent, UNIQUE_ID);
+        var moveEvent = new PointerEvent("pointermove",
+          {pointerId: 1,
+            bubbles: true,
+            cancelable: true,
+            pointerType: "pen",
+            width: 100,
+            height: 100,
+            isPrimary: true,
+            deviceProperties: deviceProps
+          });
+        CheckDeviceId(moveEvent, UNIQUE_ID);
+        var upEvent = new PointerEvent("pointerup",
+          {pointerId: 1,
+            bubbles: true,
+            cancelable: true,
+            pointerType: "pen",
+            width: 100,
+            height: 100,
+            isPrimary: true,
+            deviceProperties: deviceProps
+          });
+        CheckDeviceId(upEvent, UNIQUE_ID);
+    }, 'PointerEvent.deviceProperties via DevicePropertiesInit');
+
+    promise_test(async () => {
+        if (!window.internals)
+          return;
+        var emptyDeviceProps = new DeviceProperties({});
+        var downEventEmptyProps = new PointerEvent("pointerdown",
+          {pointerId: 1,
+            bubbles: true,
+            cancelable: true,
+            pointerType: "pen",
+            width: 100,
+            height: 100,
+            isPrimary: true,
+            deviceProperties: emptyDeviceProps
+        });
+        CheckDeviceId(downEventEmptyProps, INVALID_UNIQUE_ID);
+    }, 'PointerEvent.deviceProperties via empty DevicePropertiesInit');
+
+    promise_test(async () => {
+        if (!window.internals)
+          return;
+        var downEventEmptyProps = new PointerEvent("pointerdown",
+          {pointerId: 1,
+            bubbles: true,
+            cancelable: true,
+            pointerType: "pen",
+            width: 100,
+            height: 100,
+            isPrimary: true,
+        });
+        CheckDeviceId(downEventEmptyProps, INVALID_UNIQUE_ID);
+    }, 'No deviceProperties in PointerEventInit');
+</script>
\ No newline at end of file