// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/devtools/protocol/input_handler.h"

#include <stddef.h>

#include <memory>
#include <tuple>
#include <utility>
#include <vector>

#include "base/check.h"
#include "base/check_deref.h"
#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/trace_event/trace_event.h"
#include "base/types/expected.h"
#include "components/input/render_widget_host_input_event_router.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/protocol/native_input_event_builder.h"
#include "content/browser/devtools/protocol/protocol.h"
#include "content/browser/renderer_host/data_transfer_util.h"
#include "content/browser/renderer_host/input/touch_emulator_impl.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/input/synthetic_pinch_gesture.h"
#include "content/common/input/synthetic_pinch_gesture_params.h"
#include "content/common/input/synthetic_pointer_action.h"
#include "content/common/input/synthetic_pointer_driver.h"
#include "content/common/input/synthetic_smooth_scroll_gesture.h"
#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
#include "content/common/input/synthetic_tap_gesture.h"
#include "content/common/input/synthetic_tap_gesture_params.h"
#include "content/public/common/content_features.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/page/page_zoom.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/blink/web_input_event_traits.h"
#include "ui/events/event_constants.h"
#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/range/range.h"

namespace content::protocol {

namespace {

gfx::PointF CssPixelsToPointF(double x, double y, float scale_factor) {
  return gfx::PointF(x * scale_factor, y * scale_factor);
}

gfx::Vector2dF CssPixelsToVector2dF(double x, double y, float scale_factor) {
  return gfx::Vector2dF(x * scale_factor, y * scale_factor);
}

bool StringToGestureSourceType(std::optional<std::string> in,
                               content::mojom::GestureSourceType& out) {
  if (!in.has_value()) {
    out = content::mojom::GestureSourceType::kDefaultInput;
    return true;
  }
  if (in.value() == Input::GestureSourceTypeEnum::Default) {
    out = content::mojom::GestureSourceType::kDefaultInput;
    return true;
  }
  if (in.value() == Input::GestureSourceTypeEnum::Touch) {
    out = content::mojom::GestureSourceType::kTouchInput;
    return true;
  }
  if (in.value() == Input::GestureSourceTypeEnum::Mouse) {
    out = content::mojom::GestureSourceType::kMouseInput;
    return true;
  }
  return false;
}

int GetEventModifiers(int modifiers,
                      bool auto_repeat,
                      bool is_keypad,
                      int location,
                      int buttons) {
  int result = blink::WebInputEvent::kFromDebugger;
  if (auto_repeat)
    result |= blink::WebInputEvent::kIsAutoRepeat;
  if (is_keypad)
    result |= blink::WebInputEvent::kIsKeyPad;

  if (modifiers & 1)
    result |= blink::WebInputEvent::kAltKey;
  if (modifiers & 2)
    result |= blink::WebInputEvent::kControlKey;
  if (modifiers & 4)
    result |= blink::WebInputEvent::kMetaKey;
  if (modifiers & 8)
    result |= blink::WebInputEvent::kShiftKey;

  if (location & 1)
    result |= blink::WebInputEvent::kIsLeft;
  if (location & 2)
    result |= blink::WebInputEvent::kIsRight;

  if (buttons & 1)
    result |= blink::WebMouseEvent::kLeftButtonDown;
  if (buttons & 2)
    result |= blink::WebInputEvent::kRightButtonDown;
  if (buttons & 4)
    result |= blink::WebInputEvent::kMiddleButtonDown;
  if (buttons & 8)
    result |= blink::WebInputEvent::kBackButtonDown;
  if (buttons & 16)
    result |= blink::WebInputEvent::kForwardButtonDown;
  return result;
}

base::TimeTicks GetEventTimeTicks(const std::optional<double>& timestamp) {
  // Convert timestamp, in seconds since unix epoch, to an event timestamp
  // which is time ticks since platform start time.
  return timestamp.has_value()
             ? base::Seconds(timestamp.value()) + base::TimeTicks::UnixEpoch()
             : base::TimeTicks::Now();
}

bool SetKeyboardEventText(
    base::span<char16_t, blink::WebKeyboardEvent::kTextLengthCap> to,
    std::optional<std::string> from) {
  if (!from.has_value()) {
    return true;
  }

  std::u16string text16 = base::UTF8ToUTF16(from.value());
  if (text16.size() >= to.size()) {
    return false;
  }

  base::span<char16_t> to_text;
  base::span<char16_t> to_nul;
  std::tie(to_text, to_nul) = to.split_at(text16.size());
  to_text.copy_from(text16);
  to_nul.front() = 0;
  return true;
}

bool GetMouseEventButton(const std::string& button,
                         blink::WebPointerProperties::Button* event_button,
                         int* event_modifiers) {
  *event_modifiers = blink::WebInputEvent::kFromDebugger;
  if (button.empty())
    return true;

  if (button == Input::MouseButtonEnum::None) {
    *event_button = blink::WebMouseEvent::Button::kNoButton;
  } else if (button == Input::MouseButtonEnum::Left) {
    *event_button = blink::WebMouseEvent::Button::kLeft;
    *event_modifiers |= blink::WebInputEvent::kLeftButtonDown;
  } else if (button == Input::MouseButtonEnum::Middle) {
    *event_button = blink::WebMouseEvent::Button::kMiddle;
    *event_modifiers |= blink::WebInputEvent::kMiddleButtonDown;
  } else if (button == Input::MouseButtonEnum::Right) {
    *event_button = blink::WebMouseEvent::Button::kRight;
    *event_modifiers |= blink::WebInputEvent::kRightButtonDown;
  } else if (button == Input::MouseButtonEnum::Back) {
    *event_button = blink::WebMouseEvent::Button::kBack;
    *event_modifiers |= blink::WebInputEvent::kBackButtonDown;
  } else if (button == Input::MouseButtonEnum::Forward) {
    *event_button = blink::WebMouseEvent::Button::kForward;
    *event_modifiers |= blink::WebInputEvent::kForwardButtonDown;
  } else {
    return false;
  }
  return true;
}

blink::WebInputEvent::Type GetMouseEventType(const std::string& type) {
  if (type == Input::DispatchMouseEvent::TypeEnum::MousePressed)
    return blink::WebInputEvent::Type::kMouseDown;
  if (type == Input::DispatchMouseEvent::TypeEnum::MouseReleased)
    return blink::WebInputEvent::Type::kMouseUp;
  if (type == Input::DispatchMouseEvent::TypeEnum::MouseMoved)
    return blink::WebInputEvent::Type::kMouseMove;
  if (type == Input::DispatchMouseEvent::TypeEnum::MouseWheel)
    return blink::WebInputEvent::Type::kMouseWheel;
  return blink::WebInputEvent::Type::kUndefined;
}

blink::WebInputEvent::Type GetTouchEventType(const std::string& type) {
  if (type == Input::DispatchTouchEvent::TypeEnum::TouchStart)
    return blink::WebInputEvent::Type::kTouchStart;
  if (type == Input::DispatchTouchEvent::TypeEnum::TouchEnd)
    return blink::WebInputEvent::Type::kTouchEnd;
  if (type == Input::DispatchTouchEvent::TypeEnum::TouchMove)
    return blink::WebInputEvent::Type::kTouchMove;
  if (type == Input::DispatchTouchEvent::TypeEnum::TouchCancel)
    return blink::WebInputEvent::Type::kTouchCancel;
  return blink::WebInputEvent::Type::kUndefined;
}

blink::WebPointerProperties::PointerType GetPointerType(
    const std::string& type) {
  if (type == Input::DispatchMouseEvent::PointerTypeEnum::Mouse)
    return blink::WebPointerProperties::PointerType::kMouse;
  if (type == Input::DispatchMouseEvent::PointerTypeEnum::Pen)
    return blink::WebPointerProperties::PointerType::kPen;
  return blink::WebPointerProperties::PointerType::kMouse;
}

SyntheticPointerActionParams::PointerActionType GetTouchPointerActionType(
    const std::string& type) {
  if (type == Input::DispatchTouchEvent::TypeEnum::TouchStart)
    return SyntheticPointerActionParams::PointerActionType::PRESS;
  if (type == Input::DispatchTouchEvent::TypeEnum::TouchEnd)
    return SyntheticPointerActionParams::PointerActionType::RELEASE;
  if (type == Input::DispatchTouchEvent::TypeEnum::TouchMove)
    return SyntheticPointerActionParams::PointerActionType::MOVE;
  if (type == Input::DispatchTouchEvent::TypeEnum::TouchCancel)
    return SyntheticPointerActionParams::PointerActionType::CANCEL;
  return SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED;
}

bool GenerateTouchPoints(
    blink::WebTouchEvent* event,
    blink::WebInputEvent::Type type,
    const base::flat_map<int, blink::WebTouchPoint>& points,
    const blink::WebTouchPoint& changing) {
  event->touches_length = 1;
  event->touches[0] = changing;
  for (auto& it : points) {
    if (it.first == changing.id)
      continue;
    if (event->touches_length == blink::WebTouchEvent::kTouchesLengthCap)
      return false;
    event->touches[event->touches_length] = it.second;
    event->touches[event->touches_length].state =
        type == blink::WebInputEvent::Type::kTouchCancel
            ? blink::WebTouchPoint::State::kStateCancelled
            : blink::WebTouchPoint::State::kStateStationary;
    event->touches_length++;
  }
  if (type == blink::WebInputEvent::Type::kTouchCancel ||
      type == blink::WebInputEvent::Type::kTouchEnd) {
    event->touches[0].state = type == blink::WebInputEvent::Type::kTouchCancel
                                  ? blink::WebTouchPoint::State::kStateCancelled
                                  : blink::WebTouchPoint::State::kStateReleased;
    event->SetType(type);
  } else if (!base::Contains(points, changing.id)) {
    event->touches[0].state = blink::WebTouchPoint::State::kStatePressed;
    event->SetType(blink::WebInputEvent::Type::kTouchStart);
  } else {
    event->touches[0].state = blink::WebTouchPoint::State::kStateMoved;
    event->SetType(blink::WebInputEvent::Type::kTouchMove);
  }
  return true;
}

std::string ValidatePointerEventProperties(double force,
                                           double tangential_pressure,
                                           double tilt_x,
                                           double tilt_y,
                                           int twist) {
  if (force < 0.0f || force > 1.0f) {
    return "'force' should be in the range of [0,1]";
  }
  if (tangential_pressure < -1.0f || tangential_pressure > 1.0f) {
    return "'tangential_pressure' should be in the range of [-1,1]";
  }
  if (tilt_x < -90.0f || tilt_x > 90.0f) {
    return "'tilt_x' should be in the range of [-90,90]";
  }
  if (tilt_y < -90.0f || tilt_y > 90.0f) {
    return "'tilt_y' should be in the range of [-90,90]";
  }
  if (twist < 0 || twist > 359)
    return "'twist' should be in the range of [0,359]";
  return "";
}

void SendSynthesizePinchGestureResponse(
    std::unique_ptr<Input::Backend::SynthesizePinchGestureCallback> callback,
    SyntheticGesture::Result result) {
  if (result == SyntheticGesture::Result::GESTURE_FINISHED) {
    callback->sendSuccess();
  } else {
    callback->sendFailure(Response::ServerError(
        base::StringPrintf("Synthetic pinch failed, result was %d", result)));
  }
}

class TapGestureResponse {
 public:
  TapGestureResponse(
      std::unique_ptr<Input::Backend::SynthesizeTapGestureCallback> callback,
      int count)
      : callback_(std::move(callback)),
        count_(count) {
  }

  void OnGestureResult(SyntheticGesture::Result result) {
    --count_;
    // Still waiting for more taps to finish.
    if (result == SyntheticGesture::Result::GESTURE_FINISHED && count_)
      return;
    if (callback_) {
      if (result == SyntheticGesture::Result::GESTURE_FINISHED) {
        callback_->sendSuccess();
      } else {
        callback_->sendFailure(Response::ServerError(
            base::StringPrintf("Synthetic tap failed, result was %d", result)));
      }
      callback_.reset();
    }
    if (!count_)
      delete this;
  }

 private:
  std::unique_ptr<Input::Backend::SynthesizeTapGestureCallback> callback_;
  int count_;
};

void SendSynthesizeScrollGestureResponse(
    std::unique_ptr<Input::Backend::SynthesizeScrollGestureCallback> callback,
    SyntheticGesture::Result result) {
  if (result == SyntheticGesture::Result::GESTURE_FINISHED) {
    callback->sendSuccess();
  } else {
    callback->sendFailure(Response::ServerError(
        base::StringPrintf("Synthetic scroll failed, result was %d", result)));
  }
}

void DispatchPointerActionsResponse(
    std::unique_ptr<Input::Backend::DispatchTouchEventCallback> callback,
    SyntheticGesture::Result result) {
  if (result == SyntheticGesture::Result::GESTURE_FINISHED) {
    callback->sendSuccess();
  } else {
    callback->sendFailure(Response::ServerError(
        base::StringPrintf("Action sequence failed, result was %d", result)));
  }
}

DropData ProtocolDragDataToDropData(std::unique_ptr<Input::DragData> data) {
  std::vector<blink::mojom::DragItemPtr> items;

  for (const auto& item : *data->GetItems()) {
    blink::mojom::DragItemStringPtr mojo_item =
        blink::mojom::DragItemString::New();
    mojo_item->string_type = item->GetMimeType();
    mojo_item->string_data = base::UTF8ToUTF16(item->GetData());
    if (item->HasBaseURL())
      mojo_item->base_url = GURL(item->GetBaseURL(""));
    if (item->HasTitle())
      mojo_item->title = base::UTF8ToUTF16(item->GetTitle(""));
    items.push_back(blink::mojom::DragItem::NewString(std::move(mojo_item)));
  }

  blink::mojom::DragDataPtr mojo_data = blink::mojom::DragData::New(
      std::move(items), std::nullopt,
      /*force_default_action=*/false, network::mojom::ReferrerPolicy::kDefault);
  DropData drop_data = DragDataToDropData(*mojo_data);

  protocol::Array<protocol::String> default_value;
  for (const auto& file : *data->GetFiles(&default_value)) {
    drop_data.filenames.emplace_back(base::FilePath::FromUTF8Unsafe(file),
                                     base::FilePath());
  }

  return drop_data;
}

base::expected<std::unique_ptr<blink::WebMouseEvent>, protocol::Response>
CreateWebMouseEvent(const std::string& event_type,
                    double x,
                    double y,
                    float scale_factor,
                    std::optional<int> modifiers,
                    std::optional<double> timestamp,
                    std::optional<std::string> button,
                    std::optional<int> buttons,
                    std::optional<int> click_count,
                    std::optional<double> force,
                    std::optional<double> tangential_pressure,
                    std::optional<double> tilt_x,
                    std::optional<double> tilt_y,
                    std::optional<int> twist,
                    std::optional<double> delta_x,
                    std::optional<double> delta_y,
                    std::optional<std::string> pointer_type) {
  blink::WebInputEvent::Type type = GetMouseEventType(event_type);
  if (type == blink::WebInputEvent::Type::kUndefined) {
    return base::unexpected(Response::InvalidParams(
        base::StringPrintf("Unexpected event type '%s'", event_type.c_str())));
  }

  blink::WebPointerProperties::Button event_button =
      blink::WebPointerProperties::Button::kNoButton;
  int button_modifiers = 0;
  if (!GetMouseEventButton(button.value_or(""), &event_button,
                           &button_modifiers)) {
    return base::unexpected(Response::InvalidParams("Invalid mouse button"));
  }

  int event_modifiers =
      GetEventModifiers(modifiers.value_or(blink::WebInputEvent::kNoModifiers),
                        false, false, 0, buttons.value_or(0));
  event_modifiers |= button_modifiers;
  base::TimeTicks event_timestamp = GetEventTimeTicks(timestamp);

  std::unique_ptr<blink::WebMouseEvent> mouse_event;

  if (type == blink::WebInputEvent::Type::kMouseWheel) {
    auto wheel_event = std::make_unique<blink::WebMouseWheelEvent>(
        type, event_modifiers, event_timestamp);
    if (!delta_x.has_value() || !delta_y.has_value()) {
      return base::unexpected(Response::InvalidParams(
          "'deltaX' and 'deltaY' are expected for mouseWheel event"));
    }
    wheel_event->delta_x = static_cast<float>(-delta_x.value());
    wheel_event->delta_y = static_cast<float>(-delta_y.value());
    if (wheel_event->delta_x != 0.0f) {
      wheel_event->wheel_ticks_x = wheel_event->delta_x > 0.0f ? 1.0f : -1.0f;
    }
    if (wheel_event->delta_y != 0.0f) {
      wheel_event->wheel_ticks_y = wheel_event->delta_y > 0.0f ? 1.0f : -1.0f;
    }
    wheel_event->phase = blink::WebMouseWheelEvent::kPhaseBegan;
    wheel_event->delta_units = ui::ScrollGranularity::kScrollByPrecisePixel;
    wheel_event->dispatch_type = blink::WebInputEvent::DispatchType::kBlocking;
    mouse_event = std::move(wheel_event);
  } else {
    mouse_event = std::make_unique<blink::WebMouseEvent>(type, event_modifiers,
                                                         event_timestamp);
    std::string message = ValidatePointerEventProperties(
        force.value_or(0), tangential_pressure.value_or(0), tilt_x.value_or(0),
        tilt_y.value_or(0), twist.value_or(0));
    if (!message.empty()) {
      return base::unexpected(Response::InvalidParams(message));
    }
  }

  mouse_event->button = event_button;
  mouse_event->click_count = click_count.value_or(0);
  mouse_event->pointer_type = GetPointerType(pointer_type.value_or(""));
  mouse_event->force = force.value_or(0);
  mouse_event->tangential_pressure = tangential_pressure.value_or(0);
  mouse_event->tilt_x = tilt_x.value_or(0);
  mouse_event->tilt_y = tilt_y.value_or(0);
  mouse_event->twist = twist.value_or(0);

  mouse_event->SetPositionInWidget(CssPixelsToPointF(x, y, scale_factor));
  mouse_event->SetPositionInScreen(mouse_event->PositionInWidget());

  return mouse_event;
}

base::expected<std::vector<blink::WebTouchEvent>, protocol::Response>
CreateWebTouchEvents(
    const std::string& event_type,
    std::optional<int> modifiers,
    std::optional<double> timestamp,
    float scale_factor,
    base::flat_map<blink::PointerId, blink::WebTouchPoint>& touched_points,
    std::unique_ptr<Array<Input::TouchPoint>> touch_points) {
  blink::WebInputEvent::Type type = GetTouchEventType(event_type);
  if (type == blink::WebInputEvent::Type::kUndefined) {
    return base::unexpected(Response::InvalidParams(
        base::StringPrintf("Unexpected event type '%s'", event_type.c_str())));
  }

  int event_modifiers =
      GetEventModifiers(modifiers.value_or(blink::WebInputEvent::kNoModifiers),
                        false, false, 0, 0);
  base::TimeTicks event_timestamp = GetEventTimeTicks(timestamp);

  if ((type == blink::WebInputEvent::Type::kTouchStart ||
       type == blink::WebInputEvent::Type::kTouchMove) &&
      touch_points->empty()) {
    return base::unexpected(Response::InvalidParams(
        "TouchStart and TouchMove must have at least one touch point."));
  }
  if (type == blink::WebInputEvent::Type::kTouchCancel &&
      !touch_points->empty()) {
    return base::unexpected(
        Response::InvalidParams("TouchCancel must not have any touch points."));
  }
  if (type != blink::WebInputEvent::Type::kTouchStart &&
      touched_points.empty()) {
    return base::unexpected(Response::InvalidParams(
        "Must send a TouchStart first to start a new touch."));
  }

  base::flat_map<blink::PointerId, blink::WebTouchPoint> points;
  size_t with_id = 0;
  for (size_t i = 0; i < touch_points->size(); ++i) {
    Input::TouchPoint* point = (*touch_points)[i].get();
    int id = point->GetId(i);  // index |i| is default for the id.
    if (point->HasId()) {
      with_id++;
    }
    std::string message = ValidatePointerEventProperties(
        point->GetForce(1.0f), point->GetTangentialPressure(0.0f),
        point->GetTiltX(0.0f), point->GetTiltY(0.0f), point->GetTwist(0));
    if (!message.empty()) {
      return base::unexpected(Response::InvalidParams(message));
    }
    points[id].id = id;
    points[id].radius_x = point->GetRadiusX(1.0f);
    points[id].radius_y = point->GetRadiusY(1.0f);
    points[id].rotation_angle = point->GetRotationAngle(0.0f);
    points[id].force = point->GetForce(1.0f);
    points[id].pointer_type = blink::WebPointerProperties::PointerType::kTouch;
    points[id].SetPositionInWidget(
        CssPixelsToPointF(point->GetX(), point->GetY(), scale_factor));
    points[id].SetPositionInScreen(points[id].PositionInScreen());
    points[id].tilt_x = point->GetTiltX(0);
    points[id].tilt_y = point->GetTiltY(0);
    points[id].tangential_pressure = point->GetTangentialPressure(0);
    points[id].twist = point->GetTwist(0);
  }
  if (with_id > 0 && with_id < touch_points->size()) {
    return base::unexpected(Response::InvalidParams(
        "All or none of the provided TouchPoints must supply ids."));
  }

  std::vector<blink::WebTouchEvent> events;
  bool ok = true;
  for (auto& id_point : points) {
    if (base::Contains(touched_points, id_point.first) &&
        type == blink::WebInputEvent::Type::kTouchMove &&
        touched_points[id_point.first].PositionInWidget() ==
            id_point.second.PositionInWidget()) {
      continue;
    }

    events.emplace_back(type, event_modifiers, event_timestamp);
    ok &= GenerateTouchPoints(&events.back(), type, touched_points,
                              id_point.second);
    if (type == blink::WebInputEvent::Type::kTouchStart ||
        type == blink::WebInputEvent::Type::kTouchMove) {
      touched_points[id_point.first] = id_point.second;
    } else if (type == blink::WebInputEvent::Type::kTouchEnd) {
      touched_points.erase(id_point.first);
    }
  }

  if (touch_points->size() == 0 && touched_points.size() > 0) {
    if (type == blink::WebInputEvent::Type::kTouchCancel) {
      events.emplace_back(type, event_modifiers, event_timestamp);
      ok &= GenerateTouchPoints(&events.back(), type, touched_points,
                                touched_points.begin()->second);
      touched_points.clear();
    } else if (type == blink::WebInputEvent::Type::kTouchEnd) {
      for (auto it = touched_points.begin(); it != touched_points.end();) {
        events.emplace_back(type, event_modifiers, event_timestamp);
        ok &= GenerateTouchPoints(&events.back(), type, touched_points,
                                  it->second);
        it = touched_points.erase(it);
      }
    }
  }
  if (!ok) {
    return base::unexpected(Response::ServerError(
        base::StringPrintf("Exceeded maximum touch points limit of %d",
                           blink::WebTouchEvent::kTouchesLengthCap)));
  }

  return events;
}

// Converts a point from the coordinate space of a given RenderWidgetHostView
// to the absolute screen coordinate space.
gfx::PointF ConvertWidgetPointToScreenPoint(
    RenderWidgetHostViewBase& view,
    const gfx::PointF& point_in_widget) {
  gfx::Rect view_bounds_in_screen = view.GetViewBounds();
  return point_in_widget + view_bounds_in_screen.OffsetFromOrigin();
}

}  // namespace

// FailSafe sends a failure to a given backend callback if the wrapper is never
// called. It's _only_ meant to be used when a OnceCallback isn't called due to
// a null WeakPtr. In any other situation, you should call this directly to be
// declarative (even when it's an internal error).
template <class BackendCallback>
class FailSafe {
 public:
  explicit FailSafe(std::unique_ptr<BackendCallback> callback)
      : callback_(std::move(callback)) {}
  ~FailSafe() {
    if (callback_) {
      sendFailure(Response::InternalError());
    }
  }

  FailSafe(const FailSafe& other) = delete;
  FailSafe& operator=(const FailSafe& other) = delete;

  FailSafe(FailSafe&& other) = default;
  FailSafe& operator=(FailSafe&& other) = default;

  void sendSuccess() {
    DCHECK(callback_) << "Already called before.";
    std::move(callback_)->sendSuccess();
  }
  void sendFailure(const DispatchResponse& response) {
    DCHECK(callback_) << "Already called before.";
    std::move(callback_)->sendFailure(response);
  }
  void fallThrough() {
    DCHECK(callback_) << "Already called before.";
    std::move(callback_)->fallthrough();
  }

  std::unique_ptr<BackendCallback> release() { return std::move(callback_); }

 private:
  std::unique_ptr<BackendCallback> callback_;
};

class InputHandler::InputInjector
    : public RenderWidgetHost::InputEventObserver {
 public:
  InputInjector(InputHandler* owner, RenderWidgetHostImpl* widget_host)
      : owner_(owner), widget_host_(widget_host->GetWeakPtr()) {
    widget_host->AddInputEventObserver(this);
    // Make sure the input event observer is not blocked by browser-side
    // paint-holding.
    widget_host_->ForceFirstFrameAfterNavigationTimeout();
  }

  InputInjector(const InputInjector&) = delete;
  InputInjector& operator=(const InputInjector&) = delete;

  void Cleanup() {
    for (auto& callback : pending_key_callbacks_)
      callback->sendSuccess();
    pending_key_callbacks_.clear();
    for (auto& callback : pending_mouse_callbacks_)
      callback->sendSuccess();
    pending_mouse_callbacks_.clear();
    MaybeSelfDestruct();
  }

  bool HasWidgetHost(RenderWidgetHostImpl* widget_host) {
    return widget_host == widget_host_.get();
  }

  void InjectWheelEvent(blink::WebMouseWheelEvent* wheel_event,
                        std::unique_ptr<DispatchMouseEventCallback> callback) {
    if (!widget_host_) {
      callback->sendFailure(Response::InternalError());
      return;
    }

    widget_host_->Focus();
    input_queued_ = false;
    pending_mouse_callbacks_.push_back(std::move(callback));
    // This may destroy the injector if the events get discarded.
    base::WeakPtr<InputHandler::InputInjector> weak_this =
        weak_ptr_factory_.GetWeakPtr();
    widget_host_->ForwardWheelEvent(*wheel_event);
    if (!weak_this) {
      return;
    }
    if (!input_queued_) {
      pending_mouse_callbacks_.back()->sendSuccess();
      pending_mouse_callbacks_.pop_back();
      MaybeSelfDestruct();
      return;
    }

    // Send a synthetic wheel event with phaseEnded to finish scrolling.
    wheel_event->delta_x = 0;
    wheel_event->delta_y = 0;
    wheel_event->wheel_ticks_x = 0;
    wheel_event->wheel_ticks_y = 0;
    wheel_event->phase = blink::WebMouseWheelEvent::kPhaseEnded;
    wheel_event->dispatch_type =
        blink::WebInputEvent::DispatchType::kEventNonBlocking;
    widget_host_->ForwardWheelEvent(*wheel_event);
  }

  void InjectMouseEvent(const blink::WebMouseEvent& mouse_event,
                        std::unique_ptr<DispatchMouseEventCallback> callback) {
    if (!widget_host_) {
      callback->sendFailure(Response::InternalError());
      return;
    }

    if (owner_->drag_controller_.HandleMouseEvent(*widget_host_, mouse_event,
                                                  callback)) {
      return;
    }

    widget_host_->Focus();
    input_queued_ = false;
    pending_mouse_callbacks_.push_back(std::move(callback));
    // This may destroy the injector if the events get discarded.
    base::WeakPtr<InputHandler::InputInjector> weak_this =
        weak_ptr_factory_.GetWeakPtr();
    widget_host_->ForwardMouseEvent(mouse_event);
    if (!weak_this) {
      return;
    }
    if (!input_queued_) {
      pending_mouse_callbacks_.back()->sendSuccess();
      pending_mouse_callbacks_.pop_back();
      MaybeSelfDestruct();
    }
  }

  void InjectKeyboardEvent(const input::NativeWebKeyboardEvent& keyboard_event,
                           std::unique_ptr<Array<std::string>> commands,
                           std::unique_ptr<DispatchKeyEventCallback> callback) {
    if (!widget_host_) {
      callback->sendFailure(Response::InternalError());
      return;
    }

    widget_host_->Focus();
    input_queued_ = false;
    pending_key_callbacks_.push_back(std::move(callback));
    ui::LatencyInfo latency;
    std::vector<blink::mojom::EditCommandPtr> edit_commands;
    if (commands) {
      for (const std::string& command : *commands) {
        edit_commands.push_back(blink::mojom::EditCommand::New(command, ""));
      }
    }
    // This may close the target, for example, if pressing Ctrl+W.
    base::WeakPtr<InputHandler::InputInjector> weak_this =
        weak_ptr_factory_.GetWeakPtr();
    widget_host_->ForwardKeyboardEventWithCommands(keyboard_event, latency,
                                                   std::move(edit_commands));
    if (!weak_this)
      return;
    if (!input_queued_) {
      pending_key_callbacks_.back()->sendSuccess();
      pending_key_callbacks_.pop_back();
      MaybeSelfDestruct();
    }
  }

  void InjectTouchEvents(const std::vector<blink::WebTouchEvent>& events,
                         std::unique_ptr<DispatchTouchEventCallback> callback) {
    if (!widget_host_) {
      callback->sendFailure(Response::InternalError());
      return;
    }

    widget_host_->Focus();
    widget_host_->GetTouchEmulator(/*create_if_necessary=*/true)
        ->Enable(input::TouchEmulator::Mode::kInjectingTouchEvents,
                 ui::GestureProviderConfigType::CURRENT_PLATFORM);
    base::OnceClosure closure = base::BindOnce(
        &DispatchTouchEventCallback::sendSuccess, std::move(callback));
    // This may destroy the injector if the events get discarded.
    base::WeakPtr<InputHandler::InputInjector> weak_this =
        weak_ptr_factory_.GetWeakPtr();
    for (size_t i = 0; i < events.size(); i++) {
      widget_host_->GetTouchEmulator(/*create_if_necessary=*/true)
          ->InjectTouchEvent(events[i], widget_host_->GetView(),
                             i == events.size() - 1 ? std::move(closure)
                                                    : base::OnceClosure());
      if (!weak_this) {
        return;
      }
    }
    MaybeSelfDestruct();
  }

 private:
  void OnInputEvent(const RenderWidgetHost& widget,
                    const blink::WebInputEvent& event) override {
    input_queued_ = true;
  }

  void OnInputEventAck(const RenderWidgetHost& widget,
                       blink::mojom::InputEventResultSource source,
                       blink::mojom::InputEventResultState state,
                       const blink::WebInputEvent& event) override {
    if ((event.GetModifiers() & blink::WebInputEvent::kFromDebugger) == 0)
      return;

    if (blink::WebInputEvent::IsKeyboardEventType(event.GetType()) &&
        !pending_key_callbacks_.empty()) {
      pending_key_callbacks_.front()->sendSuccess();
      pending_key_callbacks_.pop_front();
      MaybeSelfDestruct();
      return;
    }

    if ((blink::WebInputEvent::IsMouseEventType(event.GetType()) ||
         event.GetType() == blink::WebInputEvent::Type::kMouseWheel) &&
        !pending_mouse_callbacks_.empty()) {
      auto callback = std::move(pending_mouse_callbacks_.front());
      pending_mouse_callbacks_.pop_front();
      // We need to handle the event in the drag controller in case drag was
      // initiated at some point between dispatch and now because the event will
      // have been ignored during dispatch in this case.
      //
      // Note this also applies to the mouse move that triggers the drag, so
      // HandleMouseEvent has special logic to handle this specific case.
      if (!widget_host_ ||
          !owner_->drag_controller_.HandleMouseEvent(
              *widget_host_, static_cast<const blink::WebMouseEvent&>(event),
              callback)) {
        callback->sendSuccess();
      }
      MaybeSelfDestruct();
      return;
    }
  }

  void MaybeSelfDestruct() {
    if (!pending_key_callbacks_.empty() || !pending_mouse_callbacks_.empty())
      return;
    if (widget_host_)
      widget_host_->RemoveInputEventObserver(this);
    owner_->injectors_.erase(this);
  }

  const raw_ptr<InputHandler> owner_;
  base::WeakPtr<RenderWidgetHostImpl> widget_host_;
  // Callbacks for calls to Input.dispatchKey/MouseEvent that have been sent to
  // the renderer, but that we haven't yet received an ack for.
  bool input_queued_ = false;
  base::circular_deque<std::unique_ptr<DispatchKeyEventCallback>>
      pending_key_callbacks_;
  base::circular_deque<std::unique_ptr<DispatchMouseEventCallback>>
      pending_mouse_callbacks_;
  base::WeakPtrFactory<InputHandler::InputInjector> weak_ptr_factory_{this};
};

struct InputHandler::DragController::DragState {
  DropData data;
  blink::DragOperationsMask mask;
  base::WeakPtr<RenderWidgetHostImpl> host;
  gfx::PointF pos;
  // Acts as a counting semaphore for concurrent updates.
  size_t updating;
  base::OnceClosure updated_callback;
};

struct InputHandler::DragController::InitialState {
  std::unique_ptr<blink::WebMouseEvent> event;
  base::WeakPtr<RenderWidgetHostImpl> host;
};

InputHandler::DragController::DragController(InputHandler& handler)
    : handler_(handler) {}

InputHandler::DragController::~DragController() = default;

bool InputHandler::DragController::HandleMouseEvent(
    RenderWidgetHostImpl& host,
    const blink::WebMouseEvent& event,
    std::unique_ptr<DispatchMouseEventCallback>& callback) {
  if (!drag_state_) {
    switch (event.GetType()) {
      case blink::mojom::EventType::kMouseMove:
        // Check if the user started a mouse down through CDP.
        if (initial_state_) {
          // Set the move event in case dragging starts from this event.
          initial_state_->event = std::make_unique<blink::WebMouseEvent>(event);
          initial_state_->host = host.GetWeakPtr();
        }
        break;
      case blink::mojom::EventType::kMouseDown:
        // If the user performs a mouse down using CDP, then set the initial
        // state. OS dragging is not possible beyond this point.
        initial_state_ = std::make_unique<InitialState>();
        break;
      case blink::mojom::EventType::kMouseUp:
        // If the user performs a mouse up using CDP, then reset the initial
        // state. OS dragging is possible beyond this point.
        initial_state_ = nullptr;
        break;
      default:
        break;
    }
    return false;
  }
  switch (event.GetType()) {
    case blink::mojom::EventType::kMouseMove:
      // It's possible that the mouse movement that starts a drag is acked
      // after dragging starts. When this happens,
      //
      //  1. `StartDragging` will update the drag state with the mouse
      //     movement (through `last_mouse_move_`), then
      //  2. the mouse movement (this time from acking in `OnInputEventAck`)
      //     will attempt to update the drag state _again_ and go through this
      //     branch.
      //
      // Since we only want the mouse movement to update the drag state once,
      // we attempt to stop it here.
      //
      // Since we don't have unique identifiers for each event, the best we
      // can hope for is the timestamps are the same.
      //
      // Note that in general, the mouse movement will be acked before the
      // dragging starts, so this should happen rarely.
      if (initial_state_) {
        CHECK(initial_state_->event);
        auto timestamp = initial_state_->event->TimeStamp();
        initial_state_ = nullptr;
        if (timestamp == event.TimeStamp()) {
          return false;
        }
      }
      UpdateDragging(host, std::make_unique<blink::WebMouseEvent>(event),
                     std::make_unique<FailSafe<DispatchMouseEventCallback>>(
                         std::move(callback)));
      return true;
    case blink::mojom::EventType::kMouseUp:
      EndDragging(&host, std::make_unique<blink::WebMouseEvent>(event),
                  std::make_unique<FailSafe<DispatchMouseEventCallback>>(
                      std::move(callback)));
      return true;
    default:
      break;
  }
  return false;
}

void InputHandler::DragController::EnsureDraggingEntered(
    RenderWidgetHostImpl& host,
    const blink::WebMouseEvent& event) {
  // If the host is the same, then we've already entered into the widget.
  if (drag_state_->host.get() == &host) {
    return;
  }
  // If we entered a widget previously, we need to leave it.
  if (drag_state_->host) {
    drag_state_->host->DragTargetDragLeave(drag_state_->pos, drag_state_->pos);
  }
  drag_state_->data.view_id = host.GetRoutingID();
  host.DragTargetDragEnter(drag_state_->data, drag_state_->pos,
                           drag_state_->pos, drag_state_->mask,
                           event.GetModifiers(), base::DoNothing());
  drag_state_->host = host.GetWeakPtr();
}

void InputHandler::DragController::StartDragging(
    const content::DropData& drop_data,
    blink::DragOperationsMask drag_operations_mask) {
  if (!initial_state_->host || !initial_state_->event) {
    CancelDragging(base::DoNothing());
    return;
  }

  drag_state_ = std::make_unique<DragState>(
      DragState{drop_data, drag_operations_mask, nullptr, gfx::PointF(), 0,
                base::DoNothing()});
  UpdateDragging(*initial_state_->host,
                 // Note we don't move it here. See
                 // InputHandler::DragController::HandleMouseEvent.
                 std::make_unique<blink::WebMouseEvent>(*initial_state_->event),
                 nullptr);
}

void InputHandler::DragController::CancelDragging(base::OnceClosure callback) {
  if (!drag_state_ || !drag_state_->host) {
    if (auto* view = handler_->GetRootView()) {
      view->GetRenderWidgetHost()->DragSourceSystemDragEnded();
    }
    std::move(callback).Run();
    return;
  }

  drag_state_->host->DragTargetDragLeave(drag_state_->pos, drag_state_->pos);
  drag_state_->host->DragSourceEndedAt(drag_state_->pos, drag_state_->pos,
                                       ui::mojom::DragOperation::kNone,
                                       std::move(callback));
}

void InputHandler::DragController::UpdateDragging(
    RenderWidgetHostImpl& host,
    std::unique_ptr<blink::WebMouseEvent> event,
    std::unique_ptr<FailSafe<DispatchMouseEventCallback>> callback) {
  ++drag_state_->updating;

  drag_state_->pos = event->PositionInWidget();

  EnsureDraggingEntered(host, *event);
  const int modifiers = event->GetModifiers();
  drag_state_->host->DragTargetDragOver(
      drag_state_->pos, drag_state_->pos, drag_state_->mask, modifiers,
      base::BindOnce(&InputHandler::DragController::DragUpdated,
                     weak_factory_.GetWeakPtr(), std::move(event),
                     std::move(callback)));
}

void InputHandler::DragController::DragUpdated(
    std::unique_ptr<blink::WebMouseEvent> event,
    std::unique_ptr<FailSafe<DispatchMouseEventCallback>> callback,
    ui::mojom::DragOperation operation,
    bool document_is_handling_drag) {
  if (!drag_state_) {
    // Dragging ended, perhaps due to a previous mouse up or a drag
    // cancellation.
    handler_->HandleMouseEvent(std::move(event), callback->release());
    return;
  }
  drag_state_->data.operation = operation;
  drag_state_->data.document_is_handling_drag = document_is_handling_drag;

  --drag_state_->updating;
  if (callback) {
    callback->sendSuccess();
  }

  if (drag_state_->updating == 0 && drag_state_->updated_callback) {
    std::move(drag_state_->updated_callback).Run();
  }
}

void InputHandler::DragController::EndDragging(
    RenderWidgetHostImpl* host_hint,
    std::unique_ptr<blink::WebMouseEvent> event,
    std::unique_ptr<FailSafe<DispatchMouseEventCallback>> callback) {
  if (!drag_state_) {
    // Dragging already ended.
    return;
  }
  if (drag_state_->updating > 0) {
    auto update_callback = base::BindOnce(
        &InputHandler::DragController::EndDragging, weak_factory_.GetWeakPtr(),
        nullptr, std::move(event), std::move(callback));
    // Chaining callbacks to ensure none get replaced.
    drag_state_->updated_callback =
        drag_state_->updated_callback ? std::move(drag_state_->updated_callback)
                                            .Then(std::move(update_callback))
                                      : std::move(update_callback);
    return;
  }
  if (host_hint) {
    EndDraggingWithRenderWidgetHostAtPoint(
        std::move(event), std::move(callback),
        host_hint->GetRenderWidgetHostViewBase()->GetWeakPtr(),
        drag_state_->pos);
    return;
  }
  handler_->web_contents_->GetRenderWidgetHostAtPointAsynchronously(
      handler_->GetRootView(), drag_state_->pos,
      base::BindOnce(
          &InputHandler::DragController::EndDraggingWithRenderWidgetHostAtPoint,
          weak_factory_.GetWeakPtr(), std::move(event), std::move(callback)));
}

void InputHandler::DragController::EndDraggingWithRenderWidgetHostAtPoint(
    std::unique_ptr<blink::WebMouseEvent> event,
    std::unique_ptr<FailSafe<DispatchMouseEventCallback>> callback,
    base::WeakPtr<RenderWidgetHostViewBase> view,
    std::optional<gfx::PointF> maybe_point) {
  if (!view || !maybe_point) {
    CancelDragging(
        base::BindOnce(&FailSafe<DispatchMouseEventCallback>::sendFailure,
                       std::move(callback), DispatchResponse::InternalError()));
    return;
  }
  if (!drag_state_) {
    // Dragging ended, perhaps due to a previous mouse up or a drag
    // cancellation.
    handler_->OnWidgetForDispatchMouseEvent(
        callback->release(), std::move(event), view, maybe_point);
    return;
  }
  auto* host = RenderWidgetHostImpl::From(view->GetRenderWidgetHost());
  auto point = *maybe_point;

  host->DragTargetDrop(drag_state_->data, point, point, event->GetModifiers(),
                       base::DoNothing());
  host->DragSourceEndedAt(
      point, point, drag_state_->data.operation,
      base::BindOnce(&FailSafe<DispatchMouseEventCallback>::sendSuccess,
                     std::move(callback)));
}

InputHandler::InputHandler(bool allow_file_access,
                           bool allow_sending_input_to_browser)
    : DevToolsDomainHandler(Input::Metainfo::domainName),
      drag_controller_(*this),
      allow_file_access_(allow_file_access),
      allow_sending_input_to_browser_(allow_sending_input_to_browser) {}

InputHandler::~InputHandler() = default;

// static
std::vector<InputHandler*> InputHandler::ForAgentHost(
    DevToolsAgentHostImpl* host) {
  return host->HandlersByName<InputHandler>(Input::Metainfo::domainName);
}

void InputHandler::SetRenderer(int process_host_id,
                               RenderFrameHostImpl* frame_host) {
  if (frame_host == host_)
    return;
  ClearInputState();

  auto* old_web_contents = WebContentsImpl::FromRenderFrameHostImpl(host_);
  host_ = frame_host;
  web_contents_ = WebContentsImpl::FromRenderFrameHostImpl(host_);

  if (ignore_input_events_ && old_web_contents != web_contents_) {
    if (web_contents_) {
      scoped_ignore_input_events_ =
          web_contents_->IgnoreInputEvents(std::nullopt);
    } else {
      scoped_ignore_input_events_.reset();
    }
  }
}

void InputHandler::Wire(UberDispatcher* dispatcher) {
  frontend_ = std::make_unique<Input::Frontend>(dispatcher->channel());
  Input::Dispatcher::wire(dispatcher, this);
}

Response InputHandler::Disable() {
  ClearInputState();
  scoped_ignore_input_events_.reset();
  ignore_input_events_ = false;
  pointer_ids_.clear();
  touch_points_.clear();
  return Response::Success();
}

void InputHandler::DispatchKeyEvent(
    const std::string& type,
    std::optional<int> modifiers,
    std::optional<double> timestamp,
    std::optional<std::string> text,
    std::optional<std::string> unmodified_text,
    std::optional<std::string> key_identifier,
    std::optional<std::string> code,
    std::optional<std::string> key,
    std::optional<int> windows_virtual_key_code,
    std::optional<int> native_virtual_key_code,
    std::optional<bool> auto_repeat,
    std::optional<bool> is_keypad,
    std::optional<bool> is_system_key,
    std::optional<int> location,
    std::unique_ptr<Array<std::string>> commands,
    std::unique_ptr<DispatchKeyEventCallback> callback) {
  blink::WebInputEvent::Type web_event_type;

  if (type == Input::DispatchKeyEvent::TypeEnum::KeyDown) {
    web_event_type = blink::WebInputEvent::Type::kKeyDown;
  } else if (type == Input::DispatchKeyEvent::TypeEnum::KeyUp) {
    web_event_type = blink::WebInputEvent::Type::kKeyUp;
  } else if (type == Input::DispatchKeyEvent::TypeEnum::Char) {
    web_event_type = blink::WebInputEvent::Type::kChar;
  } else if (type == Input::DispatchKeyEvent::TypeEnum::RawKeyDown) {
    web_event_type = blink::WebInputEvent::Type::kRawKeyDown;
  } else {
    callback->sendFailure(Response::InvalidParams(
        base::StringPrintf("Unexpected event type '%s'", type.c_str())));
    return;
  }

  input::NativeWebKeyboardEvent event(
      web_event_type,
      GetEventModifiers(modifiers.value_or(blink::WebInputEvent::kNoModifiers),
                        auto_repeat.value_or(false), is_keypad.value_or(false),
                        location.value_or(0), 0),
      GetEventTimeTicks(timestamp));

  if (!SetKeyboardEventText(event.text, std::move(text))) {
    callback->sendFailure(Response::InvalidParams("Invalid 'text' parameter"));
    return;
  }
  if (!SetKeyboardEventText(event.unmodified_text,
                            std::move(unmodified_text))) {
    callback->sendFailure(
        Response::InvalidParams("Invalid 'unmodifiedText' parameter"));
    return;
  }

  if (windows_virtual_key_code.has_value()) {
    event.windows_key_code = windows_virtual_key_code.value();
  }
  if (native_virtual_key_code.has_value()) {
    event.native_key_code = native_virtual_key_code.value();
  }
  if (is_system_key.has_value()) {
    event.is_system_key = is_system_key.value();
  }

  if (code.has_value()) {
    event.dom_code = static_cast<int>(
        ui::KeycodeConverter::CodeStringToDomCode(code.value()));
  }

  if (key.has_value()) {
    event.dom_key =
        static_cast<int>(ui::KeycodeConverter::KeyStringToDomKey(key.value()));
  }

  if (!host_ || !host_->GetRenderWidgetHost()) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  RenderWidgetHostImpl* widget_host = host_->GetRenderWidgetHost();
  if (!host_->GetParent() && widget_host->delegate()) {
    RenderWidgetHostImpl* target_host =
        widget_host->delegate()->GetFocusedRenderWidgetHost(widget_host);
    if (target_host)
      widget_host = target_host;
  }

  // We do not pass events to browser if there is no native key event
  // due to Mac needing the actual os_event.
  if (event.native_key_code && allow_sending_input_to_browser_)
    event.os_event = NativeInputEventBuilder::CreateEvent(event);
  else
    event.skip_if_unhandled = true;

  EnsureInjector(widget_host)
      ->InjectKeyboardEvent(event, std::move(commands), std::move(callback));
}

void InputHandler::InsertText(const std::string& text,
                              std::unique_ptr<InsertTextCallback> callback) {
  std::u16string text16 = base::UTF8ToUTF16(text);
  if (!host_ || !host_->GetRenderWidgetHost()) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  RenderWidgetHostImpl* widget_host = host_->GetRenderWidgetHost();
  if (!host_->GetParent() && widget_host->delegate()) {
    RenderWidgetHostImpl* target_host =
        widget_host->delegate()->GetFocusedRenderWidgetHost(widget_host);
    if (target_host)
      widget_host = target_host;
  }

  base::OnceClosure closure =
      base::BindOnce(&InsertTextCallback::sendSuccess, std::move(callback));

  widget_host->Focus();
  widget_host->GetWidgetInputHandler()->ImeCommitText(
      text16, std::vector<ui::ImeTextSpan>(), gfx::Range::InvalidRange(), 0,
      std::move(closure));
}

void InputHandler::ImeSetComposition(
    const std::string& text,
    int selection_start,
    int selection_end,
    std::optional<int> replacement_start,
    std::optional<int> replacement_end,
    std::unique_ptr<ImeSetCompositionCallback> callback) {
  std::u16string text16 = base::UTF8ToUTF16(text);
  if (!host_ || !host_->GetRenderWidgetHost() || !web_contents_) {
    callback->sendFailure(Response::InternalError());
    return;
  }
  // Currently no DevTools target for Prerender.
  if (host_->GetLifecycleState() ==
      RenderFrameHost::LifecycleState::kPrerendering) {
    NOTREACHED();
  }

  // |RenderFrameHostImpl::GetRenderWidgetHost| returns the RWHImpl of the
  // nearest local root of |host_|.
  RenderWidgetHostImpl* widget_host = host_->GetRenderWidgetHost();
  if (widget_host->delegate()) {
    RenderWidgetHostImpl* target_host =
        widget_host->delegate()->GetFocusedRenderWidgetHost(widget_host);
    if (target_host)
      widget_host = target_host;
  }

  // If replacement start and end are not specified, then the range is invalid,
  // so no replacing will be done.
  gfx::Range replacement_range = gfx::Range::InvalidRange();

  // Check if replacement_start and end parameters were passed in
  if (replacement_start.has_value()) {
    replacement_range.set_start(replacement_start.value());
    if (replacement_end.has_value()) {
      replacement_range.set_end(replacement_end.value());
    } else {
      callback->sendFailure(Response::InvalidParams(
          "Either both replacement start/end are specified or neither."));
      return;
    }
  }

  base::OnceClosure closure = base::BindOnce(
      &ImeSetCompositionCallback::sendSuccess, std::move(callback));

  widget_host->Focus();

  widget_host->GetWidgetInputHandler()->ImeSetComposition(
      text16, std::vector<ui::ImeTextSpan>(), replacement_range,
      selection_start, selection_end, std::move(closure));
}

void InputHandler::DispatchMouseEvent(
    const std::string& event_type,
    double x,
    double y,
    std::optional<int> modifiers,
    std::optional<double> timestamp,
    std::optional<std::string> button,
    std::optional<int> buttons,
    std::optional<int> click_count,
    std::optional<double> force,
    std::optional<double> tangential_pressure,
    std::optional<double> tilt_x,
    std::optional<double> tilt_y,
    std::optional<int> twist,
    std::optional<double> delta_x,
    std::optional<double> delta_y,
    std::optional<std::string> pointer_type,
    std::unique_ptr<DispatchMouseEventCallback> callback) {
  base::expected<std::unique_ptr<blink::WebMouseEvent>, protocol::Response>
      maybe_event = CreateWebMouseEvent(
          event_type, x, y, ScaleFactor(), std::move(modifiers),
          std::move(timestamp), std::move(button), std::move(buttons),
          std::move(click_count), std::move(force),
          std::move(tangential_pressure), std::move(tilt_x), std::move(tilt_y),
          std::move(twist), std::move(delta_x), std::move(delta_y),
          std::move(pointer_type));
  if (!maybe_event.has_value()) {
    callback->sendFailure(std::move(maybe_event).error());
    return;
  }

  HandleMouseEvent(std::move(maybe_event).value(), std::move(callback));
}

void InputHandler::HandleMouseEvent(
    std::unique_ptr<blink::WebMouseEvent> event,
    std::unique_ptr<DispatchMouseEventCallback> callback) {
  bool is_wheel_event =
      event->GetType() == blink::WebInputEvent::Type::kMouseWheel;

  RenderWidgetHostImpl* widget_host =
      host_ ? host_->GetRenderWidgetHost() : nullptr;
  if (!widget_host || !widget_host->delegate() ||
      !widget_host->delegate()->GetInputEventRouter() ||
      !widget_host->GetView()) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  auto findWidgetAndDispatchEvent = base::BindOnce(
      [](base::WeakPtr<InputHandler> self,
         base::WeakPtr<RenderWidgetHostImpl> widget_host,
         std::unique_ptr<blink::WebMouseEvent> event,
         std::unique_ptr<DispatchMouseEventCallback> callback, bool success) {
        if (!self || !widget_host)
          return;
        gfx::PointF position = event->PositionInWidget();
        widget_host->delegate()
            ->GetRenderWidgetHostAtPointAsynchronously(
                widget_host->GetView(), position,
                base::BindOnce(&InputHandler::OnWidgetForDispatchMouseEvent,
                               self, std::move(callback), std::move(event)));
      },
      weak_factory_.GetWeakPtr(), widget_host->GetWeakPtr(), std::move(event),
      std::move(callback));
  // We make sure the compositor is up to date before sending a wheel event.
  // Otherwise it wont be picked up by newly added event listeners on the main
  // thread.
  if (is_wheel_event) {
    widget_host->InsertVisualStateCallback(
        std::move(findWidgetAndDispatchEvent));
  } else {
    std::move(findWidgetAndDispatchEvent).Run(true);
  }
}

void InputHandler::DispatchDragEvent(
    const std::string& event_type,
    double x,
    double y,
    std::unique_ptr<Input::DragData> data,
    std::optional<int> modifiers,
    std::unique_ptr<DispatchDragEventCallback> callback) {
  if (!allow_file_access_ && data->HasFiles()) {
    callback->sendFailure(Response::InvalidParams("Not allowed"));
    return;
  }

  RenderWidgetHostImpl* widget_host =
      host_ ? host_->GetRenderWidgetHost() : nullptr;
  if (!widget_host || !widget_host->delegate() ||
      !widget_host->delegate()->GetInputEventRouter() ||
      !widget_host->GetView()) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  widget_host->delegate()
      ->GetRenderWidgetHostAtPointAsynchronously(
          widget_host->GetView(), CssPixelsToPointF(x, y, ScaleFactor()),
          base::BindOnce(&InputHandler::OnWidgetForDispatchDragEvent,
                         weak_factory_.GetWeakPtr(), event_type, x, y,
                         std::move(data), std::move(modifiers),
                         std::move(callback)));
}

void InputHandler::OnWidgetForDispatchDragEvent(
    const std::string& event_type,
    double x,
    double y,
    std::unique_ptr<Input::DragData> data,
    std::optional<int> modifiers,
    std::unique_ptr<DispatchDragEventCallback> callback,
    base::WeakPtr<RenderWidgetHostViewBase> target,
    std::optional<gfx::PointF> maybe_point) {
  if (!target || !maybe_point.has_value()) {
    callback->sendFailure(Response::InternalError());
    return;
  }
  auto point = *maybe_point;
  RenderWidgetHostImpl* widget_host =
      RenderWidgetHostImpl::From(target->GetRenderWidgetHost());
  auto mask =
      static_cast<blink::DragOperationsMask>(data->GetDragOperationsMask());
  std::unique_ptr<DropData> drop_data =
      std::make_unique<DropData>(ProtocolDragDataToDropData(std::move(data)));
  drop_data->view_id = widget_host->GetRoutingID();
  int event_modifiers =
      GetEventModifiers(modifiers.value_or(blink::WebInputEvent::kNoModifiers),
                        false, false, 0, 0);
  if (event_type == Input::DispatchDragEvent::TypeEnum::DragEnter) {
    widget_host->DragTargetDragEnter(
        *drop_data, point, point, mask, event_modifiers,
        base::BindOnce(
            [](std::unique_ptr<DispatchDragEventCallback> callback,
               ::ui::mojom::DragOperation operation,
               bool document_is_handling_drag) { callback->sendSuccess(); },
            std::move(callback)));
  } else if (event_type == Input::DispatchDragEvent::TypeEnum::DragOver) {
    widget_host->DragTargetDragOver(
        point, point, mask, event_modifiers,
        base::BindOnce(
            [](std::unique_ptr<DispatchDragEventCallback> callback,
               ::ui::mojom::DragOperation operation,
               bool document_is_handling_drag) { callback->sendSuccess(); },
            std::move(callback)));
  } else if (event_type == Input::DispatchDragEvent::TypeEnum::Drop) {
    widget_host->DragTargetDragOver(
        point, point, mask, event_modifiers,
        base::BindOnce(
            [](std::unique_ptr<DropData> drop_data, int event_modifiers,
               std::unique_ptr<DispatchDragEventCallback> callback,
               base::WeakPtr<RenderWidgetHostViewBase> target,
               gfx::PointF point, ui::mojom::DragOperation current_op,
               bool document_is_handling_drag) {
              if (!target) {
                callback->sendFailure(Response::InternalError());
                return;
              }
              drop_data->operation = current_op;
              drop_data->document_is_handling_drag = document_is_handling_drag;
              RenderWidgetHostImpl* widget_host =
                  RenderWidgetHostImpl::From(target->GetRenderWidgetHost());
              widget_host->DragTargetDrop(*drop_data, point, point,
                                          event_modifiers, base::DoNothing());
              widget_host->DragSourceSystemDragEnded();
              widget_host->DragSourceEndedAt(
                  point, point, current_op,
                  base::BindOnce(
                      [](std::unique_ptr<DispatchDragEventCallback> callback) {
                        callback->sendSuccess();
                      },
                      std::move(callback)));
            },
            std::move(drop_data), event_modifiers, std::move(callback),
            std::move(target), point));

  } else if (event_type == Input::DispatchDragEvent::TypeEnum::DragCancel) {
    widget_host->DragSourceSystemDragEnded();
    widget_host->DragSourceEndedAt(
        point, point, ui::mojom::DragOperation::kNone,
        base::BindOnce(
            [](std::unique_ptr<DispatchDragEventCallback> callback) {
              callback->sendSuccess();
            },
            std::move(callback)));
  } else {
    callback->sendFailure(Response::InvalidParams(
        base::StringPrintf("Unexpected event type '%s'", event_type.c_str())));
  }
}

float InputHandler::ScaleFactor() {
  DCHECK(web_contents_);
  // Browser zoom
  RenderWidgetHostImpl* widget_host_for_zoom_level =
      (host_ && host_->GetRenderWidgetHost())
          ? host_->GetRenderWidgetHost()
          : web_contents_->GetPrimaryMainFrame()->GetRenderWidgetHost();
  float scale_factor = blink::ZoomLevelToZoomFactor(
      web_contents_->GetPendingZoomLevel(widget_host_for_zoom_level));
  // CSS zoom applied to embedding element (e.g. <iframe>), if applicable.
  if (host_) {
    if (RenderWidgetHostImpl* widget_host = host_->GetRenderWidgetHost()) {
      if (auto* view = widget_host->GetView()) {
        scale_factor *= view->GetCSSZoomFactor();
      }
    }
  }
  // Pinch zoom
  // TODO(crbug.com/400860567): Investigate if this should also be
  // host_->GetPage() when `host_` is available.
  scale_factor *= web_contents_->GetPrimaryPage().GetPageScaleFactor();

  return scale_factor;
}

void InputHandler::StartDragging(const content::DropData& drop_data,
                                 const blink::mojom::DragData& drag_data,
                                 blink::DragOperationsMask drag_operations_mask,
                                 bool* intercepted) {
  // Only allow when Input.setInterceptDrags is disabled.
  if (!intercept_drags_) {
    // If `last_mouse_move_` exists, then CDP is the currently handling mouse
    // movement, so intercept dragging.
    if (drag_controller_.initial_state_) {
      drag_controller_.StartDragging(drop_data, drag_operations_mask);
      *intercepted = true;
    }
    return;
  }

  if (*intercepted) {
    return;
  }
  *intercepted = true;

  auto items =
      std::make_unique<protocol::Array<protocol::Input::DragDataItem>>();
  for (const auto& item : drag_data.items) {
    if (!item->is_string())
      continue;
    const auto& string_item = item->get_string();
    auto protocol_item =
        protocol::Input::DragDataItem::Create()
            .SetMimeType(string_item->string_type)
            .SetData(base::UTF16ToUTF8(string_item->string_data))
            .Build();
    if (string_item->base_url.has_value())
      protocol_item->SetBaseURL(string_item->base_url->spec());
    if (string_item->title.has_value())
      protocol_item->SetTitle(base::UTF16ToUTF8(string_item->title.value()));
    items->push_back(std::move(protocol_item));
  }
  frontend_->DragIntercepted(protocol::Input::DragData::Create()
                                 .SetDragOperationsMask(drag_operations_mask)
                                 .SetItems(std::move(items))
                                 .Build());
}

void InputHandler::DragEnded() {
  drag_controller_.drag_state_ = nullptr;
  drag_controller_.initial_state_ = nullptr;
}

Response InputHandler::SetInterceptDrags(bool enabled) {
  intercept_drags_ = enabled;
  return Response::Success();
}

void InputHandler::OnWidgetForDispatchMouseEvent(
    std::unique_ptr<DispatchMouseEventCallback> callback,
    std::unique_ptr<blink::WebMouseEvent> event,
    base::WeakPtr<RenderWidgetHostViewBase> target,
    std::optional<gfx::PointF> point) {
  if (!target || !point.has_value()) {
    callback->sendFailure(Response::InternalError());
    return;
  }
  event->SetPositionInWidget(*point);
  event->SetPositionInScreen(
      ConvertWidgetPointToScreenPoint(CHECK_DEREF(target.get()), *point));

  RenderWidgetHostImpl* widget_host =
      RenderWidgetHostImpl::From(target->GetRenderWidgetHost());
  if (event->GetType() == blink::WebInputEvent::Type::kMouseWheel) {
    EnsureInjector(widget_host)
        ->InjectWheelEvent(static_cast<blink::WebMouseWheelEvent*>(event.get()),
                           std::move(callback));
  } else {
    EnsureInjector(widget_host)->InjectMouseEvent(*event, std::move(callback));
  }
}

void InputHandler::DispatchTouchEvent(
    const std::string& event_type,
    std::unique_ptr<Array<Input::TouchPoint>> touch_points,
    std::optional<int> modifiers,
    std::optional<double> timestamp,
    std::unique_ptr<DispatchTouchEventCallback> callback) {
  if (base::FeatureList::IsEnabled(features::kSyntheticPointerActions)) {
    DispatchSyntheticPointerActionTouch(
        event_type, std::move(touch_points), std::move(modifiers),
        std::move(timestamp), std::move(callback));
    return;
  }

  DispatchWebTouchEvent(event_type, std::move(touch_points),
                        std::move(modifiers), std::move(timestamp),
                        std::move(callback));
}

void InputHandler::CancelDragging(
    std::unique_ptr<CancelDraggingCallback> callback) {
  if (!drag_controller_.IsDragging()) {
    callback->sendSuccess();
    return;
  }
  drag_controller_.CancelDragging(base::BindOnce(
      &FailSafe<CancelDraggingCallback>::sendSuccess,
      std::make_unique<FailSafe<CancelDraggingCallback>>(std::move(callback))));
}

void InputHandler::DispatchWebTouchEvent(
    const std::string& event_type,
    std::unique_ptr<Array<Input::TouchPoint>> touch_points,
    std::optional<int> modifiers,
    std::optional<double> timestamp,
    std::unique_ptr<DispatchTouchEventCallback> callback) {
  base::expected<std::vector<blink::WebTouchEvent>, protocol::Response>
      maybe_events = CreateWebTouchEvents(
          event_type, std::move(modifiers), std::move(timestamp), ScaleFactor(),
          touch_points_, std::move(touch_points));
  if (!maybe_events.has_value()) {
    callback->sendFailure(std::move(maybe_events).error());
    return;
  }

  std::vector<blink::WebTouchEvent> events = std::move(maybe_events).value();
  if (events.empty()) {
    callback->sendSuccess();
    return;
  }

  RenderWidgetHostImpl* widget_host =
      host_ ? host_->GetRenderWidgetHost() : nullptr;
  if (!widget_host || !widget_host->delegate() ||
      !widget_host->delegate()->GetInputEventRouter() ||
      !widget_host->GetView()) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  // We make sure the compositor is up to date before
  // sending a touch event. Otherwise it wont be
  // picked up by newly added event listeners on the main thread.
  widget_host->InsertVisualStateCallback(base::BindOnce(
      [](base::WeakPtr<InputHandler> self,
         base::WeakPtr<RenderWidgetHostImpl> widget_host,
         std::vector<blink::WebTouchEvent> events,
         std::unique_ptr<DispatchTouchEventCallback> callback, bool success) {
        if (!self || !widget_host) {
          return;
        }
        gfx::PointF point(events[0].touches[0].PositionInWidget());
        widget_host->delegate()
            ->GetRenderWidgetHostAtPointAsynchronously(
                widget_host->GetView(), point,
                base::BindOnce(&InputHandler::OnWidgetForDispatchWebTouchEvent,
                               self, std::move(callback), std::move(events)));
      },
      weak_factory_.GetWeakPtr(), widget_host->GetWeakPtr(), std::move(events),
      std::move(callback)));
}

void InputHandler::OnWidgetForDispatchWebTouchEvent(
    std::unique_ptr<DispatchTouchEventCallback> callback,
    std::vector<blink::WebTouchEvent> events,
    base::WeakPtr<RenderWidgetHostViewBase> target,
    std::optional<gfx::PointF> transformed) {
  if (!target || !transformed.has_value()) {
    callback->sendFailure(Response::InternalError());
    return;
  }
  RenderWidgetHostImpl* widget_host =
      RenderWidgetHostImpl::From(target->GetRenderWidgetHost());

  gfx::PointF original(events[0].touches[0].PositionInWidget());
  gfx::Vector2dF delta = *transformed - original;
  for (auto& event : events) {
    event.dispatch_type =
        event.GetType() == blink::WebInputEvent::Type::kTouchCancel
            ? blink::WebInputEvent::DispatchType::kEventNonBlocking
            : blink::WebInputEvent::DispatchType::kBlocking;
    event.moved_beyond_slop_region = true;
    event.unique_touch_event_id = ui::GetNextTouchEventId();
    for (unsigned j = 0; j < event.touches_length; j++) {
      gfx::PointF point = event.touches[j].PositionInWidget();
      gfx::PointF position_in_widget(point.x() + delta.x(),
                                     point.y() + delta.y());
      event.touches[j].SetPositionInWidget(position_in_widget);
      event.touches[j].SetPositionInScreen(ConvertWidgetPointToScreenPoint(
          CHECK_DEREF(target.get()), position_in_widget));
    }
  }
  EnsureInjector(widget_host)->InjectTouchEvents(events, std::move(callback));
}

void InputHandler::DispatchSyntheticPointerActionTouch(
    const std::string& event_type,
    std::unique_ptr<Array<Input::TouchPoint>> touch_points,
    std::optional<int> modifiers,
    std::optional<double> timestamp,
    std::unique_ptr<DispatchTouchEventCallback> callback) {
  if (!host_ || !host_->GetRenderWidgetHost()) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  SyntheticPointerActionParams::PointerActionType pointer_action_type =
      GetTouchPointerActionType(event_type);
  if (pointer_action_type ==
      SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED) {
    callback->sendFailure(Response::InvalidParams(
        base::StringPrintf("Unexpected event type '%s'", event_type.c_str())));
    return;
  }

  int event_modifiers =
      GetEventModifiers(modifiers.value_or(blink::WebInputEvent::kNoModifiers),
                        false, false, 0, 0);

  if ((pointer_action_type ==
           SyntheticPointerActionParams::PointerActionType::PRESS ||
       pointer_action_type ==
           SyntheticPointerActionParams::PointerActionType::MOVE) &&
      touch_points->empty()) {
    callback->sendFailure(Response::InvalidParams(
        "TouchStart and TouchMove must have at least one touch point."));
    return;
  }
  if ((pointer_action_type ==
           SyntheticPointerActionParams::PointerActionType::RELEASE ||
       pointer_action_type ==
           SyntheticPointerActionParams::PointerActionType::CANCEL) &&
      !touch_points->empty()) {
    callback->sendFailure(Response::InvalidParams(
        "TouchEnd and TouchCancel must not have any touch points."));
    return;
  }
  if (pointer_action_type ==
          SyntheticPointerActionParams::PointerActionType::PRESS &&
      !pointer_ids_.empty()) {
    callback->sendFailure(Response::InvalidParams(
        "Must have no prior active touch points to start a new touch."));
    return;
  }
  if (pointer_action_type !=
          SyntheticPointerActionParams::PointerActionType::PRESS &&
      pointer_ids_.empty()) {
    callback->sendFailure(Response::InvalidParams(
        "Must send a TouchStart first to start a new touch."));
    return;
  }

  content::mojom::GestureSourceType gesture_source_type =
      content::mojom::GestureSourceType::kTouchInput;
  SyntheticPointerActionListParams action_list_params;
  SyntheticPointerActionListParams::ParamList param_list;
  action_list_params.gesture_source_type = gesture_source_type;
  if (pointer_action_type ==
          SyntheticPointerActionParams::PointerActionType::RELEASE ||
      pointer_action_type ==
          SyntheticPointerActionParams::PointerActionType::CANCEL) {
    for (auto it = pointer_ids_.begin(); it != pointer_ids_.end();) {
      SyntheticPointerActionParams action_params =
          PrepareSyntheticPointerActionParams(pointer_action_type, *it, 0, 0,
                                              event_modifiers);
      param_list.push_back(action_params);
      it = pointer_ids_.erase(it);
    }
  }

  size_t with_id = 0;
  gfx::PointF original;
  std::set<int> current_pointer_ids;
  for (size_t i = 0; i < touch_points->size(); ++i) {
    Input::TouchPoint* point = (*touch_points)[i].get();
    int id = point->GetId(i);  // index |i| is default for the id.
    if (point->HasId())
      with_id++;

    SyntheticPointerActionParams::PointerActionType action_type =
        SyntheticPointerActionParams::PointerActionType::MOVE;
    if (!base::Contains(pointer_ids_, id)) {
      pointer_ids_.insert(id);
      action_type = SyntheticPointerActionParams::PointerActionType::PRESS;
    }
    SyntheticPointerActionParams action_params =
        PrepareSyntheticPointerActionParams(
            action_type, id, point->GetX(), point->GetY(), event_modifiers,
            point->GetRadiusX(1.0f), point->GetRadiusY(1.0f),
            point->GetRotationAngle(0.0f), point->GetForce(1.0f));
    param_list.push_back(action_params);
    original = gfx::PointF(point->GetX(), point->GetY());
    current_pointer_ids.insert(id);
  }
  if (with_id > 0 && with_id < touch_points->size()) {
    callback->sendFailure(Response::InvalidParams(
        "All or none of the provided TouchPoints must supply ids."));
    return;
  }

  if (pointer_action_type ==
          SyntheticPointerActionParams::PointerActionType::MOVE &&
      current_pointer_ids.size() < pointer_ids_.size()) {
    for (auto it = pointer_ids_.begin(); it != pointer_ids_.end();) {
      if (base::Contains(current_pointer_ids, *it)) {
        it++;
        continue;
      }
      SyntheticPointerActionParams action_params =
          PrepareSyntheticPointerActionParams(
              SyntheticPointerActionParams::PointerActionType::RELEASE, *it, 0,
              0, event_modifiers);
      param_list.push_back(action_params);
      it = pointer_ids_.erase(it);
    }
  }
  action_list_params.PushPointerActionParamsList(param_list);

  if (!synthetic_pointer_driver_) {
    synthetic_pointer_driver_ =
        SyntheticPointerDriver::Create(gesture_source_type, true);
  }
  std::unique_ptr<SyntheticPointerAction> synthetic_gesture =
      std::make_unique<SyntheticPointerAction>(action_list_params);
  synthetic_gesture->SetSyntheticPointerDriver(
      synthetic_pointer_driver_->AsWeakPtr());

  RenderWidgetHostViewBase* root_view = GetRootView();
  if (!root_view) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  root_view->host()->QueueSyntheticGesture(
      std::move(synthetic_gesture),
      base::BindOnce(&DispatchPointerActionsResponse, std::move(callback)));
}

SyntheticPointerActionParams InputHandler::PrepareSyntheticPointerActionParams(
    SyntheticPointerActionParams::PointerActionType pointer_action_type,
    int id,
    double x,
    double y,
    int key_modifiers,
    float radius_x,
    float radius_y,
    float rotation_angle,
    float force) {
  SyntheticPointerActionParams action_params(pointer_action_type);
  action_params.set_pointer_id(id);
  const SyntheticPointerActionParams::Button button =
      SyntheticPointerActionParams::Button::NO_BUTTON;
  switch (pointer_action_type) {
    case SyntheticPointerActionParams::PointerActionType::PRESS:
      action_params.set_position(
          gfx::PointF(x * ScaleFactor(), y * ScaleFactor()));
      action_params.set_button(button);
      action_params.set_key_modifiers(key_modifiers);
      action_params.set_width(radius_x * 2.f);
      action_params.set_height(radius_y * 2.f);
      action_params.set_rotation_angle(rotation_angle);
      action_params.set_force(force);
      break;
    case SyntheticPointerActionParams::PointerActionType::MOVE:
      action_params.set_position(
          gfx::PointF(x * ScaleFactor(), y * ScaleFactor()));
      action_params.set_key_modifiers(key_modifiers);
      action_params.set_width(radius_x * 2.f);
      action_params.set_height(radius_y * 2.f);
      action_params.set_rotation_angle(rotation_angle);
      action_params.set_force(force);
      break;
    case SyntheticPointerActionParams::PointerActionType::RELEASE:
    case SyntheticPointerActionParams::PointerActionType::CANCEL:
      action_params.set_button(button);
      action_params.set_key_modifiers(key_modifiers);
      break;
    case SyntheticPointerActionParams::PointerActionType::LEAVE:
    case SyntheticPointerActionParams::PointerActionType::IDLE:
    case SyntheticPointerActionParams::PointerActionType::NOT_INITIALIZED:
      NOTREACHED();
  }
  return action_params;
}

Response InputHandler::EmulateTouchFromMouseEvent(
    const std::string& type,
    int x,
    int y,
    const std::string& button,
    std::optional<double> timestamp,
    std::optional<double> delta_x,
    std::optional<double> delta_y,
    std::optional<int> modifiers,
    std::optional<int> click_count) {
  blink::WebInputEvent::Type event_type;
  if (type == Input::EmulateTouchFromMouseEvent::TypeEnum::MouseWheel) {
    event_type = blink::WebInputEvent::Type::kMouseWheel;
    if (!delta_x.has_value() || !delta_y.has_value()) {
      return Response::InvalidParams(
          "'deltaX' and 'deltaY' are expected for mouseWheel event");
    }
  } else {
    event_type = GetMouseEventType(type);
    if (event_type == blink::WebInputEvent::Type::kUndefined) {
      return Response::InvalidParams(
          base::StringPrintf("Unexpected event type '%s'", type.c_str()));
    }
  }

  blink::WebPointerProperties::Button event_button =
      blink::WebPointerProperties::Button::kNoButton;
  int button_modifiers = 0;
  if (!GetMouseEventButton(button, &event_button, &button_modifiers))
    return Response::InvalidParams("Invalid mouse button");

  ui::WebScopedInputEvent event;
  blink::WebMouseWheelEvent* wheel_event = nullptr;
  blink::WebMouseEvent* mouse_event = nullptr;
  if (type == Input::EmulateTouchFromMouseEvent::TypeEnum::MouseWheel) {
    wheel_event = new blink::WebMouseWheelEvent(
        event_type,
        GetEventModifiers(
            modifiers.value_or(blink::WebInputEvent::kNoModifiers), false,
            false, 0, 0) |
            button_modifiers,
        GetEventTimeTicks(timestamp));
    mouse_event = wheel_event;
    event.reset(wheel_event);
    wheel_event->delta_x = static_cast<float>(delta_x.value());
    wheel_event->delta_y = static_cast<float>(delta_y.value());
    wheel_event->phase = blink::WebMouseWheelEvent::kPhaseBegan;
  } else {
    mouse_event = new blink::WebMouseEvent(
        event_type,
        GetEventModifiers(
            modifiers.value_or(blink::WebInputEvent::kNoModifiers), false,
            false, 0, 0) |
            button_modifiers,
        GetEventTimeTicks(timestamp));
    event.reset(mouse_event);
  }

  if (!host_ || !host_->GetRenderWidgetHost() || !host_->GetView()) {
    return Response::InternalError();
  }

  gfx::PointF position_in_widget(x, y);
  mouse_event->SetPositionInWidget(position_in_widget);
  mouse_event->button = event_button;
  mouse_event->SetPositionInScreen(ConvertWidgetPointToScreenPoint(
      CHECK_DEREF(host_->GetView()), position_in_widget));
  mouse_event->click_count = click_count.value_or(0);
  mouse_event->pointer_type = blink::WebPointerProperties::PointerType::kTouch;

  base::OnceCallback<void(bool)> forward_event_func;

  if (wheel_event) {
    forward_event_func = base::BindOnce(
        [](base::WeakPtr<InputHandler> self,
           base::WeakPtr<RenderWidgetHostImpl> widget_host,
           blink::WebMouseWheelEvent* event,
           ui::WebScopedInputEvent event_deleter, bool success) {
          if (!self || !widget_host)
            return;

          widget_host->ForwardWheelEvent(*event);
          // Send a synthetic wheel event with phaseEnded to finish scrolling.
          event->delta_x = 0;
          event->delta_y = 0;
          event->phase = blink::WebMouseWheelEvent::kPhaseEnded;
          event->dispatch_type =
              blink::WebInputEvent::DispatchType::kEventNonBlocking;
          widget_host->ForwardWheelEvent(*event);
        },
        weak_factory_.GetWeakPtr(), host_->GetRenderWidgetHost()->GetWeakPtr(),
        wheel_event, std::move(event));
  } else {
    forward_event_func = base::BindOnce(
        [](base::WeakPtr<InputHandler> self,
           base::WeakPtr<RenderWidgetHostImpl> widget_host,
           blink::WebMouseEvent* event, ui::WebScopedInputEvent event_deleter,
           bool success) {
          if (!self || !widget_host)
            return;
          widget_host->ForwardMouseEvent(*event);
        },
        weak_factory_.GetWeakPtr(), host_->GetRenderWidgetHost()->GetWeakPtr(),
        mouse_event, std::move(event));
  }
  // We make sure the compositor is up to date before sending a mouse event.
  // Otherwise it wont be picked up by newly added event listeners on the main
  // thread.
  host_->GetRenderWidgetHost()->InsertVisualStateCallback(
      std::move(forward_event_func));
  return Response::Success();
}

Response InputHandler::SetIgnoreInputEvents(bool ignore) {
  ignore_input_events_ = ignore;
  if (!ignore) {
    scoped_ignore_input_events_.reset();
  } else if (web_contents_) {
    scoped_ignore_input_events_ =
        web_contents_->IgnoreInputEvents(std::nullopt);
  }
  return Response::Success();
}

void InputHandler::SynthesizePinchGesture(
    double x,
    double y,
    double scale_factor,
    std::optional<int> relative_speed,
    std::optional<std::string> gesture_source_type,
    std::unique_ptr<SynthesizePinchGestureCallback> callback) {
  if (!host_ || !host_->GetRenderWidgetHost()) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  SyntheticPinchGestureParams gesture_params;
  const int kDefaultRelativeSpeed = 800;

  gesture_params.from_devtools_debugger = true;
  gesture_params.scale_factor = scale_factor;
  gesture_params.anchor = CssPixelsToPointF(x, y, ScaleFactor());
  if (!PointIsWithinContents(gesture_params.anchor)) {
    callback->sendFailure(Response::InvalidParams("Position out of bounds"));
    return;
  }

  gesture_params.relative_pointer_speed_in_pixels_s =
      relative_speed.value_or(kDefaultRelativeSpeed);

  if (!StringToGestureSourceType(
      std::move(gesture_source_type),
      gesture_params.gesture_source_type)) {
    callback->sendFailure(
        Response::InvalidParams("Unknown gestureSourceType"));
    return;
  }

  RenderWidgetHostViewBase* root_view = GetRootView();
  if (!root_view) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  root_view->host()->QueueSyntheticGesture(
      std::make_unique<SyntheticPinchGesture>(gesture_params),
      base::BindOnce(&SendSynthesizePinchGestureResponse, std::move(callback)));
}

void InputHandler::SynthesizeScrollGesture(
    double x,
    double y,
    std::optional<double> x_distance,
    std::optional<double> y_distance,
    std::optional<double> x_overscroll,
    std::optional<double> y_overscroll,
    std::optional<bool> prevent_fling,
    std::optional<int> speed,
    std::optional<std::string> gesture_source_type,
    std::optional<int> repeat_count,
    std::optional<int> repeat_delay_ms,
    std::optional<std::string> interaction_marker_name,
    std::unique_ptr<SynthesizeScrollGestureCallback> callback) {
  if (!host_ || !host_->GetRenderWidgetHost()) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  SyntheticSmoothScrollGestureParams gesture_params;
  gesture_params.from_devtools_debugger = true;
  gesture_params.granularity = ui::ScrollGranularity::kScrollByPrecisePixel;

  gesture_params.anchor = CssPixelsToPointF(x, y, ScaleFactor());
  if (!PointIsWithinContents(gesture_params.anchor)) {
    callback->sendFailure(Response::InvalidParams("Position out of bounds"));
    return;
  }

  const bool kDefaultPreventFling = true;
  const int kDefaultSpeed = 800;
  gesture_params.prevent_fling = prevent_fling.value_or(kDefaultPreventFling);
  gesture_params.speed_in_pixels_s = speed.value_or(kDefaultSpeed);

  if (x_distance.has_value() || y_distance.has_value()) {
    gesture_params.distances.push_back(CssPixelsToVector2dF(
        x_distance.value_or(0), y_distance.value_or(0), ScaleFactor()));
  }

  if (x_overscroll.has_value() || y_overscroll.has_value()) {
    gesture_params.distances.push_back(CssPixelsToVector2dF(
        -x_overscroll.value_or(0), -y_overscroll.value_or(0), ScaleFactor()));
  }

  if (!StringToGestureSourceType(
      std::move(gesture_source_type),
      gesture_params.gesture_source_type)) {
    callback->sendFailure(
        Response::InvalidParams("Unknown gestureSourceType"));
    return;
  }

  SynthesizeRepeatingScroll(gesture_params, repeat_count.value_or(0),
                            base::Milliseconds(repeat_delay_ms.value_or(250)),
                            interaction_marker_name.value_or(""), ++last_id_,
                            std::move(callback));
}

void InputHandler::SynthesizeRepeatingScroll(
    SyntheticSmoothScrollGestureParams gesture_params,
    int repeat_count,
    base::TimeDelta repeat_delay,
    std::string interaction_marker_name,
    int id,
    std::unique_ptr<SynthesizeScrollGestureCallback> callback) {
  RenderWidgetHostViewBase* root_view = GetRootView();
  if (!root_view) {
    callback->sendFailure(Response::ServerError("Frame was detached"));
    return;
  }

  if (!interaction_marker_name.empty()) {
    // TODO(alexclarke): Can we move this elsewhere? It doesn't really fit here.
    TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN0(
        "benchmark", interaction_marker_name.c_str(),
        TRACE_ID_WITH_SCOPE(interaction_marker_name.c_str(), id));
  }

  root_view->host()->QueueSyntheticGesture(
      std::make_unique<SyntheticSmoothScrollGesture>(gesture_params),
      base::BindOnce(&InputHandler::OnScrollFinished,
                     weak_factory_.GetWeakPtr(), gesture_params, repeat_count,
                     repeat_delay, interaction_marker_name, id,
                     std::move(callback)));
}

void InputHandler::OnScrollFinished(
    SyntheticSmoothScrollGestureParams gesture_params,
    int repeat_count,
    base::TimeDelta repeat_delay,
    std::string interaction_marker_name,
    int id,
    std::unique_ptr<SynthesizeScrollGestureCallback> callback,
    SyntheticGesture::Result result) {
  if (!interaction_marker_name.empty()) {
    TRACE_EVENT_COPY_NESTABLE_ASYNC_END0(
        "benchmark", interaction_marker_name.c_str(),
        TRACE_ID_WITH_SCOPE(interaction_marker_name.c_str(), id));
  }

  if (repeat_count > 0) {
    base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&InputHandler::SynthesizeRepeatingScroll,
                       weak_factory_.GetWeakPtr(), gesture_params,
                       repeat_count - 1, repeat_delay, interaction_marker_name,
                       id, std::move(callback)),
        repeat_delay);
  } else {
    SendSynthesizeScrollGestureResponse(std::move(callback), result);
  }
}

void InputHandler::SynthesizeTapGesture(
    double x,
    double y,
    std::optional<int> duration,
    std::optional<int> tap_count,
    std::optional<std::string> gesture_source_type,
    std::unique_ptr<SynthesizeTapGestureCallback> callback) {
  if (!host_ || !host_->GetRenderWidgetHost()) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  SyntheticTapGestureParams gesture_params;
  const int kDefaultDuration = 50;
  const int kDefaultTapCount = 1;

  gesture_params.position = CssPixelsToPointF(x, y, ScaleFactor());
  gesture_params.from_devtools_debugger = true;
  if (!PointIsWithinContents(gesture_params.position)) {
    callback->sendFailure(Response::InvalidParams("Position out of bounds"));
    return;
  }

  gesture_params.duration_ms = duration.value_or(kDefaultDuration);

  if (!StringToGestureSourceType(
      std::move(gesture_source_type),
      gesture_params.gesture_source_type)) {
    callback->sendFailure(
        Response::InvalidParams("Unknown gestureSourceType"));
    return;
  }

  int count = tap_count.value_or(kDefaultTapCount);
  if (!count) {
    callback->sendSuccess();
    return;
  }

  RenderWidgetHostViewBase* root_view = GetRootView();
  if (!root_view) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  TapGestureResponse* response =
      new TapGestureResponse(std::move(callback), count);
  for (int i = 0; i < count; i++) {
    root_view->host()->QueueSyntheticGesture(
        std::make_unique<SyntheticTapGesture>(gesture_params),
        base::BindOnce(&TapGestureResponse::OnGestureResult,
                       base::Unretained(response)));
  }
}

void InputHandler::ClearInputState() {
  while (!injectors_.empty())
    (*injectors_.begin())->Cleanup();
  // TODO(dgozman): cleanup touch callbacks as well?
  pointer_ids_.clear();
}

bool InputHandler::PointIsWithinContents(gfx::PointF point) const {
  gfx::Rect bounds = host_->GetView()->GetViewBounds();
  bounds -= bounds.OffsetFromOrigin();  // Translate the bounds to (0,0).
  return bounds.Contains(point.x(), point.y());
}

InputHandler::InputInjector* InputHandler::EnsureInjector(
    RenderWidgetHostImpl* widget_host) {
  for (auto& it : injectors_) {
    if (it->HasWidgetHost(widget_host))
      return it.get();
  }
  InputInjector* injector = new InputInjector(this, widget_host);
  injectors_.emplace(injector);
  return injector;
}

RenderWidgetHostViewBase* InputHandler::GetRootView() {
  if (!host_)
    return nullptr;

  RenderWidgetHostViewBase* view =
      static_cast<RenderWidgetHostViewBase*>(host_->GetView());
  if (!view)
    return nullptr;

  return view->GetRootView();
}

}  // namespace content::protocol
