scheduler: Detect single event gestures correctly

When a single event gesture such as a press (i.e., a single touchstart
event) is observed, the scheduler would previously wait for two
subsequent touchmove events before deciding the gesture was established
and stop blocking tasks unrelated to input handling. The problem was
that with single event gestures, these additional events are never sent,
so the scheduler would remain in 'touchstart' mode for 100ms, possibly
causing important tasks to get delayed.

This patch fixes the issue by telling the scheduler how the touchstart
event was handled. If the event handler calls preventDefault() on the
event, the scheduler can immediately conclude that the gesture is
handled by the main thread without waiting for any further events. If
preventDefault() is not called, we maintain the previous behavior.

BUG=639300

Review-Url: https://codereview.chromium.org/2661443003
Cr-Commit-Position: refs/heads/master@{#446921}
diff --git a/content/renderer/input/input_event_filter.cc b/content/renderer/input/input_event_filter.cc
index af4cb4b..f3da1c9 100644
--- a/content/renderer/input/input_event_filter.cc
+++ b/content/renderer/input/input_event_filter.cc
@@ -108,9 +108,11 @@
   }
 }
 
-void InputEventFilter::NotifyInputEventHandled(int routing_id,
-                                               blink::WebInputEvent::Type type,
-                                               InputEventAckState ack_result) {
+void InputEventFilter::NotifyInputEventHandled(
+    int routing_id,
+    blink::WebInputEvent::Type type,
+    blink::WebInputEventResult result,
+    InputEventAckState ack_result) {
   DCHECK(main_task_runner_->BelongsToCurrentThread());
   scoped_refptr<MainThreadEventQueue> queue;
   {
@@ -121,7 +123,7 @@
     queue = iter->second;
   }
 
-  queue->EventHandled(type, ack_result);
+  queue->EventHandled(type, result, ack_result);
 }
 
 void InputEventFilter::ProcessRafAlignedInput(int routing_id) {
diff --git a/content/renderer/input/input_event_filter.h b/content/renderer/input/input_event_filter.h
index 3fd3442..cdec887 100644
--- a/content/renderer/input/input_event_filter.h
+++ b/content/renderer/input/input_event_filter.h
@@ -73,6 +73,7 @@
 
   void NotifyInputEventHandled(int routing_id,
                                blink::WebInputEvent::Type type,
+                               blink::WebInputEventResult result,
                                InputEventAckState ack_result) override;
   void ProcessRafAlignedInput(int routing_id) override;
 
diff --git a/content/renderer/input/input_handler_manager.cc b/content/renderer/input/input_handler_manager.cc
index 825cc7d2..73fb3bba 100644
--- a/content/renderer/input/input_handler_manager.cc
+++ b/content/renderer/input/input_handler_manager.cc
@@ -191,8 +191,9 @@
 void InputHandlerManager::NotifyInputEventHandledOnMainThread(
     int routing_id,
     blink::WebInputEvent::Type type,
+    blink::WebInputEventResult result,
     InputEventAckState ack_result) {
-  client_->NotifyInputEventHandled(routing_id, type, ack_result);
+  client_->NotifyInputEventHandled(routing_id, type, result, ack_result);
 }
 
 void InputHandlerManager::ProcessRafAlignedInputOnMainThread(int routing_id) {
diff --git a/content/renderer/input/input_handler_manager.h b/content/renderer/input/input_handler_manager.h
index 2fc8dad..4aba6ca 100644
--- a/content/renderer/input/input_handler_manager.h
+++ b/content/renderer/input/input_handler_manager.h
@@ -75,6 +75,7 @@
 
   void NotifyInputEventHandledOnMainThread(int routing_id,
                                            blink::WebInputEvent::Type,
+                                           blink::WebInputEventResult,
                                            InputEventAckState);
   void ProcessRafAlignedInputOnMainThread(int routing_id);
 
diff --git a/content/renderer/input/input_handler_manager_client.h b/content/renderer/input/input_handler_manager_client.h
index bbad896c3..eb1fbefd 100644
--- a/content/renderer/input/input_handler_manager_client.h
+++ b/content/renderer/input/input_handler_manager_client.h
@@ -11,6 +11,7 @@
 #include "content/common/content_export.h"
 #include "content/common/input/input_event_ack_state.h"
 #include "third_party/WebKit/public/platform/WebCoalescedInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEventResult.h"
 #include "ui/gfx/geometry/vector2d_f.h"
 
 namespace ui {
@@ -30,6 +31,7 @@
   virtual void SetInputHandlerManager(InputHandlerManager*) = 0;
   virtual void NotifyInputEventHandled(int routing_id,
                                        blink::WebInputEvent::Type type,
+                                       blink::WebInputEventResult result,
                                        InputEventAckState ack_result) = 0;
   virtual void ProcessRafAlignedInput(int routing_id) = 0;
 
diff --git a/content/renderer/input/main_thread_event_queue.cc b/content/renderer/input/main_thread_event_queue.cc
index aad6fb5..fdee19f 100644
--- a/content/renderer/input/main_thread_event_queue.cc
+++ b/content/renderer/input/main_thread_event_queue.cc
@@ -231,13 +231,14 @@
 }
 
 void MainThreadEventQueue::EventHandled(blink::WebInputEvent::Type type,
+                                        blink::WebInputEventResult result,
                                         InputEventAckState ack_result) {
   if (in_flight_event_) {
     for (const auto id : in_flight_event_->blockingCoalescedEventIds()) {
       client_->SendInputEventAck(routing_id_, type, ack_result, id);
       if (renderer_scheduler_) {
         renderer_scheduler_->DidHandleInputEventOnMainThread(
-            in_flight_event_->event());
+            in_flight_event_->event(), result);
       }
     }
   }
diff --git a/content/renderer/input/main_thread_event_queue.h b/content/renderer/input/main_thread_event_queue.h
index 96d0760..09c16117 100644
--- a/content/renderer/input/main_thread_event_queue.h
+++ b/content/renderer/input/main_thread_event_queue.h
@@ -129,6 +129,7 @@
   // Call once the main thread has handled an outstanding |type| event
   // in flight.
   void EventHandled(blink::WebInputEvent::Type type,
+                    blink::WebInputEventResult result,
                     InputEventAckState ack_result);
 
  private:
diff --git a/content/renderer/input/main_thread_event_queue_unittest.cc b/content/renderer/input/main_thread_event_queue_unittest.cc
index dda0969..f7ccb8c 100644
--- a/content/renderer/input/main_thread_event_queue_unittest.cc
+++ b/content/renderer/input/main_thread_event_queue_unittest.cc
@@ -78,6 +78,7 @@
         event->event(), event->getCoalescedEventsPointers()));
 
     queue_->EventHandled(event->event().type(),
+                         blink::WebInputEventResult::HandledApplication,
                          INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
   }
 
@@ -326,7 +327,8 @@
   kEvents[3].PressPoint(10, 10);
   kEvents[3].MovePoint(0, 35, 35);
 
-  EXPECT_CALL(renderer_scheduler_, DidHandleInputEventOnMainThread(testing::_))
+  EXPECT_CALL(renderer_scheduler_,
+              DidHandleInputEventOnMainThread(testing::_, testing::_))
       .Times(2);
   // Ensure that coalescing takes place.
   HandleEvent(kEvents[0], INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
diff --git a/content/renderer/input/render_widget_input_handler.cc b/content/renderer/input/render_widget_input_handler.cc
index b0db53de..40bef46 100644
--- a/content/renderer/input/render_widget_input_handler.cc
+++ b/content/renderer/input/render_widget_input_handler.cc
@@ -394,7 +394,8 @@
       dispatch_type == DISPATCH_TYPE_NON_BLOCKING_NOTIFY_MAIN) {
     // |non_blocking| means it was ack'd already by the InputHandlerProxy
     // so let the delegate know the event has been handled.
-    delegate_->NotifyInputEventHandled(input_event.type(), ack_result);
+    delegate_->NotifyInputEventHandled(input_event.type(), processed,
+                                       ack_result);
   }
 
   if ((dispatch_type == DISPATCH_TYPE_BLOCKING ||
@@ -410,7 +411,7 @@
   if (RenderThreadImpl::current()) {
     RenderThreadImpl::current()
         ->GetRendererScheduler()
-        ->DidHandleInputEventOnMainThread(input_event);
+        ->DidHandleInputEventOnMainThread(input_event, processed);
   }
 
 #if defined(OS_ANDROID)
diff --git a/content/renderer/input/render_widget_input_handler_delegate.h b/content/renderer/input/render_widget_input_handler_delegate.h
index d1fd030..ad351887 100644
--- a/content/renderer/input/render_widget_input_handler_delegate.h
+++ b/content/renderer/input/render_widget_input_handler_delegate.h
@@ -9,6 +9,7 @@
 
 #include "content/common/content_export.h"
 #include "content/common/input/input_event_ack.h"
+#include "third_party/WebKit/public/platform/WebInputEventResult.h"
 
 namespace blink {
 class WebGestureEvent;
@@ -56,6 +57,7 @@
   // (DISPATCH_TYPE_*_NOTIFY_MAIN) of |handled_type| has been processed
   // by the main thread.
   virtual void NotifyInputEventHandled(blink::WebInputEvent::Type handled_type,
+                                       blink::WebInputEventResult result,
                                        InputEventAckState ack_result) = 0;
 
   // Notifies the delegate of the |input_handler| managing it.
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index a797669..c3f96d8 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -113,6 +113,7 @@
 #include "third_party/WebKit/public/platform/WebHTTPBody.h"
 #include "third_party/WebKit/public/platform/WebImage.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebInputEventResult.h"
 #include "third_party/WebKit/public/platform/WebMessagePortChannel.h"
 #include "third_party/WebKit/public/platform/WebPoint.h"
 #include "third_party/WebKit/public/platform/WebRect.h"
@@ -2710,6 +2711,7 @@
 
   if (dispatch_type == DISPATCH_TYPE_BLOCKING_NOTIFY_MAIN) {
     NotifyInputEventHandled(input_event->type(),
+                            blink::WebInputEventResult::NotHandled,
                             INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
   }
 
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 2ef8c177..d9edfea 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -1003,13 +1003,14 @@
 
 void RenderWidget::NotifyInputEventHandled(
     blink::WebInputEvent::Type handled_type,
+    blink::WebInputEventResult result,
     InputEventAckState ack_result) {
   RenderThreadImpl* render_thread = RenderThreadImpl::current();
   InputHandlerManager* input_handler_manager =
       render_thread ? render_thread->input_handler_manager() : NULL;
   if (input_handler_manager) {
     input_handler_manager->NotifyInputEventHandledOnMainThread(
-        routing_id_, handled_type, ack_result);
+        routing_id_, handled_type, result, ack_result);
   }
 }
 
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index f1b6289..fde0e32 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -263,6 +263,7 @@
   void OnDidOverscroll(const ui::DidOverscrollParams& params) override;
   void OnInputEventAck(std::unique_ptr<InputEventAck> input_event_ack) override;
   void NotifyInputEventHandled(blink::WebInputEvent::Type handled_type,
+                               blink::WebInputEventResult result,
                                InputEventAckState ack_result) override;
   void SetInputHandler(RenderWidgetInputHandler* input_handler) override;
   void ShowVirtualKeyboard() override;
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
index 130d539..cb4938d 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
@@ -757,7 +757,8 @@
 }
 
 void RendererSchedulerImpl::DidHandleInputEventOnMainThread(
-    const blink::WebInputEvent& web_input_event) {
+    const WebInputEvent& web_input_event,
+    WebInputEventResult result) {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
                "RendererSchedulerImpl::DidHandleInputEventOnMainThread");
   helper_.CheckOnValidThread();
@@ -765,6 +766,17 @@
     base::AutoLock lock(any_thread_lock_);
     AnyThread().user_model.DidFinishProcessingInputEvent(
         helper_.scheduler_tqm_delegate()->NowTicks());
+
+    // If we were waiting for a touchstart response and the main thread has
+    // prevented the default gesture, consider the gesture established. This
+    // ensures single-event gestures such as button presses are promptly
+    // detected.
+    if (AnyThread().awaiting_touch_start_response &&
+        result == WebInputEventResult::HandledApplication) {
+      AnyThread().awaiting_touch_start_response = false;
+      AnyThread().default_gesture_prevented = true;
+      UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED);
+    }
   }
 }
 
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
index a401289..26162de4 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
@@ -104,8 +104,8 @@
   void DidHandleInputEventOnCompositorThread(
       const WebInputEvent& web_input_event,
       InputEventState event_state) override;
-  void DidHandleInputEventOnMainThread(
-      const WebInputEvent& web_input_event) override;
+  void DidHandleInputEventOnMainThread(const WebInputEvent& web_input_event,
+                                       WebInputEventResult result) override;
   void DidAnimateForInputOnCompositorThread() override;
   void OnRendererBackgrounded() override;
   void OnRendererForegrounded() override;
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
index ad4910c..48cc8add 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
@@ -455,25 +455,29 @@
           FakeInputEvent(blink::WebInputEvent::TouchStart),
           RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
       scheduler_->DidHandleInputEventOnMainThread(
-          FakeInputEvent(blink::WebInputEvent::TouchStart));
+          FakeInputEvent(blink::WebInputEvent::TouchStart),
+          WebInputEventResult::HandledSystem);
 
       scheduler_->DidHandleInputEventOnCompositorThread(
           FakeInputEvent(blink::WebInputEvent::TouchMove),
           RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
       scheduler_->DidHandleInputEventOnMainThread(
-          FakeInputEvent(blink::WebInputEvent::TouchMove));
+          FakeInputEvent(blink::WebInputEvent::TouchMove),
+          WebInputEventResult::HandledSystem);
 
       scheduler_->DidHandleInputEventOnCompositorThread(
           FakeInputEvent(blink::WebInputEvent::TouchMove),
           RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
       scheduler_->DidHandleInputEventOnMainThread(
-          FakeInputEvent(blink::WebInputEvent::TouchMove));
+          FakeInputEvent(blink::WebInputEvent::TouchMove),
+          WebInputEventResult::HandledSystem);
     }
     if (gesture_type != blink::WebInputEvent::Undefined) {
       scheduler_->DidHandleInputEventOnCompositorThread(
           FakeInputEvent(gesture_type),
           RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
-      scheduler_->DidHandleInputEventOnMainThread(FakeInputEvent(gesture_type));
+      scheduler_->DidHandleInputEventOnMainThread(
+          FakeInputEvent(gesture_type), WebInputEventResult::HandledSystem);
     }
   }
 
@@ -484,7 +488,8 @@
         RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
     clock_->Advance(begin_main_frame_duration);
     scheduler_->DidHandleInputEventOnMainThread(
-        FakeInputEvent(blink::WebInputEvent::TouchMove));
+        FakeInputEvent(blink::WebInputEvent::TouchMove),
+        WebInputEventResult::HandledApplication);
     scheduler_->DidCommitFrameToCompositor();
   }
 
@@ -950,7 +955,8 @@
   EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING,
             CurrentUseCase());
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::GestureFlingStart));
+      FakeInputEvent(blink::WebInputEvent::GestureFlingStart),
+      WebInputEventResult::HandledSystem);
 }
 
 TEST_F(RendererSchedulerImplTest,
@@ -969,7 +975,56 @@
   EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING,
             CurrentUseCase());
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::GestureFlingStart));
+      FakeInputEvent(blink::WebInputEvent::GestureFlingStart),
+      WebInputEventResult::HandledSystem);
+}
+
+TEST_F(RendererSchedulerImplTest,
+       TestCompositorPolicy_MainThreadHandlesInput_SingleEvent_PreventDefault) {
+  std::vector<std::string> run_order;
+  PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
+
+  scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
+  EnableIdleTasks();
+  scheduler_->DidHandleInputEventOnCompositorThread(
+      FakeInputEvent(blink::WebInputEvent::TouchStart),
+      RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
+  scheduler_->DidHandleInputEventOnMainThread(
+      FakeInputEvent(blink::WebInputEvent::TouchStart),
+      WebInputEventResult::HandledApplication);
+  RunUntilIdle();
+  // Because the main thread is performing custom input handling, we let all
+  // tasks run. However compositing tasks are still given priority.
+  EXPECT_THAT(run_order,
+              testing::ElementsAre(std::string("C1"), std::string("C2"),
+                                   std::string("L1"), std::string("D1"),
+                                   std::string("D2"), std::string("I1")));
+  EXPECT_EQ(RendererSchedulerImpl::UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING,
+            CurrentUseCase());
+}
+
+TEST_F(
+    RendererSchedulerImplTest,
+    TestCompositorPolicy_MainThreadHandlesInput_SingleEvent_NoPreventDefault) {
+  std::vector<std::string> run_order;
+  PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
+
+  scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
+  EnableIdleTasks();
+  scheduler_->DidHandleInputEventOnCompositorThread(
+      FakeInputEvent(blink::WebInputEvent::TouchStart),
+      RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
+  scheduler_->DidHandleInputEventOnMainThread(
+      FakeInputEvent(blink::WebInputEvent::TouchStart),
+      WebInputEventResult::HandledSystem);
+  RunUntilIdle();
+  // Because we are still waiting for the touchstart to be processed,
+  // non-essential tasks like loading tasks are blocked.
+  EXPECT_THAT(run_order,
+              testing::ElementsAre(std::string("C1"), std::string("C2"),
+                                   std::string("D1"), std::string("D2"),
+                                   std::string("I1")));
+  EXPECT_EQ(RendererSchedulerImpl::UseCase::TOUCHSTART, CurrentUseCase());
 }
 
 TEST_F(RendererSchedulerImplTest, TestCompositorPolicy_DidAnimateForInput) {
@@ -1121,7 +1176,8 @@
       FakeInputEvent(blink::WebInputEvent::TouchStart),
       RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::TouchStart));
+      FakeInputEvent(blink::WebInputEvent::TouchStart),
+      WebInputEventResult::HandledSystem);
   EnableIdleTasks();
   RunUntilIdle();
   EXPECT_THAT(run_order,
@@ -1134,12 +1190,14 @@
       FakeInputEvent(blink::WebInputEvent::GestureFlingCancel),
       RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::GestureFlingCancel));
+      FakeInputEvent(blink::WebInputEvent::GestureFlingCancel),
+      WebInputEventResult::HandledSystem);
   scheduler_->DidHandleInputEventOnCompositorThread(
       FakeInputEvent(blink::WebInputEvent::GestureTapDown),
       RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::GestureTapDown));
+      FakeInputEvent(blink::WebInputEvent::GestureTapDown),
+      WebInputEventResult::HandledSystem);
   RunUntilIdle();
   EXPECT_TRUE(run_order.empty());
 
@@ -1150,7 +1208,8 @@
       FakeInputEvent(blink::WebInputEvent::GestureScrollBegin),
       RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::GestureScrollBegin));
+      FakeInputEvent(blink::WebInputEvent::GestureScrollBegin),
+      WebInputEventResult::HandledSystem);
   RunUntilIdle();
 
   EXPECT_THAT(run_order,
@@ -1266,8 +1325,10 @@
               testing::ElementsAre(std::string("C1"), std::string("C2"),
                                    std::string("D1"), std::string("D2"),
                                    std::string("I1")));
-  scheduler_->DidHandleInputEventOnMainThread(FakeInputEvent(
-      blink::WebInputEvent::MouseMove, blink::WebInputEvent::LeftButtonDown));
+  scheduler_->DidHandleInputEventOnMainThread(
+      FakeInputEvent(blink::WebInputEvent::MouseMove,
+                     blink::WebInputEvent::LeftButtonDown),
+      WebInputEventResult::HandledSystem);
 }
 
 TEST_F(RendererSchedulerImplTest,
@@ -1464,7 +1525,8 @@
   EXPECT_EQ(RendererSchedulerImpl::UseCase::NONE, CurrentUseCase());
   // Note compositor tasks are not prioritized.
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::KeyDown));
+      FakeInputEvent(blink::WebInputEvent::KeyDown),
+      WebInputEventResult::HandledSystem);
 }
 
 TEST_F(RendererSchedulerImplTest,
@@ -1693,7 +1755,8 @@
   // task we post here represents the enqueued input task.
   clock_->Advance(priority_escalation_after_input_duration() * 2);
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::GestureFlingStart));
+      FakeInputEvent(blink::WebInputEvent::GestureFlingStart),
+      WebInputEventResult::HandledSystem);
   RunUntilIdle();
 
   // Even though we exceeded the input priority escalation period, we should
@@ -1774,7 +1837,8 @@
   EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
 
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::TouchStart));
+      FakeInputEvent(blink::WebInputEvent::TouchStart),
+      WebInputEventResult::HandledSystem);
   EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
 
   clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
@@ -1796,7 +1860,8 @@
   EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
 
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::TouchStart));
+      FakeInputEvent(blink::WebInputEvent::TouchStart),
+      WebInputEventResult::HandledSystem);
   EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
 
   // The second call to DidHandleInputEventOnCompositorThread should not post a
@@ -1809,7 +1874,8 @@
 
   // We expect DidHandleInputEvent to trigger a policy update.
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::TouchMove));
+      FakeInputEvent(blink::WebInputEvent::TouchMove),
+      WebInputEventResult::HandledSystem);
   EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
 
   // The third call to DidHandleInputEventOnCompositorThread should post a
@@ -1823,7 +1889,8 @@
 
   // We expect DidHandleInputEvent to trigger a policy update.
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::TouchMove));
+      FakeInputEvent(blink::WebInputEvent::TouchMove),
+      WebInputEventResult::HandledSystem);
   EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
 
   clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
@@ -1845,7 +1912,8 @@
   EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
 
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::TouchStart));
+      FakeInputEvent(blink::WebInputEvent::TouchStart),
+      WebInputEventResult::HandledSystem);
   EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
 
   clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
@@ -1863,7 +1931,8 @@
   EXPECT_EQ(3, mock_scheduler_->update_policy_count_);
 
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::TouchMove));
+      FakeInputEvent(blink::WebInputEvent::TouchMove),
+      WebInputEventResult::HandledSystem);
   EXPECT_EQ(3, mock_scheduler_->update_policy_count_);
 
   clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
@@ -1906,13 +1975,17 @@
       RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
 
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::TouchStart));
+      FakeInputEvent(blink::WebInputEvent::TouchStart),
+      WebInputEventResult::HandledSystem);
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::TouchMove));
+      FakeInputEvent(blink::WebInputEvent::TouchMove),
+      WebInputEventResult::HandledSystem);
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::TouchMove));
+      FakeInputEvent(blink::WebInputEvent::TouchMove),
+      WebInputEventResult::HandledSystem);
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::TouchEnd));
+      FakeInputEvent(blink::WebInputEvent::TouchEnd),
+      WebInputEventResult::HandledSystem);
 
   EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
 
@@ -2371,7 +2444,8 @@
   // INPUT_EVENT_ACK_STATE_NOT_CONSUMED. There are legitimate reasons for the
   // compositor to not be there and we don't want to make debugging impossible.
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::GestureFlingStart));
+      FakeInputEvent(blink::WebInputEvent::GestureFlingStart),
+      WebInputEventResult::HandledSystem);
 }
 
 TEST_F(RendererSchedulerImplTest, BeginMainFrameOnCriticalPath) {
@@ -2540,7 +2614,8 @@
       FakeInputEvent(blink::WebInputEvent::TouchEnd),
       RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
   scheduler_->DidHandleInputEventOnMainThread(
-      FakeInputEvent(blink::WebInputEvent::TouchEnd));
+      FakeInputEvent(blink::WebInputEvent::TouchEnd),
+      WebInputEventResult::HandledSystem);
 
   clock_->Advance(priority_escalation_after_input_duration() * 2);
   EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase());
diff --git a/third_party/WebKit/Source/platform/scheduler/test/fake_renderer_scheduler.cc b/third_party/WebKit/Source/platform/scheduler/test/fake_renderer_scheduler.cc
index df3a4b7..93bae1e3 100644
--- a/third_party/WebKit/Source/platform/scheduler/test/fake_renderer_scheduler.cc
+++ b/third_party/WebKit/Source/platform/scheduler/test/fake_renderer_scheduler.cc
@@ -69,7 +69,8 @@
     InputEventState event_state) {}
 
 void FakeRendererScheduler::DidHandleInputEventOnMainThread(
-    const blink::WebInputEvent& web_input_event) {}
+    const blink::WebInputEvent& web_input_event,
+    WebInputEventResult result) {}
 
 void FakeRendererScheduler::DidAnimateForInputOnCompositorThread() {}
 
diff --git a/third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h b/third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h
index 3c68b79..f383b687 100644
--- a/third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h
+++ b/third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h
@@ -14,6 +14,7 @@
 #include "public/platform/scheduler/renderer/render_widget_scheduling_state.h"
 #include "public/platform/WebCommon.h"
 #include "public/platform/WebInputEvent.h"
+#include "public/platform/WebInputEventResult.h"
 #include "public/platform/WebScheduler.h"
 #include "v8/include/v8.h"
 
@@ -110,7 +111,8 @@
   // Tells the scheduler that the system processed an input event. Must be
   // called from the main thread.
   virtual void DidHandleInputEventOnMainThread(
-      const WebInputEvent& web_input_event) = 0;
+      const WebInputEvent& web_input_event,
+      WebInputEventResult result) = 0;
 
   // Tells the scheduler that the system is displaying an input animation (e.g.
   // a fling). Called by the compositor (impl) thread.
diff --git a/third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h b/third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h
index 4c01d6f..ddb575a 100644
--- a/third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h
+++ b/third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h
@@ -37,8 +37,8 @@
   void DidHandleInputEventOnCompositorThread(
       const WebInputEvent& web_input_event,
       InputEventState event_state) override;
-  void DidHandleInputEventOnMainThread(
-      const WebInputEvent& web_input_event) override;
+  void DidHandleInputEventOnMainThread(const WebInputEvent& web_input_event,
+                                       WebInputEventResult result) override;
   void DidAnimateForInputOnCompositorThread() override;
   void OnRendererBackgrounded() override;
   void OnRendererForegrounded() override;
diff --git a/third_party/WebKit/public/platform/scheduler/test/mock_renderer_scheduler.h b/third_party/WebKit/public/platform/scheduler/test/mock_renderer_scheduler.h
index 628908d..90b2b56 100644
--- a/third_party/WebKit/public/platform/scheduler/test/mock_renderer_scheduler.h
+++ b/third_party/WebKit/public/platform/scheduler/test/mock_renderer_scheduler.h
@@ -37,7 +37,8 @@
   MOCK_METHOD0(DidCommitFrameToCompositor, void());
   MOCK_METHOD2(DidHandleInputEventOnCompositorThread,
                void(const WebInputEvent&, InputEventState));
-  MOCK_METHOD1(DidHandleInputEventOnMainThread, void(const WebInputEvent&));
+  MOCK_METHOD2(DidHandleInputEventOnMainThread,
+               void(const WebInputEvent&, WebInputEventResult));
   MOCK_METHOD0(DidAnimateForInputOnCompositorThread, void());
   MOCK_METHOD0(OnRendererBackgrounded, void());
   MOCK_METHOD0(OnRendererForegrounded, void());