// Copyright 2013 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.

#include "third_party/blink/public/platform/input/input_handler_proxy.h"

#include <stddef.h>

#include <algorithm>

#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/check_op.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/profiler/sample_metadata.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_tick_clock.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "cc/base/features.h"
#include "cc/input/main_thread_scrolling_reason.h"
#include "cc/metrics/event_metrics.h"
#include "services/tracing/public/cpp/perfetto/flow_event_utils.h"
#include "services/tracing/public/cpp/perfetto/macros.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/input/web_input_event_attribution.h"
#include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
#include "third_party/blink/public/common/input/web_pointer_event.h"
#include "third_party/blink/public/common/input/web_touch_event.h"
#include "third_party/blink/public/platform/input/input_handler_proxy_client.h"
#include "third_party/blink/renderer/platform/widget/input/compositor_thread_event_queue.h"
#include "third_party/blink/renderer/platform/widget/input/cursor_control_handler.h"
#include "third_party/blink/renderer/platform/widget/input/elastic_overscroll_controller.h"
#include "third_party/blink/renderer/platform/widget/input/event_with_callback.h"
#include "third_party/blink/renderer/platform/widget/input/input_metrics.h"
#include "third_party/blink/renderer/platform/widget/input/momentum_scroll_jank_tracker.h"
#include "third_party/blink/renderer/platform/widget/input/scroll_predictor.h"
#include "ui/events/types/scroll_input_type.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/latency/latency_info.h"

using perfetto::protos::pbzero::ChromeLatencyInfo;
using perfetto::protos::pbzero::TrackEvent;

using ScrollThread = cc::InputHandler::ScrollThread;

namespace blink {
namespace {

cc::ScrollState CreateScrollStateForGesture(const WebGestureEvent& event) {
  cc::ScrollStateData scroll_state_data;
  switch (event.GetType()) {
    case WebInputEvent::Type::kGestureScrollBegin:
      scroll_state_data.position_x = event.PositionInWidget().x();
      scroll_state_data.position_y = event.PositionInWidget().y();
      scroll_state_data.delta_x_hint = -event.data.scroll_begin.delta_x_hint;
      scroll_state_data.delta_y_hint = -event.data.scroll_begin.delta_y_hint;
      scroll_state_data.is_beginning = true;
      // On Mac, a GestureScrollBegin in the inertial phase indicates a fling
      // start.
      scroll_state_data.is_in_inertial_phase =
          (event.data.scroll_begin.inertial_phase ==
           WebGestureEvent::InertialPhaseState::kMomentum);
      scroll_state_data.delta_granularity =
          event.data.scroll_begin.delta_hint_units;

      if (cc::ElementId::IsValid(
              event.data.scroll_begin.scrollable_area_element_id)) {
        cc::ElementId target_scroller(
            event.data.scroll_begin.scrollable_area_element_id);
        scroll_state_data.set_current_native_scrolling_element(target_scroller);

        // If the target scroller comes from a main thread hit test, we're in
        // scroll unification.
        scroll_state_data.is_main_thread_hit_tested =
            event.data.scroll_begin.main_thread_hit_tested;
        DCHECK(!event.data.scroll_begin.main_thread_hit_tested ||
               base::FeatureList::IsEnabled(::features::kScrollUnification));
      } else {
        // If a main thread hit test didn't yield a target we should have
        // discarded this event before this point.
        DCHECK(!event.data.scroll_begin.main_thread_hit_tested);
      }

      break;
    case WebInputEvent::Type::kGestureScrollUpdate:
      scroll_state_data.delta_x = -event.data.scroll_update.delta_x;
      scroll_state_data.delta_y = -event.data.scroll_update.delta_y;
      scroll_state_data.velocity_x = event.data.scroll_update.velocity_x;
      scroll_state_data.velocity_y = event.data.scroll_update.velocity_y;
      scroll_state_data.is_in_inertial_phase =
          event.data.scroll_update.inertial_phase ==
          WebGestureEvent::InertialPhaseState::kMomentum;
      scroll_state_data.delta_granularity =
          event.data.scroll_update.delta_units;
      break;
    case WebInputEvent::Type::kGestureScrollEnd:
      scroll_state_data.is_ending = true;
      break;
    default:
      NOTREACHED();
      break;
  }
  scroll_state_data.is_direct_manipulation =
      event.SourceDevice() == WebGestureDevice::kTouchscreen;
  return cc::ScrollState(scroll_state_data);
}

cc::ScrollState CreateScrollStateForInertialUpdate(
    const gfx::Vector2dF& delta) {
  cc::ScrollStateData scroll_state_data;
  scroll_state_data.delta_x = delta.x();
  scroll_state_data.delta_y = delta.y();
  scroll_state_data.is_in_inertial_phase = true;
  return cc::ScrollState(scroll_state_data);
}

ui::ScrollInputType GestureScrollInputType(WebGestureDevice device) {
  switch (device) {
    case WebGestureDevice::kTouchpad:
      return ui::ScrollInputType::kWheel;
    case WebGestureDevice::kTouchscreen:
      return ui::ScrollInputType::kTouchscreen;
    case WebGestureDevice::kSyntheticAutoscroll:
      return ui::ScrollInputType::kAutoscroll;
    case WebGestureDevice::kScrollbar:
      return ui::ScrollInputType::kScrollbar;
    case WebGestureDevice::kUninitialized:
      NOTREACHED();
      return ui::ScrollInputType::kMaxValue;
  }
}

cc::SnapFlingController::GestureScrollType GestureScrollEventType(
    WebInputEvent::Type web_event_type) {
  switch (web_event_type) {
    case WebInputEvent::Type::kGestureScrollBegin:
      return cc::SnapFlingController::GestureScrollType::kBegin;
    case WebInputEvent::Type::kGestureScrollUpdate:
      return cc::SnapFlingController::GestureScrollType::kUpdate;
    case WebInputEvent::Type::kGestureScrollEnd:
      return cc::SnapFlingController::GestureScrollType::kEnd;
    default:
      NOTREACHED();
      return cc::SnapFlingController::GestureScrollType::kBegin;
  }
}

cc::SnapFlingController::GestureScrollUpdateInfo GetGestureScrollUpdateInfo(
    const WebGestureEvent& event) {
  cc::SnapFlingController::GestureScrollUpdateInfo info;
  info.delta = gfx::Vector2dF(-event.data.scroll_update.delta_x,
                              -event.data.scroll_update.delta_y);
  info.is_in_inertial_phase = event.data.scroll_update.inertial_phase ==
                              WebGestureEvent::InertialPhaseState::kMomentum;
  info.event_time = event.TimeStamp();
  return info;
}

cc::ScrollBeginThreadState RecordScrollingThread(
    bool scrolling_on_compositor_thread,
    bool blocked_on_main_thread_event_handler,
    WebGestureDevice device) {
  const char* kWheelHistogramName = "Renderer4.ScrollingThread.Wheel";
  const char* kTouchHistogramName = "Renderer4.ScrollingThread.Touch";

  auto status = cc::ScrollBeginThreadState::kScrollingOnMain;
  if (scrolling_on_compositor_thread) {
    status =
        blocked_on_main_thread_event_handler
            ? cc::ScrollBeginThreadState::kScrollingOnCompositorBlockedOnMain
            : cc::ScrollBeginThreadState::kScrollingOnCompositor;
  }

  if (device == WebGestureDevice::kTouchscreen) {
    UMA_HISTOGRAM_ENUMERATION(kTouchHistogramName, status);
  } else if (device == WebGestureDevice::kTouchpad) {
    UMA_HISTOGRAM_ENUMERATION(kWheelHistogramName, status);
  } else if (device == WebGestureDevice::kScrollbar) {
    // TODO(crbug.com/1101502): Add support for
    // Renderer4.ScrollingThread.Scrollbar
  } else {
    NOTREACHED();
  }
  return status;
}

bool IsGestureScrollOrPinch(WebInputEvent::Type type) {
  switch (type) {
    case WebGestureEvent::Type::kGestureScrollBegin:
    case WebGestureEvent::Type::kGestureScrollUpdate:
    case WebGestureEvent::Type::kGestureScrollEnd:
    case WebGestureEvent::Type::kGesturePinchBegin:
    case WebGestureEvent::Type::kGesturePinchUpdate:
    case WebGestureEvent::Type::kGesturePinchEnd:
      return true;
    default:
      return false;
  }
}

}  // namespace

InputHandlerProxy::InputHandlerProxy(cc::InputHandler& input_handler,
                                     InputHandlerProxyClient* client)
    : client_(client),
      input_handler_(&input_handler),
      synchronous_input_handler_(nullptr),
      handling_gesture_on_impl_thread_(false),
      scroll_sequence_ignored_(false),
      current_overscroll_params_(nullptr),
      has_seen_first_gesture_scroll_update_after_begin_(false),
      last_injected_gesture_was_begin_(false),
      tick_clock_(base::DefaultTickClock::GetInstance()),
      snap_fling_controller_(std::make_unique<cc::SnapFlingController>(this)),
      cursor_control_handler_(std::make_unique<CursorControlHandler>()) {
  DCHECK(client);
  input_handler_->BindToClient(this);
  cc::ScrollElasticityHelper* scroll_elasticity_helper =
      input_handler_->CreateScrollElasticityHelper();
  if (scroll_elasticity_helper) {
    elastic_overscroll_controller_ =
        ElasticOverscrollController::Create(scroll_elasticity_helper);
  }
  compositor_event_queue_ = std::make_unique<CompositorThreadEventQueue>();
  scroll_predictor_ =
      base::FeatureList::IsEnabled(blink::features::kResamplingScrollEvents)
          ? std::make_unique<ScrollPredictor>()
          : nullptr;

  if (base::FeatureList::IsEnabled(blink::features::kSkipTouchEventFilter) &&
      GetFieldTrialParamValueByFeature(
          blink::features::kSkipTouchEventFilter,
          blink::features::kSkipTouchEventFilterFilteringProcessParamName) ==
          blink::features::
              kSkipTouchEventFilterFilteringProcessParamValueBrowserAndRenderer) {
    // Skipping filtering for touch events on renderer process is enabled.
    // Always skip filtering discrete events.
    skip_touch_filter_discrete_ = true;
    if (GetFieldTrialParamValueByFeature(
            blink::features::kSkipTouchEventFilter,
            blink::features::kSkipTouchEventFilterTypeParamName) ==
        blink::features::kSkipTouchEventFilterTypeParamValueAll) {
      // The experiment config also specifies to skip touchmove events.
      skip_touch_filter_all_ = true;
    }
  }
}

InputHandlerProxy::~InputHandlerProxy() {}

void InputHandlerProxy::WillShutdown() {
  elastic_overscroll_controller_.reset();
  input_handler_ = nullptr;
  client_->WillShutdown();
}

void InputHandlerProxy::HandleInputEventWithLatencyInfo(
    std::unique_ptr<blink::WebCoalescedInputEvent> event,
    std::unique_ptr<cc::EventMetrics> metrics,
    EventDispositionCallback callback) {
  DCHECK(input_handler_);

  input_handler_->NotifyInputEvent();

  int64_t trace_id = event->latency_info().trace_id();
  TRACE_EVENT("input,benchmark", "LatencyInfo.Flow",
              [trace_id](perfetto::EventContext ctx) {
                ChromeLatencyInfo* info =
                    ctx.event()->set_chrome_latency_info();
                info->set_trace_id(trace_id);
                info->set_step(ChromeLatencyInfo::STEP_HANDLE_INPUT_EVENT_IMPL);
                tracing::FillFlowEvent(ctx, TrackEvent::LegacyEvent::FLOW_INOUT,
                                       trace_id);
              });

  auto event_with_callback = std::make_unique<EventWithCallback>(
      std::move(event), tick_clock_->NowTicks(), std::move(callback),
      std::move(metrics));

  enum {
    NO_SCROLL_PINCH = 0,
    ONGOING_SCROLL_PINCH = 1,
    SCROLL_PINCH = 2,
  };
  // Note: Other input can race ahead of gesture input as they don't have to go
  // through the queue, but we believe it's OK to do so.
  if (!IsGestureScrollOrPinch(event_with_callback->event().GetType())) {
    base::ScopedSampleMetadata metadata("Input.GestureScrollOrPinch",
                                        NO_SCROLL_PINCH);
    DispatchSingleInputEvent(std::move(event_with_callback),
                             tick_clock_->NowTicks());
    return;
  }

  base::ScopedSampleMetadata metadata(
      "Input.GestureScrollOrPinch", currently_active_gesture_device_.has_value()
                                        ? ONGOING_SCROLL_PINCH
                                        : SCROLL_PINCH);
  const auto& gesture_event =
      static_cast<const WebGestureEvent&>(event_with_callback->event());
  const bool is_first_gesture_scroll_update =
      !has_seen_first_gesture_scroll_update_after_begin_ &&
      gesture_event.GetType() == WebGestureEvent::Type::kGestureScrollUpdate;

  if (gesture_event.GetType() == WebGestureEvent::Type::kGestureScrollBegin) {
    has_seen_first_gesture_scroll_update_after_begin_ = false;
  } else if (gesture_event.GetType() ==
             WebGestureEvent::Type::kGestureScrollUpdate) {
    has_seen_first_gesture_scroll_update_after_begin_ = true;
  }

  if (currently_active_gesture_device_.has_value()) {
    // Scroll updates should typically be queued and wait until a
    // BeginImplFrame to dispatch. However, the first scroll update to be
    // generated from a *blocking* touch sequence will have waited for the
    // touch event to be ACK'ed by the renderer as unconsumed. Queueing here
    // again until BeginImplFrame means we'll likely add a whole frame of
    // latency to so we flush the queue immediately. This happens only for the
    // first scroll update because once a scroll starts touch events are
    // dispatched non-blocking so scroll updates don't wait for a touch ACK.
    // The |is_source_touch_event_set_blocking| bit is set based on the
    // renderer's reply that a blocking touch stream should be made
    // non-blocking. Note: unlike wheel events below, the first GSU in a touch
    // may have come from a non-blocking touch sequence, e.g. if the earlier
    // touchstart determined we're in a |touch-action: pan-y| region. Because
    // of this, we can't simply look at the first GSU like wheels do.
    bool is_from_blocking_touch =
        gesture_event.SourceDevice() == WebGestureDevice::kTouchscreen &&
        gesture_event.is_source_touch_event_set_blocking;

    // TODO(bokan): This was added in https://crrev.com/c/557463 before async
    // wheel events. It's not clear to me why flushing on a scroll end would
    // help or why this is specific to wheel events but I suspect it's no
    // longer needed now that wheel scrolling uses non-blocking events.
    bool is_scroll_end_from_wheel =
        gesture_event.SourceDevice() == WebGestureDevice::kTouchpad &&
        gesture_event.GetType() == WebGestureEvent::Type::kGestureScrollEnd;

    // Wheel events have the same issue as the blocking touch issue above.
    // However, all wheel events are initially sent blocking and become non-
    // blocking on the first unconsumed event. We can therefore simply look for
    // the first scroll update in a wheel gesture.
    bool is_first_wheel_scroll_update =
        gesture_event.SourceDevice() == WebGestureDevice::kTouchpad &&
        is_first_gesture_scroll_update;

    // |synchronous_input_handler_| is WebView only. WebView has different
    // mechanisms and we want to forward all events immediately.
    if (is_from_blocking_touch || is_scroll_end_from_wheel ||
        is_first_wheel_scroll_update || synchronous_input_handler_) {
      compositor_event_queue_->Queue(std::move(event_with_callback),
                                     tick_clock_->NowTicks());
      DispatchQueuedInputEvents();
      return;
    }

    bool needs_animate_input = compositor_event_queue_->empty();
    compositor_event_queue_->Queue(std::move(event_with_callback),
                                   tick_clock_->NowTicks());
    if (needs_animate_input)
      input_handler_->SetNeedsAnimateInput();
    return;
  }

  // We have to dispatch the event to know whether the gesture sequence will be
  // handled by the compositor or not.
  DispatchSingleInputEvent(std::move(event_with_callback),
                           tick_clock_->NowTicks());
}

void InputHandlerProxy::ContinueScrollBeginAfterMainThreadHitTest(
    std::unique_ptr<blink::WebCoalescedInputEvent> event,
    std::unique_ptr<cc::EventMetrics> metrics,
    EventDispositionCallback callback,
    cc::ElementIdType hit_test_result) {
  DCHECK(base::FeatureList::IsEnabled(::features::kScrollUnification));
  DCHECK_EQ(event->Event().GetType(),
            WebGestureEvent::Type::kGestureScrollBegin);
  DCHECK(hit_testing_scroll_begin_on_main_thread_);
  DCHECK(currently_active_gesture_device_);
  DCHECK(input_handler_);

  hit_testing_scroll_begin_on_main_thread_ = false;

  // HandleGestureScrollBegin has logic to end an existing scroll when an
  // unexpected scroll begin arrives. We currently think we're in a scroll
  // because of the first ScrollBegin so clear this so we don't spurriously
  // call ScrollEnd. It will be set again in HandleGestureScrollBegin.
  currently_active_gesture_device_ = base::nullopt;

  auto* gesture_event =
      static_cast<blink::WebGestureEvent*>(event->EventPointer());
  if (cc::ElementId::IsValid(hit_test_result)) {
    gesture_event->data.scroll_begin.scrollable_area_element_id =
        hit_test_result;
    gesture_event->data.scroll_begin.main_thread_hit_tested = true;

    if (metrics) {
      // The event is going to be re-processed on the compositor thread; so,
      // reset timstamps of following dispatch stages.
      metrics->ResetToDispatchStage(
          cc::EventMetrics::DispatchStage::kArrivedInRendererCompositor);
    }
    auto event_with_callback = std::make_unique<EventWithCallback>(
        std::move(event), tick_clock_->NowTicks(), std::move(callback),
        std::move(metrics));

    DispatchSingleInputEvent(std::move(event_with_callback),
                             tick_clock_->NowTicks());
  } else {
    // TODO(bokan): This looks odd but is actually what happens in the
    // non-unified path. If a scroll is DROP_EVENT'ed, we still call
    // RecordMainThreadScrollingReasons and then LTHI::RecordScrollEnd when we
    // DROP the ScrollEnd. We call this to ensure symmetry between
    // RecordScrollBegin and RecordScrollEnd but we should probably be avoiding
    // this if the scroll never starts. https://crbug.com/1082601.
    RecordMainThreadScrollingReasons(gesture_event->SourceDevice(), 0);

    // If the main thread failed to return a scroller for whatever reason,
    // consider the ScrollBegin to be dropped.
    scroll_sequence_ignored_ = true;
    WebInputEventAttribution attribution =
        PerformEventAttribution(event->Event());
    std::move(callback).Run(DROP_EVENT, std::move(event),
                            /*overscroll_params=*/nullptr, attribution,
                            std::move(metrics));
  }

  // We blocked the compositor gesture event queue while the hit test was
  // pending so scroll updates may be waiting in the queue. Now that we've
  // finished the hit test and performed the scroll begin, flush the queue.
  DispatchQueuedInputEvents();
}

void InputHandlerProxy::DispatchSingleInputEvent(
    std::unique_ptr<EventWithCallback> event_with_callback,
    const base::TimeTicks now) {
  ui::LatencyInfo monitored_latency_info = event_with_callback->latency_info();
  std::unique_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor =
      input_handler_->CreateLatencyInfoSwapPromiseMonitor(
          &monitored_latency_info);

  current_overscroll_params_.reset();

  WebInputEventAttribution attribution =
      PerformEventAttribution(event_with_callback->event());
  InputHandlerProxy::EventDisposition disposition =
      RouteToTypeSpecificHandler(event_with_callback.get(), attribution);

  const WebInputEvent& event = event_with_callback->event();
  const WebGestureEvent::Type type = event.GetType();
  switch (type) {
    case WebGestureEvent::Type::kGestureScrollBegin:
    case WebGestureEvent::Type::kGesturePinchBegin:
      if (disposition == DID_HANDLE ||
          disposition == REQUIRES_MAIN_THREAD_HIT_TEST ||
          (disposition == DROP_EVENT && handling_gesture_on_impl_thread_)) {
        // REQUIRES_MAIN_THREAD_HIT_TEST means the scroll will be handled by
        // the compositor but needs to block until a hit test is performed by
        // Blink. We need to set this to indicate we're in a scroll so that
        // gestures are queued rather than dispatched immediately.
        // TODO(bokan): It's a bit of an open question if we need to also set
        // |handling_gesture_on_impl_thread_|. Ideally these two bits would be
        // merged. The queueing behavior is currently just determined by having
        // an active gesture device.
        //
        // DROP_EVENT and handling_gesture_on_impl_thread_ means that the
        // gesture was handled but the scroll was not consumed.
        currently_active_gesture_device_ =
            static_cast<const WebGestureEvent&>(event).SourceDevice();
      }
      break;

    case WebGestureEvent::Type::kGestureScrollEnd:
    case WebGestureEvent::Type::kGesturePinchEnd:
      if (!handling_gesture_on_impl_thread_)
        currently_active_gesture_device_ = base::nullopt;
      break;
    default:
      break;
  }

  // Handle jank tracking during the momentum phase of a scroll gesture. The
  // class filters non-momentum events internally.
  switch (type) {
    case WebGestureEvent::Type::kGestureScrollBegin:
      momentum_scroll_jank_tracker_ =
          std::make_unique<MomentumScrollJankTracker>();
      break;
    case WebGestureEvent::Type::kGestureScrollUpdate:
      // It's possible to get a scroll update without a begin. Ignore these
      // cases.
      if (momentum_scroll_jank_tracker_) {
        momentum_scroll_jank_tracker_->OnDispatchedInputEvent(
            event_with_callback.get(), now);
      }
      break;
    case WebGestureEvent::Type::kGestureScrollEnd:
      momentum_scroll_jank_tracker_.reset();
      break;
    default:
      break;
  }

  // Will run callback for every original events.
  event_with_callback->RunCallbacks(disposition, monitored_latency_info,
                                    std::move(current_overscroll_params_),
                                    attribution);
}

void InputHandlerProxy::DispatchQueuedInputEvents() {
  // Block flushing the compositor gesture event queue while there's an async
  // scroll begin hit test outstanding. We'll flush the queue when the hit test
  // responds.
  if (hit_testing_scroll_begin_on_main_thread_) {
    DCHECK(base::FeatureList::IsEnabled(::features::kScrollUnification));
    return;
  }

  // Calling |NowTicks()| is expensive so we only want to do it once.
  base::TimeTicks now = tick_clock_->NowTicks();
  while (!compositor_event_queue_->empty())
    DispatchSingleInputEvent(compositor_event_queue_->Pop(), now);
}

void InputHandlerProxy::InjectScrollbarGestureScroll(
    const WebInputEvent::Type type,
    const gfx::PointF& position_in_widget,
    const cc::InputHandlerPointerResult& pointer_result,
    const ui::LatencyInfo& latency_info,
    const base::TimeTicks original_timestamp,
    const cc::EventMetrics* original_metrics) {
  gfx::Vector2dF scroll_delta(pointer_result.scroll_offset.x(),
                              pointer_result.scroll_offset.y());

  std::unique_ptr<WebGestureEvent> synthetic_gesture_event =
      WebGestureEvent::GenerateInjectedScrollGesture(
          type, original_timestamp, WebGestureDevice::kScrollbar,
          position_in_widget, scroll_delta, pointer_result.scroll_units);

  // This will avoid hit testing and directly scroll the scroller with the
  // provided element_id.
  if (type == WebInputEvent::Type::kGestureScrollBegin) {
    synthetic_gesture_event->data.scroll_begin.scrollable_area_element_id =
        pointer_result.target_scroller.GetStableId();
  }

  // Send in a LatencyInfo with SCROLLBAR type so that the end to end latency
  // is calculated specifically for scrollbars.
  ui::LatencyInfo scrollbar_latency_info(latency_info);
  scrollbar_latency_info.set_source_event_type(ui::SourceEventType::SCROLLBAR);

  // This latency_info should not have already been scheduled for rendering -
  // i.e. it should be the original latency_info that was associated with the
  // input event that caused this scroll injection. If it has already been
  // scheduled it won't get queued to be shipped off with the CompositorFrame
  // when the gesture is handled.
  DCHECK(!scrollbar_latency_info.FindLatency(
      ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, nullptr));

  base::Optional<cc::EventMetrics::ScrollUpdateType> scroll_update_type;
  if (type == WebInputEvent::Type::kGestureScrollBegin) {
    last_injected_gesture_was_begin_ = true;
  } else {
    if (type == WebInputEvent::Type::kGestureScrollUpdate) {
      // For injected GSUs, add a scroll update component to the latency info
      // so that it is properly classified as a scroll. If the last injected
      // gesture was a GSB, then this GSU is the first scroll update - mark
      // the LatencyInfo as such.
      scrollbar_latency_info.AddLatencyNumberWithTimestamp(
          last_injected_gesture_was_begin_
              ? ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT
              : ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
          original_timestamp);
      scroll_update_type = last_injected_gesture_was_begin_
                               ? cc::EventMetrics::ScrollUpdateType::kStarted
                               : cc::EventMetrics::ScrollUpdateType::kContinued;
    }

    last_injected_gesture_was_begin_ = false;
  }

  std::unique_ptr<cc::EventMetrics> metrics =
      cc::EventMetrics::CreateFromExisting(
          synthetic_gesture_event->GetTypeAsUiEventType(), scroll_update_type,
          synthetic_gesture_event->GetScrollInputType(),
          cc::EventMetrics::DispatchStage::kArrivedInRendererCompositor,
          original_metrics);
  auto gesture_event_with_callback_update = std::make_unique<EventWithCallback>(
      std::make_unique<WebCoalescedInputEvent>(
          std::move(synthetic_gesture_event), scrollbar_latency_info),
      original_timestamp, base::DoNothing(), std::move(metrics));

  bool needs_animate_input = compositor_event_queue_->empty();
  compositor_event_queue_->Queue(std::move(gesture_event_with_callback_update),
                                 original_timestamp);

  if (needs_animate_input)
    input_handler_->SetNeedsAnimateInput();
}

bool HasScrollbarJumpKeyModifier(const WebInputEvent& event) {
#if defined(OS_MAC)
  // Mac uses the "Option" key (which is mapped to the enum "kAltKey").
  return event.GetModifiers() & WebInputEvent::kAltKey;
#else
  return event.GetModifiers() & WebInputEvent::kShiftKey;
#endif
}

InputHandlerProxy::EventDisposition
InputHandlerProxy::RouteToTypeSpecificHandler(
    EventWithCallback* event_with_callback,
    const WebInputEventAttribution& original_attribution) {
  DCHECK(input_handler_);

  cc::EventsMetricsManager::ScopedMonitor::DoneCallback done_callback;
  if (event_with_callback->metrics()) {
    event_with_callback->WillStartProcessingForMetrics();
    done_callback = base::BindOnce(
        [](EventWithCallback* event, bool handled) {
          event->DidCompleteProcessingForMetrics();
          std::unique_ptr<cc::EventMetrics> result =
              handled ? event->TakeMetrics() : nullptr;
          return result;
        },
        event_with_callback);
  }
  auto scoped_event_monitor =
      input_handler_->GetScopedEventMetricsMonitor(std::move(done_callback));

  const WebInputEvent& event = event_with_callback->event();
  if (event.IsGestureScroll() &&
      (snap_fling_controller_->FilterEventForSnap(
          GestureScrollEventType(event.GetType())))) {
    return DROP_EVENT;
  }

  if (base::Optional<InputHandlerProxy::EventDisposition> handled =
          cursor_control_handler_->ObserveInputEvent(event))
    return *handled;

  switch (event.GetType()) {
    case WebInputEvent::Type::kMouseWheel:
      return HandleMouseWheel(static_cast<const WebMouseWheelEvent&>(event));

    case WebInputEvent::Type::kGestureScrollBegin:
      return HandleGestureScrollBegin(
          static_cast<const WebGestureEvent&>(event));

    case WebInputEvent::Type::kGestureScrollUpdate:
      return HandleGestureScrollUpdate(
          static_cast<const WebGestureEvent&>(event), original_attribution,
          event_with_callback->metrics());

    case WebInputEvent::Type::kGestureScrollEnd:
      return HandleGestureScrollEnd(static_cast<const WebGestureEvent&>(event));

    case WebInputEvent::Type::kGesturePinchBegin: {
      DCHECK(!gesture_pinch_in_progress_);
      input_handler_->PinchGestureBegin();
      gesture_pinch_in_progress_ = true;
      return DID_HANDLE;
    }

    case WebInputEvent::Type::kGesturePinchEnd: {
      DCHECK(gesture_pinch_in_progress_);
      gesture_pinch_in_progress_ = false;
      const WebGestureEvent& gesture_event =
          static_cast<const WebGestureEvent&>(event);
      input_handler_->PinchGestureEnd(
          gfx::ToFlooredPoint(gesture_event.PositionInWidget()),
          gesture_event.SourceDevice() == WebGestureDevice::kTouchpad);
      return DID_HANDLE;
    }

    case WebInputEvent::Type::kGesturePinchUpdate: {
      DCHECK(gesture_pinch_in_progress_);
      const WebGestureEvent& gesture_event =
          static_cast<const WebGestureEvent&>(event);
      input_handler_->PinchGestureUpdate(
          gesture_event.data.pinch_update.scale,
          gfx::ToFlooredPoint(gesture_event.PositionInWidget()));
      return DID_HANDLE;
    }

    case WebInputEvent::Type::kTouchStart:
      return HandleTouchStart(event_with_callback);

    case WebInputEvent::Type::kTouchMove:
      return HandleTouchMove(event_with_callback);

    case WebInputEvent::Type::kTouchEnd:
      return HandleTouchEnd(event_with_callback);

    case WebInputEvent::Type::kMouseDown: {
      // Only for check scrollbar captured
      const WebMouseEvent& mouse_event =
          static_cast<const WebMouseEvent&>(event);

      if (mouse_event.button == WebMouseEvent::Button::kLeft) {
        CHECK(input_handler_);
        // TODO(arakeri): Pass in the modifier instead of a bool once the
        // refactor (crbug.com/1022097) is done. For details, see
        // crbug.com/1016955.
        HandlePointerDown(event_with_callback, mouse_event.PositionInWidget());
      }

      return DID_NOT_HANDLE;
    }
    case WebInputEvent::Type::kMouseUp: {
      // Only for release scrollbar captured
      const WebMouseEvent& mouse_event =
          static_cast<const WebMouseEvent&>(event);
      CHECK(input_handler_);
      if (mouse_event.button == WebMouseEvent::Button::kLeft)
        HandlePointerUp(event_with_callback, mouse_event.PositionInWidget());
      return DID_NOT_HANDLE;
    }
    case WebInputEvent::Type::kMouseMove: {
      const WebMouseEvent& mouse_event =
          static_cast<const WebMouseEvent&>(event);
      // TODO(davemoore): This should never happen, but bug #326635 showed some
      // surprising crashes.
      CHECK(input_handler_);
      HandlePointerMove(event_with_callback, mouse_event.PositionInWidget());
      return DID_NOT_HANDLE;
    }
    case WebInputEvent::Type::kMouseLeave: {
      CHECK(input_handler_);
      input_handler_->MouseLeave();
      return DID_NOT_HANDLE;
    }
    // Fling gestures are handled only in the browser process and not sent to
    // the renderer.
    case WebInputEvent::Type::kGestureFlingStart:
    case WebInputEvent::Type::kGestureFlingCancel:
      NOTREACHED();
      break;

    default:
      break;
  }

  return DID_NOT_HANDLE;
}

WebInputEventAttribution InputHandlerProxy::PerformEventAttribution(
    const WebInputEvent& event) {
  if (!event_attribution_enabled_) {
    return WebInputEventAttribution(WebInputEventAttribution::kUnknown);
  }

  if (WebInputEvent::IsKeyboardEventType(event.GetType())) {
    // Keyboard events should be dispatched to the focused frame.
    return WebInputEventAttribution(WebInputEventAttribution::kFocusedFrame);
  } else if (WebInputEvent::IsMouseEventType(event.GetType()) ||
             event.GetType() == WebInputEvent::Type::kMouseWheel) {
    // Mouse events are dispatched based on their location in the DOM tree.
    // Perform frame attribution via cc.
    // TODO(acomminos): handle pointer locks, or provide a hint to the renderer
    //                  to check pointer lock state
    gfx::PointF point =
        static_cast<const WebMouseEvent&>(event).PositionInWidget();
    return WebInputEventAttribution(
        WebInputEventAttribution::kTargetedFrame,
        input_handler_->FindFrameElementIdAtPoint(point));
  } else if (WebInputEvent::IsGestureEventType(event.GetType())) {
    gfx::PointF point =
        static_cast<const WebGestureEvent&>(event).PositionInWidget();
    return WebInputEventAttribution(
        WebInputEventAttribution::kTargetedFrame,
        input_handler_->FindFrameElementIdAtPoint(point));
  } else if (WebInputEvent::IsTouchEventType(event.GetType())) {
    const auto& touch_event = static_cast<const WebTouchEvent&>(event);
    if (touch_event.touches_length == 0) {
      return WebInputEventAttribution(WebInputEventAttribution::kTargetedFrame,
                                      cc::ElementId());
    }

    // Use the first touch location to perform frame attribution, similar to
    // how the renderer host performs touch event dispatch.
    // https://cs.chromium.org/chromium/src/content/browser/renderer_host/render_widget_host_input_event_router.cc?l=808&rcl=10fe9d0a725d4ed7b69266a5936c525f0a5b26d3
    gfx::PointF point = touch_event.touches[0].PositionInWidget();
    const cc::ElementId targeted_element =
        input_handler_->FindFrameElementIdAtPoint(point);

    return WebInputEventAttribution(WebInputEventAttribution::kTargetedFrame,
                                    targeted_element);
  } else {
    return WebInputEventAttribution(WebInputEventAttribution::kUnknown);
  }
}

void InputHandlerProxy::RecordMainThreadScrollingReasons(
    WebGestureDevice device,
    uint32_t reasons) {
  if (device != WebGestureDevice::kTouchpad &&
      device != WebGestureDevice::kScrollbar &&
      device != WebGestureDevice::kTouchscreen) {
    return;
  }

  // NonCompositedScrollReasons should only be set on the main thread.
  DCHECK(
      !cc::MainThreadScrollingReason::HasNonCompositedScrollReasons(reasons));

  // This records whether a scroll is handled on the main or compositor
  // threads. Note: scrolls handled on the compositor but blocked on main due
  // to event handlers are still considered compositor scrolls.
  const bool is_compositor_scroll =
      reasons == cc::MainThreadScrollingReason::kNotScrollingOnMain;

  base::Optional<EventDisposition> disposition =
      (device == WebGestureDevice::kTouchpad ? mouse_wheel_result_
                                             : touch_result_);

  // Scrolling can be handled on the compositor thread but it might be blocked
  // on the main thread waiting for non-passive event handlers to process the
  // wheel/touch events (i.e. were they preventDefaulted?).
  bool blocked_on_main_thread_handler =
      disposition.has_value() && disposition == DID_NOT_HANDLE;

  auto scroll_start_state = RecordScrollingThread(
      is_compositor_scroll, blocked_on_main_thread_handler, device);
  input_handler_->RecordScrollBegin(GestureScrollInputType(device),
                                    scroll_start_state);

  if (blocked_on_main_thread_handler) {
    // We should also collect main thread scrolling reasons if a scroll event
    // scrolls on impl thread but is blocked by main thread event handlers.
    reasons |= (device == WebGestureDevice::kTouchpad
                    ? cc::MainThreadScrollingReason::kWheelEventHandlerRegion
                    : cc::MainThreadScrollingReason::kTouchEventHandlerRegion);
  }

  RecordScrollReasonsMetric(device, reasons);
}

InputHandlerProxy::EventDisposition InputHandlerProxy::HandleMouseWheel(
    const WebMouseWheelEvent& wheel_event) {
  InputHandlerProxy::EventDisposition result = DROP_EVENT;

  if (wheel_event.dispatch_type ==
      WebInputEvent::DispatchType::kEventNonBlocking) {
    // The first wheel event in the sequence should be cancellable.
    DCHECK(wheel_event.phase != WebMouseWheelEvent::kPhaseBegan);
    // Noncancellable wheel events should have phase info.
    DCHECK(wheel_event.phase != WebMouseWheelEvent::kPhaseNone ||
           wheel_event.momentum_phase != WebMouseWheelEvent::kPhaseNone);

    // TODO(bokan): This should never happen but after changing
    // mouse_event_result_ to a base::Optional, crashes indicate that it does
    // so |if| maintains prior behavior. https://crbug.com/1069760.
    if (mouse_wheel_result_.has_value()) {
      result = mouse_wheel_result_.value();
      if (wheel_event.phase == WebMouseWheelEvent::kPhaseEnded ||
          wheel_event.phase == WebMouseWheelEvent::kPhaseCancelled ||
          wheel_event.momentum_phase == WebMouseWheelEvent::kPhaseEnded ||
          wheel_event.momentum_phase == WebMouseWheelEvent::kPhaseCancelled) {
        mouse_wheel_result_.reset();
      } else {
        return result;
      }
    }
  }

  gfx::PointF position_in_widget = wheel_event.PositionInWidget();
  if (input_handler_->HasBlockingWheelEventHandlerAt(
          gfx::Point(position_in_widget.x(), position_in_widget.y()))) {
    result = DID_NOT_HANDLE;
  } else {
    cc::EventListenerProperties properties =
        input_handler_->GetEventListenerProperties(
            cc::EventListenerClass::kMouseWheel);
    switch (properties) {
      case cc::EventListenerProperties::kBlockingAndPassive:
      case cc::EventListenerProperties::kPassive:
        result = DID_NOT_HANDLE_NON_BLOCKING;
        break;
      case cc::EventListenerProperties::kNone:
        result = DROP_EVENT;
        break;
      default:
        // If properties is kBlocking, and the event falls outside wheel event
        // handler region, we should handle it the same as kNone.
        result = DROP_EVENT;
    }
  }

  mouse_wheel_result_ = result;
  return result;
}

InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureScrollBegin(
    const WebGestureEvent& gesture_event) {
  TRACE_EVENT0("input", "InputHandlerProxy::HandleGestureScrollBegin");

  if (scroll_predictor_)
    scroll_predictor_->ResetOnGestureScrollBegin(gesture_event);

  // When a GSB is being handled, end any pre-existing gesture scrolls that are
  // in progress.
  if (currently_active_gesture_device_.has_value() &&
      handling_gesture_on_impl_thread_) {
    // TODO(arakeri): Once crbug.com/1074209 is fixed, delete calls to
    // RecordScrollEnd.
    input_handler_->RecordScrollEnd(
        GestureScrollInputType(*currently_active_gesture_device_));
    InputHandlerScrollEnd();
  }

  cc::ScrollState scroll_state = CreateScrollStateForGesture(gesture_event);
  cc::InputHandler::ScrollStatus scroll_status;
  if (gesture_event.data.scroll_begin.target_viewport) {
    scroll_status = input_handler_->RootScrollBegin(
        &scroll_state, GestureScrollInputType(gesture_event.SourceDevice()));
  } else {
    scroll_status = input_handler_->ScrollBegin(
        &scroll_state, GestureScrollInputType(gesture_event.SourceDevice()));
  }

  // If we need a hit test from the main thread, we'll reinject this scroll
  // begin event once the hit test is complete so avoid everything below for
  // now, it'll be run on the second iteration.
  if (scroll_status.needs_main_thread_hit_test) {
    DCHECK(base::FeatureList::IsEnabled(::features::kScrollUnification));
    hit_testing_scroll_begin_on_main_thread_ = true;
    return REQUIRES_MAIN_THREAD_HIT_TEST;
  }

  RecordMainThreadScrollingReasons(gesture_event.SourceDevice(),
                                   scroll_status.main_thread_scrolling_reasons);

  InputHandlerProxy::EventDisposition result = DID_NOT_HANDLE;
  scroll_sequence_ignored_ = false;
  in_inertial_scrolling_ = false;
  switch (scroll_status.thread) {
    case ScrollThread::SCROLL_ON_IMPL_THREAD:
      TRACE_EVENT_INSTANT0("input", "Handle On Impl", TRACE_EVENT_SCOPE_THREAD);
      handling_gesture_on_impl_thread_ = true;
      if (input_handler_->IsCurrentlyScrollingViewport())
        client_->DidStartScrollingViewport();
      // if the viewport cannot scroll, the scroll cannot be consumed so we
      // drop the event
      if (scroll_status.viewport_cannot_scroll)
        result = DROP_EVENT;
      else
        result = DID_HANDLE;
      break;
    case ScrollThread::SCROLL_ON_MAIN_THREAD:
      TRACE_EVENT_INSTANT0("input", "Handle On Main", TRACE_EVENT_SCOPE_THREAD);
      result = DID_NOT_HANDLE;
      break;
    case ScrollThread::SCROLL_IGNORED:
      TRACE_EVENT_INSTANT0("input", "Ignore Scroll", TRACE_EVENT_SCOPE_THREAD);
      scroll_sequence_ignored_ = true;
      result = DROP_EVENT;
      break;
    default:
      NOTREACHED();
      break;
  }

  // TODO(bokan): Should we really be calling this in cases like DROP_EVENT and
  // DID_NOT_HANDLE_NON_BLOCKING_DUE_TO_FLING? I think probably not.
  if (elastic_overscroll_controller_ && result != DID_NOT_HANDLE) {
    HandleScrollElasticityOverscroll(gesture_event,
                                     cc::InputHandlerScrollResult());
  }

  return result;
}

InputHandlerProxy::EventDisposition
InputHandlerProxy::HandleGestureScrollUpdate(
    const WebGestureEvent& gesture_event,
    const WebInputEventAttribution& original_attribution,
    const cc::EventMetrics* original_metrics) {
  TRACE_EVENT2("input", "InputHandlerProxy::HandleGestureScrollUpdate", "dx",
               -gesture_event.data.scroll_update.delta_x, "dy",
               -gesture_event.data.scroll_update.delta_y);

  if (scroll_sequence_ignored_) {
    TRACE_EVENT_INSTANT0("input", "Scroll Sequence Ignored",
                         TRACE_EVENT_SCOPE_THREAD);
    return DROP_EVENT;
  }

  if (!handling_gesture_on_impl_thread_ && !gesture_pinch_in_progress_)
    return DID_NOT_HANDLE;

  cc::ScrollState scroll_state = CreateScrollStateForGesture(gesture_event);
  in_inertial_scrolling_ = scroll_state.is_in_inertial_phase();

  TRACE_EVENT_INSTANT1(
      "input", "DeltaUnits", TRACE_EVENT_SCOPE_THREAD, "unit",
      static_cast<int>(gesture_event.data.scroll_update.delta_units));

  if (snap_fling_controller_->HandleGestureScrollUpdate(
          GetGestureScrollUpdateInfo(gesture_event))) {
    handling_gesture_on_impl_thread_ = false;
    return DROP_EVENT;
  }

  if (!base::FeatureList::IsEnabled(::features::kScrollUnification) &&
      input_handler_->ScrollingShouldSwitchtoMainThread()) {
    TRACE_EVENT_INSTANT0("input", "Move Scroll To Main Thread",
                         TRACE_EVENT_SCOPE_THREAD);
    handling_gesture_on_impl_thread_ = false;
    currently_active_gesture_device_ = base::nullopt;
    client_->GenerateScrollBeginAndSendToMainThread(
        gesture_event, original_attribution, original_metrics);

    // TODO(bokan): |!gesture_pinch_in_progress_| was put here by
    // https://crrev.com/2720903005 but it's not clear to me how this is
    // supposed to work - we already generated and sent a GSB to the main
    // thread above so it's odd to continue handling on the compositor thread
    // if a pinch was in progress. It probably makes more sense to bake this
    // condition into ScrollingShouldSwitchToMainThread().
    if (!gesture_pinch_in_progress_)
      return DID_NOT_HANDLE;
  }

  base::TimeTicks event_time = gesture_event.TimeStamp();
  base::TimeDelta delay = base::TimeTicks::Now() - event_time;

  cc::InputHandlerScrollResult scroll_result =
      input_handler_->ScrollUpdate(&scroll_state, delay);

  HandleOverscroll(gesture_event.PositionInWidget(), scroll_result);

  if (elastic_overscroll_controller_)
    HandleScrollElasticityOverscroll(gesture_event, scroll_result);

  return scroll_result.did_scroll ? DID_HANDLE : DROP_EVENT;
}

// TODO(arakeri): Ensure that redudant GSE(s) in the CompositorThreadEventQueue
// are handled gracefully. (i.e currently, when an ongoing scroll needs to end,
// we call RecordScrollEnd and InputHandlerScrollEnd synchronously. Ideally, we
// should end the scroll when the GSB is being handled).
InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureScrollEnd(
    const WebGestureEvent& gesture_event) {
  TRACE_EVENT0("input", "InputHandlerProxy::HandleGestureScrollEnd");

  // TODO(bokan): It seems odd that we'd record a ScrollEnd for a scroll
  // secuence that was ignored (i.e. the ScrollBegin was dropped). However,
  // RecordScrollBegin does get called in that case so this needs to be this
  // way for now. This makes life rather awkward for the unified scrolling path
  // so perhaps we should only record a scrolling thread if a scroll actually
  // started? https://crbug.com/1082601.
  input_handler_->RecordScrollEnd(
      GestureScrollInputType(gesture_event.SourceDevice()));

  if (scroll_sequence_ignored_) {
    DCHECK(!currently_active_gesture_device_.has_value());
    return DROP_EVENT;
  }

  if (!handling_gesture_on_impl_thread_) {
    DCHECK(!currently_active_gesture_device_.has_value());
    return DID_NOT_HANDLE;
  }

  if (!currently_active_gesture_device_.has_value() ||
      (currently_active_gesture_device_.value() !=
       gesture_event.SourceDevice()))
    return DROP_EVENT;

  InputHandlerScrollEnd();
  if (elastic_overscroll_controller_) {
    HandleScrollElasticityOverscroll(gesture_event,
                                     cc::InputHandlerScrollResult());
  }

  return DID_HANDLE;
}

void InputHandlerProxy::InputHandlerScrollEnd() {
  input_handler_->ScrollEnd(/*should_snap=*/true);
  handling_gesture_on_impl_thread_ = false;

  DCHECK(!gesture_pinch_in_progress_);
  currently_active_gesture_device_ = base::nullopt;
}

InputHandlerProxy::EventDisposition InputHandlerProxy::HitTestTouchEvent(
    const WebTouchEvent& touch_event,
    bool* is_touching_scrolling_layer,
    cc::TouchAction* allowed_touch_action) {
  TRACE_EVENT1("input", "InputHandlerProxy::HitTestTouchEvent",
               "Needs allowed TouchAction",
               static_cast<bool>(allowed_touch_action));
  *is_touching_scrolling_layer = false;
  EventDisposition result = DROP_EVENT;
  for (size_t i = 0; i < touch_event.touches_length; ++i) {
    if (touch_event.touch_start_or_first_touch_move)
      DCHECK(allowed_touch_action);
    else
      DCHECK(!allowed_touch_action);

    if (touch_event.GetType() == WebInputEvent::Type::kTouchStart &&
        touch_event.touches[i].state != WebTouchPoint::State::kStatePressed) {
      continue;
    }

    cc::TouchAction touch_action = cc::TouchAction::kAuto;
    cc::InputHandler::TouchStartOrMoveEventListenerType event_listener_type =
        input_handler_->EventListenerTypeForTouchStartOrMoveAt(
            gfx::Point(touch_event.touches[i].PositionInWidget().x(),
                       touch_event.touches[i].PositionInWidget().y()),
            &touch_action);
    if (allowed_touch_action && touch_action != cc::TouchAction::kAuto) {
      TRACE_EVENT_INSTANT1("input", "Adding TouchAction",
                           TRACE_EVENT_SCOPE_THREAD, "TouchAction",
                           cc::TouchActionToString(touch_action));
      *allowed_touch_action &= touch_action;
    }

    if (event_listener_type !=
        cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER) {
      TRACE_EVENT_INSTANT1("input", "HaveHandler", TRACE_EVENT_SCOPE_THREAD,
                           "Type", event_listener_type);

      *is_touching_scrolling_layer =
          event_listener_type ==
          cc::InputHandler::TouchStartOrMoveEventListenerType::
              HANDLER_ON_SCROLLING_LAYER;

      // A non-passive touch start / move will always set the allowed touch
      // action to TouchAction::kNone, and in that case we do not ack the event
      // from the compositor.
      if (allowed_touch_action &&
          *allowed_touch_action != cc::TouchAction::kNone) {
        TRACE_EVENT_INSTANT0("input", "NonBlocking due to allowed touchaction",
                             TRACE_EVENT_SCOPE_THREAD);
        result = DID_NOT_HANDLE_NON_BLOCKING;
      } else {
        TRACE_EVENT_INSTANT0("input", "DidNotHandle due to no touchaction",
                             TRACE_EVENT_SCOPE_THREAD);
        result = DID_NOT_HANDLE;
      }
      break;
    }
  }

  // If |result| is DROP_EVENT it wasn't processed above.
  if (result == DROP_EVENT) {
    auto event_listener_class = input_handler_->GetEventListenerProperties(
        cc::EventListenerClass::kTouchStartOrMove);
    TRACE_EVENT_INSTANT1("input", "DropEvent", TRACE_EVENT_SCOPE_THREAD,
                         "listener", event_listener_class);
    switch (event_listener_class) {
      case cc::EventListenerProperties::kPassive:
        result = DID_NOT_HANDLE_NON_BLOCKING;
        break;
      case cc::EventListenerProperties::kBlocking:
        // The touch area rects above already have checked whether it hits
        // a blocking region. Since it does not the event can be dropped.
        result = DROP_EVENT;
        break;
      case cc::EventListenerProperties::kBlockingAndPassive:
        // There is at least one passive listener that needs to possibly
        // be notified so it can't be dropped.
        result = DID_NOT_HANDLE_NON_BLOCKING;
        break;
      case cc::EventListenerProperties::kNone:
        result = DROP_EVENT;
        break;
      default:
        NOTREACHED();
        result = DROP_EVENT;
        break;
    }
  }

  // Depending on which arm of the SkipTouchEventFilter experiment we're on, we
  // may need to simulate a passive listener instead of dropping touch events.
  if (result == DROP_EVENT &&
      (skip_touch_filter_all_ ||
       (skip_touch_filter_discrete_ &&
        touch_event.GetType() == WebInputEvent::Type::kTouchStart))) {
    TRACE_EVENT_INSTANT0("input", "Non blocking due to skip filter",
                         TRACE_EVENT_SCOPE_THREAD);
    result = DID_NOT_HANDLE_NON_BLOCKING;
  }

  // Merge |touch_result_| and |result| so the result has the highest
  // priority value according to the sequence; (DROP_EVENT,
  // DID_NOT_HANDLE_NON_BLOCKING, DID_NOT_HANDLE).
  if (!touch_result_.has_value() || touch_result_ == DROP_EVENT ||
      result == DID_NOT_HANDLE) {
    TRACE_EVENT_INSTANT2(
        "input", "Update touch_result_", TRACE_EVENT_SCOPE_THREAD, "old",
        (touch_result_ ? touch_result_.value() : -1), "new", result);
    touch_result_ = result;
  }

  return result;
}

InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchStart(
    EventWithCallback* event_with_callback) {
  TRACE_EVENT0("input", "InputHandlerProxy::HandleTouchStart");
  const auto& touch_event =
      static_cast<const WebTouchEvent&>(event_with_callback->event());

  bool is_touching_scrolling_layer;
  cc::TouchAction allowed_touch_action = cc::TouchAction::kAuto;
  EventDisposition result = HitTestTouchEvent(
      touch_event, &is_touching_scrolling_layer, &allowed_touch_action);
  TRACE_EVENT_INSTANT1("input", "HitTest", TRACE_EVENT_SCOPE_THREAD,
                       "disposition", result);

  if (allowed_touch_action != cc::TouchAction::kNone &&
      touch_event.touches_length == 1) {
    DCHECK(touch_event.touches[0].state == WebTouchPoint::State::kStatePressed);
    cc::InputHandlerPointerResult pointer_result = HandlePointerDown(
        event_with_callback, touch_event.touches[0].PositionInWidget());
    if (pointer_result.type == cc::PointerResultType::kScrollbarScroll) {
      client_->SetAllowedTouchAction(
          allowed_touch_action, touch_event.unique_touch_event_id, DID_HANDLE);
      return DID_HANDLE;
    }
  }

  // If |result| is still DROP_EVENT look at the touch end handler as we may
  // not want to discard the entire touch sequence. Note this code is
  // explicitly after the assignment of the |touch_result_| in
  // HitTestTouchEvent so the touch moves are not sent to the main thread
  // un-necessarily.
  if (result == DROP_EVENT && input_handler_->GetEventListenerProperties(
                                  cc::EventListenerClass::kTouchEndOrCancel) !=
                                  cc::EventListenerProperties::kNone) {
    TRACE_EVENT_INSTANT0("input", "NonBlocking due to TouchEnd handler",
                         TRACE_EVENT_SCOPE_THREAD);
    result = DID_NOT_HANDLE_NON_BLOCKING;
  }

  bool is_in_inertial_scrolling_on_impl =
      in_inertial_scrolling_ && handling_gesture_on_impl_thread_;
  if (is_in_inertial_scrolling_on_impl && is_touching_scrolling_layer) {
    // If the touchstart occurs during a fling, it will be ACK'd immediately
    // and it and its following touch moves will be dispatched as non-blocking.
    // Due to tap suppression on the browser side, this will reset the
    // browser-side touch action (see comment in
    // TouchActionFilter::FilterGestureEvent for GestureScrollBegin). Ensure we
    // send back an allowed_touch_action that matches this non-blocking behavior
    // rather than treating it as if it'll block.
    TRACE_EVENT_INSTANT0("input", "NonBlocking due to fling",
                         TRACE_EVENT_SCOPE_THREAD);
    allowed_touch_action = cc::TouchAction::kAuto;
    result = DID_NOT_HANDLE_NON_BLOCKING_DUE_TO_FLING;
  }

  TRACE_EVENT_INSTANT2(
      "input", "Allowed TouchAction", TRACE_EVENT_SCOPE_THREAD, "TouchAction",
      cc::TouchActionToString(allowed_touch_action), "disposition", result);
  client_->SetAllowedTouchAction(allowed_touch_action,
                                 touch_event.unique_touch_event_id, result);

  return result;
}

InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchMove(
    EventWithCallback* event_with_callback) {
  const auto& touch_event =
      static_cast<const WebTouchEvent&>(event_with_callback->event());
  TRACE_EVENT2("input", "InputHandlerProxy::HandleTouchMove", "touch_result",
               touch_result_.has_value() ? touch_result_.value() : -1,
               "is_start_or_first",
               touch_event.touch_start_or_first_touch_move);
  if (touch_event.touches_length == 1) {
    cc::InputHandlerPointerResult pointer_result = HandlePointerMove(
        event_with_callback, touch_event.touches[0].PositionInWidget());
    if (pointer_result.type == cc::PointerResultType::kScrollbarScroll) {
      return DID_HANDLE;
    }
  }
  // Hit test if this is the first touch move or we don't have any results
  // from a previous hit test.
  if (!touch_result_.has_value() ||
      touch_event.touch_start_or_first_touch_move) {
    bool is_touching_scrolling_layer;
    cc::TouchAction allowed_touch_action = cc::TouchAction::kAuto;
    EventDisposition result = HitTestTouchEvent(
        touch_event, &is_touching_scrolling_layer, &allowed_touch_action);
    TRACE_EVENT_INSTANT2(
        "input", "Allowed TouchAction", TRACE_EVENT_SCOPE_THREAD, "TouchAction",
        cc::TouchActionToString(allowed_touch_action), "disposition", result);
    client_->SetAllowedTouchAction(allowed_touch_action,
                                   touch_event.unique_touch_event_id, result);
    return result;
  }
  return touch_result_.value();
}

InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchEnd(
    EventWithCallback* event_with_callback) {
  const auto& touch_event =
      static_cast<const WebTouchEvent&>(event_with_callback->event());
  TRACE_EVENT1("input", "InputHandlerProxy::HandleTouchEnd", "num_touches",
               touch_event.touches_length);
  if (touch_event.touches_length == 1) {
    cc::InputHandlerPointerResult pointer_result = HandlePointerUp(
        event_with_callback, touch_event.touches[0].PositionInWidget());
    if (pointer_result.type == cc::PointerResultType::kScrollbarScroll) {
      return DID_HANDLE;
    }
  }
  if (touch_event.touches_length == 1)
    touch_result_.reset();
  return DID_NOT_HANDLE;
}

void InputHandlerProxy::Animate(base::TimeTicks time) {
  if (elastic_overscroll_controller_)
    elastic_overscroll_controller_->Animate(time);

  snap_fling_controller_->Animate(time);

  // These animations can change the root scroll offset, so inform the
  // synchronous input handler.
  if (synchronous_input_handler_)
    input_handler_->RequestUpdateForSynchronousInputHandler();
}

void InputHandlerProxy::ReconcileElasticOverscrollAndRootScroll() {
  if (elastic_overscroll_controller_)
    elastic_overscroll_controller_->ReconcileStretchAndScroll();
}

void InputHandlerProxy::UpdateRootLayerStateForSynchronousInputHandler(
    const gfx::ScrollOffset& total_scroll_offset,
    const gfx::ScrollOffset& max_scroll_offset,
    const gfx::SizeF& scrollable_size,
    float page_scale_factor,
    float min_page_scale_factor,
    float max_page_scale_factor) {
  if (synchronous_input_handler_) {
    synchronous_input_handler_->UpdateRootLayerState(
        total_scroll_offset, max_scroll_offset, scrollable_size,
        page_scale_factor, min_page_scale_factor, max_page_scale_factor);
  }
}

void InputHandlerProxy::DeliverInputForBeginFrame(
    const viz::BeginFrameArgs& args) {
  // Block flushing the compositor gesture event queue while there's an async
  // scroll begin hit test outstanding. We'll flush the queue when the hit test
  // responds.
  if (hit_testing_scroll_begin_on_main_thread_) {
    DCHECK(base::FeatureList::IsEnabled(::features::kScrollUnification));
    return;
  }

  if (!scroll_predictor_)
    DispatchQueuedInputEvents();

  // Resampling GSUs and dispatch queued input events.
  while (!compositor_event_queue_->empty()) {
    std::unique_ptr<EventWithCallback> event_with_callback =
        scroll_predictor_->ResampleScrollEvents(compositor_event_queue_->Pop(),
                                                args.frame_time, args.interval);

    DispatchSingleInputEvent(std::move(event_with_callback), args.frame_time);
  }
}

void InputHandlerProxy::DeliverInputForHighLatencyMode() {
  // When prediction enabled, do not handle input after commit complete.
  if (!scroll_predictor_)
    DispatchQueuedInputEvents();
}

void InputHandlerProxy::SetSynchronousInputHandler(
    SynchronousInputHandler* synchronous_input_handler) {
  synchronous_input_handler_ = synchronous_input_handler;
  if (synchronous_input_handler_)
    input_handler_->RequestUpdateForSynchronousInputHandler();
}

void InputHandlerProxy::SynchronouslySetRootScrollOffset(
    const gfx::ScrollOffset& root_offset) {
  DCHECK(synchronous_input_handler_);
  input_handler_->SetSynchronousInputHandlerRootScrollOffset(root_offset);
}

void InputHandlerProxy::SynchronouslyZoomBy(float magnify_delta,
                                            const gfx::Point& anchor) {
  DCHECK(synchronous_input_handler_);
  input_handler_->PinchGestureBegin();
  input_handler_->PinchGestureUpdate(magnify_delta, anchor);
  input_handler_->PinchGestureEnd(anchor, false);
}

bool InputHandlerProxy::GetSnapFlingInfoAndSetAnimatingSnapTarget(
    const gfx::Vector2dF& natural_displacement,
    gfx::Vector2dF* initial_offset,
    gfx::Vector2dF* target_offset) const {
  return input_handler_->GetSnapFlingInfoAndSetAnimatingSnapTarget(
      natural_displacement, initial_offset, target_offset);
}

gfx::Vector2dF InputHandlerProxy::ScrollByForSnapFling(
    const gfx::Vector2dF& delta) {
  cc::ScrollState scroll_state = CreateScrollStateForInertialUpdate(delta);

  cc::InputHandlerScrollResult scroll_result =
      input_handler_->ScrollUpdate(&scroll_state, base::TimeDelta());
  return scroll_result.current_visual_offset;
}

void InputHandlerProxy::ScrollEndForSnapFling(bool did_finish) {
  input_handler_->ScrollEndForSnapFling(did_finish);
}

void InputHandlerProxy::RequestAnimationForSnapFling() {
  RequestAnimation();
}

void InputHandlerProxy::HandleOverscroll(
    const gfx::PointF& causal_event_viewport_point,
    const cc::InputHandlerScrollResult& scroll_result) {
  DCHECK(client_);
  if (!scroll_result.did_overscroll_root)
    return;

  TRACE_EVENT2("input", "InputHandlerProxy::DidOverscroll", "dx",
               scroll_result.unused_scroll_delta.x(), "dy",
               scroll_result.unused_scroll_delta.y());

  // Bundle overscroll message with triggering event response, saving an IPC.
  current_overscroll_params_ = std::make_unique<DidOverscrollParams>();
  current_overscroll_params_->accumulated_overscroll =
      scroll_result.accumulated_root_overscroll;
  current_overscroll_params_->latest_overscroll_delta =
      scroll_result.unused_scroll_delta;
  current_overscroll_params_->causal_event_viewport_point =
      causal_event_viewport_point;
  current_overscroll_params_->overscroll_behavior =
      scroll_result.overscroll_behavior;
  return;
}

void InputHandlerProxy::RequestAnimation() {
  input_handler_->SetNeedsAnimateInput();
}

void InputHandlerProxy::HandleScrollElasticityOverscroll(
    const WebGestureEvent& gesture_event,
    const cc::InputHandlerScrollResult& scroll_result) {
  DCHECK(elastic_overscroll_controller_);
  elastic_overscroll_controller_->ObserveGestureEventAndResult(gesture_event,
                                                               scroll_result);
}

void InputHandlerProxy::SetTickClockForTesting(
    const base::TickClock* tick_clock) {
  tick_clock_ = tick_clock;
}

const cc::InputHandlerPointerResult InputHandlerProxy::HandlePointerDown(
    EventWithCallback* event_with_callback,
    const gfx::PointF& position) {
  CHECK(input_handler_);
  if (input_handler_->HitTest(position) !=
      cc::PointerResultType::kScrollbarScroll)
    return cc::InputHandlerPointerResult();

  // Since a kScrollbarScroll is about to commence, ensure that any existing
  // ongoing scroll is ended.
  if (currently_active_gesture_device_.has_value()) {
    DCHECK_NE(*currently_active_gesture_device_,
              WebGestureDevice::kUninitialized);
    if (gesture_pinch_in_progress_) {
      input_handler_->PinchGestureEnd(gfx::ToFlooredPoint(position), true);
    }
    if (handling_gesture_on_impl_thread_) {
      input_handler_->RecordScrollEnd(
          GestureScrollInputType(*currently_active_gesture_device_));
      InputHandlerScrollEnd();
    }
  }

  // Generate GSB and GSU events and add them to the CompositorThreadEventQueue.
  // Note that the latency info passed in to InjectScrollbarGestureScroll is the
  // original LatencyInfo, not the one that may be currently monitored. The
  // currently monitored one may be modified by the call to
  // InjectScrollbarGestureScroll, as it will SetNeedsAnimateInput if the
  // CompositorThreadEventQueue is currently empty.
  // TODO(arakeri): Pass in the modifier instead of a bool once the refactor
  // (crbug.com/1022097) is done. For details, see crbug.com/1016955.
  const cc::InputHandlerPointerResult pointer_result =
      input_handler_->MouseDown(
          position, HasScrollbarJumpKeyModifier(event_with_callback->event()));
  InjectScrollbarGestureScroll(
      WebInputEvent::Type::kGestureScrollBegin, position, pointer_result,
      event_with_callback->latency_info(),
      event_with_callback->event().TimeStamp(), event_with_callback->metrics());

  // Don't need to inject GSU if the scroll offset is zero (this can be the case
  // where mouse down occurs on the thumb).
  if (!pointer_result.scroll_offset.IsZero()) {
    InjectScrollbarGestureScroll(WebInputEvent::Type::kGestureScrollUpdate,
                                 position, pointer_result,
                                 event_with_callback->latency_info(),
                                 event_with_callback->event().TimeStamp(),
                                 event_with_callback->metrics());
  }

  if (event_with_callback) {
    event_with_callback->SetScrollbarManipulationHandledOnCompositorThread();
  }

  return pointer_result;
}

const cc::InputHandlerPointerResult InputHandlerProxy::HandlePointerMove(
    EventWithCallback* event_with_callback,
    const gfx::PointF& position) {
  cc::InputHandlerPointerResult pointer_result =
      input_handler_->MouseMoveAt(gfx::Point(position.x(), position.y()));
  if (pointer_result.type == cc::PointerResultType::kScrollbarScroll) {
    // Generate a GSU event and add it to the CompositorThreadEventQueue if
    // delta is non zero.
    if (!pointer_result.scroll_offset.IsZero()) {
      InjectScrollbarGestureScroll(WebInputEvent::Type::kGestureScrollUpdate,
                                   position, pointer_result,
                                   event_with_callback->latency_info(),
                                   event_with_callback->event().TimeStamp(),
                                   event_with_callback->metrics());
    }
    if (event_with_callback) {
      event_with_callback->SetScrollbarManipulationHandledOnCompositorThread();
    }
  }
  return pointer_result;
}

const cc::InputHandlerPointerResult InputHandlerProxy::HandlePointerUp(
    EventWithCallback* event_with_callback,
    const gfx::PointF& position) {
  cc::InputHandlerPointerResult pointer_result =
      input_handler_->MouseUp(position);
  if (pointer_result.type == cc::PointerResultType::kScrollbarScroll) {
    // Generate a GSE and add it to the CompositorThreadEventQueue.
    InjectScrollbarGestureScroll(WebInputEvent::Type::kGestureScrollEnd,
                                 position, pointer_result,
                                 event_with_callback->latency_info(),
                                 event_with_callback->event().TimeStamp(),
                                 event_with_callback->metrics());
    if (event_with_callback) {
      event_with_callback->SetScrollbarManipulationHandledOnCompositorThread();
    }
  }
  return pointer_result;
}

}  // namespace blink
