[go: nahoru, domu]

Merge ThreadedInputHandler and InputHandler.

There is no other implementer of InputHandler, so it is an unnecessary
abstraction to separate them.  Also, the name ThreadedInputHandler is
misleading, since we use it even in single-threaded mode.

InputHandlerProxyTest does some yak-shaving to make a MockInputHandler.
(I think we should try to move away from fine-grained mocks like this.)

Bug: 1344941
Change-Id: Iaf7d9d0a19703db43dd72ec42060a4564488570e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3763157
Reviewed-by: David Bokan <bokan@chromium.org>
Commit-Queue: Steve Kobes <skobes@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1025268}
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 3eaf28c..9ae3d8c 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -43,6 +43,7 @@
     "input/browser_controls_offset_manager_client.h",
     "input/browser_controls_state.h",
     "input/compositor_input_interfaces.h",
+    "input/input_handler.cc",
     "input/input_handler.h",
     "input/layer_selection_bound.cc",
     "input/layer_selection_bound.h",
@@ -74,8 +75,6 @@
     "input/snap_fling_curve.h",
     "input/snap_selection_strategy.cc",
     "input/snap_selection_strategy.h",
-    "input/threaded_input_handler.cc",
-    "input/threaded_input_handler.h",
     "input/touch_action.h",
     "layers/append_quads_data.cc",
     "layers/append_quads_data.h",
diff --git a/cc/input/compositor_input_interfaces.h b/cc/input/compositor_input_interfaces.h
index cdc8b4f..fea6c64 100644
--- a/cc/input/compositor_input_interfaces.h
+++ b/cc/input/compositor_input_interfaces.h
@@ -29,10 +29,9 @@
 enum class ScrollbarOrientation;
 
 // This is the interface that LayerTreeHostImpl and the "graphics" side of the
-// compositor uses to talk to the compositor ThreadedInputHandler. This
-// interface is two-way; it's used used both to communicate state changes from
-// the LayerTree to the input handler and also to query and update state in the
-// input handler.
+// compositor uses to talk to the compositor InputHandler. This interface is
+// two-way; it's used used both to communicate state changes from the LayerTree
+// to the input handler and also to query and update state in the input handler.
 class InputDelegateForCompositor {
  public:
   virtual ~InputDelegateForCompositor() = default;
diff --git a/cc/input/threaded_input_handler.cc b/cc/input/input_handler.cc
similarity index 91%
rename from cc/input/threaded_input_handler.cc
rename to cc/input/input_handler.cc
index be15f49..a0a2846 100644
--- a/cc/input/threaded_input_handler.cc
+++ b/cc/input/input_handler.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "cc/input/threaded_input_handler.h"
+#include "cc/input/input_handler.h"
 
 #include <utility>
 #include <vector>
@@ -53,45 +53,42 @@
 // static
 base::WeakPtr<InputHandler> InputHandler::Create(
     CompositorDelegateForInput& compositor_delegate) {
-  auto input_handler =
-      std::make_unique<ThreadedInputHandler>(compositor_delegate);
+  auto input_handler = std::make_unique<InputHandler>(compositor_delegate);
   base::WeakPtr<InputHandler> input_handler_weak = input_handler->AsWeakPtr();
   compositor_delegate.BindToInputHandler(std::move(input_handler));
   return input_handler_weak;
 }
 
-ThreadedInputHandler::ThreadedInputHandler(
-    CompositorDelegateForInput& compositor_delegate)
+InputHandler::InputHandler(CompositorDelegateForInput& compositor_delegate)
     : compositor_delegate_(compositor_delegate),
       scrollbar_controller_(std::make_unique<ScrollbarController>(
           &compositor_delegate_.GetImplDeprecated())) {}
 
-ThreadedInputHandler::~ThreadedInputHandler() = default;
+InputHandler::~InputHandler() = default;
 
 //
 // =========== InputHandler Interface
 //
 
-base::WeakPtr<InputHandler> ThreadedInputHandler::AsWeakPtr() const {
+base::WeakPtr<InputHandler> InputHandler::AsWeakPtr() const {
   return weak_factory_.GetWeakPtr();
 }
 
-void ThreadedInputHandler::BindToClient(InputHandlerClient* client) {
+void InputHandler::BindToClient(InputHandlerClient* client) {
   DCHECK(input_handler_client_ == nullptr);
   input_handler_client_ = client;
   input_handler_client_->SetPrefersReducedMotion(prefers_reduced_motion_);
 }
 
-InputHandler::ScrollStatus ThreadedInputHandler::ScrollBegin(
-    ScrollState* scroll_state,
-    ui::ScrollInputType type) {
+InputHandler::ScrollStatus InputHandler::ScrollBegin(ScrollState* scroll_state,
+                                                     ui::ScrollInputType type) {
   DCHECK(scroll_state);
   DCHECK(scroll_state->delta_x() == 0 && scroll_state->delta_y() == 0);
 
   InputHandler::ScrollStatus scroll_status;
   scroll_status.main_thread_scrolling_reasons =
       MainThreadScrollingReason::kNotScrollingOnMain;
-  TRACE_EVENT0("cc", "ThreadedInputHandler::ScrollBegin");
+  TRACE_EVENT0("cc", "InputHandler::ScrollBegin");
 
   // If this ScrollBegin is non-animated then ensure we cancel any ongoing
   // animated scrolls.
@@ -340,10 +337,10 @@
   return scroll_status;
 }
 
-InputHandler::ScrollStatus ThreadedInputHandler::RootScrollBegin(
+InputHandler::ScrollStatus InputHandler::RootScrollBegin(
     ScrollState* scroll_state,
     ui::ScrollInputType type) {
-  TRACE_EVENT0("cc", "ThreadedInputHandler::RootScrollBegin");
+  TRACE_EVENT0("cc", "InputHandler::RootScrollBegin");
   if (!OuterViewportScrollNode()) {
     InputHandler::ScrollStatus scroll_status;
     scroll_status.thread = InputHandler::ScrollThread::SCROLL_IGNORED;
@@ -363,14 +360,14 @@
   return scroll_status;
 }
 
-InputHandlerScrollResult ThreadedInputHandler::ScrollUpdate(
+InputHandlerScrollResult InputHandler::ScrollUpdate(
     ScrollState* scroll_state,
     base::TimeDelta delayed_by) {
   DCHECK(scroll_state);
 
   // The current_native_scrolling_element should only be set for ScrollBegin.
   DCHECK(!scroll_state->data()->current_native_scrolling_element());
-  TRACE_EVENT2("cc", "ThreadedInputHandler::ScrollUpdate", "dx",
+  TRACE_EVENT2("cc", "InputHandler::ScrollUpdate", "dx",
                scroll_state->delta_x(), "dy", scroll_state->delta_y());
 
   if (!CurrentlyScrollingNode())
@@ -494,7 +491,7 @@
   return scroll_result;
 }
 
-void ThreadedInputHandler::AdjustScrollDeltaForScrollbarSnap(
+void InputHandler::AdjustScrollDeltaForScrollbarSnap(
     ScrollState* scroll_state) {
   ScrollNode* scroll_node = CurrentlyScrollingNode();
   if (!scroll_node || !scroll_node->snap_container_data)
@@ -524,7 +521,7 @@
   scroll_state->data()->delta_y = snap_position.y() - current_position.y();
 }
 
-void ThreadedInputHandler::ScrollEnd(bool should_snap) {
+void InputHandler::ScrollEnd(bool should_snap) {
   scrollbar_controller_->ResetState();
   if (!CurrentlyScrollingNode())
     return;
@@ -556,7 +553,7 @@
   SetNeedsCommit();
 }
 
-void ThreadedInputHandler::RecordScrollBegin(
+void InputHandler::RecordScrollBegin(
     ui::ScrollInputType input_type,
     ScrollBeginThreadState scroll_start_state) {
   auto tracker_type = GetTrackerTypeForScroll(input_type);
@@ -583,12 +580,12 @@
       tracker_type, scrolling_thread);
 }
 
-void ThreadedInputHandler::RecordScrollEnd(ui::ScrollInputType input_type) {
+void InputHandler::RecordScrollEnd(ui::ScrollInputType input_type) {
   compositor_delegate_.GetImplDeprecated().frame_trackers().StopSequence(
       GetTrackerTypeForScroll(input_type));
 }
 
-InputHandlerPointerResult ThreadedInputHandler::MouseMoveAt(
+InputHandlerPointerResult InputHandler::MouseMoveAt(
     const gfx::Point& viewport_point) {
   InputHandlerPointerResult result;
   if (compositor_delegate_.GetSettings()
@@ -641,15 +638,14 @@
   return result;
 }
 
-PointerResultType ThreadedInputHandler::HitTest(
-    const gfx::PointF& viewport_point) {
+PointerResultType InputHandler::HitTest(const gfx::PointF& viewport_point) {
   return compositor_delegate_.GetSettings()
                  .compositor_threaded_scrollbar_scrolling
              ? scrollbar_controller_->HitTest(viewport_point)
              : PointerResultType::kUnhandled;
 }
 
-InputHandlerPointerResult ThreadedInputHandler::MouseDown(
+InputHandlerPointerResult InputHandler::MouseDown(
     const gfx::PointF& viewport_point,
     bool shift_modifier) {
   ScrollbarAnimationController* animation_controller =
@@ -672,7 +668,7 @@
   return result;
 }
 
-InputHandlerPointerResult ThreadedInputHandler::MouseUp(
+InputHandlerPointerResult InputHandler::MouseUp(
     const gfx::PointF& viewport_point) {
   if (scroll_element_id_mouse_currently_captured_) {
     ScrollbarAnimationController* animation_controller =
@@ -694,27 +690,27 @@
   return result;
 }
 
-void ThreadedInputHandler::MouseLeave() {
+void InputHandler::MouseLeave() {
   compositor_delegate_.DidMouseLeave();
   scroll_element_id_mouse_currently_over_ = ElementId();
 }
 
-ElementId ThreadedInputHandler::FindFrameElementIdAtPoint(
+ElementId InputHandler::FindFrameElementIdAtPoint(
     const gfx::PointF& viewport_point) {
   gfx::PointF device_viewport_point = gfx::ScalePoint(
       gfx::PointF(viewport_point), compositor_delegate_.DeviceScaleFactor());
   return ActiveTree().FindFrameElementIdAtPoint(device_viewport_point);
 }
 
-void ThreadedInputHandler::RequestUpdateForSynchronousInputHandler() {
+void InputHandler::RequestUpdateForSynchronousInputHandler() {
   UpdateRootLayerStateForSynchronousInputHandler();
 }
 
-void ThreadedInputHandler::SetSynchronousInputHandlerRootScrollOffset(
+void InputHandler::SetSynchronousInputHandlerRootScrollOffset(
     const gfx::PointF& root_content_offset) {
-  TRACE_EVENT2(
-      "cc", "ThreadedInputHandler::SetSynchronousInputHandlerRootScrollOffset",
-      "offset_x", root_content_offset.x(), "offset_y", root_content_offset.y());
+  TRACE_EVENT2("cc", "InputHandler::SetSynchronousInputHandlerRootScrollOffset",
+               "offset_x", root_content_offset.x(), "offset_y",
+               root_content_offset.y());
 
   gfx::Vector2dF physical_delta =
       root_content_offset - GetViewport().TotalScrollOffset();
@@ -741,8 +737,8 @@
   compositor_delegate_.SetNeedsFullViewportRedraw();
 }
 
-void ThreadedInputHandler::PinchGestureBegin(const gfx::Point& anchor,
-                                             ui::ScrollInputType source) {
+void InputHandler::PinchGestureBegin(const gfx::Point& anchor,
+                                     ui::ScrollInputType source) {
   DCHECK(source == ui::ScrollInputType::kTouchscreen ||
          source == ui::ScrollInputType::kWheel);
 
@@ -778,9 +774,9 @@
   compositor_delegate_.DidStartPinchZoom();
 }
 
-void ThreadedInputHandler::PinchGestureUpdate(float magnify_delta,
-                                              const gfx::Point& anchor) {
-  TRACE_EVENT0("cc", "ThreadedInputHandler::PinchGestureUpdate");
+void InputHandler::PinchGestureUpdate(float magnify_delta,
+                                      const gfx::Point& anchor) {
+  TRACE_EVENT0("cc", "InputHandler::PinchGestureUpdate");
   if (!InnerViewportScrollNode())
     return;
   has_pinch_zoomed_ = true;
@@ -792,7 +788,7 @@
   UpdateRootLayerStateForSynchronousInputHandler();
 }
 
-void ThreadedInputHandler::PinchGestureEnd(const gfx::Point& anchor) {
+void InputHandler::PinchGestureEnd(const gfx::Point& anchor) {
   // Some tests create a pinch gesture without creating a viewport scroll node.
   // In those cases, PinchGestureBegin will not latch to a scroll node.
   DCHECK(latched_scroll_type_.has_value() || !CurrentlyScrollingNode());
@@ -811,23 +807,23 @@
   compositor_delegate_.DidEndPinchZoom();
 }
 
-void ThreadedInputHandler::SetNeedsAnimateInput() {
+void InputHandler::SetNeedsAnimateInput() {
   compositor_delegate_.GetImplDeprecated().SetNeedsAnimateInput();
 }
 
-bool ThreadedInputHandler::IsCurrentlyScrollingViewport() const {
+bool InputHandler::IsCurrentlyScrollingViewport() const {
   auto* node = CurrentlyScrollingNode();
   if (!node)
     return false;
   return GetViewport().ShouldScroll(*node);
 }
 
-EventListenerProperties ThreadedInputHandler::GetEventListenerProperties(
+EventListenerProperties InputHandler::GetEventListenerProperties(
     EventListenerClass event_class) const {
   return ActiveTree().event_listener_properties(event_class);
 }
 
-bool ThreadedInputHandler::HasBlockingWheelEventHandlerAt(
+bool InputHandler::HasBlockingWheelEventHandlerAt(
     const gfx::Point& viewport_point) const {
   gfx::PointF device_viewport_point = gfx::ScalePoint(
       gfx::PointF(viewport_point), compositor_delegate_.DeviceScaleFactor());
@@ -840,7 +836,7 @@
 }
 
 InputHandler::TouchStartOrMoveEventListenerType
-ThreadedInputHandler::EventListenerTypeForTouchStartOrMoveAt(
+InputHandler::EventListenerTypeForTouchStartOrMoveAt(
     const gfx::Point& viewport_point,
     TouchAction* out_touch_action) {
   gfx::PointF device_viewport_point = gfx::ScalePoint(
@@ -894,20 +890,19 @@
 }
 
 std::unique_ptr<LatencyInfoSwapPromiseMonitor>
-ThreadedInputHandler::CreateLatencyInfoSwapPromiseMonitor(
-    ui::LatencyInfo* latency) {
+InputHandler::CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency) {
   return compositor_delegate_.GetImplDeprecated()
       .CreateLatencyInfoSwapPromiseMonitor(latency);
 }
 
 std::unique_ptr<EventsMetricsManager::ScopedMonitor>
-ThreadedInputHandler::GetScopedEventMetricsMonitor(
+InputHandler::GetScopedEventMetricsMonitor(
     EventsMetricsManager::ScopedMonitor::DoneCallback done_callback) {
   return compositor_delegate_.GetImplDeprecated().GetScopedEventMetricsMonitor(
       std::move(done_callback));
 }
 
-ScrollElasticityHelper* ThreadedInputHandler::CreateScrollElasticityHelper() {
+ScrollElasticityHelper* InputHandler::CreateScrollElasticityHelper() {
   DCHECK(!scroll_elasticity_helper_);
   if (compositor_delegate_.GetSettings().enable_elastic_overscroll) {
     scroll_elasticity_helper_.reset(
@@ -917,14 +912,14 @@
   return scroll_elasticity_helper_.get();
 }
 
-void ThreadedInputHandler::DestroyScrollElasticityHelper() {
+void InputHandler::DestroyScrollElasticityHelper() {
   // Remove any stretch before destroying helper.
   scroll_elasticity_helper_->SetStretchAmount(gfx::Vector2dF());
   scroll_elasticity_helper_.reset();
 }
 
-bool ThreadedInputHandler::GetScrollOffsetForLayer(ElementId element_id,
-                                                   gfx::PointF* offset) {
+bool InputHandler::GetScrollOffsetForLayer(ElementId element_id,
+                                           gfx::PointF* offset) {
   ScrollTree& scroll_tree = GetScrollTree();
   ScrollNode* scroll_node = scroll_tree.FindNodeFromElementId(element_id);
   if (!scroll_node)
@@ -933,8 +928,8 @@
   return true;
 }
 
-bool ThreadedInputHandler::ScrollLayerTo(ElementId element_id,
-                                         const gfx::PointF& offset) {
+bool InputHandler::ScrollLayerTo(ElementId element_id,
+                                 const gfx::PointF& offset) {
   ScrollTree& scroll_tree = GetScrollTree();
   ScrollNode* scroll_node = scroll_tree.FindNodeFromElementId(element_id);
   if (!scroll_node)
@@ -946,7 +941,7 @@
   return true;
 }
 
-bool ThreadedInputHandler::ScrollingShouldSwitchtoMainThread() {
+bool InputHandler::ScrollingShouldSwitchtoMainThread() {
   DCHECK(!base::FeatureList::IsEnabled(features::kScrollUnification));
   ScrollTree& scroll_tree = GetScrollTree();
   ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode();
@@ -963,7 +958,7 @@
   return false;
 }
 
-bool ThreadedInputHandler::GetSnapFlingInfoAndSetAnimatingSnapTarget(
+bool InputHandler::GetSnapFlingInfoAndSetAnimatingSnapTarget(
     const gfx::Vector2dF& natural_displacement_in_viewport,
     gfx::PointF* out_initial_position,
     gfx::PointF* out_target_position) {
@@ -995,7 +990,7 @@
   return true;
 }
 
-void ThreadedInputHandler::ScrollEndForSnapFling(bool did_finish) {
+void InputHandler::ScrollEndForSnapFling(bool did_finish) {
   ScrollNode* scroll_node = CurrentlyScrollingNode();
   // When a snap fling animation reaches its intended target then we update the
   // scrolled node's snap targets. This also ensures blink learns about the new
@@ -1012,7 +1007,7 @@
   ScrollEnd(false /* should_snap */);
 }
 
-void ThreadedInputHandler::NotifyInputEvent() {
+void InputHandler::NotifyInputEvent() {
   compositor_delegate_.GetImplDeprecated().NotifyInputEvent();
 }
 
@@ -1020,8 +1015,7 @@
 // =========== InputDelegateForCompositor Interface
 //
 
-void ThreadedInputHandler::ProcessCommitDeltas(
-    CompositorCommitData* commit_data) {
+void InputHandler::ProcessCommitDeltas(CompositorCommitData* commit_data) {
   DCHECK(commit_data);
   if (ActiveTree().LayerListIsEmpty())
     return;
@@ -1080,7 +1074,7 @@
     last_latched_scroller_ = ElementId();
 }
 
-void ThreadedInputHandler::TickAnimations(base::TimeTicks monotonic_time) {
+void InputHandler::TickAnimations(base::TimeTicks monotonic_time) {
   if (input_handler_client_) {
     // This does not set did_animate, because if the InputHandlerClient
     // changes anything it will be through the InputHandler interface which
@@ -1089,7 +1083,7 @@
   }
 }
 
-void ThreadedInputHandler::WillShutdown() {
+void InputHandler::WillShutdown() {
   if (input_handler_client_) {
     input_handler_client_->WillShutdown();
     input_handler_client_ = nullptr;
@@ -1099,26 +1093,26 @@
     scroll_elasticity_helper_.reset();
 }
 
-void ThreadedInputHandler::WillDraw() {
+void InputHandler::WillDraw() {
   if (input_handler_client_)
     input_handler_client_->ReconcileElasticOverscrollAndRootScroll();
 }
 
-void ThreadedInputHandler::WillBeginImplFrame(const viz::BeginFrameArgs& args) {
+void InputHandler::WillBeginImplFrame(const viz::BeginFrameArgs& args) {
   if (input_handler_client_) {
     scrollbar_controller_->WillBeginImplFrame();
     input_handler_client_->DeliverInputForBeginFrame(args);
   }
 }
 
-void ThreadedInputHandler::DidCommit() {
+void InputHandler::DidCommit() {
   // In high latency mode commit cannot finish within the same frame. We need to
   // flush input here to make sure they got picked up by |PrepareTiles()|.
   if (input_handler_client_ && compositor_delegate_.IsInHighLatencyMode())
     input_handler_client_->DeliverInputForHighLatencyMode();
 }
 
-void ThreadedInputHandler::DidActivatePendingTree() {
+void InputHandler::DidActivatePendingTree() {
   // The previous scrolling node might no longer exist in the new tree.
   if (!CurrentlyScrollingNode())
     ClearCurrentlyScrollingNode();
@@ -1128,24 +1122,22 @@
   UpdateRootLayerStateForSynchronousInputHandler();
 }
 
-void ThreadedInputHandler::RootLayerStateMayHaveChanged() {
+void InputHandler::RootLayerStateMayHaveChanged() {
   UpdateRootLayerStateForSynchronousInputHandler();
 }
 
-void ThreadedInputHandler::DidRegisterScrollbar(
-    ElementId scroll_element_id,
-    ScrollbarOrientation orientation) {
+void InputHandler::DidRegisterScrollbar(ElementId scroll_element_id,
+                                        ScrollbarOrientation orientation) {
   scrollbar_controller_->DidRegisterScrollbar(scroll_element_id, orientation);
 }
 
-void ThreadedInputHandler::DidUnregisterScrollbar(
-    ElementId scroll_element_id,
-    ScrollbarOrientation orientation) {
+void InputHandler::DidUnregisterScrollbar(ElementId scroll_element_id,
+                                          ScrollbarOrientation orientation) {
   scrollbar_controller_->DidUnregisterScrollbar(scroll_element_id, orientation);
 }
 
-void ThreadedInputHandler::ScrollOffsetAnimationFinished() {
-  TRACE_EVENT0("cc", "ThreadedInputHandler::ScrollOffsetAnimationFinished");
+void InputHandler::ScrollOffsetAnimationFinished() {
+  TRACE_EVENT0("cc", "InputHandler::ScrollOffsetAnimationFinished");
   // ScrollOffsetAnimationFinished is called in two cases:
   //  1- smooth scrolling animation is over (IsAnimatingForSnap == false).
   //  2- snap scroll animation is over (IsAnimatingForSnap == true).
@@ -1175,8 +1167,7 @@
   }
 }
 
-void ThreadedInputHandler::SetPrefersReducedMotion(
-    bool prefers_reduced_motion) {
+void InputHandler::SetPrefersReducedMotion(bool prefers_reduced_motion) {
   if (prefers_reduced_motion_ == prefers_reduced_motion)
     return;
   prefers_reduced_motion_ = prefers_reduced_motion;
@@ -1185,11 +1176,11 @@
     input_handler_client_->SetPrefersReducedMotion(prefers_reduced_motion_);
 }
 
-bool ThreadedInputHandler::IsCurrentlyScrolling() const {
+bool InputHandler::IsCurrentlyScrolling() const {
   return CurrentlyScrollingNode();
 }
 
-ActivelyScrollingType ThreadedInputHandler::GetActivelyScrollingType() const {
+ActivelyScrollingType InputHandler::GetActivelyScrollingType() const {
   if (!CurrentlyScrollingNode())
     return ActivelyScrollingType::kNone;
 
@@ -1205,49 +1196,49 @@
   return ActivelyScrollingType::kPrecise;
 }
 
-ScrollNode* ThreadedInputHandler::CurrentlyScrollingNode() {
+ScrollNode* InputHandler::CurrentlyScrollingNode() {
   return GetScrollTree().CurrentlyScrollingNode();
 }
 
-const ScrollNode* ThreadedInputHandler::CurrentlyScrollingNode() const {
+const ScrollNode* InputHandler::CurrentlyScrollingNode() const {
   return GetScrollTree().CurrentlyScrollingNode();
 }
 
-ScrollTree& ThreadedInputHandler::GetScrollTree() {
+ScrollTree& InputHandler::GetScrollTree() {
   return compositor_delegate_.GetScrollTree();
 }
 
-ScrollTree& ThreadedInputHandler::GetScrollTree() const {
+ScrollTree& InputHandler::GetScrollTree() const {
   return compositor_delegate_.GetScrollTree();
 }
 
-ScrollNode* ThreadedInputHandler::InnerViewportScrollNode() const {
+ScrollNode* InputHandler::InnerViewportScrollNode() const {
   return ActiveTree().InnerViewportScrollNode();
 }
 
-ScrollNode* ThreadedInputHandler::OuterViewportScrollNode() const {
+ScrollNode* InputHandler::OuterViewportScrollNode() const {
   return ActiveTree().OuterViewportScrollNode();
 }
 
-Viewport& ThreadedInputHandler::GetViewport() const {
+Viewport& InputHandler::GetViewport() const {
   return compositor_delegate_.GetImplDeprecated().viewport();
 }
 
-void ThreadedInputHandler::SetNeedsCommit() {
+void InputHandler::SetNeedsCommit() {
   compositor_delegate_.SetNeedsCommit();
 }
 
-LayerTreeImpl& ThreadedInputHandler::ActiveTree() {
+LayerTreeImpl& InputHandler::ActiveTree() {
   DCHECK(compositor_delegate_.GetImplDeprecated().active_tree());
   return *compositor_delegate_.GetImplDeprecated().active_tree();
 }
 
-LayerTreeImpl& ThreadedInputHandler::ActiveTree() const {
+LayerTreeImpl& InputHandler::ActiveTree() const {
   DCHECK(compositor_delegate_.GetImplDeprecated().active_tree());
   return *compositor_delegate_.GetImplDeprecated().active_tree();
 }
 
-FrameSequenceTrackerType ThreadedInputHandler::GetTrackerTypeForScroll(
+FrameSequenceTrackerType InputHandler::GetTrackerTypeForScroll(
     ui::ScrollInputType input_type) const {
   switch (input_type) {
     case ui::ScrollInputType::kWheel:
@@ -1261,7 +1252,7 @@
   }
 }
 
-bool ThreadedInputHandler::IsMainThreadScrolling(
+bool InputHandler::IsMainThreadScrolling(
     const InputHandler::ScrollStatus& status,
     const ScrollNode* scroll_node) const {
   if (status.thread == InputHandler::ScrollThread::SCROLL_ON_MAIN_THREAD) {
@@ -1277,14 +1268,14 @@
   return false;
 }
 
-float ThreadedInputHandler::LineStep() const {
+float InputHandler::LineStep() const {
   return kPixelsPerLineStep;
 }
 
 // TODO(mehdika): There is some redundancy between this function and
 // ScrollbarController::GetScrollDistanceForScrollbarPart, these two need to be
 // kept in sync.
-gfx::Vector2dF ThreadedInputHandler::ResolveScrollGranularityToPixels(
+gfx::Vector2dF InputHandler::ResolveScrollGranularityToPixels(
     const ScrollNode& scroll_node,
     const gfx::Vector2dF& scroll_delta,
     ui::ScrollGranularity granularity) {
@@ -1320,7 +1311,7 @@
   return pixel_delta;
 }
 
-InputHandler::ScrollStatus ThreadedInputHandler::TryScroll(
+InputHandler::ScrollStatus InputHandler::TryScroll(
     const ScrollTree& scroll_tree,
     ScrollNode* scroll_node) const {
   DCHECK(!base::FeatureList::IsEnabled(features::kScrollUnification));
@@ -1391,7 +1382,7 @@
   return scroll_status;
 }
 
-base::flat_set<int> ThreadedInputHandler::NonFastScrollableNodes(
+base::flat_set<int> InputHandler::NonFastScrollableNodes(
     const gfx::PointF& device_viewport_point) const {
   base::flat_set<int> non_fast_scrollable_nodes;
 
@@ -1404,7 +1395,7 @@
   return non_fast_scrollable_nodes;
 }
 
-ScrollNode* ThreadedInputHandler::FindScrollNodeForCompositedScrolling(
+ScrollNode* InputHandler::FindScrollNodeForCompositedScrolling(
     const gfx::PointF& device_viewport_point,
     LayerImpl* layer_impl,
     bool* scroll_on_main_thread,
@@ -1486,8 +1477,7 @@
   return impl_scroll_node;
 }
 
-ThreadedInputHandler::ScrollHitTestResult
-ThreadedInputHandler::HitTestScrollNode(
+InputHandler::ScrollHitTestResult InputHandler::HitTestScrollNode(
     const gfx::PointF& device_viewport_point) const {
   ScrollHitTestResult result;
   result.scroll_node = nullptr;
@@ -1559,7 +1549,7 @@
 
 // Requires falling back to main thread scrolling when it hit tests in scrollbar
 // from touch.
-bool ThreadedInputHandler::IsTouchDraggingScrollbar(
+bool InputHandler::IsTouchDraggingScrollbar(
     LayerImpl* first_scrolling_layer_or_scrollbar,
     ui::ScrollInputType type) {
   return first_scrolling_layer_or_scrollbar &&
@@ -1567,7 +1557,7 @@
          type == ui::ScrollInputType::kTouchscreen;
 }
 
-ScrollNode* ThreadedInputHandler::GetNodeToScroll(ScrollNode* node) const {
+ScrollNode* InputHandler::GetNodeToScroll(ScrollNode* node) const {
   // Blink has a notion of a "root scroller", which is the scroller in a page
   // that is considered to host the main content. Typically this will be the
   // document/LayoutView contents; however, in some situations Blink may choose
@@ -1599,7 +1589,7 @@
   return node;
 }
 
-bool ThreadedInputHandler::IsInitialScrollHitTestReliable(
+bool InputHandler::IsInitialScrollHitTestReliable(
     const LayerImpl* layer_impl,
     const LayerImpl* first_scrolling_layer_or_scrollbar) const {
   if (!first_scrolling_layer_or_scrollbar)
@@ -1641,9 +1631,8 @@
   return false;
 }
 
-gfx::Vector2dF ThreadedInputHandler::ComputeScrollDelta(
-    const ScrollNode& scroll_node,
-    const gfx::Vector2dF& delta) {
+gfx::Vector2dF InputHandler::ComputeScrollDelta(const ScrollNode& scroll_node,
+                                                const gfx::Vector2dF& delta) {
   ScrollTree& scroll_tree = GetScrollTree();
   float scale_factor = compositor_delegate_.PageScaleFactor();
 
@@ -1659,7 +1648,7 @@
   return new_offset - old_offset;
 }
 
-bool ThreadedInputHandler::CalculateLocalScrollDeltaAndStartPoint(
+bool InputHandler::CalculateLocalScrollDeltaAndStartPoint(
     const ScrollNode& scroll_node,
     const gfx::PointF& viewport_point,
     const gfx::Vector2dF& viewport_delta,
@@ -1706,7 +1695,7 @@
   return true;
 }
 
-gfx::Vector2dF ThreadedInputHandler::ScrollNodeWithViewportSpaceDelta(
+gfx::Vector2dF InputHandler::ScrollNodeWithViewportSpaceDelta(
     const ScrollNode& scroll_node,
     const gfx::PointF& viewport_point,
     const gfx::Vector2dF& viewport_delta) {
@@ -1755,7 +1744,7 @@
   return actual_viewport_end_point - viewport_point;
 }
 
-gfx::Vector2dF ThreadedInputHandler::ScrollNodeWithLocalDelta(
+gfx::Vector2dF InputHandler::ScrollNodeWithLocalDelta(
     const ScrollNode& scroll_node,
     const gfx::Vector2dF& local_delta) const {
   bool scrolls_outer_viewport = scroll_node.scrolls_outer_viewport;
@@ -1782,11 +1771,10 @@
 
 // TODO(danakj): Make this into two functions, one with delta, one with
 // viewport_point, no bool required.
-gfx::Vector2dF ThreadedInputHandler::ScrollSingleNode(
-    const ScrollNode& scroll_node,
-    const gfx::Vector2dF& delta,
-    const gfx::Point& viewport_point,
-    bool is_direct_manipulation) {
+gfx::Vector2dF InputHandler::ScrollSingleNode(const ScrollNode& scroll_node,
+                                              const gfx::Vector2dF& delta,
+                                              const gfx::Point& viewport_point,
+                                              bool is_direct_manipulation) {
   gfx::Vector2dF adjusted_delta = UserScrollableDelta(scroll_node, delta);
 
   // Events representing direct manipulation of the screen (such as gesture
@@ -1807,15 +1795,15 @@
   return ScrollNodeWithLocalDelta(scroll_node, adjusted_delta);
 }
 
-void ThreadedInputHandler::ScrollLatchedScroller(ScrollState* scroll_state,
-                                                 base::TimeDelta delayed_by) {
+void InputHandler::ScrollLatchedScroller(ScrollState* scroll_state,
+                                         base::TimeDelta delayed_by) {
   DCHECK(CurrentlyScrollingNode());
   DCHECK(scroll_state);
   DCHECK(latched_scroll_type_.has_value());
 
   ScrollNode& scroll_node = *CurrentlyScrollingNode();
   const gfx::Vector2dF delta(scroll_state->delta_x(), scroll_state->delta_y());
-  TRACE_EVENT2("cc", "ThreadedInputHandler::ScrollLatchedScroller", "delta_x",
+  TRACE_EVENT2("cc", "InputHandler::ScrollLatchedScroller", "delta_x",
                delta.x(), "delta_y", delta.y());
   gfx::Vector2dF applied_delta;
   gfx::Vector2dF delta_applied_to_content;
@@ -1934,18 +1922,16 @@
   scroll_state->ConsumeDelta(applied_delta.x(), applied_delta.y());
 }
 
-bool ThreadedInputHandler::CanPropagate(ScrollNode* scroll_node,
-                                        float x,
-                                        float y) {
+bool InputHandler::CanPropagate(ScrollNode* scroll_node, float x, float y) {
   return (x == 0 || scroll_node->overscroll_behavior.x ==
                         OverscrollBehavior::Type::kAuto) &&
          (y == 0 || scroll_node->overscroll_behavior.y ==
                         OverscrollBehavior::Type::kAuto);
 }
 
-ScrollNode* ThreadedInputHandler::FindNodeToLatch(ScrollState* scroll_state,
-                                                  ScrollNode* starting_node,
-                                                  ui::ScrollInputType type) {
+ScrollNode* InputHandler::FindNodeToLatch(ScrollState* scroll_state,
+                                          ScrollNode* starting_node,
+                                          ui::ScrollInputType type) {
   ScrollTree& scroll_tree = GetScrollTree();
   ScrollNode* scroll_node = nullptr;
   ScrollNode* first_scrollable_node = nullptr;
@@ -1999,7 +1985,7 @@
   return scroll_node;
 }
 
-void ThreadedInputHandler::UpdateRootLayerStateForSynchronousInputHandler() {
+void InputHandler::UpdateRootLayerStateForSynchronousInputHandler() {
   if (!input_handler_client_)
     return;
   input_handler_client_->UpdateRootLayerStateForSynchronousInputHandler(
@@ -2009,8 +1995,8 @@
       ActiveTree().max_page_scale_factor());
 }
 
-void ThreadedInputHandler::DidLatchToScroller(const ScrollState& scroll_state,
-                                              ui::ScrollInputType type) {
+void InputHandler::DidLatchToScroller(const ScrollState& scroll_state,
+                                      ui::ScrollInputType type) {
   DCHECK(CurrentlyScrollingNode());
   deferred_scroll_end_ = false;
   compositor_delegate_.GetImplDeprecated()
@@ -2032,8 +2018,8 @@
   UpdateScrollSourceInfo(scroll_state, type);
 }
 
-bool ThreadedInputHandler::CanConsumeDelta(const ScrollState& scroll_state,
-                                           const ScrollNode& scroll_node) {
+bool InputHandler::CanConsumeDelta(const ScrollState& scroll_state,
+                                   const ScrollNode& scroll_node) {
   gfx::Vector2dF delta_to_scroll;
   if (scroll_state.is_beginning()) {
     delta_to_scroll = gfx::Vector2dF(scroll_state.delta_x_hint(),
@@ -2066,8 +2052,7 @@
   return false;
 }
 
-bool ThreadedInputHandler::ShouldAnimateScroll(
-    const ScrollState& scroll_state) const {
+bool InputHandler::ShouldAnimateScroll(const ScrollState& scroll_state) const {
   if (!compositor_delegate_.GetSettings().enable_smooth_scroll)
     return false;
 
@@ -2077,7 +2062,7 @@
   return !has_precise_scroll_deltas;
 }
 
-bool ThreadedInputHandler::SnapAtScrollEnd(SnapReason reason) {
+bool InputHandler::SnapAtScrollEnd(SnapReason reason) {
   ScrollNode* scroll_node = CurrentlyScrollingNode();
   if (!scroll_node || !scroll_node->snap_container_data.has_value())
     return false;
@@ -2151,19 +2136,19 @@
   return did_animate;
 }
 
-bool ThreadedInputHandler::IsAnimatingForSnap() const {
+bool InputHandler::IsAnimatingForSnap() const {
   return scroll_animating_snap_target_ids_ != TargetSnapAreaElementIds();
 }
 
-gfx::PointF ThreadedInputHandler::GetVisualScrollOffset(
+gfx::PointF InputHandler::GetVisualScrollOffset(
     const ScrollNode& scroll_node) const {
   if (scroll_node.scrolls_outer_viewport)
     return GetViewport().TotalScrollOffset();
   return GetScrollTree().current_scroll_offset(scroll_node.element_id);
 }
 
-void ThreadedInputHandler::ClearCurrentlyScrollingNode() {
-  TRACE_EVENT0("cc", "ThreadedInputHandler::ClearCurrentlyScrollingNode");
+void InputHandler::ClearCurrentlyScrollingNode() {
+  TRACE_EVENT0("cc", "InputHandler::ClearCurrentlyScrollingNode");
   ActiveTree().ClearCurrentlyScrollingNode();
   accumulated_root_overscroll_ = gfx::Vector2dF();
   did_scroll_x_for_scroll_gesture_ = false;
@@ -2176,7 +2161,7 @@
   compositor_delegate_.DidEndScroll();
 }
 
-bool ThreadedInputHandler::ScrollAnimationUpdateTarget(
+bool InputHandler::ScrollAnimationUpdateTarget(
     const ScrollNode& scroll_node,
     const gfx::Vector2dF& scroll_delta,
     base::TimeDelta delayed_by) {
@@ -2212,9 +2197,8 @@
   return animation_updated;
 }
 
-void ThreadedInputHandler::UpdateScrollSourceInfo(
-    const ScrollState& scroll_state,
-    ui::ScrollInputType type) {
+void InputHandler::UpdateScrollSourceInfo(const ScrollState& scroll_state,
+                                          ui::ScrollInputType type) {
   if (type == ui::ScrollInputType::kWheel &&
       scroll_state.delta_granularity() ==
           ui::ScrollGranularity::kScrollByPrecisePixel) {
@@ -2230,8 +2214,7 @@
 
 // Return true if scrollable node for 'ancestor' is the same as 'child' or an
 // ancestor along the scroll tree.
-bool ThreadedInputHandler::IsScrolledBy(LayerImpl* child,
-                                        ScrollNode* ancestor) {
+bool InputHandler::IsScrolledBy(LayerImpl* child, ScrollNode* ancestor) {
   DCHECK(ancestor && ancestor->scrollable);
   if (!child)
     return false;
@@ -2245,7 +2228,7 @@
   return false;
 }
 
-gfx::Vector2dF ThreadedInputHandler::UserScrollableDelta(
+gfx::Vector2dF InputHandler::UserScrollableDelta(
     const ScrollNode& node,
     const gfx::Vector2dF& delta) const {
   gfx::Vector2dF adjusted_delta = delta;
@@ -2257,12 +2240,11 @@
   return adjusted_delta;
 }
 
-bool ThreadedInputHandler::ScrollbarScrollIsActive() {
+bool InputHandler::ScrollbarScrollIsActive() {
   return scrollbar_controller_->ScrollbarScrollIsActive();
 }
 
-void ThreadedInputHandler::SetDeferBeginMainFrame(
-    bool defer_begin_main_frame) const {
+void InputHandler::SetDeferBeginMainFrame(bool defer_begin_main_frame) const {
   compositor_delegate_.SetDeferBeginMainFrame(defer_begin_main_frame);
 }
 
diff --git a/cc/input/input_handler.h b/cc/input/input_handler.h
index ae2ff54..585df0d 100644
--- a/cc/input/input_handler.h
+++ b/cc/input/input_handler.h
@@ -9,6 +9,7 @@
 
 #include "base/time/time.h"
 #include "cc/cc_export.h"
+#include "cc/input/compositor_input_interfaces.h"
 #include "cc/input/event_listener_properties.h"
 #include "cc/input/main_thread_scrolling_reason.h"
 #include "cc/input/overscroll_behavior.h"
@@ -16,6 +17,7 @@
 #include "cc/input/scrollbar.h"
 #include "cc/input/touch_action.h"
 #include "cc/metrics/events_metrics_manager.h"
+#include "cc/metrics/frame_sequence_metrics.h"
 #include "cc/paint/element_id.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "ui/events/types/scroll_input_type.h"
@@ -36,7 +38,10 @@
 
 class CompositorDelegateForInput;
 class LatencyInfoSwapPromiseMonitor;
+class LayerImpl;
+class ScrollbarController;
 class ScrollElasticityHelper;
+class Viewport;
 
 enum class PointerResultType { kUnhandled = 0, kScrollbarScroll };
 
@@ -131,7 +136,7 @@
 // main thread about changes that have occurred as a result of input since the
 // last commit.
 struct InputHandlerCommitData {
-  // Defined in threaded_input_handler.cc to avoid inlining since flat_set has
+  // Defined in input_handler.cc to avoid inlining since flat_set has
   // non-trivial size destructor.
   InputHandlerCommitData();
   ~InputHandlerCommitData();
@@ -157,9 +162,9 @@
   bool has_scrolled_by_precisiontouchpad = false;
 };
 
-// The InputHandler interface is a way for the embedders to interact with the
-// input system running on the compositor thread. Each instance of a compositor
-// (i.e. a LayerTreeHostImpl) is associated with one InputHandler instance. The
+// The InputHandler is a way for the embedders to interact with the input system
+// running on the compositor thread. Each instance of a compositor (i.e. a
+// LayerTreeHostImpl) is associated with one InputHandler instance. The
 // InputHandler sits in between the embedder (the UI compositor or Blink) and
 // the compositor (LayerTreeHostImpl); as such, it must be bound to both.
 //
@@ -169,7 +174,10 @@
 // the InputHandlerClient interface and bind it to the handler by calling
 // BindToClient on the input handler. This should all be done on the
 // input-handling thread (i.e. the "compositor" thread if one exists).
-class CC_EXPORT InputHandler {
+//
+// Many methods are virtual for input_handler_proxy_unittest.cc.
+// TODO: consider revising these tests to reduce reliance on mocking.
+class CC_EXPORT InputHandler : public InputDelegateForCompositor {
  public:
   // Creates an instance of the InputHandler and binds it to the layer tree
   // delegate. The delegate owns the InputHandler so their lifetimes
@@ -189,6 +197,9 @@
     LAST_SCROLL_STATUS = SCROLL_UNKNOWN
   };
 
+  explicit InputHandler(CompositorDelegateForInput& compositor_delegate);
+  ~InputHandler() override;
+
   InputHandler(const InputHandler&) = delete;
   InputHandler& operator=(const InputHandler&) = delete;
 
@@ -235,12 +246,12 @@
     HANDLER_ON_SCROLLING_LAYER
   };
 
-  virtual base::WeakPtr<InputHandler> AsWeakPtr() const = 0;
+  virtual base::WeakPtr<InputHandler> AsWeakPtr() const;
 
   // Binds a client to this handler to receive notifications. Only one client
   // can be bound to an InputHandler. The client must live at least until the
   // handler calls WillShutdown() on the client.
-  virtual void BindToClient(InputHandlerClient* client) = 0;
+  virtual void BindToClient(InputHandlerClient* client);
 
   // Selects a ScrollNode to be "latched" for scrolling using the
   // |scroll_state| start position. The selected node remains latched until the
@@ -250,12 +261,12 @@
   // SCROLL_IGNORED if there is nothing to be scrolled at the given
   // coordinates.
   virtual ScrollStatus ScrollBegin(ScrollState* scroll_state,
-                                   ui::ScrollInputType type) = 0;
+                                   ui::ScrollInputType type);
 
   // Similar to ScrollBegin, except the hit test is skipped and scroll always
   // targets at the root layer.
   virtual ScrollStatus RootScrollBegin(ScrollState* scroll_state,
-                                       ui::ScrollInputType type) = 0;
+                                       ui::ScrollInputType type);
 
   // Scroll the layer selected by |ScrollBegin| by given |scroll_state| delta.
   // Internally, the delta is transformed to local layer's coordinate space for
@@ -271,66 +282,66 @@
   // |delayed_by| is the delay from the event that caused the scroll. This is
   // taken into account when determining the duration of the animation if one
   // is created.
-  virtual InputHandlerScrollResult ScrollUpdate(ScrollState* scroll_state,
-                                                base::TimeDelta delayed_by) = 0;
+  virtual InputHandlerScrollResult ScrollUpdate(
+      ScrollState* scroll_state,
+      base::TimeDelta delayed_by = base::TimeDelta());
 
   // Stop scrolling the selected layer. Must be called only if ScrollBegin()
   // returned SCROLL_STARTED. No-op if ScrollBegin wasn't called or didn't
   // result in a successful scroll latch. Snap to a snap position if
   // |should_snap| is true.
-  virtual void ScrollEnd(bool should_snap = false) = 0;
+  virtual void ScrollEnd(bool should_snap = false);
 
   // Called to notify every time scroll-begin/end is attempted by an input
   // event.
   virtual void RecordScrollBegin(ui::ScrollInputType input_type,
-                                 ScrollBeginThreadState scroll_start_state) = 0;
-  virtual void RecordScrollEnd(ui::ScrollInputType input_type) = 0;
+                                 ScrollBeginThreadState scroll_start_state);
+  virtual void RecordScrollEnd(ui::ScrollInputType input_type);
 
-  virtual PointerResultType HitTest(const gfx::PointF& mouse_position) = 0;
+  virtual PointerResultType HitTest(const gfx::PointF& mouse_position);
   virtual InputHandlerPointerResult MouseMoveAt(
-      const gfx::Point& mouse_position) = 0;
+      const gfx::Point& mouse_position);
   // TODO(arakeri): Pass in the modifier instead of a bool once the refactor
   // (crbug.com/1022097) is done. For details, see crbug.com/1016955.
   virtual InputHandlerPointerResult MouseDown(const gfx::PointF& mouse_position,
-                                              bool shift_modifier) = 0;
-  virtual InputHandlerPointerResult MouseUp(
-      const gfx::PointF& mouse_position) = 0;
-  virtual void MouseLeave() = 0;
+                                              bool shift_modifier);
+  virtual InputHandlerPointerResult MouseUp(const gfx::PointF& mouse_position);
+  virtual void MouseLeave();
 
   // Returns visible_frame_element_id from the layer hit by the given point.
   // If the hit test failed, an invalid element ID is returned.
   virtual ElementId FindFrameElementIdAtPoint(
-      const gfx::PointF& mouse_position) = 0;
+      const gfx::PointF& mouse_position);
 
   // Requests a callback to UpdateRootLayerStateForSynchronousInputHandler()
   // giving the current root scroll and page scale information.
-  virtual void RequestUpdateForSynchronousInputHandler() = 0;
+  virtual void RequestUpdateForSynchronousInputHandler();
 
   // Called when the root scroll offset has been changed in the synchronous
   // input handler by the application (outside of input event handling). Offset
   // is expected in "content/page coordinates".
   virtual void SetSynchronousInputHandlerRootScrollOffset(
-      const gfx::PointF& root_content_offset) = 0;
+      const gfx::PointF& root_content_offset);
 
   virtual void PinchGestureBegin(const gfx::Point& anchor,
-                                 ui::ScrollInputType source) = 0;
+                                 ui::ScrollInputType source);
   virtual void PinchGestureUpdate(float magnify_delta,
-                                  const gfx::Point& anchor) = 0;
-  virtual void PinchGestureEnd(const gfx::Point& anchor) = 0;
+                                  const gfx::Point& anchor);
+  virtual void PinchGestureEnd(const gfx::Point& anchor);
 
   // Request another callback to InputHandlerClient::Animate().
-  virtual void SetNeedsAnimateInput() = 0;
+  virtual void SetNeedsAnimateInput();
 
   // Returns true if there is an active scroll on the viewport.
-  virtual bool IsCurrentlyScrollingViewport() const = 0;
+  virtual bool IsCurrentlyScrollingViewport() const;
 
   virtual EventListenerProperties GetEventListenerProperties(
-      EventListenerClass event_class) const = 0;
+      EventListenerClass event_class) const;
 
   // Returns true if |viewport_point| hits a wheel event handler region that
   // could block scrolling.
   virtual bool HasBlockingWheelEventHandlerAt(
-      const gfx::Point& viewport_point) const = 0;
+      const gfx::Point& viewport_point) const;
 
   // It returns the type of a touch start or move event listener at
   // |viewport_point|. Whether the page should be given the opportunity to
@@ -343,7 +354,7 @@
   // default touch action is auto.
   virtual TouchStartOrMoveEventListenerType
   EventListenerTypeForTouchStartOrMoveAt(const gfx::Point& viewport_point,
-                                         TouchAction* out_touch_action) = 0;
+                                         TouchAction* out_touch_action);
 
   // Calling `CreateLatencyInfoSwapPromiseMonitor()` to get a scoped
   // `LatencyInfoSwapPromiseMonitor`. During the life time of the
@@ -351,7 +362,7 @@
   // `SetNeedsRedrawRect()` is called on `LayerTreeHostImpl`, the original
   // latency info will be turned into a `LatencyInfoSwapPromise`.
   virtual std::unique_ptr<LatencyInfoSwapPromiseMonitor>
-  CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency) = 0;
+  CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency);
 
   // Returns a new instance of `EventsMetricsManager::ScopedMonitor` to monitor
   // the scope of handling an event. If `done_callback` is not a null callback,
@@ -364,19 +375,18 @@
   // it.
   virtual std::unique_ptr<EventsMetricsManager::ScopedMonitor>
   GetScopedEventMetricsMonitor(
-      EventsMetricsManager::ScopedMonitor::DoneCallback done_callback) = 0;
+      EventsMetricsManager::ScopedMonitor::DoneCallback done_callback);
 
-  virtual ScrollElasticityHelper* CreateScrollElasticityHelper() = 0;
-  virtual void DestroyScrollElasticityHelper() = 0;
+  virtual ScrollElasticityHelper* CreateScrollElasticityHelper();
+  virtual void DestroyScrollElasticityHelper();
 
   // Called by the single-threaded UI Compositor to get or set the scroll offset
   // on the impl side. Returns false if |element_id| isn't in the active tree.
   virtual bool GetScrollOffsetForLayer(ElementId element_id,
-                                       gfx::PointF* offset) = 0;
-  virtual bool ScrollLayerTo(ElementId element_id,
-                             const gfx::PointF& offset) = 0;
+                                       gfx::PointF* offset);
+  virtual bool ScrollLayerTo(ElementId element_id, const gfx::PointF& offset);
 
-  virtual bool ScrollingShouldSwitchtoMainThread() = 0;
+  virtual bool ScrollingShouldSwitchtoMainThread();
 
   // Sets the initial and target offset for scroll snapping for the currently
   // scrolling node and the given natural displacement. Also sets the target
@@ -387,27 +397,380 @@
   virtual bool GetSnapFlingInfoAndSetAnimatingSnapTarget(
       const gfx::Vector2dF& natural_displacement_in_viewport,
       gfx::PointF* initial_offset,
-      gfx::PointF* target_offset) = 0;
+      gfx::PointF* target_offset);
 
   // |did_finish| is true if the animation reached its target position (i.e.
   // it wasn't aborted).
-  virtual void ScrollEndForSnapFling(bool did_finish) = 0;
+  virtual void ScrollEndForSnapFling(bool did_finish);
 
   // Notifies when any input event is received, irrespective of whether it is
   // being handled by the InputHandler or not.
-  virtual void NotifyInputEvent() = 0;
+  virtual void NotifyInputEvent();
 
   // Returns true if ScrollbarController is in the middle of a scroll operation.
-  virtual bool ScrollbarScrollIsActive() = 0;
+  virtual bool ScrollbarScrollIsActive();
 
   // Defers posting BeginMainFrame tasks. This is used during the main thread
   // hit test for a GestureScrollBegin, to avoid posting a frame before the
   // compositor thread has had a chance to update the scroll offset.
-  virtual void SetDeferBeginMainFrame(bool defer_begin_main_frame) const = 0;
+  virtual void SetDeferBeginMainFrame(bool defer_begin_main_frame) const;
 
- protected:
-  virtual ~InputHandler() = default;
-  InputHandler() = default;
+  bool CanConsumeDelta(const ScrollState& scroll_state,
+                       const ScrollNode& scroll_node);
+  // Returns the amount of delta that can be applied to scroll_node, taking
+  // page scale into account.
+  gfx::Vector2dF ComputeScrollDelta(const ScrollNode& scroll_node,
+                                    const gfx::Vector2dF& delta);
+
+  gfx::Vector2dF ScrollSingleNode(const ScrollNode& scroll_node,
+                                  const gfx::Vector2dF& delta,
+                                  const gfx::Point& viewport_point,
+                                  bool is_direct_manipulation);
+
+  float LineStep() const;
+
+  // Resolves a delta in the given granularity for the |scroll_node| into
+  // physical pixels to scroll.
+  gfx::Vector2dF ResolveScrollGranularityToPixels(
+      const ScrollNode& scroll_node,
+      const gfx::Vector2dF& scroll_delta,
+      ui::ScrollGranularity granularity);
+
+  // Used to set the pinch gesture active state when the pinch gesture is
+  // handled on another layer tree. In a page with OOPIFs, only the main
+  // frame's layer tree directly handles pinch events. But layer trees for
+  // sub-frames need to know when pinch gestures are active so they can
+  // throttle the re-rastering. This function allows setting this flag on
+  // OOPIF layer trees using information sent (initially) from the main-frame.
+  void set_external_pinch_gesture_active(bool external_pinch_gesture_active) {
+    external_pinch_gesture_active_ = external_pinch_gesture_active;
+    // Only one of the flags should ever be true at any given time.
+    DCHECK(!pinch_gesture_active_ || !external_pinch_gesture_active_);
+  }
+
+  bool pinch_gesture_active() const {
+    return pinch_gesture_active_ || external_pinch_gesture_active_;
+  }
+
+  void set_force_smooth_wheel_scrolling_for_testing(bool enabled) {
+    force_smooth_wheel_scrolling_for_testing_ = enabled;
+  }
+
+  gfx::Vector2dF accumulated_root_overscroll_for_testing() const {
+    return accumulated_root_overscroll_;
+  }
+
+  bool animating_for_snap_for_testing() const { return IsAnimatingForSnap(); }
+
+  // =========== InputDelegateForCompositor Interface - This section implements
+  // the interface that LayerTreeHostImpl uses to communicate with the input
+  // system.
+  void ProcessCommitDeltas(CompositorCommitData* commit_data) override;
+  void TickAnimations(base::TimeTicks monotonic_time) override;
+  void WillShutdown() override;
+  void WillDraw() override;
+  void WillBeginImplFrame(const viz::BeginFrameArgs& args) override;
+  void DidCommit() override;
+  void DidActivatePendingTree() override;
+  void RootLayerStateMayHaveChanged() override;
+  void DidRegisterScrollbar(ElementId scroll_element_id,
+                            ScrollbarOrientation orientation) override;
+  void DidUnregisterScrollbar(ElementId scroll_element_id,
+                              ScrollbarOrientation orientation) override;
+  void ScrollOffsetAnimationFinished() override;
+  void SetPrefersReducedMotion(bool prefers_reduced_motion) override;
+  bool IsCurrentlyScrolling() const override;
+  ActivelyScrollingType GetActivelyScrollingType() const override;
+
+ private:
+  FRIEND_TEST_ALL_PREFIXES(ScrollUnifiedLayerTreeHostImplTest,
+                           AbortAnimatedScrollBeforeStartingAutoscroll);
+  FRIEND_TEST_ALL_PREFIXES(ScrollUnifiedLayerTreeHostImplTest,
+                           AnimatedScrollYielding);
+  FRIEND_TEST_ALL_PREFIXES(ScrollUnifiedLayerTreeHostImplTest,
+                           AutoscrollOnDeletedScrollbar);
+  FRIEND_TEST_ALL_PREFIXES(ScrollUnifiedLayerTreeHostImplTest,
+                           ThumbDragAfterJumpClick);
+  FRIEND_TEST_ALL_PREFIXES(ScrollUnifiedLayerTreeHostImplTest,
+                           ScrollOnLargeThumb);
+  FRIEND_TEST_ALL_PREFIXES(LayerTreeHostImplTest, AutoscrollTaskAbort);
+
+  // This method gets the scroll offset for a regular scroller, or the combined
+  // visual and layout offsets of the viewport.
+  gfx::PointF GetVisualScrollOffset(const ScrollNode& scroll_node) const;
+  bool IsScrolledBy(LayerImpl* child, ScrollNode* ancestor);
+  bool IsAnimatingForSnap() const;
+
+  ScrollNode* CurrentlyScrollingNode();
+  const ScrollNode* CurrentlyScrollingNode() const;
+  void ClearCurrentlyScrollingNode();
+  ScrollTree& GetScrollTree();
+  ScrollTree& GetScrollTree() const;
+  Viewport& GetViewport() const;
+
+  ScrollNode* InnerViewportScrollNode() const;
+  ScrollNode* OuterViewportScrollNode() const;
+
+  void SetNeedsCommit();
+  LayerTreeImpl& ActiveTree();
+  LayerTreeImpl& ActiveTree() const;
+
+  bool IsMainThreadScrolling(const InputHandler::ScrollStatus& status,
+                             const ScrollNode* scroll_node) const;
+
+  bool IsTouchDraggingScrollbar(
+      LayerImpl* first_scrolling_layer_or_drawn_scrollbar,
+      ui::ScrollInputType type);
+
+  void UpdateRootLayerStateForSynchronousInputHandler();
+
+  // Called during ScrollBegin once a scroller was successfully latched to
+  // (i.e.  it can and will consume scroll delta on the compositor thread). The
+  // latched scroller is now available in CurrentlyScrollingNode().
+  // TODO(bokan): There's some debate about the name of this method. We should
+  // get consensus on terminology to use and apply it consistently.
+  // https://crrev.com/c/1981336/9/cc/trees/layer_tree_host_impl.cc#4520
+  void DidLatchToScroller(const ScrollState& scroll_state,
+                          ui::ScrollInputType type);
+
+  // This function keeps track of sources of scrolls that are handled in the
+  // compositor side. The information gets shared by the main thread as part of
+  // the begin_main_frame_state. Finally Use counters are updated in the main
+  // thread side to keep track of the frequency of scrolling with different
+  // sources per page load. TODO(crbug.com/691886): Use GRC API to plumb the
+  // scroll source info for Use Counters.
+  void UpdateScrollSourceInfo(const ScrollState& scroll_state,
+                              ui::ScrollInputType type);
+
+  // Applies the scroll_state to the currently latched scroller. See comment in
+  // InputHandler::ScrollUpdate declaration for the meaning of |delayed_by|.
+  void ScrollLatchedScroller(ScrollState* scroll_state,
+                             base::TimeDelta delayed_by);
+
+  // Determines whether the given scroll node can scroll on the compositor
+  // thread or if there are any reasons it must be scrolled on the main thread
+  // or not at all. Note: in general, this is not sufficient to determine if a
+  // scroll can occur on the compositor thread. If hit testing to a scroll
+  // node, the caller must also check whether the hit point intersects a
+  // non-fast-scrolling-region of any ancestor scrolling layers. Can be removed
+  // after scroll unification https://crbug.com/476553.
+  InputHandler::ScrollStatus TryScroll(const ScrollTree& scroll_tree,
+                                       ScrollNode* scroll_node) const;
+
+  enum class SnapReason { kGestureScrollEnd, kScrollOffsetAnimationFinished };
+
+  // Creates an animation curve and returns true if we need to update the
+  // scroll position to a snap point. Otherwise returns false.
+  bool SnapAtScrollEnd(SnapReason reason);
+
+  // |layer| is returned from a regular hit test, and
+  // |first_scrolling_layer_or_drawn_scrollbar| is returned from a hit test
+  // performed only on scrollers and scrollbars. Initial scroll hit testing can
+  // be unreliable if the latter is not the direct scroll ancestor of the
+  // former. In this case, we will fall back to main thread scrolling because
+  // the compositor thread doesn't know which layer to scroll. This happens when
+  // a layer covers a scroller that doesn't scroll the former, or a scroller is
+  // masked by a mask layer for mask image, clip-path, rounded border, etc.
+  //
+  // Note, position: fixed layers use the inner viewport as their ScrollNode
+  // (since they don't scroll with the outer viewport), however, scrolls from
+  // the fixed layer still chain to the outer viewport. It's also possible for a
+  // node to have the inner viewport as its ancestor without going through the
+  // outer viewport; however, it may still scroll using the viewport(). Hence,
+  // this method must use the same scroll chaining logic we use in ApplyScroll.
+  bool IsInitialScrollHitTestReliable(
+      const LayerImpl* layer,
+      const LayerImpl* first_scrolling_layer_or_drawn_scrollbar) const;
+
+  // Similar to above but includes complicated logic to determine whether the
+  // ScrollNode is able to be scrolled on the compositor or requires main
+  // thread scrolling. If main thread scrolling is required
+  // |scroll_on_main_thread| is set to true and the reason is given in
+  // |main_thread_scrolling_reason| to on of the enum values in
+  // main_thread_scrolling_reason.h. Can be removed after scroll unification
+  // https://crbug.com/476553.
+  ScrollNode* FindScrollNodeForCompositedScrolling(
+      const gfx::PointF& device_viewport_point,
+      LayerImpl* layer_hit_by_point,
+      bool* scroll_on_main_thread,
+      uint32_t* main_thread_scrolling_reason);
+
+  // Return all ScrollNode indices that have an associated layer with a non-fast
+  // region that intersects the point.
+  base::flat_set<int> NonFastScrollableNodes(
+      const gfx::PointF& device_viewport_point) const;
+
+  // Returns the ScrollNode we should use to scroll, accounting for viewport
+  // scroll chaining rules.
+  ScrollNode* GetNodeToScroll(ScrollNode* node) const;
+
+  // Given a starting node (determined by hit-test), walks up the scroll tree
+  // looking for the first node that can consume scroll from the given
+  // scroll_state and returns the first such node. If none is found, or if
+  // starting_node is nullptr, returns nullptr;
+  ScrollNode* FindNodeToLatch(ScrollState* scroll_state,
+                              ScrollNode* starting_node,
+                              ui::ScrollInputType type);
+
+  bool CanPropagate(ScrollNode* scroll_node, float x, float y);
+
+  // Performs a hit test to determine the ScrollNode to use when scrolling at
+  // |viewport_point|. If no layer is hit, this falls back to the inner
+  // viewport scroll node. Returns:
+  // - If |hit_test_sucessful| is false, hit testing has failed and the
+  //   compositor cannot determine the correct scroll node (e.g. see comments in
+  //   IsInitialScrollHitTestReliable). |scroll_node| is always nullptr in this
+  //   case.
+  // - If |hit_test_successful| is true, returns the ScrollNode to use in
+  //   |scroll_node|. This can be nullptr if no layer was hit and there are no
+  //   viewport nodes (e.g. OOPIF, UI compositor).
+  struct ScrollHitTestResult {
+    ScrollNode* scroll_node;
+    bool hit_test_successful;
+  };
+  ScrollHitTestResult HitTestScrollNode(
+      const gfx::PointF& device_viewport_point) const;
+
+  bool ShouldAnimateScroll(const ScrollState& scroll_state) const;
+
+  bool ScrollAnimationUpdateTarget(const ScrollNode& scroll_node,
+                                   const gfx::Vector2dF& scroll_delta,
+                                   base::TimeDelta delayed_by);
+
+  // Transforms viewport start point and scroll delta to local start point and
+  // local delta, respectively. If the transformation of either the start or end
+  // point of a scroll is clipped, the function returns false.
+  bool CalculateLocalScrollDeltaAndStartPoint(
+      const ScrollNode& scroll_node,
+      const gfx::PointF& viewport_point,
+      const gfx::Vector2dF& viewport_delta,
+      gfx::Vector2dF* out_local_scroll_delta,
+      gfx::PointF* out_local_start_point = nullptr);
+  gfx::Vector2dF ScrollNodeWithViewportSpaceDelta(
+      const ScrollNode& scroll_node,
+      const gfx::PointF& viewport_point,
+      const gfx::Vector2dF& viewport_delta);
+  gfx::Vector2dF ScrollNodeWithLocalDelta(
+      const ScrollNode& scroll_node,
+      const gfx::Vector2dF& local_delta) const;
+  // This helper returns an adjusted version of |delta| where the scroll delta
+  // is cleared in any axis in which user scrolling is disabled (e.g. by
+  // |overflow-x: hidden|).
+  gfx::Vector2dF UserScrollableDelta(const ScrollNode& node,
+                                     const gfx::Vector2dF& delta) const;
+
+  void AdjustScrollDeltaForScrollbarSnap(ScrollState* scroll_state);
+
+  FrameSequenceTrackerType GetTrackerTypeForScroll(
+      ui::ScrollInputType input_type) const;
+
+  ScrollbarController* scrollbar_controller_for_testing() const {
+    return scrollbar_controller_.get();
+  }
+
+  // The input handler is owned by the delegate so their lifetimes are tied
+  // together.
+  CompositorDelegateForInput& compositor_delegate_;
+
+  raw_ptr<InputHandlerClient, DanglingUntriaged> input_handler_client_ =
+      nullptr;
+
+  // An object to implement the ScrollElasticityHelper interface and
+  // hold all state related to elasticity. May be nullptr if never requested.
+  std::unique_ptr<ScrollElasticityHelper> scroll_elasticity_helper_;
+
+  // Manages composited scrollbar hit testing.
+  std::unique_ptr<ScrollbarController> scrollbar_controller_;
+
+  // Overscroll delta accumulated on the viewport throughout a scroll gesture;
+  // reset when the gesture ends.
+  gfx::Vector2dF accumulated_root_overscroll_;
+
+  // Unconsumed scroll delta sent to the main thread for firing overscroll DOM
+  // events. Resets after each commit.
+  gfx::Vector2dF overscroll_delta_for_main_thread_;
+
+  // The source device type that started the scroll gesture. Only set between a
+  // ScrollBegin and ScrollEnd.
+  absl::optional<ui::ScrollInputType> latched_scroll_type_;
+
+  // Tracks the last scroll update/begin state received. Used to infer the most
+  // recent scroll type and direction.
+  absl::optional<ScrollState> last_scroll_begin_state_;
+  absl::optional<ScrollState> last_scroll_update_state_;
+
+  // If a scroll snap is being animated, then the value of this will be the
+  // element id(s) of the target(s). Otherwise, the ids will be invalid.
+  // At the end of a scroll animation, the target should be set as the scroll
+  // node's snap target.
+  TargetSnapAreaElementIds scroll_animating_snap_target_ids_;
+
+  // A set of elements that scroll-snapped to a new target since the last
+  // begin main frame. The snap target ids of these elements will be sent to
+  // the main thread in the next begin main frame.
+  base::flat_map<ElementId, TargetSnapAreaElementIds> updated_snapped_elements_;
+
+  ElementId scroll_element_id_mouse_currently_over_;
+  ElementId scroll_element_id_mouse_currently_captured_;
+
+  // Set in ScrollBegin and outlives the currently scrolling node so it can be
+  // used to send the scrollend and overscroll DOM events from the main thread
+  // when scrolling occurs on the compositor thread. This value is cleared at
+  // the first commit after a GSE.
+  ElementId last_latched_scroller_;
+
+  // Scroll animation can finish either before or after GSE arrival.
+  // deferred_scroll_end_ is set when the GSE has arrvied before scroll
+  // animation completion. ScrollEnd will get called once the animation is
+  // over.
+  bool deferred_scroll_end_ = false;
+
+  // Set to true when a scroll gesture being handled on the compositor has
+  // ended. i.e. When a GSE has arrived and any ongoing scroll animation has
+  // ended.
+  bool scroll_gesture_did_end_ = false;
+
+  // True iff some of the delta has been consumed for the current scroll
+  // sequence on the specific axis.
+  bool did_scroll_x_for_scroll_gesture_ = false;
+  bool did_scroll_y_for_scroll_gesture_ = false;
+
+  // did_scroll_x/y_for_scroll_gesture_ is true when contents consume the delta,
+  // but delta_consumed_for_scroll_gesture_ can be true when only browser
+  // controls consume all the delta.
+  bool delta_consumed_for_scroll_gesture_ = false;
+
+  // TODO(bokan): Mac doesn't yet have smooth scrolling for wheel; however, to
+  // allow consistency in tests we use this bit to override that decision.
+  // https://crbug.com/574283.
+  bool force_smooth_wheel_scrolling_for_testing_ = false;
+
+  // This value is used to allow the compositor to throttle re-rastering during
+  // pinch gestures, when the page scale factor may be changing frequently. It
+  // is set in one of two ways:
+  // i) In a layer tree serving the root of the frame/compositor tree, it is
+  // directly set during processing of GesturePinch events on the impl thread
+  // (only the root layer tree has access to these).
+  // ii) In a layer tree serving a sub-frame in the frame/compositor tree, it
+  // is set from the main thread during the commit process, using information
+  // sent from the root layer tree via IPC messaging.
+  bool pinch_gesture_active_ = false;
+  bool external_pinch_gesture_active_ = false;
+  bool pinch_gesture_end_should_clear_scrolling_node_ = false;
+
+  // These are used to transfer usage of different types of scrolling to the
+  // main thread.
+  bool has_pinch_zoomed_ = false;
+  bool has_scrolled_by_wheel_ = false;
+  bool has_scrolled_by_touch_ = false;
+  bool has_scrolled_by_precisiontouchpad_ = false;
+  bool has_scrolled_by_scrollbar_ = false;
+
+  bool prefers_reduced_motion_ = false;
+
+  // Must be the last member to ensure this is destroyed first in the
+  // destruction order and invalidates all weak pointers.
+  base::WeakPtrFactory<InputHandler> weak_factory_{this};
 };
 
 }  // namespace cc
diff --git a/cc/input/threaded_input_handler.h b/cc/input/threaded_input_handler.h
deleted file mode 100644
index f2e6f974..0000000
--- a/cc/input/threaded_input_handler.h
+++ /dev/null
@@ -1,473 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_INPUT_THREADED_INPUT_HANDLER_H_
-#define CC_INPUT_THREADED_INPUT_HANDLER_H_
-
-#include <memory>
-
-#include "base/containers/flat_set.h"
-#include "base/gtest_prod_util.h"
-#include "base/memory/raw_ptr.h"
-#include "base/time/time.h"
-#include "cc/input/compositor_input_interfaces.h"
-#include "cc/input/event_listener_properties.h"
-#include "cc/input/input_handler.h"
-#include "cc/input/scroll_snap_data.h"
-#include "cc/input/scroll_state.h"
-#include "cc/input/touch_action.h"
-#include "cc/metrics/events_metrics_manager.h"
-#include "cc/metrics/frame_sequence_metrics.h"
-#include "cc/paint/element_id.h"
-#include "components/viz/common/frame_sinks/begin_frame_args.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "ui/events/types/scroll_input_type.h"
-
-namespace gfx {
-class Point;
-class PointF;
-class Vector2dF;
-}  // namespace gfx
-
-namespace cc {
-
-class LatencyInfoSwapPromiseMonitor;
-class LayerImpl;
-class ScrollbarController;
-class ScrollElasticityHelper;
-struct ScrollNode;
-class ScrollTree;
-class Viewport;
-
-class CC_EXPORT ThreadedInputHandler : public InputHandler,
-                                       public InputDelegateForCompositor {
- public:
-  explicit ThreadedInputHandler(
-      CompositorDelegateForInput& compositor_delegate);
-  ~ThreadedInputHandler() override;
-
-  // =========== InputHandler "Interface" - will override in a future CL
-  base::WeakPtr<InputHandler> AsWeakPtr() const override;
-  void BindToClient(InputHandlerClient* client) override;
-  InputHandler::ScrollStatus ScrollBegin(ScrollState* scroll_state,
-                                         ui::ScrollInputType type) override;
-  InputHandler::ScrollStatus RootScrollBegin(ScrollState* scroll_state,
-                                             ui::ScrollInputType type) override;
-  InputHandlerScrollResult ScrollUpdate(
-      ScrollState* scroll_state,
-      base::TimeDelta delayed_by = base::TimeDelta()) override;
-  void ScrollEnd(bool should_snap = false) override;
-  PointerResultType HitTest(const gfx::PointF& viewport_point) override;
-  void RecordScrollBegin(ui::ScrollInputType input_type,
-                         ScrollBeginThreadState scroll_start_state) override;
-  void RecordScrollEnd(ui::ScrollInputType input_type) override;
-  InputHandlerPointerResult MouseMoveAt(
-      const gfx::Point& viewport_point) override;
-  InputHandlerPointerResult MouseDown(const gfx::PointF& viewport_point,
-                                      bool shift_modifier) override;
-  InputHandlerPointerResult MouseUp(const gfx::PointF& viewport_point) override;
-  void MouseLeave() override;
-  ElementId FindFrameElementIdAtPoint(
-      const gfx::PointF& viewport_point) override;
-  void RequestUpdateForSynchronousInputHandler() override;
-  void SetSynchronousInputHandlerRootScrollOffset(
-      const gfx::PointF& root_content_offset) override;
-  void PinchGestureBegin(const gfx::Point& anchor,
-                         ui::ScrollInputType source) override;
-  void PinchGestureUpdate(float magnify_delta,
-                          const gfx::Point& anchor) override;
-  void PinchGestureEnd(const gfx::Point& anchor) override;
-  void SetNeedsAnimateInput() override;
-  bool IsCurrentlyScrollingViewport() const override;
-  EventListenerProperties GetEventListenerProperties(
-      EventListenerClass event_class) const override;
-  bool HasBlockingWheelEventHandlerAt(
-      const gfx::Point& viewport_point) const override;
-  InputHandler::TouchStartOrMoveEventListenerType
-  EventListenerTypeForTouchStartOrMoveAt(
-      const gfx::Point& viewport_port,
-      TouchAction* out_touch_action) override;
-  std::unique_ptr<LatencyInfoSwapPromiseMonitor>
-  CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency) override;
-  std::unique_ptr<EventsMetricsManager::ScopedMonitor>
-  GetScopedEventMetricsMonitor(
-      EventsMetricsManager::ScopedMonitor::DoneCallback done_callback) override;
-  ScrollElasticityHelper* CreateScrollElasticityHelper() override;
-  void DestroyScrollElasticityHelper() override;
-  bool GetScrollOffsetForLayer(ElementId element_id,
-                               gfx::PointF* offset) override;
-  bool ScrollLayerTo(ElementId element_id, const gfx::PointF& offset) override;
-  bool ScrollingShouldSwitchtoMainThread() override;
-  bool GetSnapFlingInfoAndSetAnimatingSnapTarget(
-      const gfx::Vector2dF& natural_displacement_in_viewport,
-      gfx::PointF* out_initial_position,
-      gfx::PointF* out_target_position) override;
-  void ScrollEndForSnapFling(bool did_finish) override;
-  void NotifyInputEvent() override;
-  bool ScrollbarScrollIsActive() override;
-  void SetDeferBeginMainFrame(bool defer_begin_main_frame) const override;
-
-  // =========== InputDelegateForCompositor Interface - This section implements
-  // the interface that LayerTreeHostImpl uses to communicate with the input
-  // system.
-  void ProcessCommitDeltas(CompositorCommitData* commit_data) override;
-  void TickAnimations(base::TimeTicks monotonic_time) override;
-  void WillShutdown() override;
-  void WillDraw() override;
-  void WillBeginImplFrame(const viz::BeginFrameArgs& args) override;
-  void DidCommit() override;
-  void DidActivatePendingTree() override;
-  void RootLayerStateMayHaveChanged() override;
-  void DidRegisterScrollbar(ElementId scroll_element_id,
-                            ScrollbarOrientation orientation) override;
-  void DidUnregisterScrollbar(ElementId scroll_element_id,
-                              ScrollbarOrientation orientation) override;
-  void ScrollOffsetAnimationFinished() override;
-  void SetPrefersReducedMotion(bool prefers_reduced_motion) override;
-  bool IsCurrentlyScrolling() const override;
-  ActivelyScrollingType GetActivelyScrollingType() const override;
-
-  // =========== Public Interface
-
-  bool CanConsumeDelta(const ScrollState& scroll_state,
-                       const ScrollNode& scroll_node);
-  // Returns the amount of delta that can be applied to scroll_node, taking
-  // page scale into account.
-  gfx::Vector2dF ComputeScrollDelta(const ScrollNode& scroll_node,
-                                    const gfx::Vector2dF& delta);
-
-  gfx::Vector2dF ScrollSingleNode(const ScrollNode& scroll_node,
-                                  const gfx::Vector2dF& delta,
-                                  const gfx::Point& viewport_point,
-                                  bool is_direct_manipulation);
-
-  float LineStep() const;
-
-  // Resolves a delta in the given granularity for the |scroll_node| into
-  // physical pixels to scroll.
-  gfx::Vector2dF ResolveScrollGranularityToPixels(
-      const ScrollNode& scroll_node,
-      const gfx::Vector2dF& scroll_delta,
-      ui::ScrollGranularity granularity);
-
-  // Used to set the pinch gesture active state when the pinch gesture is
-  // handled on another layer tree. In a page with OOPIFs, only the main
-  // frame's layer tree directly handles pinch events. But layer trees for
-  // sub-frames need to know when pinch gestures are active so they can
-  // throttle the re-rastering. This function allows setting this flag on
-  // OOPIF layer trees using information sent (initially) from the main-frame.
-  void set_external_pinch_gesture_active(bool external_pinch_gesture_active) {
-    external_pinch_gesture_active_ = external_pinch_gesture_active;
-    // Only one of the flags should ever be true at any given time.
-    DCHECK(!pinch_gesture_active_ || !external_pinch_gesture_active_);
-  }
-
-  bool pinch_gesture_active() const {
-    return pinch_gesture_active_ || external_pinch_gesture_active_;
-  }
-
-  void set_force_smooth_wheel_scrolling_for_testing(bool enabled) {
-    force_smooth_wheel_scrolling_for_testing_ = enabled;
-  }
-
-  gfx::Vector2dF accumulated_root_overscroll_for_testing() const {
-    return accumulated_root_overscroll_;
-  }
-
-  bool animating_for_snap_for_testing() const { return IsAnimatingForSnap(); }
-
- private:
-  FRIEND_TEST_ALL_PREFIXES(ScrollUnifiedLayerTreeHostImplTest,
-                           AbortAnimatedScrollBeforeStartingAutoscroll);
-  FRIEND_TEST_ALL_PREFIXES(ScrollUnifiedLayerTreeHostImplTest,
-                           AnimatedScrollYielding);
-  FRIEND_TEST_ALL_PREFIXES(ScrollUnifiedLayerTreeHostImplTest,
-                           AutoscrollOnDeletedScrollbar);
-  FRIEND_TEST_ALL_PREFIXES(ScrollUnifiedLayerTreeHostImplTest,
-                           ThumbDragAfterJumpClick);
-  FRIEND_TEST_ALL_PREFIXES(ScrollUnifiedLayerTreeHostImplTest,
-                           ScrollOnLargeThumb);
-  FRIEND_TEST_ALL_PREFIXES(LayerTreeHostImplTest, AutoscrollTaskAbort);
-
-  // This method gets the scroll offset for a regular scroller, or the combined
-  // visual and layout offsets of the viewport.
-  gfx::PointF GetVisualScrollOffset(const ScrollNode& scroll_node) const;
-  bool IsScrolledBy(LayerImpl* child, ScrollNode* ancestor);
-  bool IsAnimatingForSnap() const;
-
-  ScrollNode* CurrentlyScrollingNode();
-  const ScrollNode* CurrentlyScrollingNode() const;
-  void ClearCurrentlyScrollingNode();
-  ScrollTree& GetScrollTree();
-  ScrollTree& GetScrollTree() const;
-  Viewport& GetViewport() const;
-
-  ScrollNode* InnerViewportScrollNode() const;
-  ScrollNode* OuterViewportScrollNode() const;
-
-  void SetNeedsCommit();
-  LayerTreeImpl& ActiveTree();
-  LayerTreeImpl& ActiveTree() const;
-
-  bool IsMainThreadScrolling(const InputHandler::ScrollStatus& status,
-                             const ScrollNode* scroll_node) const;
-
-  bool IsTouchDraggingScrollbar(
-      LayerImpl* first_scrolling_layer_or_drawn_scrollbar,
-      ui::ScrollInputType type);
-
-  void UpdateRootLayerStateForSynchronousInputHandler();
-
-  // Called during ScrollBegin once a scroller was successfully latched to
-  // (i.e.  it can and will consume scroll delta on the compositor thread). The
-  // latched scroller is now available in CurrentlyScrollingNode().
-  // TODO(bokan): There's some debate about the name of this method. We should
-  // get consensus on terminology to use and apply it consistently.
-  // https://crrev.com/c/1981336/9/cc/trees/layer_tree_host_impl.cc#4520
-  void DidLatchToScroller(const ScrollState& scroll_state,
-                          ui::ScrollInputType type);
-
-  // This function keeps track of sources of scrolls that are handled in the
-  // compositor side. The information gets shared by the main thread as part of
-  // the begin_main_frame_state. Finally Use counters are updated in the main
-  // thread side to keep track of the frequency of scrolling with different
-  // sources per page load. TODO(crbug.com/691886): Use GRC API to plumb the
-  // scroll source info for Use Counters.
-  void UpdateScrollSourceInfo(const ScrollState& scroll_state,
-                              ui::ScrollInputType type);
-
-  // Applies the scroll_state to the currently latched scroller. See comment in
-  // InputHandler::ScrollUpdate declaration for the meaning of |delayed_by|.
-  void ScrollLatchedScroller(ScrollState* scroll_state,
-                             base::TimeDelta delayed_by);
-
-  // Determines whether the given scroll node can scroll on the compositor
-  // thread or if there are any reasons it must be scrolled on the main thread
-  // or not at all. Note: in general, this is not sufficient to determine if a
-  // scroll can occur on the compositor thread. If hit testing to a scroll
-  // node, the caller must also check whether the hit point intersects a
-  // non-fast-scrolling-region of any ancestor scrolling layers. Can be removed
-  // after scroll unification https://crbug.com/476553.
-  InputHandler::ScrollStatus TryScroll(const ScrollTree& scroll_tree,
-                                       ScrollNode* scroll_node) const;
-
-  enum class SnapReason { kGestureScrollEnd, kScrollOffsetAnimationFinished };
-
-  // Creates an animation curve and returns true if we need to update the
-  // scroll position to a snap point. Otherwise returns false.
-  bool SnapAtScrollEnd(SnapReason reason);
-
-  // |layer| is returned from a regular hit test, and
-  // |first_scrolling_layer_or_drawn_scrollbar| is returned from a hit test
-  // performed only on scrollers and scrollbars. Initial scroll hit testing can
-  // be unreliable if the latter is not the direct scroll ancestor of the
-  // former. In this case, we will fall back to main thread scrolling because
-  // the compositor thread doesn't know which layer to scroll. This happens when
-  // a layer covers a scroller that doesn't scroll the former, or a scroller is
-  // masked by a mask layer for mask image, clip-path, rounded border, etc.
-  //
-  // Note, position: fixed layers use the inner viewport as their ScrollNode
-  // (since they don't scroll with the outer viewport), however, scrolls from
-  // the fixed layer still chain to the outer viewport. It's also possible for a
-  // node to have the inner viewport as its ancestor without going through the
-  // outer viewport; however, it may still scroll using the viewport(). Hence,
-  // this method must use the same scroll chaining logic we use in ApplyScroll.
-  bool IsInitialScrollHitTestReliable(
-      const LayerImpl* layer,
-      const LayerImpl* first_scrolling_layer_or_drawn_scrollbar) const;
-
-  // Similar to above but includes complicated logic to determine whether the
-  // ScrollNode is able to be scrolled on the compositor or requires main
-  // thread scrolling. If main thread scrolling is required
-  // |scroll_on_main_thread| is set to true and the reason is given in
-  // |main_thread_scrolling_reason| to on of the enum values in
-  // main_thread_scrolling_reason.h. Can be removed after scroll unification
-  // https://crbug.com/476553.
-  ScrollNode* FindScrollNodeForCompositedScrolling(
-      const gfx::PointF& device_viewport_point,
-      LayerImpl* layer_hit_by_point,
-      bool* scroll_on_main_thread,
-      uint32_t* main_thread_scrolling_reason);
-
-  // Return all ScrollNode indices that have an associated layer with a non-fast
-  // region that intersects the point.
-  base::flat_set<int> NonFastScrollableNodes(
-      const gfx::PointF& device_viewport_point) const;
-
-  // Returns the ScrollNode we should use to scroll, accounting for viewport
-  // scroll chaining rules.
-  ScrollNode* GetNodeToScroll(ScrollNode* node) const;
-
-  // Given a starting node (determined by hit-test), walks up the scroll tree
-  // looking for the first node that can consume scroll from the given
-  // scroll_state and returns the first such node. If none is found, or if
-  // starting_node is nullptr, returns nullptr;
-  ScrollNode* FindNodeToLatch(ScrollState* scroll_state,
-                              ScrollNode* starting_node,
-                              ui::ScrollInputType type);
-
-  bool CanPropagate(ScrollNode* scroll_node, float x, float y);
-
-  // Performs a hit test to determine the ScrollNode to use when scrolling at
-  // |viewport_point|. If no layer is hit, this falls back to the inner
-  // viewport scroll node. Returns:
-  // - If |hit_test_sucessful| is false, hit testing has failed and the
-  //   compositor cannot determine the correct scroll node (e.g. see comments in
-  //   IsInitialScrollHitTestReliable). |scroll_node| is always nullptr in this
-  //   case.
-  // - If |hit_test_successful| is true, returns the ScrollNode to use in
-  //   |scroll_node|. This can be nullptr if no layer was hit and there are no
-  //   viewport nodes (e.g. OOPIF, UI compositor).
-  struct ScrollHitTestResult {
-    ScrollNode* scroll_node;
-    bool hit_test_successful;
-  };
-  ScrollHitTestResult HitTestScrollNode(
-      const gfx::PointF& device_viewport_point) const;
-
-  bool ShouldAnimateScroll(const ScrollState& scroll_state) const;
-
-  bool ScrollAnimationUpdateTarget(const ScrollNode& scroll_node,
-                                   const gfx::Vector2dF& scroll_delta,
-                                   base::TimeDelta delayed_by);
-
-  // Transforms viewport start point and scroll delta to local start point and
-  // local delta, respectively. If the transformation of either the start or end
-  // point of a scroll is clipped, the function returns false.
-  bool CalculateLocalScrollDeltaAndStartPoint(
-      const ScrollNode& scroll_node,
-      const gfx::PointF& viewport_point,
-      const gfx::Vector2dF& viewport_delta,
-      gfx::Vector2dF* out_local_scroll_delta,
-      gfx::PointF* out_local_start_point = nullptr);
-  gfx::Vector2dF ScrollNodeWithViewportSpaceDelta(
-      const ScrollNode& scroll_node,
-      const gfx::PointF& viewport_point,
-      const gfx::Vector2dF& viewport_delta);
-  gfx::Vector2dF ScrollNodeWithLocalDelta(
-      const ScrollNode& scroll_node,
-      const gfx::Vector2dF& local_delta) const;
-  // This helper returns an adjusted version of |delta| where the scroll delta
-  // is cleared in any axis in which user scrolling is disabled (e.g. by
-  // |overflow-x: hidden|).
-  gfx::Vector2dF UserScrollableDelta(const ScrollNode& node,
-                                     const gfx::Vector2dF& delta) const;
-
-  void AdjustScrollDeltaForScrollbarSnap(ScrollState* scroll_state);
-
-  FrameSequenceTrackerType GetTrackerTypeForScroll(
-      ui::ScrollInputType input_type) const;
-
-  ScrollbarController* scrollbar_controller_for_testing() const {
-    return scrollbar_controller_.get();
-  }
-
-  // The input handler is owned by the delegate so their lifetimes are tied
-  // together.
-  CompositorDelegateForInput& compositor_delegate_;
-
-  raw_ptr<InputHandlerClient, DanglingUntriaged> input_handler_client_ =
-      nullptr;
-
-  // An object to implement the ScrollElasticityHelper interface and
-  // hold all state related to elasticity. May be nullptr if never requested.
-  std::unique_ptr<ScrollElasticityHelper> scroll_elasticity_helper_;
-
-  // Manages composited scrollbar hit testing.
-  std::unique_ptr<ScrollbarController> scrollbar_controller_;
-
-  // Overscroll delta accumulated on the viewport throughout a scroll gesture;
-  // reset when the gesture ends.
-  gfx::Vector2dF accumulated_root_overscroll_;
-
-  // Unconsumed scroll delta sent to the main thread for firing overscroll DOM
-  // events. Resets after each commit.
-  gfx::Vector2dF overscroll_delta_for_main_thread_;
-
-  // The source device type that started the scroll gesture. Only set between a
-  // ScrollBegin and ScrollEnd.
-  absl::optional<ui::ScrollInputType> latched_scroll_type_;
-
-  // Tracks the last scroll update/begin state received. Used to infer the most
-  // recent scroll type and direction.
-  absl::optional<ScrollState> last_scroll_begin_state_;
-  absl::optional<ScrollState> last_scroll_update_state_;
-
-  // If a scroll snap is being animated, then the value of this will be the
-  // element id(s) of the target(s). Otherwise, the ids will be invalid.
-  // At the end of a scroll animation, the target should be set as the scroll
-  // node's snap target.
-  TargetSnapAreaElementIds scroll_animating_snap_target_ids_;
-
-  // A set of elements that scroll-snapped to a new target since the last
-  // begin main frame. The snap target ids of these elements will be sent to
-  // the main thread in the next begin main frame.
-  base::flat_map<ElementId, TargetSnapAreaElementIds> updated_snapped_elements_;
-
-  ElementId scroll_element_id_mouse_currently_over_;
-  ElementId scroll_element_id_mouse_currently_captured_;
-
-  // Set in ScrollBegin and outlives the currently scrolling node so it can be
-  // used to send the scrollend and overscroll DOM events from the main thread
-  // when scrolling occurs on the compositor thread. This value is cleared at
-  // the first commit after a GSE.
-  ElementId last_latched_scroller_;
-
-  // Scroll animation can finish either before or after GSE arrival.
-  // deferred_scroll_end_ is set when the GSE has arrvied before scroll
-  // animation completion. ScrollEnd will get called once the animation is
-  // over.
-  bool deferred_scroll_end_ = false;
-
-  // Set to true when a scroll gesture being handled on the compositor has
-  // ended. i.e. When a GSE has arrived and any ongoing scroll animation has
-  // ended.
-  bool scroll_gesture_did_end_ = false;
-
-  // True iff some of the delta has been consumed for the current scroll
-  // sequence on the specific axis.
-  bool did_scroll_x_for_scroll_gesture_ = false;
-  bool did_scroll_y_for_scroll_gesture_ = false;
-
-  // did_scroll_x/y_for_scroll_gesture_ is true when contents consume the delta,
-  // but delta_consumed_for_scroll_gesture_ can be true when only browser
-  // controls consume all the delta.
-  bool delta_consumed_for_scroll_gesture_ = false;
-
-  // TODO(bokan): Mac doesn't yet have smooth scrolling for wheel; however, to
-  // allow consistency in tests we use this bit to override that decision.
-  // https://crbug.com/574283.
-  bool force_smooth_wheel_scrolling_for_testing_ = false;
-
-  // This value is used to allow the compositor to throttle re-rastering during
-  // pinch gestures, when the page scale factor may be changing frequently. It
-  // is set in one of two ways:
-  // i) In a layer tree serving the root of the frame/compositor tree, it is
-  // directly set during processing of GesturePinch events on the impl thread
-  // (only the root layer tree has access to these).
-  // ii) In a layer tree serving a sub-frame in the frame/compositor tree, it
-  // is set from the main thread during the commit process, using information
-  // sent from the root layer tree via IPC messaging.
-  bool pinch_gesture_active_ = false;
-  bool external_pinch_gesture_active_ = false;
-  bool pinch_gesture_end_should_clear_scrolling_node_ = false;
-
-  // These are used to transfer usage of different types of scrolling to the
-  // main thread.
-  bool has_pinch_zoomed_ = false;
-  bool has_scrolled_by_wheel_ = false;
-  bool has_scrolled_by_touch_ = false;
-  bool has_scrolled_by_precisiontouchpad_ = false;
-  bool has_scrolled_by_scrollbar_ = false;
-
-  bool prefers_reduced_motion_ = false;
-
-  // Must be the last member to ensure this is destroyed first in the
-  // destruction order and invalidates all weak pointers.
-  base::WeakPtrFactory<ThreadedInputHandler> weak_factory_{this};
-};
-
-}  // namespace cc
-
-#endif  // CC_INPUT_THREADED_INPUT_HANDLER_H_
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 6a148c3..ac94526 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -536,16 +536,16 @@
   compositor_frame_reporting_controller_ = nullptr;
 }
 
-ThreadedInputHandler& LayerTreeHostImpl::GetInputHandler() {
+InputHandler& LayerTreeHostImpl::GetInputHandler() {
   DCHECK(input_delegate_) << "Requested InputHandler when one wasn't bound. "
                              "Call BindToInputHandler to bind to one";
-  return static_cast<ThreadedInputHandler&>(*input_delegate_.get());
+  return static_cast<InputHandler&>(*input_delegate_.get());
 }
 
-const ThreadedInputHandler& LayerTreeHostImpl::GetInputHandler() const {
+const InputHandler& LayerTreeHostImpl::GetInputHandler() const {
   DCHECK(input_delegate_) << "Requested InputHandler when one wasn't bound. "
                              "Call BindToInputHandler to bind to one";
-  return static_cast<const ThreadedInputHandler&>(*input_delegate_.get());
+  return static_cast<const InputHandler&>(*input_delegate_.get());
 }
 
 void LayerTreeHostImpl::DidSendBeginMainFrame(const viz::BeginFrameArgs& args) {
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index c16415c..500737d1 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -29,7 +29,6 @@
 #include "cc/input/browser_controls_offset_manager_client.h"
 #include "cc/input/input_handler.h"
 #include "cc/input/scrollbar_animation_controller.h"
-#include "cc/input/threaded_input_handler.h"
 #include "cc/layers/layer_collections.h"
 #include "cc/metrics/average_lag_tracking_manager.h"
 #include "cc/metrics/dropped_frame_counter.h"
@@ -279,8 +278,8 @@
   // TODO(bokan): This getter is an escape-hatch for code that hasn't yet been
   // cleaned up to decouple input from graphics. Callers should be cleaned up
   // to avoid calling it and it should be removed.
-  ThreadedInputHandler& GetInputHandler();
-  const ThreadedInputHandler& GetInputHandler() const;
+  InputHandler& GetInputHandler();
+  const InputHandler& GetInputHandler() const;
 
   void StartPageScaleAnimation(const gfx::Point& target_offset,
                                bool anchor_point,
@@ -351,7 +350,7 @@
   void SetFullViewportDamage();
   void SetViewportDamage(const gfx::Rect& damage_rect);
 
-  // Interface for ThreadedInputHandler
+  // Interface for InputHandler
   void BindToInputHandler(
       std::unique_ptr<InputDelegateForCompositor> delegate) override;
   ScrollTree& GetScrollTree() const override;
@@ -673,7 +672,7 @@
   // TODO(bokan): These input-related methods shouldn't be part of
   // LayerTreeHostImpl's interface.
   bool IsPinchGestureActive() const;
-  // See comment in equivalent ThreadedInputHandler method for what this means.
+  // See comment in equivalent InputHandler method for what this means.
   ActivelyScrollingType GetActivelyScrollingType() const;
   bool ScrollAffectsScrollHandler() const;
   bool CurrentScrollCheckerboardsDueToNoRecording() const {
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 1294176..bcd7585 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -28,11 +28,11 @@
 #include "cc/base/histograms.h"
 #include "cc/document_transition/document_transition_request.h"
 #include "cc/input/browser_controls_offset_manager.h"
+#include "cc/input/input_handler.h"
 #include "cc/input/main_thread_scrolling_reason.h"
 #include "cc/input/page_scale_animation.h"
 #include "cc/input/scroll_utils.h"
 #include "cc/input/scrollbar_controller.h"
-#include "cc/input/threaded_input_handler.h"
 #include "cc/layers/append_quads_data.h"
 #include "cc/layers/layer_impl.h"
 #include "cc/layers/painted_overlay_scrollbar_layer_impl.h"
@@ -831,9 +831,7 @@
     }
   }
 
-  ThreadedInputHandler& GetInputHandler() {
-    return host_impl_->GetInputHandler();
-  }
+  InputHandler& GetInputHandler() { return host_impl_->GetInputHandler(); }
 
   FakeImplTaskRunnerProvider task_runner_provider_;
   DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
diff --git a/cc/trees/tree_synchronizer_unittest.cc b/cc/trees/tree_synchronizer_unittest.cc
index 99a90139..7cfeade 100644
--- a/cc/trees/tree_synchronizer_unittest.cc
+++ b/cc/trees/tree_synchronizer_unittest.cc
@@ -802,7 +802,7 @@
 
   // Since this test simulates a scroll it needs an input handler.
   // TODO(bokan): Required because scroll commit is part of InputHandler - that
-  // shouldn't be. See comment in ThreadedInputHandler::ProcessCommitDeltas.
+  // shouldn't be. See comment in InputHandler::ProcessCommitDeltas.
   InputHandler::Create(static_cast<CompositorDelegateForInput&>(*host_impl));
 
   scoped_refptr<Layer> scroll_layer = SetupScrollLayer();
@@ -828,7 +828,7 @@
 
   // Since this test simulates a scroll it needs an input handler.
   // TODO(bokan): Required because scroll commit is part of InputHandler - that
-  // shouldn't be. See comment in ThreadedInputHandler::ProcessCommitDeltas.
+  // shouldn't be. See comment in InputHandler::ProcessCommitDeltas.
   InputHandler::Create(static_cast<CompositorDelegateForInput&>(*host_impl));
 
   scoped_refptr<Layer> scroll_layer = SetupScrollLayer();
diff --git a/third_party/blink/renderer/platform/widget/input/DEPS b/third_party/blink/renderer/platform/widget/input/DEPS
index b83088a42..193e786 100644
--- a/third_party/blink/renderer/platform/widget/input/DEPS
+++ b/third_party/blink/renderer/platform/widget/input/DEPS
@@ -21,3 +21,10 @@
   "+ui/events/types/scroll_types.h",
   "+ui/latency/latency_info.h",
 ]
+
+specific_include_rules = {
+    # Let tests create cc::FakeLayerTreeHost and its dependencies.
+    ".*_unittest\.cc": [
+        "+cc/test",
+    ],
+}
diff --git a/third_party/blink/renderer/platform/widget/input/input_handler_proxy_unittest.cc b/third_party/blink/renderer/platform/widget/input/input_handler_proxy_unittest.cc
index 630bb90..51a03e9 100644
--- a/third_party/blink/renderer/platform/widget/input/input_handler_proxy_unittest.cc
+++ b/third_party/blink/renderer/platform/widget/input/input_handler_proxy_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/containers/circular_deque.h"
+#include "base/lazy_instance.h"
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
@@ -18,7 +19,11 @@
 #include "build/build_config.h"
 #include "cc/base/features.h"
 #include "cc/input/main_thread_scrolling_reason.h"
+#include "cc/test/fake_impl_task_runner_provider.h"
+#include "cc/test/fake_layer_tree_host_impl.h"
+#include "cc/test/test_task_graph_runner.h"
 #include "cc/trees/latency_info_swap_promise_monitor.h"
+#include "cc/trees/layer_tree_settings.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/input/web_input_event.h"
@@ -80,9 +85,53 @@
   return gesture;
 }
 
+class FakeCompositorDelegateForInput : public cc::CompositorDelegateForInput {
+ public:
+  FakeCompositorDelegateForInput()
+      : host_impl_(&task_runner_provider_, &task_graph_runner_) {}
+  void BindToInputHandler(
+      std::unique_ptr<cc::InputDelegateForCompositor> delegate) override {}
+  cc::ScrollTree& GetScrollTree() const override { return scroll_tree_; }
+  bool HasAnimatedScrollbars() const override { return false; }
+  void SetNeedsCommit() override {}
+  void SetNeedsFullViewportRedraw() override {}
+  void SetDeferBeginMainFrame(bool defer_begin_main_frame) const override {}
+  void DidUpdateScrollAnimationCurve() override {}
+  void AccumulateScrollDeltaForTracing(const gfx::Vector2dF& delta) override {}
+  void DidStartPinchZoom() override {}
+  void DidUpdatePinchZoom() override {}
+  void DidEndPinchZoom() override {}
+  void DidStartScroll() override {}
+  void DidEndScroll() override {}
+  void DidMouseLeave() override {}
+  bool IsInHighLatencyMode() const override { return false; }
+  void WillScrollContent(cc::ElementId element_id) override {}
+  void DidScrollContent(cc::ElementId element_id, bool animated) override {}
+  float DeviceScaleFactor() const override { return 0; }
+  float PageScaleFactor() const override { return 0; }
+  gfx::Size VisualDeviceViewportSize() const override { return gfx::Size(); }
+  const cc::LayerTreeSettings& GetSettings() const override {
+    return settings_;
+  }
+  cc::LayerTreeHostImpl& GetImplDeprecated() override { return host_impl_; }
+  const cc::LayerTreeHostImpl& GetImplDeprecated() const override {
+    return host_impl_;
+  }
+
+ private:
+  mutable cc::ScrollTree scroll_tree_;
+  cc::LayerTreeSettings settings_;
+  cc::FakeImplTaskRunnerProvider task_runner_provider_;
+  cc::TestTaskGraphRunner task_graph_runner_;
+  cc::FakeLayerTreeHostImpl host_impl_;
+};
+
+base::LazyInstance<FakeCompositorDelegateForInput>::Leaky
+    g_fake_compositor_delegate = LAZY_INSTANCE_INITIALIZER;
+
 class MockInputHandler : public cc::InputHandler {
  public:
-  MockInputHandler() = default;
+  MockInputHandler() : cc::InputHandler(g_fake_compositor_delegate.Get()) {}
   MockInputHandler(const MockInputHandler&) = delete;
   MockInputHandler& operator=(const MockInputHandler&) = delete;
 
@@ -396,6 +445,7 @@
   void GestureScrollIgnored();
   void FlingAndSnap();
 
+  base::test::SingleThreadTaskEnvironment task_environment_;
   testing::StrictMock<MockInputHandler> mock_input_handler_;
   testing::StrictMock<MockSynchronousInputHandler>
       mock_synchronous_input_handler_;
@@ -562,6 +612,7 @@
   }
 
  protected:
+  base::test::SingleThreadTaskEnvironment task_environment_;
   testing::StrictMock<MockInputHandler> mock_input_handler_;
   testing::StrictMock<MockInputHandlerProxyClient> mock_client_;
   TestInputHandlerProxy input_handler_proxy_;
@@ -570,7 +621,6 @@
 
   uint64_t next_begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber;
 
-  base::test::SingleThreadTaskEnvironment task_environment_;
   base::WeakPtrFactory<InputHandlerProxyEventQueueTest> weak_ptr_factory_{this};
 };
 
@@ -2047,6 +2097,7 @@
   }
 
  protected:
+  base::test::SingleThreadTaskEnvironment task_environment_;
   NiceMock<MockInputHandler> mock_input_handler_;
   NiceMock<MockInputHandlerProxyClient> mock_client_;
 
@@ -2438,6 +2489,7 @@
 }
 
 TEST(SynchronousInputHandlerProxyTest, StartupShutdown) {
+  base::test::SingleThreadTaskEnvironment task_environment;
   testing::StrictMock<MockInputHandler> mock_input_handler;
   testing::StrictMock<MockInputHandlerProxyClient> mock_client;
   testing::StrictMock<MockSynchronousInputHandler>
@@ -2464,6 +2516,7 @@
 }
 
 TEST(SynchronousInputHandlerProxyTest, UpdateRootLayerState) {
+  base::test::SingleThreadTaskEnvironment task_environment;
   testing::NiceMock<MockInputHandler> mock_input_handler;
   testing::StrictMock<MockInputHandlerProxyClient> mock_client;
   testing::StrictMock<MockSynchronousInputHandler>
@@ -2487,6 +2540,7 @@
 }
 
 TEST(SynchronousInputHandlerProxyTest, SetOffset) {
+  base::test::SingleThreadTaskEnvironment task_environment;
   testing::NiceMock<MockInputHandler> mock_input_handler;
   testing::StrictMock<MockInputHandlerProxyClient> mock_client;
   testing::StrictMock<MockSynchronousInputHandler>
@@ -4030,6 +4084,7 @@
 
   uint64_t next_begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber;
 
+  base::test::SingleThreadTaskEnvironment task_environment_;
   testing::NiceMock<MockInputHandler> mock_input_handler_;
   testing::NiceMock<MockInputHandlerProxyClient> mock_client_;
   TestInputHandlerProxy input_handler_proxy_;