Unify input delay computations for UMA, UKM, and EventTiming

This CL moves the input delay computations for UKM to further down the
pipeline to where they are computed for EventTiming. After this CL, the
same types of events are logged by both UMA/UKM and EventTiming. The
WebViewTest is fixed so that the artificial events move further enough
down the pipeline. The tests checking for pointerCancels are no longer
applicable since these only applied to the UMA/UKM computations, per
issue 924278.

By unifying input delay computation, this CL also fixes frame
attribution for the UMA/UKM input delays: PageWidgetDelegate does not
know the target frame (before, it would tell the root that an event has
occurred even if it occurred in an iframe.

Bug: 897656, 925130
Change-Id: I27dba1cbb82ad780d21166a5469001e266612a78
Reviewed-on: https://chromium-review.googlesource.com/c/1476070
Reviewed-by: Steven Holte <holte@chromium.org>
Reviewed-by: Charlie Harrison <csharrison@chromium.org>
Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
Commit-Queue: Nicolás Peña Moreno <npm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#635687}
diff --git a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc
index 32e1739..40b14f6 100644
--- a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc
@@ -99,13 +99,13 @@
 const char kHistogramInteractiveToInteractiveDetection[] =
     "PageLoad.Internal.InteractiveToInteractiveDetection";
 const char kHistogramFirstInputDelay[] =
-    "PageLoad.InteractiveTiming.FirstInputDelay2";
+    "PageLoad.InteractiveTiming.FirstInputDelay3";
 const char kHistogramFirstInputTimestamp[] =
-    "PageLoad.InteractiveTiming.FirstInputTimestamp2";
+    "PageLoad.InteractiveTiming.FirstInputTimestamp3";
 const char kHistogramLongestInputDelay[] =
-    "PageLoad.InteractiveTiming.LongestInputDelay2";
+    "PageLoad.InteractiveTiming.LongestInputDelay3";
 const char kHistogramLongestInputTimestamp[] =
-    "PageLoad.InteractiveTiming.LongestInputTimestamp2";
+    "PageLoad.InteractiveTiming.LongestInputTimestamp3";
 const char kHistogramParseStartToFirstMeaningfulPaint[] =
     "PageLoad.Experimental.PaintTiming.ParseStartToFirstMeaningfulPaint";
 const char kHistogramParseStartToFirstContentfulPaint[] =
diff --git a/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.cc
index 66ae720..4a91a82 100644
--- a/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.cc
@@ -38,7 +38,7 @@
 const char kHistogramFromGWSParseStart[] =
     "PageLoad.Clients.FromGoogleSearch.ParseTiming.NavigationToParseStart";
 const char kHistogramFromGWSFirstInputDelay[] =
-    "PageLoad.Clients.FromGoogleSearch.InteractiveTiming.FirstInputDelay2";
+    "PageLoad.Clients.FromGoogleSearch.InteractiveTiming.FirstInputDelay3";
 
 const char kHistogramFromGWSAbortNewNavigationBeforeCommit[] =
     "PageLoad.Clients.FromGoogleSearch.Experimental.AbortTiming.NewNavigation."
diff --git a/chrome/browser/page_load_metrics/observers/histogram_suffixes.cc b/chrome/browser/page_load_metrics/observers/histogram_suffixes.cc
index 6cd0a21..79cde8c 100644
--- a/chrome/browser/page_load_metrics/observers/histogram_suffixes.cc
+++ b/chrome/browser/page_load_metrics/observers/histogram_suffixes.cc
@@ -15,7 +15,7 @@
 const char kHistogramFirstImagePaintSuffix[] =
     "PaintTiming.NavigationToFirstImagePaint";
 const char kHistogramFirstInputDelaySuffix[] =
-    "InteractiveTiming.FirstInputDelay2";
+    "InteractiveTiming.FirstInputDelay3";
 const char kHistogramFirstLayoutSuffix[] =
     "DocumentTiming.NavigationToFirstLayout";
 const char kHistogramFirstMeaningfulPaintSuffix[] =
diff --git a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc
index 76f67e5..9fe1bf70 100644
--- a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc
@@ -29,7 +29,7 @@
     "PageLoad.Clients.ServiceWorker2.ParseTiming.NavigationToParseStart."
     "Background";
 const char kHistogramServiceWorkerFirstInputDelay[] =
-    "PageLoad.Clients.ServiceWorker2.InteractiveTiming.FirstInputDelay2";
+    "PageLoad.Clients.ServiceWorker2.InteractiveTiming.FirstInputDelay3";
 const char kHistogramServiceWorkerFirstPaint[] =
     "PageLoad.Clients.ServiceWorker2.PaintTiming.NavigationToFirstPaint";
 const char kHistogramServiceWorkerFirstContentfulPaint[] =
diff --git a/chrome/browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer.cc
index b9afac3..b689691 100644
--- a/chrome/browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer.cc
@@ -15,7 +15,7 @@
 constexpr char kHistogramSignedExchangeParseStart[] =
     HISTOGRAM_PREFIX "ParseTiming.NavigationToParseStart";
 constexpr char kHistogramSignedExchangeFirstInputDelay[] =
-    HISTOGRAM_PREFIX "InteractiveTiming.FirstInputDelay2";
+    HISTOGRAM_PREFIX "InteractiveTiming.FirstInputDelay3";
 constexpr char kHistogramSignedExchangeFirstPaint[] =
     HISTOGRAM_PREFIX "PaintTiming.NavigationToFirstPaint";
 constexpr char kHistogramSignedExchangeFirstContentfulPaint[] =
diff --git a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc
index 8968681..249be35 100644
--- a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc
@@ -252,26 +252,26 @@
   if (timing.interactive_timing->first_input_delay) {
     base::TimeDelta first_input_delay =
         timing.interactive_timing->first_input_delay.value();
-    builder.SetInteractiveTiming_FirstInputDelay2(
+    builder.SetInteractiveTiming_FirstInputDelay3(
         first_input_delay.InMilliseconds());
   }
   if (timing.interactive_timing->first_input_timestamp) {
     base::TimeDelta first_input_timestamp =
         timing.interactive_timing->first_input_timestamp.value();
-    builder.SetInteractiveTiming_FirstInputTimestamp2(
+    builder.SetInteractiveTiming_FirstInputTimestamp3(
         first_input_timestamp.InMilliseconds());
   }
 
   if (timing.interactive_timing->longest_input_delay) {
     base::TimeDelta longest_input_delay =
         timing.interactive_timing->longest_input_delay.value();
-    builder.SetInteractiveTiming_LongestInputDelay2(
+    builder.SetInteractiveTiming_LongestInputDelay3(
         longest_input_delay.InMilliseconds());
   }
   if (timing.interactive_timing->longest_input_timestamp) {
     base::TimeDelta longest_input_timestamp =
         timing.interactive_timing->longest_input_timestamp.value();
-    builder.SetInteractiveTiming_LongestInputTimestamp2(
+    builder.SetInteractiveTiming_LongestInputTimestamp3(
         longest_input_timestamp.InMilliseconds());
   }
 
diff --git a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc
index 3570b6ed..c92fbb2b 100644
--- a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc
@@ -650,9 +650,9 @@
     test_ukm_recorder().ExpectEntrySourceHasUrl(kv.second.get(),
                                                 GURL(kTestUrl1));
     test_ukm_recorder().ExpectEntryMetric(
-        kv.second.get(), PageLoad::kInteractiveTiming_FirstInputDelay2Name, 50);
+        kv.second.get(), PageLoad::kInteractiveTiming_FirstInputDelay3Name, 50);
     test_ukm_recorder().ExpectEntryMetric(
-        kv.second.get(), PageLoad::kInteractiveTiming_FirstInputTimestamp2Name,
+        kv.second.get(), PageLoad::kInteractiveTiming_FirstInputTimestamp3Name,
         712);
   }
 }
@@ -681,11 +681,11 @@
     test_ukm_recorder().ExpectEntrySourceHasUrl(kv.second.get(),
                                                 GURL(kTestUrl1));
     test_ukm_recorder().ExpectEntryMetric(
-        kv.second.get(), PageLoad::kInteractiveTiming_LongestInputDelay2Name,
+        kv.second.get(), PageLoad::kInteractiveTiming_LongestInputDelay3Name,
         50);
     test_ukm_recorder().ExpectEntryMetric(
         kv.second.get(),
-        PageLoad::kInteractiveTiming_LongestInputTimestamp2Name, 712);
+        PageLoad::kInteractiveTiming_LongestInputTimestamp3Name, 712);
   }
 }
 
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
index b810d86..eebef5c 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -2083,6 +2083,9 @@
   histogram_tester_.ExpectTotalCount(internal::kHistogramInputToFirstPaint, 1);
   histogram_tester_.ExpectTotalCount(
       internal::kHistogramInputToFirstContentfulPaint, 1);
+  histogram_tester_.ExpectTotalCount(internal::kHistogramFirstInputDelay, 1);
+  histogram_tester_.ExpectTotalCount(internal::kHistogramFirstInputTimestamp,
+                                     1);
 }
 
 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, InputEventsForOmniboxMatch) {
@@ -2132,6 +2135,9 @@
   histogram_tester_.ExpectTotalCount(internal::kHistogramInputToFirstPaint, 1);
   histogram_tester_.ExpectTotalCount(
       internal::kHistogramInputToFirstContentfulPaint, 1);
+  histogram_tester_.ExpectTotalCount(internal::kHistogramFirstInputDelay, 1);
+  histogram_tester_.ExpectTotalCount(internal::kHistogramFirstInputTimestamp,
+                                     1);
 }
 
 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest,
@@ -2165,3 +2171,27 @@
   histogram_tester_.ExpectTotalCount(
       internal::kHistogramInputToFirstContentfulPaint, 1);
 }
+
+IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, FirstInputFromScroll) {
+  embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
+  content::SetupCrossSiteRedirector(embedded_test_server());
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  auto waiter = CreatePageLoadMetricsTestWaiter();
+  waiter->AddPageExpectation(TimingField::kLoadEvent);
+  waiter->AddPageExpectation(TimingField::kFirstContentfulPaint);
+  ui_test_utils::NavigateToURL(
+      browser(),
+      embedded_test_server()->GetURL("/page_load_metrics/scroll.html"));
+  waiter->Wait();
+
+  content::SimulateGestureScrollSequence(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      gfx::Point(100, 100), gfx::Vector2dF(0, 15));
+  NavigateToUntrackedUrl();
+
+  // First Input Delay should not be reported from a scroll!
+  histogram_tester_.ExpectTotalCount(internal::kHistogramFirstInputDelay, 0);
+  histogram_tester_.ExpectTotalCount(internal::kHistogramFirstInputTimestamp,
+                                     0);
+}
diff --git a/chrome/test/data/page_load_metrics/scroll.html b/chrome/test/data/page_load_metrics/scroll.html
new file mode 100644
index 0000000..fc96ee0
--- /dev/null
+++ b/chrome/test/data/page_load_metrics/scroll.html
@@ -0,0 +1,15 @@
+<html>
+  <head>
+    <style>
+      body {
+        overflow: scroll;
+      }
+      div {
+        font-size: 2000px;
+      }
+    </style>
+  </head>
+  <body>
+    <div>Hi</div>
+  </body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
index ae2135a..3b6dab5 100644
--- a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
+++ b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
@@ -45,7 +45,6 @@
 #include "third_party/blink/renderer/core/frame/use_counter.h"
 #include "third_party/blink/renderer/core/html/html_element.h"
 #include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
-#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
 #include "third_party/blink/renderer/core/timing/event_timing.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
 
@@ -140,15 +139,9 @@
     return DispatchEventResult::kNotCanceled;
   }
   std::unique_ptr<EventTiming> eventTiming;
-  if (origin_trials::EventTimingEnabled(&node_->GetDocument())) {
-    LocalFrame* frame = node_->GetDocument().GetFrame();
-    if (frame && frame->DomWindow()) {
-      UseCounter::Count(node_->GetDocument(),
-                        WebFeature::kPerformanceEventTimingConstructor);
-      eventTiming = std::make_unique<EventTiming>(frame->DomWindow());
-      eventTiming->WillDispatchEvent(*event_);
-    }
-  }
+  LocalFrame* frame = node_->GetDocument().GetFrame();
+  if (frame && frame->DomWindow())
+    eventTiming = EventTiming::Create(frame->DomWindow(), *event_);
   event_->GetEventPath().EnsureWindowEventContext();
 
   const bool is_click =
@@ -156,7 +149,6 @@
 
   if (is_click && event_->isTrusted()) {
     Document& document = node_->GetDocument();
-    LocalFrame* frame = document.GetFrame();
     if (frame) {
       // A genuine mouse click cannot be triggered by script so we don't expect
       // there are any script in the stack.
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc
index 5d6f5d74..b1747d9 100644
--- a/third_party/blink/renderer/core/exported/web_view_test.cc
+++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -5246,21 +5246,21 @@
   web_view->MainFrameWidget()->HandleInputEvent(
       WebCoalescedInputEvent(key_event3));
 
-  histogram_tester.ExpectTotalCount("PageLoad.InteractiveTiming.InputDelay2",
+  histogram_tester.ExpectTotalCount("PageLoad.InteractiveTiming.InputDelay3",
                                     3);
-  histogram_tester.ExpectBucketCount("PageLoad.InteractiveTiming.InputDelay2",
+  histogram_tester.ExpectBucketCount("PageLoad.InteractiveTiming.InputDelay3",
                                      50, 2);
-  histogram_tester.ExpectBucketCount("PageLoad.InteractiveTiming.InputDelay2",
+  histogram_tester.ExpectBucketCount("PageLoad.InteractiveTiming.InputDelay3",
                                      70, 1);
 
   histogram_tester.ExpectTotalCount(
-      "PageLoad.InteractiveTiming.InputTimestamp2", 3);
+      "PageLoad.InteractiveTiming.InputTimestamp3", 3);
   histogram_tester.ExpectBucketCount(
-      "PageLoad.InteractiveTiming.InputTimestamp2", 70, 1);
+      "PageLoad.InteractiveTiming.InputTimestamp3", 70, 1);
   histogram_tester.ExpectBucketCount(
-      "PageLoad.InteractiveTiming.InputTimestamp2", 120, 1);
+      "PageLoad.InteractiveTiming.InputTimestamp3", 120, 1);
   histogram_tester.ExpectBucketCount(
-      "PageLoad.InteractiveTiming.InputTimestamp2", 170, 1);
+      "PageLoad.InteractiveTiming.InputTimestamp3", 170, 1);
 }
 
 // Tests that if the page was backgrounded while an input event was queued,
@@ -5398,6 +5398,7 @@
   EXPECT_EQ(key_event_time, interactive_detector->GetLongestInputTimestamp());
 }
 
+// TODO(npm): Improve this test to receive real input sequences and avoid hacks.
 // Check that first input delay is correctly reported to the document when the
 // first input is a pointer down event, and we receive a pointer up event.
 TEST_F(WebViewTest, PointerDownUpFirstInputDelay) {
@@ -5405,6 +5406,11 @@
   WebURL base_url = url_test_helpers::ToKURL("http://example.com/");
   frame_test_helpers::LoadHTMLString(web_view->MainFrameImpl(),
                                      "<html><body></body></html>", base_url);
+  // Add an event listener for pointerdown to ensure it is not optimized out
+  // before reaching the EventDispatcher.
+  WebLocalFrame* frame = web_view_helper_.LocalMainFrame();
+  frame->ExecuteScript(
+      WebScriptSource("addEventListener('pointerdown', function() {});"));
 
   LocalFrame* main_frame = web_view->MainFrameImpl()->GetFrame();
   ASSERT_NE(nullptr, main_frame);
@@ -5423,6 +5429,9 @@
       WebInputEvent::kPointerDown,
       WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5);
   pointer_down.SetTimeStamp(CurrentTimeTicks());
+  // Set this to the left button, needed for testing to behave properly.
+  pointer_down.SetModifiers(WebInputEvent::kLeftButtonDown);
+  pointer_down.button = WebPointerProperties::Button::kLeft;
   clock.Advance(TimeDelta::FromMilliseconds(50));
   web_view->MainFrameWidget()->HandleInputEvent(
       WebCoalescedInputEvent(pointer_down));
@@ -5447,178 +5456,6 @@
                     .InMillisecondsF());
 }
 
-// Check that first input delay isn't reported to the document when the
-// first input is a pointer down event followed by a pointer cancel event.
-TEST_F(WebViewTest, PointerDownCancelFirstInputDelay) {
-  WebViewImpl* web_view = web_view_helper_.Initialize();
-  WebURL base_url = url_test_helpers::ToKURL("http://example.com/");
-  frame_test_helpers::LoadHTMLString(web_view->MainFrameImpl(),
-                                     "<html><body></body></html>", base_url);
-
-  LocalFrame* main_frame = web_view->MainFrameImpl()->GetFrame();
-  ASSERT_NE(nullptr, main_frame);
-
-  Document* document = main_frame->GetDocument();
-  ASSERT_NE(nullptr, document);
-
-  WTF::ScopedMockClock clock;
-  clock.Advance(TimeDelta::FromMilliseconds(70));
-
-  InteractiveDetector* interactive_detector(
-      InteractiveDetector::From(*document));
-  ASSERT_NE(nullptr, interactive_detector);
-
-  WebPointerEvent pointer_down(
-      WebInputEvent::kPointerDown,
-      WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5);
-  pointer_down.SetTimeStamp(CurrentTimeTicks());
-  clock.Advance(TimeDelta::FromMilliseconds(50));
-  web_view->MainFrameWidget()->HandleInputEvent(
-      WebCoalescedInputEvent(pointer_down));
-
-  // We don't know if this pointer event will result in a scroll or not, so we
-  // can't report its delay. We don't consider a scroll to be meaningful input.
-  EXPECT_TRUE(interactive_detector->GetFirstInputDelay().is_zero());
-
-  // When we receive a pointer cancel, we should not report the pointer down.
-  WebPointerEvent pointer_cancel(
-      WebInputEvent::kPointerCancel,
-      WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5);
-  clock.Advance(TimeDelta::FromMilliseconds(60));
-  pointer_cancel.SetTimeStamp(CurrentTimeTicks());
-  web_view->MainFrameWidget()->HandleInputEvent(
-      WebCoalescedInputEvent(pointer_cancel));
-
-  // We received a pointer cancel, so this is a scroll gesture. No meaningful
-  // input has occurred yet.
-  EXPECT_TRUE(interactive_detector->GetFirstInputDelay().is_zero());
-  EXPECT_TRUE(interactive_detector->GetFirstInputTimestamp().is_null());
-}
-
-// Check that input delay isn't reported when there is pointer down, pointer
-// cancel, and pointer up.
-TEST_F(WebViewTest, PointerDownCancelUpInputDelay) {
-  WebViewImpl* web_view = web_view_helper_.Initialize();
-  WebURL base_url = url_test_helpers::ToKURL("http://example.com/");
-  frame_test_helpers::LoadHTMLString(web_view->MainFrameImpl(),
-                                     "<html><body></body onpointerdown="
-                                     "></html>",
-                                     base_url);
-
-  LocalFrame* main_frame = web_view->MainFrameImpl()->GetFrame();
-  ASSERT_NE(nullptr, main_frame);
-  Document* document = main_frame->GetDocument();
-  ASSERT_NE(nullptr, document);
-
-  WTF::ScopedMockClock clock;
-  clock.Advance(TimeDelta::FromMilliseconds(70));
-
-  InteractiveDetector* interactive_detector(
-      InteractiveDetector::From(*document));
-  ASSERT_NE(nullptr, interactive_detector);
-
-  WebPointerEvent pointer_down(
-      WebInputEvent::kPointerDown,
-      WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5);
-  pointer_down.SetTimeStamp(CurrentTimeTicks());
-  clock.Advance(TimeDelta::FromMilliseconds(50));
-  web_view->MainFrameWidget()->HandleInputEvent(
-      WebCoalescedInputEvent(pointer_down));
-
-  // We don't know if this pointer event will result in a scroll or not, so we
-  // can't report its delay. We don't consider a scroll to be meaningful input.
-  EXPECT_TRUE(interactive_detector->GetFirstInputDelay().is_zero());
-
-  // When we receive a pointer cancel, we should not report the pointer down.
-  WebPointerEvent pointer_cancel(
-      WebInputEvent::kPointerCancel,
-      WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5);
-  clock.Advance(TimeDelta::FromMilliseconds(60));
-  pointer_cancel.SetTimeStamp(CurrentTimeTicks());
-  web_view->MainFrameWidget()->HandleInputEvent(
-      WebCoalescedInputEvent(pointer_cancel));
-
-  EXPECT_TRUE(interactive_detector->GetFirstInputDelay().is_zero());
-
-  // When we receive a pointer up, because we received a pointer cancel, no
-  // input delay should be recorded.
-  WebPointerEvent pointer_up(
-      WebInputEvent::kPointerUp,
-      WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5);
-  clock.Advance(TimeDelta::FromMilliseconds(60));
-  pointer_up.SetTimeStamp(CurrentTimeTicks());
-  web_view->MainFrameWidget()->HandleInputEvent(
-      WebCoalescedInputEvent(pointer_up));
-
-  EXPECT_TRUE(interactive_detector->GetFirstInputDelay().is_zero());
-  EXPECT_TRUE(interactive_detector->GetFirstInputTimestamp().is_null());
-  EXPECT_TRUE(interactive_detector->GetLongestInputDelay().is_zero());
-  EXPECT_TRUE(interactive_detector->GetLongestInputTimestamp().is_null());
-}
-
-// Check that first input delay isn't reported when there is pointer down,
-// pointer caused UA action, and pointer up.
-TEST_F(WebViewTest, PointerDownCausedUaActionUpInputDelay) {
-  WebViewImpl* web_view = web_view_helper_.Initialize();
-  WebURL base_url = url_test_helpers::ToKURL("http://example.com/");
-  frame_test_helpers::LoadHTMLString(web_view->MainFrameImpl(),
-                                     "<html><body></body onpointerdown="
-                                     "></html>",
-                                     base_url);
-
-  LocalFrame* main_frame = web_view->MainFrameImpl()->GetFrame();
-  ASSERT_NE(nullptr, main_frame);
-  Document* document = main_frame->GetDocument();
-  ASSERT_NE(nullptr, document);
-
-  WTF::ScopedMockClock clock;
-  clock.Advance(TimeDelta::FromMilliseconds(70));
-
-  InteractiveDetector* interactive_detector(
-      InteractiveDetector::From(*document));
-  ASSERT_NE(nullptr, interactive_detector);
-
-  WebPointerEvent pointer_down(
-      WebInputEvent::kPointerDown,
-      WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5);
-  pointer_down.SetTimeStamp(CurrentTimeTicks());
-  clock.Advance(TimeDelta::FromMilliseconds(50));
-  web_view->MainFrameWidget()->HandleInputEvent(
-      WebCoalescedInputEvent(pointer_down));
-
-  // We don't know if this pointer event will result in a scroll or not, so we
-  // can't report its delay. We don't consider a scroll to be meaningful input.
-  EXPECT_TRUE(interactive_detector->GetFirstInputDelay().is_zero());
-
-  // When we receive a pointer caused UA action, we should not report the
-  // pointer down.
-  WebPointerEvent pointer_cancel(
-      WebInputEvent::kPointerCausedUaAction,
-      WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5);
-  clock.Advance(TimeDelta::FromMilliseconds(60));
-  pointer_cancel.SetTimeStamp(CurrentTimeTicks());
-  web_view->MainFrameWidget()->HandleInputEvent(
-      WebCoalescedInputEvent(pointer_cancel));
-
-  EXPECT_TRUE(interactive_detector->GetFirstInputDelay().is_zero());
-  EXPECT_TRUE(interactive_detector->GetFirstInputTimestamp().is_null());
-
-  // When we receive a pointer up, because we received a pointer caused UA
-  // action, no input delay should be recorded.
-  WebPointerEvent pointer_up(
-      WebInputEvent::kPointerUp,
-      WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5);
-  clock.Advance(TimeDelta::FromMilliseconds(60));
-  pointer_up.SetTimeStamp(CurrentTimeTicks());
-  web_view->MainFrameWidget()->HandleInputEvent(
-      WebCoalescedInputEvent(pointer_up));
-
-  EXPECT_TRUE(interactive_detector->GetFirstInputDelay().is_zero());
-  EXPECT_TRUE(interactive_detector->GetFirstInputTimestamp().is_null());
-  EXPECT_TRUE(interactive_detector->GetLongestInputDelay().is_zero());
-  EXPECT_TRUE(interactive_detector->GetLongestInputTimestamp().is_null());
-}
-
 // We need a way for JS to advance the mock clock. Hook into console.log, so
 // that logging advances the clock by |event_handling_delay| seconds.
 class MockClockAdvancingWebFrameClient
diff --git a/third_party/blink/renderer/core/loader/interactive_detector.cc b/third_party/blink/renderer/core/loader/interactive_detector.cc
index f55d34e..cdc30cf6 100644
--- a/third_party/blink/renderer/core/loader/interactive_detector.cc
+++ b/third_party/blink/renderer/core/loader/interactive_detector.cc
@@ -4,8 +4,8 @@
 
 #include "third_party/blink/renderer/core/loader/interactive_detector.h"
 
-#include "third_party/blink/public/platform/web_input_event.h"
 #include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
 #include "third_party/blink/renderer/platform/histogram.h"
@@ -22,9 +22,9 @@
 // requests for this duration of time.
 constexpr int kNetworkQuietMaximumConnections = 2;
 
-const char kHistogramInputDelay[] = "PageLoad.InteractiveTiming.InputDelay2";
+const char kHistogramInputDelay[] = "PageLoad.InteractiveTiming.InputDelay3";
 const char kHistogramInputTimestamp[] =
-    "PageLoad.InteractiveTiming.InputTimestamp2";
+    "PageLoad.InteractiveTiming.InputTimestamp3";
 
 // static
 const char InteractiveDetector::kSupplementName[] = "InteractiveDetector";
@@ -167,45 +167,39 @@
   return false;
 }  // namespace blink
 
-// This is called early enough in the pipeline that we don't need to worry about
-// javascript dispatching untrusted input events.
-void InteractiveDetector::HandleForInputDelay(const WebInputEvent& event) {
-  DCHECK(event.GetType() != WebInputEvent::kTouchStart);
+void InteractiveDetector::HandleForInputDelay(
+    const Event& event,
+    TimeTicks event_platform_timestamp,
+    TimeTicks processing_start) {
+  DCHECK(event.isTrusted());
 
   // This only happens sometimes on tests unrelated to InteractiveDetector. It
   // is safe to ignore events that are not properly initialized.
-  if (event.TimeStamp().is_null())
+  if (event_platform_timestamp.is_null())
     return;
 
   // We can't report a pointerDown until the pointerUp, in case it turns into a
   // scroll.
-  if (event.GetType() == WebInputEvent::kPointerDown) {
-    pending_pointerdown_delay_ = CurrentTimeTicks() - event.TimeStamp();
-    pending_pointerdown_timestamp_ = event.TimeStamp();
-    return;
-  }
-  if (event.GetType() == WebInputEvent::kPointerCancel ||
-      event.GetType() == WebInputEvent::kPointerCausedUaAction) {
-    pending_pointerdown_delay_ = base::TimeDelta();
-    pending_pointerdown_timestamp_ = base::TimeTicks();
+  if (event.type() == event_type_names::kPointerdown) {
+    pending_pointerdown_delay_ = processing_start - event_platform_timestamp;
+    pending_pointerdown_timestamp_ = event_platform_timestamp;
     return;
   }
 
-  bool event_is_meaningful =
-      event.GetType() == WebInputEvent::kMouseDown ||
-      event.GetType() == WebInputEvent::kKeyDown ||
-      event.GetType() == WebInputEvent::kRawKeyDown ||
-      // We need to explicitly include tap, as if there are no listeners, we
-      // won't receive the pointer events.
-      event.GetType() == WebInputEvent::kGestureTap ||
-      event.GetType() == WebInputEvent::kPointerUp;
+  // We receive any event relevant for EventTiming, but we only care about
+  // events relevant for FirstInputDelay.
+  bool event_is_meaningful = event.type() == event_type_names::kPointerup ||
+                             event.type() == event_type_names::kClick ||
+                             event.type() == event_type_names::kKeydown ||
+                             event.type() == event_type_names::kMousedown;
 
   if (!event_is_meaningful)
     return;
 
+  // These variables track the values which will be reported to histograms.
   TimeDelta delay;
   TimeTicks event_timestamp;
-  if (event.GetType() == WebInputEvent::kPointerUp) {
+  if (event.type() == event_type_names::kPointerup) {
     // PointerUp by itself is not considered a significant input.
     if (pending_pointerdown_timestamp_.is_null())
       return;
@@ -217,8 +211,8 @@
     delay = pending_pointerdown_delay_;
     event_timestamp = pending_pointerdown_timestamp_;
   } else {
-    delay = CurrentTimeTicks() - event.TimeStamp();
-    event_timestamp = event.TimeStamp();
+    delay = processing_start - event_platform_timestamp;
+    event_timestamp = event_platform_timestamp;
   }
 
   pending_pointerdown_delay_ = base::TimeDelta();
diff --git a/third_party/blink/renderer/core/loader/interactive_detector.h b/third_party/blink/renderer/core/loader/interactive_detector.h
index 48d94724..de38469 100644
--- a/third_party/blink/renderer/core/loader/interactive_detector.h
+++ b/third_party/blink/renderer/core/loader/interactive_detector.h
@@ -22,7 +22,7 @@
 namespace blink {
 
 class Document;
-class WebInputEvent;
+class Event;
 
 // Detects when a page reaches First Idle and Time to Interactive. See
 // https://goo.gl/SYt55W for detailed description and motivation of First Idle
@@ -107,7 +107,9 @@
 
   // Process an input event, updating first_input_delay and
   // first_input_timestamp if needed.
-  void HandleForInputDelay(const WebInputEvent&);
+  void HandleForInputDelay(const Event&,
+                           TimeTicks event_platform_timestamp,
+                           TimeTicks processing_start);
 
   // ContextLifecycleObserver
   void ContextDestroyed(ExecutionContext*) override;
diff --git a/third_party/blink/renderer/core/page/page_widget_delegate.cc b/third_party/blink/renderer/core/page/page_widget_delegate.cc
index 4d98a13c..76542b4 100644
--- a/third_party/blink/renderer/core/page/page_widget_delegate.cc
+++ b/third_party/blink/renderer/core/page/page_widget_delegate.cc
@@ -39,7 +39,6 @@
 #include "third_party/blink/renderer/core/input/event_handler.h"
 #include "third_party/blink/renderer/core/layout/jank_tracker.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/loader/interactive_detector.h"
 #include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
 #include "third_party/blink/renderer/core/page/autoscroll_controller.h"
 #include "third_party/blink/renderer/core/page/page.h"
@@ -121,14 +120,6 @@
     Document* document = root->GetDocument();
     DCHECK(document);
 
-    InteractiveDetector* interactive_detector(
-        InteractiveDetector::From(*document));
-
-    // interactive_detector is null in the OOPIF case.
-    // TODO(crbug.com/808089): report across OOPIFs.
-    if (interactive_detector)
-      interactive_detector->HandleForInputDelay(event);
-
     if (origin_trials::JankTrackingEnabled(document)) {
       if (LocalFrameView* view = document->View())
         view->GetJankTracker().NotifyInput(event);
diff --git a/third_party/blink/renderer/core/timing/event_timing.cc b/third_party/blink/renderer/core/timing/event_timing.cc
index cca33b2..3b30279a 100644
--- a/third_party/blink/renderer/core/timing/event_timing.cc
+++ b/third_party/blink/renderer/core/timing/event_timing.cc
@@ -7,17 +7,23 @@
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/events/pointer_event.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/loader/interactive_detector.h"
+#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
 #include "third_party/blink/renderer/core/timing/dom_window_performance.h"
 #include "third_party/blink/renderer/core/timing/performance_event_timing.h"
 #include "third_party/blink/renderer/platform/wtf/time.h"
 
 namespace blink {
 
-EventTiming::EventTiming(LocalDOMWindow* window) {
-  performance_ = DOMWindowPerformance::performance(*window);
+bool ShouldLogEvent(const Event& event) {
+  return event.type() == event_type_names::kPointerdown ||
+         event.type() == event_type_names::kPointerup ||
+         event.type() == event_type_names::kClick ||
+         event.type() == event_type_names::kKeydown ||
+         event.type() == event_type_names::kMousedown;
 }
 
-bool EventTiming::ShouldReportForEventTiming(const Event& event) const {
+bool IsEventTypeForEventTiming(const Event& event) {
   return (event.IsMouseEvent() || event.IsPointerEvent() ||
           event.IsTouchEvent() || event.IsKeyboardEvent() ||
           event.IsWheelEvent() || event.IsInputEvent() ||
@@ -25,37 +31,70 @@
          event.isTrusted();
 }
 
-void EventTiming::WillDispatchEvent(const Event& event) {
-  // Assume each event can be dispatched only once.
-  DCHECK(!finished_will_dispatch_event_);
-  if (!performance_ || !ShouldReportForEventTiming(event))
-    return;
+bool ShouldReportForEventTiming(WindowPerformance* performance) {
+  if (!origin_trials::EventTimingEnabled(performance->GetExecutionContext()))
+    return false;
 
-  // Although we screen the events for timing by setting these conditions here,
-  // we cannot assume that the conditions should still hold true in
-  // DidDispatchEvent. These conditions have to be re-tested before an entry is
-  // dispatched.
-  if ((performance_->ShouldBufferEntries() &&
-       !performance_->IsEventTimingBufferFull()) ||
-      performance_->HasObserverFor(PerformanceEntry::kEvent) ||
-      !performance_->FirstInputDetected()) {
-    processing_start_ = CurrentTimeTicks();
-    finished_will_dispatch_event_ = true;
+  if (performance->ShouldBufferEntries() &&
+      !performance->IsEventTimingBufferFull()) {
+    return true;
   }
+  if (performance->HasObserverFor(PerformanceEntry::kEvent) ||
+      !performance->FirstInputDetected()) {
+    return true;
+  }
+
+  return false;
+}
+
+EventTiming::EventTiming(TimeTicks processing_start,
+                         TimeTicks event_timestamp,
+                         WindowPerformance* performance)
+    : processing_start_(processing_start),
+      event_timestamp_(event_timestamp),
+      performance_(performance) {}
+
+// static
+std::unique_ptr<EventTiming> EventTiming::Create(LocalDOMWindow* window,
+                                                 const Event& event) {
+  auto* performance = DOMWindowPerformance::performance(*window);
+  if (!performance || !IsEventTypeForEventTiming(event))
+    return nullptr;
+
+  bool should_report_for_event_timing = ShouldReportForEventTiming(performance);
+  bool should_log_event = ShouldLogEvent(event);
+
+  if (!should_report_for_event_timing && !should_log_event)
+    return nullptr;
+
+  TimeTicks processing_start = CurrentTimeTicks();
+  TimeTicks event_timestamp =
+      event.IsPointerEvent() ? ToPointerEvent(&event)->OldestPlatformTimeStamp()
+                             : event.PlatformTimeStamp();
+
+  if (should_log_event) {
+    Document* document =
+        DynamicTo<Document>(performance->GetExecutionContext());
+    InteractiveDetector* interactive_detector =
+        InteractiveDetector::From(*document);
+    if (interactive_detector) {
+      interactive_detector->HandleForInputDelay(event, event_timestamp,
+                                                processing_start);
+    }
+  }
+
+  return should_report_for_event_timing
+             ? std::make_unique<EventTiming>(processing_start, event_timestamp,
+                                             performance)
+             : nullptr;
 }
 
 void EventTiming::DidDispatchEvent(const Event& event) {
-  if (!finished_will_dispatch_event_)
-    return;
-
-  TimeTicks start_time;
-  if (event.IsPointerEvent())
-    start_time = ToPointerEvent(&event)->OldestPlatformTimeStamp();
-  else
-    start_time = event.PlatformTimeStamp();
-
-  performance_->RegisterEventTiming(event.type(), start_time, processing_start_,
-                                    CurrentTimeTicks(), event.cancelable());
+  DCHECK(
+      origin_trials::EventTimingEnabled(performance_->GetExecutionContext()));
+  performance_->RegisterEventTiming(event.type(), event_timestamp_,
+                                    processing_start_, CurrentTimeTicks(),
+                                    event.cancelable());
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/timing/event_timing.h b/third_party/blink/renderer/core/timing/event_timing.h
index f18a3d57..bac8409 100644
--- a/third_party/blink/renderer/core/timing/event_timing.h
+++ b/third_party/blink/renderer/core/timing/event_timing.h
@@ -23,16 +23,23 @@
   USING_FAST_MALLOC(EventTiming);
 
  public:
-  explicit EventTiming(LocalDOMWindow*);
+  // Processes an event that will be dispatched. Notifies the
+  // InteractiveDetector if it needs to be logged into input delay histograms.
+  // Returns an object only if the event is relevant for the EventTiming API.
+  static std::unique_ptr<EventTiming> Create(LocalDOMWindow*, const Event&);
 
-  void WillDispatchEvent(const Event&);
+  explicit EventTiming(TimeTicks processing_start,
+                       TimeTicks event_timestamp,
+                       WindowPerformance* performance);
+
+  // Notifies the Performance object that the event has been dispatched.
   void DidDispatchEvent(const Event&);
 
  private:
-  bool ShouldReportForEventTiming(const Event& event) const;
   // The time the first event handler or default action started to execute.
   TimeTicks processing_start_;
-  bool finished_will_dispatch_event_ = false;
+  // The event timestamp to be used in EventTiming and in histograms.
+  TimeTicks event_timestamp_;
 
   Persistent<WindowPerformance> performance_;
   DISALLOW_COPY_AND_ASSIGN(EventTiming);
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 63dd60e..a48d9da 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -79350,6 +79350,26 @@
 
 <histogram name="PageLoad.InteractiveTiming.FirstInputDelay2" units="ms"
     expires_after="2020-01-23">
+  <obsolete>
+    Removed on February 2019 in favor of
+    PageLoad.InteractiveTiming.FirstInputDelay3 which brings the metric more in
+    line with the EventTiming API.
+  </obsolete>
+  <owner>tdresser@chromium.org</owner>
+  <owner>speed-metrics-dev@chromium.org</owner>
+  <summary>
+    Measures First Input Delay, the duration between the hardware timestamp and
+    the start of event processing on the main thread for the first meaningful
+    input per navigation. Recorded on first page interaction. See
+    https://goo.gl/tr1oTZ for a detailed explanation. Excludes scrolls.
+
+    Do not modify this metric in any way without contacting
+    speed-metrics-dev@chromium.org.
+  </summary>
+</histogram>
+
+<histogram name="PageLoad.InteractiveTiming.FirstInputDelay3" units="ms"
+    expires_after="2020-02-23">
   <owner>tdresser@chromium.org</owner>
   <owner>speed-metrics-dev@chromium.org</owner>
   <summary>
@@ -79379,6 +79399,22 @@
 
 <histogram name="PageLoad.InteractiveTiming.FirstInputTimestamp2" units="ms"
     expires_after="2020-01-23">
+  <obsolete>
+    Removed on February 2019 in favor of
+    PageLoad.InteractiveTiming.FirstInputTimestamp3 which brings the metric more
+    in line with the EventTiming API.
+  </obsolete>
+  <owner>tdresser@chromium.org</owner>
+  <owner>speed-metrics-dev@chromium.org</owner>
+  <summary>
+    The duration between navigation start and the hardware timestamp of the
+    first meaningful input per navigation. Recorded on first page interaction.
+    See https://goo.gl/tr1oTZ for a detailed explanation. Excludes scrolls.
+  </summary>
+</histogram>
+
+<histogram name="PageLoad.InteractiveTiming.FirstInputTimestamp3" units="ms"
+    expires_after="2020-02-23">
   <owner>tdresser@chromium.org</owner>
   <owner>speed-metrics-dev@chromium.org</owner>
   <summary>
@@ -79407,6 +79443,23 @@
 
 <histogram name="PageLoad.InteractiveTiming.InputDelay2" units="ms"
     expires_after="2020-01-23">
+  <obsolete>
+    Removed on February 2019 in favor of PageLoad.InteractiveTiming.InputDelay3
+    which brings the metric more in line with the EventTiming API.
+  </obsolete>
+  <owner>tdresser@chromium.org</owner>
+  <owner>speed-metrics-dev@chromium.org</owner>
+  <summary>
+    The duration between the hardware timestamp and the start of event
+    processing on the main thread for a meaningful input. Excludes scrolls.
+
+    Do not modify this metric in any way without contacting
+    speed-metrics-dev@chromium.org.
+  </summary>
+</histogram>
+
+<histogram name="PageLoad.InteractiveTiming.InputDelay3" units="ms"
+    expires_after="2020-02-23">
   <owner>tdresser@chromium.org</owner>
   <owner>speed-metrics-dev@chromium.org</owner>
   <summary>
@@ -79433,6 +79486,21 @@
 
 <histogram name="PageLoad.InteractiveTiming.InputTimestamp2" units="ms"
     expires_after="2020-01-23">
+  <obsolete>
+    Removed on February 2019 in favor of
+    PageLoad.InteractiveTiming.InputTimestamp3 which brings the metric more in
+    line with the EventTiming API.
+  </obsolete>
+  <owner>tdresser@chromium.org</owner>
+  <owner>speed-metrics-dev@chromium.org</owner>
+  <summary>
+    The duration between navigation start and the hardware timestamp of a
+    meaningful input. Excludes scrolls.
+  </summary>
+</histogram>
+
+<histogram name="PageLoad.InteractiveTiming.InputTimestamp3" units="ms"
+    expires_after="2020-02-23">
   <owner>tdresser@chromium.org</owner>
   <owner>speed-metrics-dev@chromium.org</owner>
   <summary>
@@ -79457,6 +79525,22 @@
 
 <histogram name="PageLoad.InteractiveTiming.LongestInputDelay2" units="ms"
     expires_after="2020-01-23">
+  <obsolete>
+    Removed on February 2019 in favor of
+    PageLoad.InteractiveTiming.LongestInputDelay3 which brings the metric more
+    in line with the EventTiming API.
+  </obsolete>
+  <owner>tdresser@chromium.org</owner>
+  <owner>speed-metrics-dev@chromium.org</owner>
+  <summary>
+    Measures longest Input Delay, the longest duration between the hardware
+    timestamp and the start of event processing on the main thread for the
+    meaningful input per navigation. Excludes scrolls.
+  </summary>
+</histogram>
+
+<histogram name="PageLoad.InteractiveTiming.LongestInputDelay3" units="ms"
+    expires_after="2020-01-23">
   <owner>tdresser@chromium.org</owner>
   <owner>speed-metrics-dev@chromium.org</owner>
   <summary>
@@ -79481,6 +79565,22 @@
 
 <histogram name="PageLoad.InteractiveTiming.LongestInputTimestamp2" units="ms"
     expires_after="2020-01-23">
+  <obsolete>
+    Removed on February 2019 in favor of
+    PageLoad.InteractiveTiming.LongestInputTimestamp3 which brings the metric
+    more in line with the EventTiming API.
+  </obsolete>
+  <owner>tdresser@chromium.org</owner>
+  <owner>speed-metrics-dev@chromium.org</owner>
+  <summary>
+    The duration between navigation start and the hardware timestamp of the
+    meaningful input with longest queuing delay per navigation. Excludes
+    scrolls.
+  </summary>
+</histogram>
+
+<histogram name="PageLoad.InteractiveTiming.LongestInputTimestamp3" units="ms"
+    expires_after="2020-02-23">
   <owner>tdresser@chromium.org</owner>
   <owner>speed-metrics-dev@chromium.org</owner>
   <summary>
@@ -138095,6 +138195,7 @@
       name="PageLoad.Experimental.PaintTiming.NavigationToFirstMeaningfulPaint"/>
   <affected-histogram name="PageLoad.InteractiveTiming.FirstInputDelay"/>
   <affected-histogram name="PageLoad.InteractiveTiming.FirstInputDelay2"/>
+  <affected-histogram name="PageLoad.InteractiveTiming.FirstInputDelay3"/>
   <affected-histogram
       name="PageLoad.PaintTiming.NavigationToFirstContentfulPaint"/>
 </histogram_suffixes>
@@ -141590,6 +141691,7 @@
   <affected-histogram
       name="PageLoad.Experimental.AbortTiming.Stop.BeforeCommit"/>
   <affected-histogram name="PageLoad.InteractiveTiming.FirstInputDelay2"/>
+  <affected-histogram name="PageLoad.InteractiveTiming.FirstInputDelay3"/>
   <affected-histogram name="PageLoad.PageTiming.ForegroundDuration"/>
   <affected-histogram
       name="PageLoad.PaintTiming.NavigationToFirstContentfulPaint"/>
@@ -141884,6 +141986,7 @@
       name="PageLoad.Experimental.PaintTiming.ParseStartToFirstMeaningfulPaint"/>
   <affected-histogram name="PageLoad.InteractiveTiming.FirstInputDelay"/>
   <affected-histogram name="PageLoad.InteractiveTiming.FirstInputDelay2"/>
+  <affected-histogram name="PageLoad.InteractiveTiming.FirstInputDelay3"/>
   <affected-histogram
       name="PageLoad.PaintTiming.NavigationToFirstContentfulPaint"/>
   <affected-histogram name="PageLoad.PaintTiming.NavigationToFirstPaint"/>
@@ -142085,6 +142188,7 @@
       name="PageLoad.Experimental.PaintTiming.ParseStartToFirstMeaningfulPaint"/>
   <affected-histogram name="PageLoad.InteractiveTiming.FirstInputDelay"/>
   <affected-histogram name="PageLoad.InteractiveTiming.FirstInputDelay2"/>
+  <affected-histogram name="PageLoad.InteractiveTiming.FirstInputDelay3"/>
   <affected-histogram
       name="PageLoad.PaintTiming.NavigationToFirstContentfulPaint"/>
   <affected-histogram name="PageLoad.PaintTiming.NavigationToFirstPaint"/>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 2ff4b58..9355ffa 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -3585,6 +3585,26 @@
     </aggregation>
   </metric>
   <metric name="InteractiveTiming.FirstInputDelay2">
+    <obsolete>
+      Removed on February 2019 in favor of InteractiveTiming.FirstInputDelay3
+      which brings the metric more in line with the EventTiming API.
+    </obsolete>
+    <summary>
+      Measures First Input Delay, the duration between the hardware timestamp
+      and the start of event processing on the main thread for the first
+      meaningful input per navigation. See https://goo.gl/tr1oTZ for a detailed
+      explanation. In ms.
+    </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
+  <metric name="InteractiveTiming.FirstInputDelay3">
     <summary>
       Measures First Input Delay, the duration between the hardware timestamp
       and the start of event processing on the main thread for the first
@@ -3613,6 +3633,23 @@
     </summary>
   </metric>
   <metric name="InteractiveTiming.FirstInputTimestamp2">
+    <obsolete>
+      Removed on February 2019 in favor of
+      InteractiveTiming.FirstInputTimestamp3 which brings the metric more in
+      line with the EventTiming API.
+    </obsolete>
+    <summary>
+      The duration between navigation start and the hardware timestamp of the
+      first meaningful input per navigation. See https://goo.gl/tr1oTZ for a
+      detailed explanation. In ms.
+    </summary>
+  </metric>
+  <metric name="InteractiveTiming.FirstInputTimestamp3">
+    <obsolete>
+      Removed on February 2019 in favor of
+      InteractiveTiming.FirstInputTimestamp3 which brings the metric more in
+      line with the EventTiming API.
+    </obsolete>
     <summary>
       The duration between navigation start and the hardware timestamp of the
       first meaningful input per navigation. See https://goo.gl/tr1oTZ for a
@@ -3632,6 +3669,25 @@
     </summary>
   </metric>
   <metric name="InteractiveTiming.LongestInputDelay2">
+    <obsolete>
+      Removed on February 2019 in favor of InteractiveTiming.LongestInputDelay3
+      which brings the metric more in line with the EventTiming API.
+    </obsolete>
+    <summary>
+      Measures longest Input Delay, the longest duration between the hardware
+      timestamp and the start of event processing on the main thread for the
+      meaningful input per navigation. In ms.
+    </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
+  <metric name="InteractiveTiming.LongestInputDelay3">
     <summary>
       Measures longest Input Delay, the longest duration between the hardware
       timestamp and the start of event processing on the main thread for the
@@ -3658,6 +3714,17 @@
     </summary>
   </metric>
   <metric name="InteractiveTiming.LongestInputTimestamp2">
+    <obsolete>
+      Removed on February 2019 in favor of
+      InteractiveTiming.LongestInputTimestamp3 which brings the metric more in
+      line with the EventTiming API.
+    </obsolete>
+    <summary>
+      The duration between navigation start and the hardware timestamp of the
+      meaningful input with longest queuing delay per navigation. In ms.
+    </summary>
+  </metric>
+  <metric name="InteractiveTiming.LongestInputTimestamp3">
     <summary>
       The duration between navigation start and the hardware timestamp of the
       meaningful input with longest queuing delay per navigation. In ms.