[EventTiming] Implement EventCounts

This CL adds support for performance.eventCounts, gated behind the
EventTiming flag. EventCounts is maplike and enables computing the
number of input events that have occurred for any of the supported event
types. It is populated on WindowPerformance::RegisterEventTiming so that
it matches when timing with when the PerformanceEventTiming entry is
created for slow events. The spec for this is here:
https://wicg.github.io/event-timing/#sec-event-counts

Bug: 543598

Change-Id: I95bd8b977556557811a1eff8d9fc5d106af0d2b1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2125019
Commit-Queue: Nicolás Peña Moreno <npm@chromium.org>
Reviewed-by: Yoav Weiss <yoavweiss@chromium.org>
Cr-Commit-Position: refs/heads/master@{#755468}
diff --git a/event-timing/event-click-counts.html b/event-timing/event-click-counts.html
new file mode 100644
index 0000000..880897a
--- /dev/null
+++ b/event-timing/event-click-counts.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<meta charset=utf-8 />
+<title>Event Timing: eventCounts.</title>
+<div id='div'>Click me</div>
+<button id='button'>Click me</div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/testdriver.js></script>
+<script src=/resources/testdriver-vendor.js></script>
+<script src=resources/event-timing-test-utils.js></script>
+<script>
+  promise_test( t => {
+    assert_precondition(window.EventCounts, "Event Counts isn't supported");
+    function testClicks(expectedCount, resolve) {
+      const clickCount = performance.eventCounts.get('click');
+      if (!clickCount || clickCount < expectedCount) {
+        t.step_timeout(function() {
+          testClicks(expectedCount, resolve);
+        }, 5);
+        return;
+      }
+      assert_equals(clickCount, expectedCount,'Incorrect click count.');
+      assert_equals(performance.eventCounts.get('mousedown'), expectedCount, 'Incorrect mousedown count');
+      assert_equals(performance.eventCounts.get('mouseup'), expectedCount, 'Incorrect mouseup count.');
+      assert_equals(performance.eventCounts.get('mouseover'), expectedCount, 'Incorrect mouseover count.');
+      // There should be no other input type recorded.
+      assert_equals(performance.eventCounts.size, 4, 'There should only be 4 types observed.');
+      resolve();
+    }
+    function promiseClicks(expectedCount) {
+      return new Promise(resolve => {
+        testClicks(1, resolve)
+      });
+    }
+
+    assert_equals(performance.eventCounts.size, 0);
+    test_driver.click(document.getElementById('div'));
+    return promiseClicks(1).then(() => {
+      test_driver.click(document.getElementById('button'));
+      return promiseClicks(2);
+    }).then(() => {
+      test_driver.click(document.getElementById('div'));
+      return promiseClicks(3);
+    });
+  })
+</script>
+</html>