// Copyright 2015 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 "content/renderer/input/render_widget_input_handler.h"

#include <stddef.h>
#include <stdint.h>
#include <utility>

#include "base/auto_reset.h"
#include "base/command_line.h"
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
#include "cc/paint/element_id.h"
#include "cc/trees/latency_info_swap_promise_monitor.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "content/common/input/input_event_ack.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/input_event_ack_state.h"
#include "content/public/renderer/render_frame.h"
#include "content/renderer/ime_event_guard.h"
#include "content/renderer/input/render_widget_input_handler_delegate.h"
#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_widget.h"
#include "third_party/blink/public/common/input/web_gesture_device.h"
#include "third_party/blink/public/common/input/web_gesture_event.h"
#include "third_party/blink/public/common/input/web_keyboard_event.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/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_node.h"
#include "ui/events/blink/event_with_callback.h"
#include "ui/events/blink/web_input_event_traits.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/latency/latency_info.h"

#if defined(OS_ANDROID)
#include <android/keycodes.h>
#endif

using blink::WebGestureEvent;
using blink::WebInputEvent;
using blink::WebInputEventResult;
using blink::WebKeyboardEvent;
using blink::WebMouseEvent;
using blink::WebMouseWheelEvent;
using blink::WebPointerEvent;
using blink::WebTouchEvent;
using blink::WebTouchPoint;
using ui::DidOverscrollParams;

namespace content {

namespace {

int64_t GetEventLatencyMicros(base::TimeTicks event_timestamp,
                              base::TimeTicks now) {
  return (now - event_timestamp).InMicroseconds();
}

void LogInputEventLatencyUma(const WebInputEvent& event, base::TimeTicks now) {
  UMA_HISTOGRAM_CUSTOM_COUNTS("Event.AggregatedLatency.Renderer2",
                              GetEventLatencyMicros(event.TimeStamp(), now), 1,
                              10000000, 100);
}

void LogPassiveEventListenersUma(WebInputEventResult result,
                                 WebInputEvent::DispatchType dispatch_type,
                                 base::TimeTicks event_timestamp,
                                 const ui::LatencyInfo& latency_info) {
  // This enum is backing a histogram. Do not remove or reorder members.
  enum ListenerEnum {
    PASSIVE_LISTENER_UMA_ENUM_PASSIVE,
    PASSIVE_LISTENER_UMA_ENUM_UNCANCELABLE,
    PASSIVE_LISTENER_UMA_ENUM_SUPPRESSED,
    PASSIVE_LISTENER_UMA_ENUM_CANCELABLE,
    PASSIVE_LISTENER_UMA_ENUM_CANCELABLE_AND_CANCELED,
    PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_FLING,
    PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_MAIN_THREAD_RESPONSIVENESS_DEPRECATED,
    PASSIVE_LISTENER_UMA_ENUM_COUNT
  };

  ListenerEnum enum_value;
  switch (dispatch_type) {
    case WebInputEvent::kListenersForcedNonBlockingDueToFling:
      enum_value = PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_FLING;
      break;
    case WebInputEvent::kListenersNonBlockingPassive:
      enum_value = PASSIVE_LISTENER_UMA_ENUM_PASSIVE;
      break;
    case WebInputEvent::kEventNonBlocking:
      enum_value = PASSIVE_LISTENER_UMA_ENUM_UNCANCELABLE;
      break;
    case WebInputEvent::kBlocking:
      if (result == WebInputEventResult::kHandledApplication)
        enum_value = PASSIVE_LISTENER_UMA_ENUM_CANCELABLE_AND_CANCELED;
      else if (result == WebInputEventResult::kHandledSuppressed)
        enum_value = PASSIVE_LISTENER_UMA_ENUM_SUPPRESSED;
      else
        enum_value = PASSIVE_LISTENER_UMA_ENUM_CANCELABLE;
      break;
    default:
      NOTREACHED();
      return;
  }

  UMA_HISTOGRAM_ENUMERATION("Event.PassiveListeners", enum_value,
                            PASSIVE_LISTENER_UMA_ENUM_COUNT);
}

void LogAllPassiveEventListenersUma(const WebInputEvent& input_event,
                                    WebInputEventResult result,
                                    const ui::LatencyInfo& latency_info) {
  // TODO(dtapuska): Use the input_event.timeStampSeconds as the start
  // ideally this should be when the event was sent by the compositor to the
  // renderer. https://crbug.com/565348.
  if (input_event.GetType() == WebInputEvent::kTouchStart ||
      input_event.GetType() == WebInputEvent::kTouchMove ||
      input_event.GetType() == WebInputEvent::kTouchEnd) {
    const WebTouchEvent& touch = static_cast<const WebTouchEvent&>(input_event);

    LogPassiveEventListenersUma(result, touch.dispatch_type,
                                input_event.TimeStamp(), latency_info);
  } else if (input_event.GetType() == WebInputEvent::kMouseWheel) {
    LogPassiveEventListenersUma(
        result,
        static_cast<const WebMouseWheelEvent&>(input_event).dispatch_type,
        input_event.TimeStamp(), latency_info);
  }
}

blink::WebCoalescedInputEvent GetCoalescedWebPointerEventForTouch(
    const WebPointerEvent& pointer_event,
    blink::WebVector<const WebInputEvent*> coalesced_events,
    blink::WebVector<const WebInputEvent*> predicted_events) {
  blink::WebVector<WebPointerEvent> related_pointer_events;
  for (const WebInputEvent* event : coalesced_events) {
    DCHECK(WebInputEvent::IsTouchEventType(event->GetType()));
    const WebTouchEvent& touch_event =
        static_cast<const WebTouchEvent&>(*event);
    for (unsigned i = 0; i < touch_event.touches_length; ++i) {
      if (touch_event.touches[i].id == pointer_event.id &&
          touch_event.touches[i].state != WebTouchPoint::kStateStationary) {
        related_pointer_events.emplace_back(
            WebPointerEvent(touch_event, touch_event.touches[i]));
      }
    }
  }
  blink::WebVector<WebPointerEvent> predicted_pointer_events;
  for (const WebInputEvent* event : predicted_events) {
    DCHECK(WebInputEvent::IsTouchEventType(event->GetType()));
    const WebTouchEvent& touch_event =
        static_cast<const WebTouchEvent&>(*event);
    for (unsigned i = 0; i < touch_event.touches_length; ++i) {
      if (touch_event.touches[i].id == pointer_event.id &&
          touch_event.touches[i].state != WebTouchPoint::kStateStationary) {
        predicted_pointer_events.emplace_back(
            WebPointerEvent(touch_event, touch_event.touches[i]));
      }
    }
  }

  return blink::WebCoalescedInputEvent(pointer_event, related_pointer_events,
                                       predicted_pointer_events);
}

viz::FrameSinkId GetRemoteFrameSinkId(const blink::WebHitTestResult& result) {
  const blink::WebNode& node = result.GetNode();
  DCHECK(!node.IsNull());
  blink::WebFrame* result_frame = blink::WebFrame::FromFrameOwnerElement(node);
  if (!result_frame || !result_frame->IsWebRemoteFrame())
    return viz::FrameSinkId();

  blink::WebRemoteFrame* remote_frame = result_frame->ToWebRemoteFrame();
  if (remote_frame->IsIgnoredForHitTest() || !result.ContentBoxContainsPoint())
    return viz::FrameSinkId();

  return RenderFrameProxy::FromWebFrame(remote_frame)->frame_sink_id();
}

InputEventAckState GetAckResult(WebInputEventResult processed) {
  return processed == WebInputEventResult::kNotHandled
             ? INPUT_EVENT_ACK_STATE_NOT_CONSUMED
             : INPUT_EVENT_ACK_STATE_CONSUMED;
}

}  // namespace

// This class should be placed on the stack when handling an input event. It
// stores information from callbacks from blink while handling an input event
// and allows them to be returned in the InputEventAck result.
class RenderWidgetInputHandler::HandlingState {
 public:
  HandlingState(base::WeakPtr<RenderWidgetInputHandler> input_handler_param,
                blink::WebInputEvent::Type type)
      : event_type(type), input_handler(std::move(input_handler_param)) {
    previous_was_handling_input = input_handler->handling_input_event_;
    previous_state = input_handler->handling_input_state_;
    input_handler->handling_input_event_ = true;
    input_handler->handling_input_state_ = this;
  }

  ~HandlingState() {
    // Unwinding the HandlingState on the stack might result in an
    // input_handler_ that got destroyed. i.e. via a nested event loop.
    if (!input_handler)
      return;
    input_handler->handling_input_event_ = previous_was_handling_input;
    DCHECK_EQ(input_handler->handling_input_state_, this);
    input_handler->handling_input_state_ = previous_state;
  }

  // Used to intercept overscroll notifications while an event is being
  // handled. If the event causes overscroll, the overscroll metadata can be
  // bundled in the event ack, saving an IPC.  Note that we must continue
  // supporting overscroll IPC notifications due to fling animation updates.
  std::unique_ptr<ui::DidOverscrollParams> event_overscroll;

  base::Optional<cc::TouchAction> touch_action;

  // Used to hold a sequence of parameters corresponding to scroll gesture
  // events that should be injected once the current input event is done
  // being processed.
  std::unique_ptr<
      std::vector<RenderWidgetInputHandler::InjectScrollGestureParams>>
      injected_scroll_params;

  // Type of the input event we are currently handling.
  blink::WebInputEvent::Type event_type;

 private:
  HandlingState* previous_state;
  bool previous_was_handling_input;
  base::WeakPtr<RenderWidgetInputHandler> input_handler;
};

RenderWidgetInputHandler::RenderWidgetInputHandler(
    RenderWidgetInputHandlerDelegate* delegate,
    RenderWidget* widget)
    : delegate_(delegate), widget_(widget) {
  DCHECK(delegate);
  DCHECK(widget);
  delegate->SetInputHandler(this);
}

RenderWidgetInputHandler::~RenderWidgetInputHandler() {}

viz::FrameSinkId RenderWidgetInputHandler::GetFrameSinkIdAtPoint(
    const gfx::PointF& point,
    gfx::PointF* local_point) {
  // This method must only be called on a local root, which is guaranteed to
  // have a WebWidget.
  // TODO(https://crbug.com/995981): Eventually we should be able to remove this
  // DCHECK, since RenderWidget's lifetime [and thus this instance's] will be
  // synchronized with the WebWidget.
  DCHECK(widget_->GetWebWidget());
  gfx::PointF point_in_pixel(point);
  if (widget_->compositor_deps()->IsUseZoomForDSFEnabled()) {
    point_in_pixel = gfx::ConvertPointToPixel(
        widget_->GetOriginalScreenInfo().device_scale_factor, point_in_pixel);
  }
  blink::WebHitTestResult result =
      widget_->GetWebWidget()->HitTestResultAt(ToRoundedPoint(point_in_pixel));

  blink::WebNode result_node = result.GetNode();
  *local_point = gfx::PointF(point);

  // TODO(crbug.com/797828): When the node is null the caller may
  // need to do extra checks. Like maybe update the layout and then
  // call the hit-testing API. Either way it might be better to have
  // a DCHECK for the node rather than a null check here.
  if (result_node.IsNull()) {
    return widget_->GetFrameSinkId();
  }

  viz::FrameSinkId frame_sink_id = GetRemoteFrameSinkId(result);
  if (frame_sink_id.is_valid()) {
    *local_point = gfx::PointF(result.LocalPointWithoutContentBoxOffset());
    if (widget_->compositor_deps()->IsUseZoomForDSFEnabled()) {
      *local_point = gfx::ConvertPointToDIP(
          widget_->GetOriginalScreenInfo().device_scale_factor, *local_point);
    }
    return frame_sink_id;
  }

  // Return the FrameSinkId for the current widget if the point did not hit
  // test to a remote frame, or the point is outside of the remote frame's
  // content box, or the remote frame doesn't have a valid FrameSinkId yet.
  return widget_->GetFrameSinkId();
}

WebInputEventResult RenderWidgetInputHandler::HandleTouchEvent(
    const blink::WebCoalescedInputEvent& coalesced_event) {
  const WebInputEvent& input_event = coalesced_event.Event();

  if (input_event.GetType() == WebInputEvent::kTouchScrollStarted) {
    WebPointerEvent pointer_event =
        WebPointerEvent::CreatePointerCausesUaActionEvent(
            blink::WebPointerProperties::PointerType::kUnknown,
            input_event.TimeStamp());
    return widget_->GetWebWidget()->HandleInputEvent(
        blink::WebCoalescedInputEvent(pointer_event));
  }

  const WebTouchEvent touch_event =
      static_cast<const WebTouchEvent&>(input_event);
  for (unsigned i = 0; i < touch_event.touches_length; ++i) {
    const WebTouchPoint& touch_point = touch_event.touches[i];
    if (touch_point.state != blink::WebTouchPoint::kStateStationary) {
      const WebPointerEvent& pointer_event =
          WebPointerEvent(touch_event, touch_point);
      const blink::WebCoalescedInputEvent& coalesced_pointer_event =
          GetCoalescedWebPointerEventForTouch(
              pointer_event, coalesced_event.GetCoalescedEventsPointers(),
              coalesced_event.GetPredictedEventsPointers());
      widget_->GetWebWidget()->HandleInputEvent(coalesced_pointer_event);
    }
  }
  return widget_->GetWebWidget()->DispatchBufferedTouchEvents();
}

void RenderWidgetInputHandler::HandleInputEvent(
    const blink::WebCoalescedInputEvent& coalesced_event,
    const ui::LatencyInfo& latency_info,
    HandledEventCallback callback) {
  const WebInputEvent& input_event = coalesced_event.Event();

  // Keep a WeakPtr to this RenderWidgetInputHandler to detect if executing the
  // input event destroyed the associated RenderWidget (and this handler).
  base::WeakPtr<RenderWidgetInputHandler> weak_self =
      weak_ptr_factory_.GetWeakPtr();
  HandlingState handling_state(weak_self, input_event.GetType());

#if defined(OS_ANDROID)
  ImeEventGuard guard(widget_->AsWeakPtr());
#endif

  base::TimeTicks start_time;
  if (base::TimeTicks::IsHighResolution())
    start_time = base::TimeTicks::Now();

  TRACE_EVENT1("renderer,benchmark,rail",
               "RenderWidgetInputHandler::OnHandleInputEvent", "event",
               WebInputEvent::GetName(input_event.GetType()));
  TRACE_EVENT_WITH_FLOW1("input,benchmark", "LatencyInfo.Flow",
                         TRACE_ID_GLOBAL(latency_info.trace_id()),
                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
                         "step", "HandleInputEventMain");

  // If we don't have a high res timer, these metrics won't be accurate enough
  // to be worth collecting. Note that this does introduce some sampling bias.
  if (!start_time.is_null())
    LogInputEventLatencyUma(input_event, start_time);

  ui::LatencyInfo swap_latency_info(latency_info);
  swap_latency_info.AddLatencyNumber(
      ui::LatencyComponentType::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT);
  cc::LatencyInfoSwapPromiseMonitor swap_promise_monitor(
      &swap_latency_info, widget_->layer_tree_host()->GetSwapPromiseManager(),
      nullptr);

  bool prevent_default = false;
  bool show_virtual_keyboard_for_mouse = false;
  if (WebInputEvent::IsMouseEventType(input_event.GetType())) {
    const WebMouseEvent& mouse_event =
        static_cast<const WebMouseEvent&>(input_event);
    TRACE_EVENT2("renderer", "HandleMouseMove", "x",
                 mouse_event.PositionInWidget().x(), "y",
                 mouse_event.PositionInWidget().y());

    prevent_default = delegate_->WillHandleMouseEvent(mouse_event);

    // Reset the last known cursor if mouse has left this widget. So next
    // time that the mouse enters we always set the cursor accordingly.
    if (mouse_event.GetType() == WebInputEvent::kMouseLeave)
      current_cursor_.reset();

    if (mouse_event.button == WebPointerProperties::Button::kLeft &&
        mouse_event.GetType() == WebInputEvent::kMouseUp) {
      show_virtual_keyboard_for_mouse = true;
    }
  }

  if (WebInputEvent::IsKeyboardEventType(input_event.GetType())) {
#if defined(OS_ANDROID)
    // The DPAD_CENTER key on Android has a dual semantic: (1) in the general
    // case it should behave like a select key (i.e. causing a click if a button
    // is focused). However, if a text field is focused (2), its intended
    // behavior is to just show the IME and don't propagate the key.
    // A typical use case is a web form: the DPAD_CENTER should bring up the IME
    // when clicked on an input text field and cause the form submit if clicked
    // when the submit button is focused, but not vice-versa.
    // The UI layer takes care of translating DPAD_CENTER into a RETURN key,
    // but at this point we have to swallow the event for the scenario (2).
    const WebKeyboardEvent& key_event =
        static_cast<const WebKeyboardEvent&>(input_event);
    if (key_event.native_key_code == AKEYCODE_DPAD_CENTER &&
        widget_->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE) {
      // Show the keyboard on keyup (not keydown) to match the behavior of
      // Android's TextView.
      if (key_event.GetType() == WebInputEvent::kKeyUp)
        widget_->ShowVirtualKeyboardOnElementFocus();
      // Prevent default for both keydown and keyup (letting the keydown go
      // through to the web app would cause compatibility problems since
      // DPAD_CENTER is also used as a "confirm" button).
      prevent_default = true;
    }
#endif
  }

  if (WebInputEvent::IsGestureEventType(input_event.GetType())) {
    const WebGestureEvent& gesture_event =
        static_cast<const WebGestureEvent&>(input_event);
    prevent_default =
        prevent_default || delegate_->WillHandleGestureEvent(gesture_event);
  }

  WebInputEventResult processed = prevent_default
                                      ? WebInputEventResult::kHandledSuppressed
                                      : WebInputEventResult::kNotHandled;
  if (input_event.GetType() != WebInputEvent::kChar ||
      !suppress_next_char_events_) {
    suppress_next_char_events_ = false;
    if (processed == WebInputEventResult::kNotHandled &&
        widget_->GetWebWidget()) {
      if (!widget_->GetWebWidget()->IsPepperWidget() &&
          WebInputEvent::IsTouchEventType(input_event.GetType()))
        processed = HandleTouchEvent(coalesced_event);
      else
        processed = widget_->GetWebWidget()->HandleInputEvent(coalesced_event);
    }

    // The associated RenderWidget (and this RenderWidgetInputHandler) could
    // have been destroyed. If it was return early before accessing any more of
    // this class.
    if (!weak_self) {
      if (callback) {
        std::move(callback).Run(GetAckResult(processed), swap_latency_info,
                                std::move(handling_state.event_overscroll),
                                handling_state.touch_action);
      }
      return;
    }
  }

  LogAllPassiveEventListenersUma(input_event, processed, latency_info);

  // If this RawKeyDown event corresponds to a browser keyboard shortcut and
  // it's not processed by webkit, then we need to suppress the upcoming Char
  // events.
  bool is_keyboard_shortcut =
      input_event.GetType() == WebInputEvent::kRawKeyDown &&
      static_cast<const WebKeyboardEvent&>(input_event).is_browser_shortcut;
  if (processed == WebInputEventResult::kNotHandled && is_keyboard_shortcut)
    suppress_next_char_events_ = true;

  // The handling of some input events on the main thread may require injecting
  // scroll gestures back into blink, e.g., a mousedown on a scrollbar. We
  // do this here so that we can attribute latency information from the mouse as
  // a scroll interaction, instead of just classifying as mouse input.
  if (handling_state.injected_scroll_params &&
      handling_state.injected_scroll_params->size()) {
    HandleInjectedScrollGestures(
        std::move(*handling_state.injected_scroll_params), input_event,
        latency_info);
  }

  // Send gesture scroll events and their dispositions to the compositor thread,
  // so that they can be used to produce the elastic overscroll effect on Mac.
  if (input_event.GetType() == WebInputEvent::kGestureScrollBegin ||
      input_event.GetType() == WebInputEvent::kGestureScrollEnd ||
      input_event.GetType() == WebInputEvent::kGestureScrollUpdate) {
    const WebGestureEvent& gesture_event =
        static_cast<const WebGestureEvent&>(input_event);
    if (gesture_event.SourceDevice() == blink::WebGestureDevice::kTouchpad) {
      gfx::Vector2dF latest_overscroll_delta =
          handling_state.event_overscroll
              ? handling_state.event_overscroll->latest_overscroll_delta
              : gfx::Vector2dF();
      cc::OverscrollBehavior overscroll_behavior =
          handling_state.event_overscroll
              ? handling_state.event_overscroll->overscroll_behavior
              : cc::OverscrollBehavior();
      delegate_->ObserveGestureEventAndResult(
          gesture_event, latest_overscroll_delta, overscroll_behavior,
          processed != WebInputEventResult::kNotHandled);
    }
  }

  if (callback) {
    std::move(callback).Run(GetAckResult(processed), swap_latency_info,
                            std::move(handling_state.event_overscroll),
                            handling_state.touch_action);
  } else {
    DCHECK(!handling_state.event_overscroll)
        << "Unexpected overscroll for un-acked event";
  }

  // Show the virtual keyboard if enabled and a user gesture triggers a focus
  // change.
  if ((processed != WebInputEventResult::kNotHandled &&
       input_event.GetType() == WebInputEvent::kTouchEnd) ||
      show_virtual_keyboard_for_mouse) {
    delegate_->ShowVirtualKeyboard();
  }

  if (!prevent_default &&
      WebInputEvent::IsKeyboardEventType(input_event.GetType()))
    delegate_->OnDidHandleKeyEvent();

// TODO(rouslan): Fix ChromeOS and Windows 8 behavior of autofill popup with
// virtual keyboard.
#if !defined(OS_ANDROID)
  // Virtual keyboard is not supported, so react to focus change immediately.
  if ((processed != WebInputEventResult::kNotHandled &&
       input_event.GetType() == WebInputEvent::kMouseDown) ||
      input_event.GetType() == WebInputEvent::kGestureTap) {
    delegate_->FocusChangeComplete();
  }
#endif

  // Ensure all injected scrolls were handled or queue up - any remaining
  // injected scrolls at this point would not be processed.
  DCHECK(!handling_state.injected_scroll_params ||
         (handling_state.injected_scroll_params)->empty());
}

void RenderWidgetInputHandler::DidOverscrollFromBlink(
    const gfx::Vector2dF& overscrollDelta,
    const gfx::Vector2dF& accumulatedOverscroll,
    const gfx::PointF& position,
    const gfx::Vector2dF& velocity,
    const cc::OverscrollBehavior& behavior) {
  std::unique_ptr<DidOverscrollParams> params(new DidOverscrollParams());
  params->accumulated_overscroll = accumulatedOverscroll;
  params->latest_overscroll_delta = overscrollDelta;
  params->current_fling_velocity = velocity;
  params->causal_event_viewport_point = position;
  params->overscroll_behavior = behavior;

  // If we're currently handling an event, stash the overscroll data such that
  // it can be bundled in the event ack.
  if (handling_input_state_) {
    handling_input_state_->event_overscroll = std::move(params);
    return;
  }

  delegate_->OnDidOverscroll(*params);
}

void RenderWidgetInputHandler::InjectGestureScrollEvent(
    blink::WebGestureDevice device,
    const gfx::Vector2dF& delta,
    ui::ScrollGranularity granularity,
    cc::ElementId scrollable_area_element_id,
    WebInputEvent::Type injected_type) {
  DCHECK(ui::IsGestureScroll(injected_type));
  // If we're currently handling an input event, cache the appropriate
  // parameters so we can dispatch the events directly once blink finishes
  // handling the event.
  // Otherwise, queue the event on the main thread event queue.
  // The latter may occur when scrollbar scrolls are injected due to
  // autoscroll timer - i.e. not within the handling of a mouse event.
  // We don't always just enqueue events, since events queued to the
  // MainThreadEventQueue in the middle of dispatch (which we are) won't
  // be dispatched until the next time the queue gets to run. The side effect
  // of that would be an extra frame of latency if we're injecting a scroll
  // during the handling of a rAF aligned input event, such as mouse move.
  if (handling_input_state_) {
    // Multiple gestures may be injected during the dispatch of a single
    // input event (e.g. Begin/Update). Create a vector and append to the
    // end of it - the gestures will subsequently be injected in order.
    if (!handling_input_state_->injected_scroll_params) {
      handling_input_state_->injected_scroll_params =
          std::make_unique<std::vector<InjectScrollGestureParams>>();
    }

    InjectScrollGestureParams params{device, delta, granularity,
                                     scrollable_area_element_id, injected_type};
    handling_input_state_->injected_scroll_params->push_back(params);
  } else {
    base::TimeTicks now = base::TimeTicks::Now();
    std::unique_ptr<WebGestureEvent> gesture_event =
        ui::GenerateInjectedScrollGesture(
            injected_type, now, device, gfx::PointF(0, 0), delta, granularity);
    if (injected_type == WebInputEvent::Type::kGestureScrollBegin) {
      gesture_event->data.scroll_begin.scrollable_area_element_id =
          scrollable_area_element_id.GetStableId();
    }

    ui::LatencyInfo latency_info;
    ui::WebScopedInputEvent web_scoped_gesture_event(gesture_event.release());

    widget_->GetInputEventQueue()->HandleEvent(
        std::move(web_scoped_gesture_event), latency_info,
        DISPATCH_TYPE_NON_BLOCKING, INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
        HandledEventCallback());
  }
}

void RenderWidgetInputHandler::HandleInjectedScrollGestures(
    std::vector<InjectScrollGestureParams> injected_scroll_params,
    const WebInputEvent& input_event,
    const ui::LatencyInfo& original_latency_info) {
  DCHECK(injected_scroll_params.size());

  base::TimeTicks original_timestamp;
  bool found_original_component = original_latency_info.FindLatency(
      ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, &original_timestamp);
  DCHECK(found_original_component);

  gfx::PointF position = ui::PositionInWidgetFromInputEvent(input_event);
  for (const InjectScrollGestureParams& params : injected_scroll_params) {
    // Set up a new LatencyInfo for the injected scroll - this is the original
    // LatencyInfo for the input event that was being handled when the scroll
    // was injected. This new LatencyInfo will have a modified type, and an
    // additional scroll update component. Also set up a SwapPromiseMonitor that
    // will cause the LatencyInfo to be sent up with the compositor frame, if
    // the GSU causes a commit. This allows end to end latency to be logged for
    // the injected scroll, annotated with the correct type.
    ui::LatencyInfo scrollbar_latency_info(original_latency_info);

    // Currently only scrollbar is supported - if this DCHECK hits due to a
    // new type being injected, please modify the type passed to
    // |set_source_event_type()|.
    DCHECK(params.device == blink::WebGestureDevice::kScrollbar);
    scrollbar_latency_info.set_source_event_type(
        ui::SourceEventType::SCROLLBAR);
    scrollbar_latency_info.AddLatencyNumber(
        ui::LatencyComponentType::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT);

    if (params.type == WebInputEvent::Type::kGestureScrollUpdate) {
      if (input_event.GetType() != WebInputEvent::Type::kGestureScrollUpdate) {
        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);
      } else {
        // If we're injecting a GSU in response to a GSU (touch drags of the
        // scrollbar thumb in Blink handles GSUs, and reverses them with
        // injected GSUs), the LatencyInfo will already have the appropriate
        // SCROLL_UPDATE component set.
        DCHECK(
            scrollbar_latency_info.FindLatency(
                ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
                nullptr) ||
            scrollbar_latency_info.FindLatency(
                ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
                nullptr));
      }
    }

    std::unique_ptr<WebGestureEvent> gesture_event =
        ui::GenerateInjectedScrollGesture(
            params.type, input_event.TimeStamp(), params.device, position,
            params.scroll_delta, params.granularity);
    if (params.type == WebInputEvent::Type::kGestureScrollBegin) {
      gesture_event->data.scroll_begin.scrollable_area_element_id =
          params.scrollable_area_element_id.GetStableId();
      last_injected_gesture_was_begin_ = true;
    } else {
      last_injected_gesture_was_begin_ = false;
    }

    {
      cc::LatencyInfoSwapPromiseMonitor swap_promise_monitor(
          &scrollbar_latency_info,
          widget_->layer_tree_host()->GetSwapPromiseManager(), nullptr);
      widget_->GetWebWidget()->HandleInputEvent(
          blink::WebCoalescedInputEvent(*gesture_event.get()));
    }
  }
}

bool RenderWidgetInputHandler::DidChangeCursor(const WebCursor& cursor) {
  if (current_cursor_.has_value() && current_cursor_.value() == cursor)
    return false;
  current_cursor_ = cursor;
  return true;
}

bool RenderWidgetInputHandler::ProcessTouchAction(
    cc::TouchAction touch_action) {
  if (!handling_input_state_)
    return false;
  // Ignore setTouchAction calls that result from synthetic touch events (eg.
  // when blink is emulating touch with mouse).
  if (handling_input_state_->event_type != WebInputEvent::kTouchStart)
    return false;

  handling_input_state_->touch_action = touch_action;
  return true;
}

}  // namespace content
