/*
 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights
 * reserved.
 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies)
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/core/input/event_handler.h"

#include <memory>
#include <utility>

#include "build/build_config.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/dom/events/event_path.h"
#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/user_gesture_indicator.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/editor.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/selection_controller.h"
#include "third_party/blink/renderer/core/events/gesture_event.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
#include "third_party/blink/renderer/core/events/mouse_event.h"
#include "third_party/blink/renderer/core/events/pointer_event.h"
#include "third_party/blink/renderer/core/events/text_event.h"
#include "third_party/blink/renderer/core/events/touch_event.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/frame/event_handler_registry.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/html_dialog_element.h"
#include "third_party/blink/renderer/core/html/html_frame_element_base.h"
#include "third_party/blink/renderer/core/html/html_frame_set_element.h"
#include "third_party/blink/renderer/core/input/event_handling_util.h"
#include "third_party/blink/renderer/core/input/input_device_capabilities.h"
#include "third_party/blink/renderer/core/input/touch_action_util.h"
#include "third_party/blink/renderer/core/input/touch_list.h"
#include "third_party/blink/renderer/core/input_type_names.h"
#include "third_party/blink/renderer/core/layout/hit_test_request.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/loader/frame_loader.h"
#include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
#include "third_party/blink/renderer/core/page/autoscroll_controller.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/drag_state.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
#include "third_party/blink/renderer/core/page/frame_tree.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scrolling/scroll_state.h"
#include "third_party/blink/renderer/core/page/touch_adjustment.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/scroll/scroll_animator_base.h"
#include "third_party/blink/renderer/core/scroll/scrollbar.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/style/cursor_data.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/windows_keyboard_codes.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/time.h"

namespace blink {

namespace {

// Refetch the event target node if it is removed or currently is the shadow
// node inside an <input> element.  If a mouse event handler changes the input
// element type to one that has a EmbeddedContentView associated, we'd like to
// EventHandler::handleMousePressEvent to pass the event to the
// EmbeddedContentView and thus the event target node can't still be the shadow
// node.
bool ShouldRefetchEventTarget(const MouseEventWithHitTestResults& mev) {
  Node* target_node = mev.InnerNode();
  if (!target_node || !target_node->parentNode())
    return true;
  return target_node->IsShadowRoot() &&
         IsHTMLInputElement(ToShadowRoot(target_node)->host());
}

}  // namespace

// The amount of time to wait for a cursor update on style and layout changes
// Set to 50Hz, no need to be faster than common screen refresh rate
static constexpr TimeDelta kCursorUpdateInterval =
    TimeDelta::FromMilliseconds(20);

static const int kMaximumCursorSize = 128;

// It's pretty unlikely that a scale of less than one would ever be used. But
// all we really need to ensure here is that the scale isn't so small that
// integer overflow can occur when dividing cursor sizes (limited above) by the
// scale.
static const double kMinimumCursorScale = 0.001;

// The minimum amount of time an element stays active after a ShowPress
// This is roughly 9 frames, which should be long enough to be noticeable.
constexpr TimeDelta kMinimumActiveInterval = TimeDelta::FromSecondsD(0.15);

EventHandler::EventHandler(LocalFrame& frame)
    : frame_(frame),
      selection_controller_(SelectionController::Create(frame)),
      hover_timer_(frame.GetTaskRunner(TaskType::kUserInteraction),
                   this,
                   &EventHandler::HoverTimerFired),
      cursor_update_timer_(
          frame.GetTaskRunner(TaskType::kInternalUserInteraction),
          this,
          &EventHandler::CursorUpdateTimerFired),
      event_handler_will_reset_capturing_mouse_events_node_(0),
      should_only_fire_drag_over_event_(false),
      event_handler_registry_(
          frame_->IsLocalRoot()
              ? MakeGarbageCollected<EventHandlerRegistry>(*frame_)
              : &frame_->LocalFrameRoot().GetEventHandlerRegistry()),
      scroll_manager_(new ScrollManager(frame)),
      mouse_event_manager_(new MouseEventManager(frame, *scroll_manager_)),
      mouse_wheel_event_manager_(new MouseWheelEventManager(frame)),
      keyboard_event_manager_(
          MakeGarbageCollected<KeyboardEventManager>(frame, *scroll_manager_)),
      pointer_event_manager_(
          new PointerEventManager(frame, *mouse_event_manager_)),
      gesture_manager_(
          MakeGarbageCollected<GestureManager>(frame,
                                               *scroll_manager_,
                                               *mouse_event_manager_,
                                               *pointer_event_manager_,
                                               *selection_controller_)),
      active_interval_timer_(frame.GetTaskRunner(TaskType::kUserInteraction),
                             this,
                             &EventHandler::ActiveIntervalTimerFired) {}

void EventHandler::Trace(blink::Visitor* visitor) {
  visitor->Trace(frame_);
  visitor->Trace(selection_controller_);
  visitor->Trace(capturing_mouse_events_node_);
  visitor->Trace(last_mouse_move_event_subframe_);
  visitor->Trace(last_scrollbar_under_mouse_);
  visitor->Trace(drag_target_);
  visitor->Trace(frame_set_being_resized_);
  visitor->Trace(event_handler_registry_);
  visitor->Trace(scroll_manager_);
  visitor->Trace(mouse_event_manager_);
  visitor->Trace(mouse_wheel_event_manager_);
  visitor->Trace(keyboard_event_manager_);
  visitor->Trace(pointer_event_manager_);
  visitor->Trace(gesture_manager_);
  visitor->Trace(last_deferred_tap_element_);
}

void EventHandler::Clear() {
  hover_timer_.Stop();
  cursor_update_timer_.Stop();
  active_interval_timer_.Stop();
  last_mouse_move_event_subframe_ = nullptr;
  last_scrollbar_under_mouse_ = nullptr;
  frame_set_being_resized_ = nullptr;
  drag_target_ = nullptr;
  should_only_fire_drag_over_event_ = false;
  last_mouse_down_user_gesture_token_ = nullptr;
  capturing_mouse_events_node_ = nullptr;
  pointer_event_manager_->Clear();
  scroll_manager_->Clear();
  gesture_manager_->Clear();
  mouse_event_manager_->Clear();
  mouse_wheel_event_manager_->Clear();
  last_show_press_timestamp_.reset();
  last_deferred_tap_element_ = nullptr;
  event_handler_will_reset_capturing_mouse_events_node_ = false;
  should_use_touch_event_adjusted_point_ = false;
  touch_adjustment_result_.unique_event_id = 0;
}

void EventHandler::UpdateSelectionForMouseDrag() {
  mouse_event_manager_->UpdateSelectionForMouseDrag();
}

void EventHandler::StartMiddleClickAutoscroll(LayoutObject* layout_object) {
  DCHECK(RuntimeEnabledFeatures::MiddleClickAutoscrollEnabled());
  if (!layout_object->IsBox())
    return;
  AutoscrollController* controller = scroll_manager_->GetAutoscrollController();
  if (!controller)
    return;
  controller->StartMiddleClickAutoscroll(
      layout_object->GetFrame(),
      frame_->GetPage()->GetVisualViewport().ViewportToRootFrame(
          FloatPoint(mouse_event_manager_->LastKnownMousePosition())),
      mouse_event_manager_->LastKnownMousePositionGlobal());
  mouse_event_manager_->InvalidateClick();
}

void EventHandler::PerformHitTest(const HitTestLocation& location,
                                  HitTestResult& result,
                                  bool no_lifecycle_update) const {
  // LayoutView::hitTest causes a layout, and we don't want to hit that until
  // the first layout because until then, there is nothing shown on the screen -
  // the user can't have intentionally clicked on something belonging to this
  // page.  Furthermore, mousemove events before the first layout should not
  // lead to a premature layout() happening, which could show a flash of white.
  // See also the similar code in Document::performMouseEventHitTest.
  // The check to LifecycleUpdatesActive() prevents hit testing to frames
  // that have already had layout but are throttled to prevent painting
  // because the current Document isn't ready to render yet. In that case
  // the lifecycle update prompted by HitTest() would fail.
  if (!frame_->ContentLayoutObject() || !frame_->View() ||
      !frame_->View()->DidFirstLayout() ||
      !frame_->View()->LifecycleUpdatesActive())
    return;

  if (no_lifecycle_update) {
    frame_->ContentLayoutObject()->HitTestNoLifecycleUpdate(location, result);
  } else {
    frame_->ContentLayoutObject()->HitTest(location, result);
  }
  const HitTestRequest& request = result.GetHitTestRequest();
  if (!request.ReadOnly()) {
    frame_->GetDocument()->UpdateHoverActiveState(request,
                                                  result.InnerElement());
  }
}

HitTestResult EventHandler::HitTestResultAtLocation(
    const HitTestLocation& location,
    HitTestRequest::HitTestRequestType hit_type,
    const LayoutObject* stop_node,
    bool no_lifecycle_update) {
  TRACE_EVENT0("blink", "EventHandler::HitTestResultAtLocation");

  // We always send HitTestResultAtLocation to the main frame if we have one,
  // otherwise we might hit areas that are obscured by higher frames.
  if (frame_->GetPage()) {
    LocalFrame& main_frame = frame_->LocalFrameRoot();
    if (frame_ != &main_frame) {
      LocalFrameView* frame_view = frame_->View();
      LocalFrameView* main_view = main_frame.View();
      if (frame_view && main_view) {
        if (location.IsRectBasedTest()) {
          DCHECK(location.IsRectilinear());
          LayoutPoint main_content_point =
              main_view->ConvertFromRootFrame(frame_view->ConvertToRootFrame(
                  location.BoundingBox().Location()));
          HitTestLocation adjusted_location(
              (LayoutRect(main_content_point, location.BoundingBox().Size())));
          return main_frame.GetEventHandler().HitTestResultAtLocation(
              adjusted_location, hit_type, stop_node, no_lifecycle_update);
        } else {
          HitTestLocation adjusted_location(main_view->ConvertFromRootFrame(
              frame_view->ConvertToRootFrame(location.Point())));
          return main_frame.GetEventHandler().HitTestResultAtLocation(
              adjusted_location, hit_type, stop_node, no_lifecycle_update);
        }
      }
    }
  }
  // HitTestResultAtLocation is specifically used to hitTest into all frames,
  // thus it always allows child frame content.
  HitTestRequest request(hit_type | HitTestRequest::kAllowChildFrameContent,
                         stop_node);
  HitTestResult result(request, location);
  PerformHitTest(location, result, no_lifecycle_update);
  return result;
}

void EventHandler::StopAutoscroll() {
  scroll_manager_->StopMiddleClickAutoscroll();
  scroll_manager_->StopAutoscroll();
}

// TODO(bokan): This should be merged with logicalScroll assuming
// defaultSpaceEventHandler's chaining scroll can be done crossing frames.
bool EventHandler::BubblingScroll(ScrollDirection direction,
                                  ScrollGranularity granularity,
                                  Node* starting_node) {
  return scroll_manager_->BubblingScroll(
      direction, granularity, starting_node,
      mouse_event_manager_->MousePressNode());
}

IntPoint EventHandler::LastKnownMousePositionInRootFrame() const {
  return frame_->GetPage()->GetVisualViewport().ViewportToRootFrame(
      mouse_event_manager_->LastKnownMousePosition());
}

IntPoint EventHandler::DragDataTransferLocationForTesting() {
  if (mouse_event_manager_->GetDragState().drag_data_transfer_)
    return mouse_event_manager_->GetDragState()
        .drag_data_transfer_->DragLocation();

  return IntPoint();
}

static bool IsSubmitImage(Node* node) {
  return IsHTMLInputElement(node) &&
         ToHTMLInputElement(node)->type() == input_type_names::kImage;
}

bool EventHandler::UseHandCursor(Node* node, bool is_over_link) {
  if (!node)
    return false;

  return ((is_over_link || IsSubmitImage(node)) && !HasEditableStyle(*node));
}

void EventHandler::CursorUpdateTimerFired(TimerBase*) {
  DCHECK(frame_);
  DCHECK(frame_->GetDocument());

  UpdateCursor();
}

void EventHandler::UpdateCursor() {
  TRACE_EVENT0("input", "EventHandler::updateCursor");

  // We must do a cross-frame hit test because the frame that triggered the
  // cursor update could be occluded by a different frame.
  DCHECK_EQ(frame_, &frame_->LocalFrameRoot());

  LocalFrameView* view = frame_->View();
  if (!view || !view->ShouldSetCursor())
    return;

  auto* layout_view = view->GetLayoutView();
  if (!layout_view)
    return;

  frame_->GetDocument()->UpdateStyleAndLayout();

  HitTestRequest request(HitTestRequest::kReadOnly |
                         HitTestRequest::kAllowChildFrameContent);
  HitTestLocation location(
      view->ViewportToFrame(mouse_event_manager_->LastKnownMousePosition()));
  HitTestResult result(request, location);
  layout_view->HitTest(location, result);

  if (LocalFrame* frame = result.InnerNodeFrame()) {
    EventHandler::OptionalCursor optional_cursor =
        frame->GetEventHandler().SelectCursor(location, result);
    if (optional_cursor.IsCursorChange()) {
      view->SetCursor(optional_cursor.GetCursor());
    }
  }
}

bool EventHandler::ShouldShowResizeForNode(const Node* node,
                                           const HitTestLocation& location) {
  if (LayoutObject* layout_object = node->GetLayoutObject()) {
    PaintLayer* layer = layout_object->EnclosingLayer();
    if (layer->GetScrollableArea() &&
        layer->GetScrollableArea()->IsPointInResizeControl(
            RoundedIntPoint(location.Point()), kResizerForPointer)) {
      return true;
    }
  }
  return false;
}

bool EventHandler::IsSelectingLink(const HitTestResult& result) {
  // If a drag may be starting or we're capturing mouse events for a particular
  // node, don't treat this as a selection. Note calling
  // ComputeVisibleSelectionInDOMTreeDeprecated may update layout.
  const bool mouse_selection =
      !capturing_mouse_events_node_ &&
      mouse_event_manager_->MousePressed() &&
      GetSelectionController().MouseDownMayStartSelect() &&
      !mouse_event_manager_->MouseDownMayStartDrag() &&
      !frame_->Selection()
           .ComputeVisibleSelectionInDOMTreeDeprecated()
           .IsNone();
  return mouse_selection && result.IsOverLink();
}

bool EventHandler::ShouldShowIBeamForNode(const Node* node,
                                          const HitTestResult& result) {
  if (!node)
    return false;

  if (node->IsTextNode() && (node->CanStartSelection() || result.IsOverLink()))
    return true;

  return HasEditableStyle(*node);
}

EventHandler::OptionalCursor EventHandler::SelectCursor(
    const HitTestLocation& location,
    const HitTestResult& result) {
  if (scroll_manager_->InResizeMode())
    return kNoCursorChange;

  Page* page = frame_->GetPage();
  if (!page)
    return kNoCursorChange;
  if (scroll_manager_->MiddleClickAutoscrollInProgress())
    return kNoCursorChange;

  if (result.GetScrollbar() && !result.GetScrollbar()->IsCustomScrollbar())
    return PointerCursor();

  Node* node = result.InnerPossiblyPseudoNode();
  if (!node)
    return SelectAutoCursor(result, node, IBeamCursor());

  if (ShouldShowResizeForNode(node, location))
    return PointerCursor();

  LayoutObject* layout_object = node->GetLayoutObject();
  const ComputedStyle* style = layout_object ? layout_object->Style() : nullptr;

  if (layout_object) {
    Cursor override_cursor;
    switch (layout_object->GetCursor(RoundedIntPoint(result.LocalPoint()),
                                     override_cursor)) {
      case kSetCursorBasedOnStyle:
        break;
      case kSetCursor:
        return override_cursor;
      case kDoNotSetCursor:
        return kNoCursorChange;
    }
  }

  if (style && style->Cursors()) {
    const CursorList* cursors = style->Cursors();
    for (unsigned i = 0; i < cursors->size(); ++i) {
      StyleImage* style_image = (*cursors)[i].GetImage();
      if (!style_image)
        continue;
      ImageResourceContent* cached_image = style_image->CachedImage();
      if (!cached_image)
        continue;
      float scale = style_image->ImageScaleFactor();
      bool hot_spot_specified = (*cursors)[i].HotSpotSpecified();
      // Get hotspot and convert from logical pixels to physical pixels.
      IntPoint hot_spot = (*cursors)[i].HotSpot();
      hot_spot.Scale(scale, scale);
      IntSize size = cached_image->GetImage()->Size();
      if (cached_image->ErrorOccurred())
        continue;
      // Limit the size of cursors (in UI pixels) so that they cannot be
      // used to cover UI elements in chrome.
      size.Scale(1 / scale);
      if (size.Width() > kMaximumCursorSize ||
          size.Height() > kMaximumCursorSize)
        continue;

      Image* image = cached_image->GetImage();
      // Ensure no overflow possible in calculations above.
      if (scale < kMinimumCursorScale)
        continue;
      return Cursor(image, hot_spot_specified, hot_spot, scale);
    }
  }

  bool horizontal_text = !style || style->IsHorizontalWritingMode();
  const Cursor& i_beam = horizontal_text ? IBeamCursor() : VerticalTextCursor();

  switch (style ? style->Cursor() : ECursor::kAuto) {
    case ECursor::kAuto: {
      return SelectAutoCursor(result, node, i_beam);
    }
    case ECursor::kCrosshair:
      return CrossCursor();
    case ECursor::kPointer:
      return IsSelectingLink(result) ? i_beam : HandCursor();
    case ECursor::kMove:
      return MoveCursor();
    case ECursor::kAllScroll:
      return MoveCursor();
    case ECursor::kEResize:
      return EastResizeCursor();
    case ECursor::kWResize:
      return WestResizeCursor();
    case ECursor::kNResize:
      return NorthResizeCursor();
    case ECursor::kSResize:
      return SouthResizeCursor();
    case ECursor::kNeResize:
      return NorthEastResizeCursor();
    case ECursor::kSwResize:
      return SouthWestResizeCursor();
    case ECursor::kNwResize:
      return NorthWestResizeCursor();
    case ECursor::kSeResize:
      return SouthEastResizeCursor();
    case ECursor::kNsResize:
      return NorthSouthResizeCursor();
    case ECursor::kEwResize:
      return EastWestResizeCursor();
    case ECursor::kNeswResize:
      return NorthEastSouthWestResizeCursor();
    case ECursor::kNwseResize:
      return NorthWestSouthEastResizeCursor();
    case ECursor::kColResize:
      return ColumnResizeCursor();
    case ECursor::kRowResize:
      return RowResizeCursor();
    case ECursor::kText:
      return i_beam;
    case ECursor::kWait:
      return WaitCursor();
    case ECursor::kHelp:
      return HelpCursor();
    case ECursor::kVerticalText:
      return VerticalTextCursor();
    case ECursor::kCell:
      return CellCursor();
    case ECursor::kContextMenu:
      return ContextMenuCursor();
    case ECursor::kProgress:
      return ProgressCursor();
    case ECursor::kNoDrop:
      return NoDropCursor();
    case ECursor::kAlias:
      return AliasCursor();
    case ECursor::kCopy:
      return CopyCursor();
    case ECursor::kNone:
      return NoneCursor();
    case ECursor::kNotAllowed:
      return NotAllowedCursor();
    case ECursor::kDefault:
      return PointerCursor();
    case ECursor::kZoomIn:
      return ZoomInCursor();
    case ECursor::kZoomOut:
      return ZoomOutCursor();
    case ECursor::kGrab:
      return GrabCursor();
    case ECursor::kGrabbing:
      return GrabbingCursor();
  }
  return PointerCursor();
}

EventHandler::OptionalCursor EventHandler::SelectAutoCursor(
    const HitTestResult& result,
    Node* node,
    const Cursor& i_beam) {
  if (ShouldShowIBeamForNode(node, result))
    return i_beam;

  return PointerCursor();
}

WebInputEventResult EventHandler::DispatchBufferedTouchEvents() {
  return pointer_event_manager_->FlushEvents();
}

WebInputEventResult EventHandler::HandlePointerEvent(
    const WebPointerEvent& web_pointer_event,
    const Vector<WebPointerEvent>& coalesced_events,
    const Vector<WebPointerEvent>& predicted_events) {
  return pointer_event_manager_->HandlePointerEvent(
      web_pointer_event, coalesced_events, predicted_events);
}

WebInputEventResult EventHandler::HandleMousePressEvent(
    const WebMouseEvent& mouse_event) {
  TRACE_EVENT0("blink", "EventHandler::handleMousePressEvent");

  // For 4th/5th button in the mouse since Chrome does not yet send
  // button value to Blink but in some cases it does send the event.
  // This check is needed to suppress such an event (crbug.com/574959)
  if (mouse_event.button == WebPointerProperties::Button::kNoButton)
    return WebInputEventResult::kHandledSuppressed;

  if (event_handler_will_reset_capturing_mouse_events_node_)
    capturing_mouse_events_node_ = nullptr;
  mouse_event_manager_->HandleMousePressEventUpdateStates(mouse_event);
  if (!frame_->View())
    return WebInputEventResult::kNotHandled;

  HitTestRequest request(HitTestRequest::kActive);
  // Save the document point we generate in case the window coordinate is
  // invalidated by what happens when we dispatch the event.
  LayoutPoint document_point = frame_->View()->ConvertFromRootFrame(
      FlooredIntPoint(mouse_event.PositionInRootFrame()));
  MouseEventWithHitTestResults mev =
      frame_->GetDocument()->PerformMouseEventHitTest(request, document_point,
                                                      mouse_event);
  if (!mev.InnerNode()) {
    mouse_event_manager_->InvalidateClick();
    return WebInputEventResult::kNotHandled;
  }

  mouse_event_manager_->SetMousePressNode(mev.InnerNode());
  frame_->GetDocument()->SetSequentialFocusNavigationStartingPoint(
      mev.InnerNode());

  LocalFrame* subframe = event_handling_util::SubframeForHitTestResult(mev);
  if (subframe) {
    WebInputEventResult result = PassMousePressEventToSubframe(mev, subframe);
    // Start capturing future events for this frame.  We only do this if we
    // didn't clear the m_mousePressed flag, which may happen if an AppKit
    // EmbeddedContentView entered a modal event loop.  The capturing should be
    // done only when the result indicates it has been handled. See
    // crbug.com/269917
    mouse_event_manager_->SetCapturesDragging(
        subframe->GetEventHandler().mouse_event_manager_->CapturesDragging());
    if (mouse_event_manager_->MousePressed() &&
        mouse_event_manager_->CapturesDragging()) {
      capturing_mouse_events_node_ = mev.InnerNode();
      event_handler_will_reset_capturing_mouse_events_node_ = true;
    }
    mouse_event_manager_->InvalidateClick();
    return result;
  }

  std::unique_ptr<UserGestureIndicator> gesture_indicator =
      LocalFrame::NotifyUserActivation(frame_);
  frame_->LocalFrameRoot()
      .GetEventHandler()
      .last_mouse_down_user_gesture_token_ =
      UserGestureIndicator::CurrentToken();
  if (RuntimeEnabledFeatures::MiddleClickAutoscrollEnabled()) {
    // We store whether middle click autoscroll is in progress before calling
    // stopAutoscroll() because it will set m_autoscrollType to NoAutoscroll on
    // return.
    bool is_middle_click_autoscroll_in_progress =
        scroll_manager_->MiddleClickAutoscrollInProgress();
    scroll_manager_->StopMiddleClickAutoscroll();
    if (is_middle_click_autoscroll_in_progress) {
      // We invalidate the click when exiting middle click auto scroll so that
      // we don't inadvertently navigate away from the current page (e.g. the
      // click was on a hyperlink). See <rdar://problem/6095023>.
      mouse_event_manager_->InvalidateClick();
      return WebInputEventResult::kHandledSuppressed;
    }
  }

  mouse_event_manager_->SetClickCount(mouse_event.click_count);
  mouse_event_manager_->SetClickElement(mev.InnerElement());

  if (!mouse_event.FromTouch())
    frame_->Selection().SetCaretBlinkingSuspended(true);

  WebInputEventResult event_result = DispatchMousePointerEvent(
      WebInputEvent::kPointerDown, mev.InnerNode(), mev.CanvasRegionId(),
      mev.Event(), Vector<WebMouseEvent>(), Vector<WebMouseEvent>());

  // Disabled form controls still need to resize the scrollable area.
  if ((event_result == WebInputEventResult::kNotHandled ||
       event_result == WebInputEventResult::kHandledSuppressed) &&
      frame_->View()) {
    LocalFrameView* view = frame_->View();
    PaintLayer* layer =
        mev.InnerNode()->GetLayoutObject()
            ? mev.InnerNode()->GetLayoutObject()->EnclosingLayer()
            : nullptr;
    IntPoint p = view->ConvertFromRootFrame(
        FlooredIntPoint(mouse_event.PositionInRootFrame()));
    if (layer && layer->GetScrollableArea() &&
        layer->GetScrollableArea()->IsPointInResizeControl(
            p, kResizerForPointer)) {
      scroll_manager_->SetResizeScrollableArea(layer, p);
      return WebInputEventResult::kHandledSystem;
    }
  }

  // m_selectionInitiationState is initialized after dispatching mousedown
  // event in order not to keep the selection by DOM APIs because we can't
  // give the user the chance to handle the selection by user action like
  // dragging if we keep the selection in case of mousedown. FireFox also has
  // the same behavior and it's more compatible with other browsers.
  GetSelectionController().InitializeSelectionState();
  HitTestResult hit_test_result = event_handling_util::HitTestResultInFrame(
      frame_, HitTestLocation(document_point), HitTestRequest::kReadOnly);
  InputDeviceCapabilities* source_capabilities =
      frame_->GetDocument()
          ->domWindow()
          ->GetInputDeviceCapabilities()
          ->FiresTouchEvents(mouse_event.FromTouch());

  if (event_result == WebInputEventResult::kNotHandled) {
    event_result = mouse_event_manager_->HandleMouseFocus(hit_test_result,
                                                          source_capabilities);
  }

  if (event_result == WebInputEventResult::kNotHandled || mev.GetScrollbar()) {
    mouse_event_manager_->SetCapturesDragging(true);
    // Main frames don't implicitly capture mouse input on MouseDown, just
    // subframes do (regardless of whether local or remote).
    if (!frame_->IsMainFrame())
      CaptureMouseEventsToWidget(true);
  } else {
    mouse_event_manager_->SetCapturesDragging(false);
  }

  // If the hit testing originally determined the event was in a scrollbar,
  // refetch the MouseEventWithHitTestResults in case the scrollbar
  // EmbeddedContentView was destroyed when the mouse event was handled.
  if (mev.GetScrollbar()) {
    const bool was_last_scroll_bar =
        mev.GetScrollbar() == last_scrollbar_under_mouse_.Get();
    HitTestRequest request(HitTestRequest::kReadOnly | HitTestRequest::kActive);
    mev = frame_->GetDocument()->PerformMouseEventHitTest(
        request, document_point, mouse_event);
    if (was_last_scroll_bar &&
        mev.GetScrollbar() != last_scrollbar_under_mouse_.Get())
      last_scrollbar_under_mouse_ = nullptr;
  }

  if (event_result != WebInputEventResult::kNotHandled) {
    // Scrollbars should get events anyway, even disabled controls might be
    // scrollable.
    PassMousePressEventToScrollbar(mev);
  } else {
    if (ShouldRefetchEventTarget(mev)) {
      HitTestRequest request(HitTestRequest::kReadOnly |
                             HitTestRequest::kActive);
      mev = frame_->GetDocument()->PerformMouseEventHitTest(
          request, document_point, mouse_event);
    }

    if (PassMousePressEventToScrollbar(mev))
      event_result = WebInputEventResult::kHandledSystem;
    else
      event_result = mouse_event_manager_->HandleMousePressEvent(mev);
  }

  if (mev.GetHitTestResult().InnerNode() &&
      mouse_event.button == WebPointerProperties::Button::kLeft) {
    DCHECK_EQ(WebInputEvent::kMouseDown, mouse_event.GetType());
    HitTestResult result = mev.GetHitTestResult();
    result.SetToShadowHostIfInRestrictedShadowRoot();
    frame_->GetChromeClient().OnMouseDown(*result.InnerNode());
  }
  return event_result;
}

WebInputEventResult EventHandler::HandleMouseMoveEvent(
    const WebMouseEvent& event,
    const Vector<WebMouseEvent>& coalesced_events,
    const Vector<WebMouseEvent>& predicted_events) {
  TRACE_EVENT0("blink", "EventHandler::handleMouseMoveEvent");
  HitTestResult hovered_node_result;
  HitTestLocation location;
  WebInputEventResult result =
      HandleMouseMoveOrLeaveEvent(event, coalesced_events, predicted_events,
                                  &hovered_node_result, &location);

  Page* page = frame_->GetPage();
  if (!page)
    return result;

  if (PaintLayer* layer =
          event_handling_util::LayerForNode(hovered_node_result.InnerNode())) {
    if (ScrollableArea* layer_scrollable_area =
            event_handling_util::AssociatedScrollableArea(layer))
      layer_scrollable_area->MouseMovedInContentArea();
  }

  hovered_node_result.SetToShadowHostIfInRestrictedShadowRoot();
  page->GetChromeClient().MouseDidMoveOverElement(*frame_, location,
                                                  hovered_node_result);

  return result;
}

void EventHandler::HandleMouseLeaveEvent(const WebMouseEvent& event) {
  TRACE_EVENT0("blink", "EventHandler::handleMouseLeaveEvent");

  Page* page = frame_->GetPage();
  if (page)
    page->GetChromeClient().ClearToolTip(*frame_);
  HandleMouseMoveOrLeaveEvent(event, Vector<WebMouseEvent>(),
                              Vector<WebMouseEvent>(), nullptr, nullptr, false,
                              true);
  pointer_event_manager_->RemoveLastMousePosition();
}

WebInputEventResult EventHandler::HandleMouseMoveOrLeaveEvent(
    const WebMouseEvent& mouse_event,
    const Vector<WebMouseEvent>& coalesced_events,
    const Vector<WebMouseEvent>& predicted_events,
    HitTestResult* hovered_node_result,
    HitTestLocation* hit_test_location,
    bool only_update_scrollbars,
    bool force_leave) {
  DCHECK(frame_);
  DCHECK(frame_->View());

  mouse_event_manager_->SetLastKnownMousePosition(mouse_event);

  hover_timer_.Stop();
  cursor_update_timer_.Stop();

  mouse_event_manager_->CancelFakeMouseMoveEvent();
  mouse_event_manager_->HandleSvgPanIfNeeded(false);

  // Mouse states need to be reset when mouse move with no button down.
  // This is for popup/context_menu opened at mouse_down event and
  // mouse_release is not handled in page.
  // crbug.com/527582
  if (mouse_event.button == WebPointerProperties::Button::kNoButton &&
      !(mouse_event.GetModifiers() &
        WebInputEvent::Modifiers::kRelativeMotionEvent)) {
    mouse_event_manager_->ClearDragHeuristicState();
    if (event_handler_will_reset_capturing_mouse_events_node_)
      capturing_mouse_events_node_ = nullptr;
    CaptureMouseEventsToWidget(false);
  }

  if (RuntimeEnabledFeatures::MiddleClickAutoscrollEnabled()) {
    if (Page* page = frame_->GetPage()) {
      if (mouse_event.GetType() == WebInputEvent::kMouseLeave &&
          mouse_event.button != WebPointerProperties::Button::kMiddle) {
        page->GetAutoscrollController().StopMiddleClickAutoscroll(frame_);
      } else {
        page->GetAutoscrollController().HandleMouseMoveForMiddleClickAutoscroll(
            frame_, mouse_event_manager_->LastKnownMousePositionGlobal(),
            mouse_event.button == WebPointerProperties::Button::kMiddle);
      }
    }
  }

  if (frame_set_being_resized_) {
    return DispatchMousePointerEvent(
        WebInputEvent::kPointerMove, frame_set_being_resized_.Get(), String(),
        mouse_event, coalesced_events, predicted_events);
  }

  // Send events right to a scrollbar if the mouse is pressed.
  if (last_scrollbar_under_mouse_ && mouse_event_manager_->MousePressed()) {
    last_scrollbar_under_mouse_->MouseMoved(mouse_event);
    return WebInputEventResult::kHandledSystem;
  }

  HitTestRequest::HitTestRequestType hit_type = HitTestRequest::kMove;
  if (mouse_event_manager_->MousePressed()) {
    hit_type |= HitTestRequest::kActive;
  } else if (only_update_scrollbars) {
    // Mouse events should be treated as "read-only" if we're updating only
    // scrollbars. This means that :hover and :active freeze in the state they
    // were in, rather than updating for nodes the mouse moves while the
    // window is not key (which will be the case if onlyUpdateScrollbars is
    // true).
    hit_type |= HitTestRequest::kReadOnly;
  }

  // Treat any mouse move events as readonly if the user is currently touching
  // the screen.
  if (pointer_event_manager_->IsAnyTouchActive() && !force_leave)
    hit_type |= HitTestRequest::kActive | HitTestRequest::kReadOnly;
  HitTestRequest request(hit_type);
  HitTestLocation out_location((LayoutPoint()));
  MouseEventWithHitTestResults mev = MouseEventWithHitTestResults(
      mouse_event, out_location, HitTestResult(request, out_location));

  // We don't want to do a hit-test in forceLeave scenarios because there
  // might actually be some other frame above this one at the specified
  // co-ordinate. So we must force the hit-test to fail, while still clearing
  // hover/active state.
  if (force_leave) {
    frame_->GetDocument()->UpdateHoverActiveState(request, nullptr);
  } else {
    mev = event_handling_util::PerformMouseEventHitTest(frame_, request,
                                                        mouse_event);
  }

  if (hovered_node_result)
    *hovered_node_result = mev.GetHitTestResult();

  if (hit_test_location)
    *hit_test_location = mev.GetHitTestLocation();

  Scrollbar* scrollbar = nullptr;

  if (scroll_manager_->InResizeMode()) {
    scroll_manager_->Resize(mev.Event());
  } else {
    if (!scrollbar)
      scrollbar = mev.GetScrollbar();

    UpdateLastScrollbarUnderMouse(scrollbar,
                                  !mouse_event_manager_->MousePressed());
    if (only_update_scrollbars)
      return WebInputEventResult::kHandledSuppressed;
  }

  WebInputEventResult event_result = WebInputEventResult::kNotHandled;
  LocalFrame* new_subframe =
      capturing_mouse_events_node_.Get()
          ? event_handling_util::SubframeForTargetNode(
                capturing_mouse_events_node_.Get())
          : event_handling_util::SubframeForHitTestResult(mev);

  // We want mouseouts to happen first, from the inside out.  First send a
  // move event to the last subframe so that it will fire mouseouts.
  if (last_mouse_move_event_subframe_ &&
      last_mouse_move_event_subframe_->Tree().IsDescendantOf(frame_) &&
      last_mouse_move_event_subframe_ != new_subframe) {
    last_mouse_move_event_subframe_->GetEventHandler().HandleMouseLeaveEvent(
        mev.Event());
    last_mouse_move_event_subframe_->GetEventHandler()
        .mouse_event_manager_->SetLastMousePositionAsUnknown();
  }

  if (new_subframe) {
    // Update over/out state before passing the event to the subframe.
    pointer_event_manager_->SendMouseAndPointerBoundaryEvents(
        EffectiveMouseEventTargetNode(mev.InnerNode()), mev.CanvasRegionId(),
        mev.Event());

    // Event dispatch in sendMouseAndPointerBoundaryEvents may have caused the
    // subframe of the target node to be detached from its LocalFrameView, in
    // which case the event should not be passed.
    if (new_subframe->View()) {
      event_result =
          PassMouseMoveEventToSubframe(mev, coalesced_events, predicted_events,
                                       new_subframe, hovered_node_result);
    }
  } else {
    if (scrollbar && !mouse_event_manager_->MousePressed()) {
      // Handle hover effects on platforms that support visual feedback on
      // scrollbar hovering.
      scrollbar->MouseMoved(mev.Event());
    }
    if (LocalFrameView* view = frame_->View()) {
      EventHandler::OptionalCursor optional_cursor =
          SelectCursor(mev.GetHitTestLocation(), mev.GetHitTestResult());
      if (optional_cursor.IsCursorChange()) {
        view->SetCursor(optional_cursor.GetCursor());
      }
    }
  }

  last_mouse_move_event_subframe_ = new_subframe;

  if (event_result != WebInputEventResult::kNotHandled)
    return event_result;

  event_result = DispatchMousePointerEvent(
      WebInputEvent::kPointerMove, mev.InnerNode(), mev.CanvasRegionId(),
      mev.Event(), coalesced_events, predicted_events);
  // TODO(crbug.com/346473): Since there is no default action for the mousemove
  // event we should consider doing drag&drop even when js cancels the
  // mouse move event.
  // https://w3c.github.io/uievents/#event-type-mousemove
  if (event_result != WebInputEventResult::kNotHandled)
    return event_result;

  return mouse_event_manager_->HandleMouseDraggedEvent(mev);
}

WebInputEventResult EventHandler::HandleMouseReleaseEvent(
    const WebMouseEvent& mouse_event) {
  TRACE_EVENT0("blink", "EventHandler::handleMouseReleaseEvent");

  // For 4th/5th button in the mouse since Chrome does not yet send
  // button value to Blink but in some cases it does send the event.
  // This check is needed to suppress such an event (crbug.com/574959)
  if (mouse_event.button == WebPointerProperties::Button::kNoButton)
    return WebInputEventResult::kHandledSuppressed;

  if (!mouse_event.FromTouch())
    frame_->Selection().SetCaretBlinkingSuspended(false);

  if (RuntimeEnabledFeatures::MiddleClickAutoscrollEnabled()) {
    if (Page* page = frame_->GetPage()) {
      page->GetAutoscrollController()
          .HandleMouseReleaseForMiddleClickAutoscroll(
              frame_,
              mouse_event.button == WebPointerProperties::Button::kMiddle);
    }
  }

  mouse_event_manager_->ReleaseMousePress();
  mouse_event_manager_->SetLastKnownMousePosition(mouse_event);
  mouse_event_manager_->HandleSvgPanIfNeeded(true);

  if (frame_set_being_resized_) {
    CaptureMouseEventsToWidget(false);
    return mouse_event_manager_->SetMousePositionAndDispatchMouseEvent(
        EffectiveMouseEventTargetNode(frame_set_being_resized_.Get()), String(),
        event_type_names::kMouseup, mouse_event);
  }

  if (last_scrollbar_under_mouse_) {
    mouse_event_manager_->InvalidateClick();
    last_scrollbar_under_mouse_->MouseUp(mouse_event);
    CaptureMouseEventsToWidget(false);
    return DispatchMousePointerEvent(
        WebInputEvent::kPointerUp, mouse_event_manager_->GetNodeUnderMouse(),
        String(), mouse_event, Vector<WebMouseEvent>(),
        Vector<WebMouseEvent>());
  }

  // Mouse events simulated from touch should not hit-test again.
  DCHECK(!mouse_event.FromTouch());

  HitTestRequest::HitTestRequestType hit_type = HitTestRequest::kRelease;
  HitTestRequest request(hit_type);
  MouseEventWithHitTestResults mev =
      event_handling_util::PerformMouseEventHitTest(frame_, request,
                                                    mouse_event);
  Element* mouse_release_target = mev.InnerElement();
  LocalFrame* subframe =
      capturing_mouse_events_node_.Get()
          ? event_handling_util::SubframeForTargetNode(
                capturing_mouse_events_node_.Get())
          : event_handling_util::SubframeForHitTestResult(mev);
  if (event_handler_will_reset_capturing_mouse_events_node_)
    capturing_mouse_events_node_ = nullptr;
  if (subframe)
    return PassMouseReleaseEventToSubframe(mev, subframe);

  // Mouse events will be associated with the Document where mousedown
  // occurred. If, e.g., there is a mousedown, then a drag to a different
  // Document and mouseup there, the mouseup's gesture will be associated with
  // the mousedown's Document. It's not absolutely certain that this is the
  // correct behavior.
  std::unique_ptr<UserGestureIndicator> gesture_indicator;
  if (frame_->LocalFrameRoot()
          .GetEventHandler()
          .last_mouse_down_user_gesture_token_) {
    gesture_indicator = std::make_unique<UserGestureIndicator>(
        std::move(frame_->LocalFrameRoot()
                      .GetEventHandler()
                      .last_mouse_down_user_gesture_token_));
  } else {
    gesture_indicator = LocalFrame::NotifyUserActivation(frame_);
  }

  WebInputEventResult event_result = DispatchMousePointerEvent(
      WebInputEvent::kPointerUp, mev.InnerNode(), mev.CanvasRegionId(),
      mev.Event(), Vector<WebMouseEvent>(), Vector<WebMouseEvent>());

  WebInputEventResult click_event_result =
      mouse_release_target ? mouse_event_manager_->DispatchMouseClickIfNeeded(
                                 mev, *mouse_release_target)
                           : WebInputEventResult::kNotHandled;

  scroll_manager_->ClearResizeScrollableArea(false);

  if (event_result == WebInputEventResult::kNotHandled)
    event_result = mouse_event_manager_->HandleMouseReleaseEvent(mev);

  mouse_event_manager_->HandleMouseReleaseEventUpdateStates();
  CaptureMouseEventsToWidget(false);

  return event_handling_util::MergeEventResult(click_event_result,
                                               event_result);
}

static bool TargetIsFrame(Node* target, LocalFrame*& frame) {
  if (!IsHTMLFrameElementBase(target))
    return false;

  // Cross-process drag and drop is not yet supported.
  if (ToHTMLFrameElementBase(target)->ContentFrame() &&
      !ToHTMLFrameElementBase(target)->ContentFrame()->IsLocalFrame())
    return false;

  frame = ToLocalFrame(ToHTMLFrameElementBase(target)->ContentFrame());
  return true;
}

WebInputEventResult EventHandler::UpdateDragAndDrop(
    const WebMouseEvent& event,
    DataTransfer* data_transfer) {
  WebInputEventResult event_result = WebInputEventResult::kNotHandled;

  if (!frame_->View())
    return event_result;

  HitTestRequest request(HitTestRequest::kReadOnly);
  MouseEventWithHitTestResults mev =
      event_handling_util::PerformMouseEventHitTest(frame_, request, event);

  // Drag events should never go to text nodes (following IE, and proper
  // mouseover/out dispatch)
  Node* new_target = mev.InnerNode();
  if (new_target && new_target->IsTextNode())
    new_target = FlatTreeTraversal::Parent(*new_target);

  if (AutoscrollController* controller =
          scroll_manager_->GetAutoscrollController()) {
    controller->UpdateDragAndDrop(new_target,
                                  FlooredIntPoint(event.PositionInRootFrame()),
                                  event.TimeStamp());
  }

  if (drag_target_ != new_target) {
    // FIXME: this ordering was explicitly chosen to match WinIE. However,
    // it is sometimes incorrect when dragging within subframes, as seen with
    // web_tests/fast/events/drag-in-frames.html.
    //
    // Moreover, this ordering conforms to section 7.9.4 of the HTML 5 spec.
    // <http://dev.w3.org/html5/spec/Overview.html#drag-and-drop-processing-model>.
    LocalFrame* target_frame;
    if (TargetIsFrame(new_target, target_frame)) {
      if (target_frame)
        event_result = target_frame->GetEventHandler().UpdateDragAndDrop(
            event, data_transfer);
    } else if (new_target) {
      // As per section 7.9.4 of the HTML 5 spec., we must always fire a drag
      // event before firing a dragenter, dragleave, or dragover event.
      if (mouse_event_manager_->GetDragState().drag_src_) {
        // For now we don't care if event handler cancels default behavior,
        // since there is none.
        mouse_event_manager_->DispatchDragSrcEvent(event_type_names::kDrag,
                                                   event);
      }
      event_result = mouse_event_manager_->DispatchDragEvent(
          event_type_names::kDragenter, new_target, drag_target_, event,
          data_transfer);
    }

    if (TargetIsFrame(drag_target_.Get(), target_frame)) {
      if (target_frame)
        event_result = target_frame->GetEventHandler().UpdateDragAndDrop(
            event, data_transfer);
    } else if (drag_target_) {
      mouse_event_manager_->DispatchDragEvent(event_type_names::kDragleave,
                                              drag_target_.Get(), new_target,
                                              event, data_transfer);
    }

    if (new_target) {
      // We do not explicitly call m_mouseEventManager->dispatchDragEvent here
      // because it could ultimately result in the appearance that two dragover
      // events fired. So, we mark that we should only fire a dragover event on
      // the next call to this function.
      should_only_fire_drag_over_event_ = true;
    }
  } else {
    LocalFrame* target_frame;
    if (TargetIsFrame(new_target, target_frame)) {
      if (target_frame)
        event_result = target_frame->GetEventHandler().UpdateDragAndDrop(
            event, data_transfer);
    } else if (new_target) {
      // Note, when dealing with sub-frames, we may need to fire only a dragover
      // event as a drag event may have been fired earlier.
      if (!should_only_fire_drag_over_event_ &&
          mouse_event_manager_->GetDragState().drag_src_) {
        // For now we don't care if event handler cancels default behavior,
        // since there is none.
        mouse_event_manager_->DispatchDragSrcEvent(event_type_names::kDrag,
                                                   event);
      }
      event_result = mouse_event_manager_->DispatchDragEvent(
          event_type_names::kDragover, new_target, nullptr, event,
          data_transfer);
      should_only_fire_drag_over_event_ = false;
    }
  }
  drag_target_ = new_target;

  return event_result;
}

void EventHandler::CancelDragAndDrop(const WebMouseEvent& event,
                                     DataTransfer* data_transfer) {
  LocalFrame* target_frame;
  if (TargetIsFrame(drag_target_.Get(), target_frame)) {
    if (target_frame)
      target_frame->GetEventHandler().CancelDragAndDrop(event, data_transfer);
  } else if (drag_target_.Get()) {
    if (mouse_event_manager_->GetDragState().drag_src_) {
      mouse_event_manager_->DispatchDragSrcEvent(event_type_names::kDrag,
                                                 event);
    }
    mouse_event_manager_->DispatchDragEvent(event_type_names::kDragleave,
                                            drag_target_.Get(), nullptr, event,
                                            data_transfer);
  }
  ClearDragState();
}

WebInputEventResult EventHandler::PerformDragAndDrop(
    const WebMouseEvent& event,
    DataTransfer* data_transfer) {
  LocalFrame* target_frame;
  WebInputEventResult result = WebInputEventResult::kNotHandled;
  if (TargetIsFrame(drag_target_.Get(), target_frame)) {
    if (target_frame)
      result = target_frame->GetEventHandler().PerformDragAndDrop(
          event, data_transfer);
  } else if (drag_target_.Get()) {
    result = mouse_event_manager_->DispatchDragEvent(
        event_type_names::kDrop, drag_target_.Get(), nullptr, event,
        data_transfer);
  }
  ClearDragState();
  return result;
}

void EventHandler::ClearDragState() {
  scroll_manager_->StopAutoscroll();
  drag_target_ = nullptr;
  capturing_mouse_events_node_ = nullptr;
  should_only_fire_drag_over_event_ = false;
}

void EventHandler::AnimateSnapFling(base::TimeTicks monotonic_time) {
  scroll_manager_->AnimateSnapFling(monotonic_time);
}

void EventHandler::RecomputeMouseHoverState() {
  mouse_event_manager_->RecomputeMouseHoverState();
}

void EventHandler::SetCapturingMouseEventsNode(Node* n) {
  CaptureMouseEventsToWidget(n);
  capturing_mouse_events_node_ = n;
}

Node* EventHandler::EffectiveMouseEventTargetNode(Node* target_node) {
  Node* new_node_under_mouse = target_node;

  if (capturing_mouse_events_node_) {
    new_node_under_mouse = capturing_mouse_events_node_.Get();
  } else {
    // If the target node is a text node, dispatch on the parent node -
    // rdar://4196646
    if (new_node_under_mouse && new_node_under_mouse->IsTextNode())
      new_node_under_mouse = FlatTreeTraversal::Parent(*new_node_under_mouse);
  }
  return new_node_under_mouse;
}

bool EventHandler::IsTouchPointerIdActiveOnFrame(int pointer_id,
                                                 LocalFrame* frame) const {
  DCHECK_EQ(frame_, &frame_->LocalFrameRoot());
  return pointer_event_manager_->IsTouchPointerIdActiveOnFrame(pointer_id,
                                                               frame);
}

bool EventHandler::RootFrameTouchPointerActiveInCurrentFrame(
    int pointer_id) const {
  return frame_ != &frame_->LocalFrameRoot() &&
         frame_->LocalFrameRoot()
             .GetEventHandler()
             .IsTouchPointerIdActiveOnFrame(pointer_id, frame_);
}

bool EventHandler::IsPointerEventActive(int pointer_id) {
  return pointer_event_manager_->IsActive(pointer_id) ||
         RootFrameTouchPointerActiveInCurrentFrame(pointer_id);
}

void EventHandler::SetPointerCapture(int pointer_id, EventTarget* target) {
  // TODO(crbug.com/591387): This functionality should be per page not per
  // frame.
  if (RootFrameTouchPointerActiveInCurrentFrame(pointer_id)) {
    frame_->LocalFrameRoot().GetEventHandler().SetPointerCapture(pointer_id,
                                                                 target);
  } else {
    pointer_event_manager_->SetPointerCapture(pointer_id, target);
  }
}

void EventHandler::ReleasePointerCapture(int pointer_id, EventTarget* target) {
  if (RootFrameTouchPointerActiveInCurrentFrame(pointer_id)) {
    frame_->LocalFrameRoot().GetEventHandler().ReleasePointerCapture(pointer_id,
                                                                     target);
  } else {
    pointer_event_manager_->ReleasePointerCapture(pointer_id, target);
  }
}

void EventHandler::ReleaseMousePointerCapture() {
  pointer_event_manager_->ReleaseMousePointerCapture();
}

bool EventHandler::HasPointerCapture(int pointer_id,
                                     const EventTarget* target) const {
  if (RootFrameTouchPointerActiveInCurrentFrame(pointer_id)) {
    return frame_->LocalFrameRoot().GetEventHandler().HasPointerCapture(
        pointer_id, target);
  } else {
    return pointer_event_manager_->HasPointerCapture(pointer_id, target);
  }
}

bool EventHandler::HasProcessedPointerCapture(int pointer_id,
                                              const EventTarget* target) const {
  return pointer_event_manager_->HasProcessedPointerCapture(pointer_id, target);
}

void EventHandler::ProcessPendingPointerCaptureForPointerLock(
    const WebMouseEvent& mouse_event) {
  pointer_event_manager_->ProcessPendingPointerCaptureForPointerLock(
      mouse_event);
}

void EventHandler::ElementRemoved(EventTarget* target) {
  pointer_event_manager_->ElementRemoved(target);
  if (target)
    mouse_wheel_event_manager_->ElementRemoved(target->ToNode());
}

WebInputEventResult EventHandler::DispatchMousePointerEvent(
    const WebInputEvent::Type event_type,
    Node* target_node,
    const String& canvas_region_id,
    const WebMouseEvent& mouse_event,
    const Vector<WebMouseEvent>& coalesced_events,
    const Vector<WebMouseEvent>& predicted_events) {
  const auto& event_result = pointer_event_manager_->SendMousePointerEvent(
      EffectiveMouseEventTargetNode(target_node), canvas_region_id, event_type,
      mouse_event, coalesced_events, predicted_events);
  return event_result;
}

WebInputEventResult EventHandler::HandleWheelEvent(
    const WebMouseWheelEvent& event) {
  return mouse_wheel_event_manager_->HandleWheelEvent(event);
}

// TODO(crbug.com/665924): This function bypasses all Handle*Event path.
// It should be using that flow instead of creating/sending events directly.
WebInputEventResult EventHandler::HandleTargetedMouseEvent(
    Node* target,
    const WebMouseEvent& event,
    const AtomicString& mouse_event_type,
    const Vector<WebMouseEvent>& coalesced_events,
    const Vector<WebMouseEvent>& predicted_events,
    const String& canvas_region_id) {
  mouse_event_manager_->SetClickCount(event.click_count);
  return pointer_event_manager_->DirectDispatchMousePointerEvent(
      target, event, mouse_event_type, coalesced_events, predicted_events,
      canvas_region_id);
}

WebInputEventResult EventHandler::HandleGestureEvent(
    const WebGestureEvent& gesture_event) {
  // Propagation to inner frames is handled below this function.
  DCHECK_EQ(frame_, &frame_->LocalFrameRoot());
  DCHECK_NE(0, gesture_event.FrameScale());

  // Scrolling-related gesture events invoke EventHandler recursively for each
  // frame down the chain, doing a single-frame hit-test per frame. This matches
  // handleWheelEvent.
  // FIXME: Add a test that traverses this path, e.g. for devtools overlay.
  if (gesture_event.IsScrollEvent())
    return HandleGestureScrollEvent(gesture_event);

  // Hit test across all frames and do touch adjustment as necessary for the
  // event type.
  GestureEventWithHitTestResults targeted_event =
      TargetGestureEvent(gesture_event);

  return HandleGestureEvent(targeted_event);
}

WebInputEventResult EventHandler::HandleGestureEvent(
    const GestureEventWithHitTestResults& targeted_event) {
  TRACE_EVENT0("input", "EventHandler::handleGestureEvent");
  if (!frame_->GetPage())
    return WebInputEventResult::kNotHandled;

  // Propagation to inner frames is handled below this function.
  DCHECK_EQ(frame_, &frame_->LocalFrameRoot());

  // Non-scrolling related gesture events do a single cross-frame hit-test and
  // jump directly to the inner most frame. This matches handleMousePressEvent
  // etc.
  DCHECK(!targeted_event.Event().IsScrollEvent());

  if (targeted_event.Event().GetType() == WebInputEvent::kGestureShowPress)
    last_show_press_timestamp_ = CurrentTimeTicks();

  // Update mouseout/leave/over/enter events before jumping directly to the
  // inner most frame.
  if (targeted_event.Event().GetType() == WebInputEvent::kGestureTap)
    UpdateGestureTargetNodeForMouseEvent(targeted_event);

  // Route to the correct frame.
  if (LocalFrame* inner_frame =
          targeted_event.GetHitTestResult().InnerNodeFrame())
    return inner_frame->GetEventHandler().HandleGestureEventInFrame(
        targeted_event);

  // No hit test result, handle in root instance. Perhaps we should just return
  // false instead?
  return gesture_manager_->HandleGestureEventInFrame(targeted_event);
}

WebInputEventResult EventHandler::HandleGestureEventInFrame(
    const GestureEventWithHitTestResults& targeted_event) {
  return gesture_manager_->HandleGestureEventInFrame(targeted_event);
}

WebInputEventResult EventHandler::HandleGestureScrollEvent(
    const WebGestureEvent& gesture_event) {
  TRACE_EVENT0("input", "EventHandler::handleGestureScrollEvent");
  if (!frame_->GetPage())
    return WebInputEventResult::kNotHandled;

  return scroll_manager_->HandleGestureScrollEvent(gesture_event);
}

WebInputEventResult EventHandler::HandleGestureScrollEnd(
    const WebGestureEvent& gesture_event) {
  if (!frame_->GetPage())
    return WebInputEventResult::kNotHandled;
  return scroll_manager_->HandleGestureScrollEnd(gesture_event);
}

void EventHandler::SetMouseDownMayStartAutoscroll() {
  mouse_event_manager_->SetMouseDownMayStartAutoscroll();
}

bool EventHandler::IsScrollbarHandlingGestures() const {
  return scroll_manager_->IsScrollbarHandlingGestures();
}

bool EventHandler::ShouldApplyTouchAdjustment(
    const WebGestureEvent& event) const {
  if (frame_->GetSettings() &&
      !frame_->GetSettings()->GetTouchAdjustmentEnabled())
    return false;

  if (event.primary_pointer_type == WebPointerProperties::PointerType::kPen)
    return false;

  return !event.TapAreaInRootFrame().IsEmpty();
}

void EventHandler::CacheTouchAdjustmentResult(uint32_t id,
                                              FloatPoint adjusted_point) {
  touch_adjustment_result_.unique_event_id = id;
  touch_adjustment_result_.adjusted_point = adjusted_point;
}

bool EventHandler::GestureCorrespondsToAdjustedTouch(
    const WebGestureEvent& event) {
  if (!RuntimeEnabledFeatures::UnifiedTouchAdjustmentEnabled())
    return false;
  // Gesture events start with a GestureTapDown. If GestureTapDown's unique id
  // matches stored adjusted touchstart event id, then we can use the stored
  // result for following gesture event.
  if (event.GetType() == WebInputEvent::kGestureTapDown) {
    should_use_touch_event_adjusted_point_ =
        (event.unique_touch_event_id != 0 &&
         event.unique_touch_event_id ==
             touch_adjustment_result_.unique_event_id);
  }

  // Check if the adjusted point is in the gesture event tap rect.
  // If not, should not use this touch point in following events.
  if (should_use_touch_event_adjusted_point_) {
    FloatRect tap_rect(FloatPoint(event.PositionInRootFrame()) -
                           FloatSize(event.TapAreaInRootFrame()) * 0.5,
                       FloatSize(event.TapAreaInRootFrame()));
    should_use_touch_event_adjusted_point_ =
        tap_rect.Contains(touch_adjustment_result_.adjusted_point);
  }

  return should_use_touch_event_adjusted_point_;
}

bool EventHandler::BestClickableNodeForHitTestResult(
    const HitTestLocation& location,
    const HitTestResult& result,
    IntPoint& target_point,
    Node*& target_node) {
  // FIXME: Unify this with the other best* functions which are very similar.

  TRACE_EVENT0("input", "EventHandler::bestClickableNodeForHitTestResult");
  DCHECK(location.IsRectBasedTest());

  // If the touch is over a scrollbar, don't adjust the touch point since touch
  // adjustment only takes into account DOM nodes so a touch over a scrollbar
  // will be adjusted towards nearby nodes. This leads to things like textarea
  // scrollbars being untouchable.
  if (result.GetScrollbar()) {
    target_node = nullptr;
    return false;
  }

  IntPoint touch_center =
      frame_->View()->ConvertToRootFrame(RoundedIntPoint(location.Point()));
  IntRect touch_rect =
      frame_->View()->ConvertToRootFrame(location.EnclosingIntRect());

  HeapVector<Member<Node>, 11> nodes;
  CopyToVector(result.ListBasedTestResult(), nodes);

  // FIXME: the explicit Vector conversion copies into a temporary and is
  // wasteful.
  return FindBestClickableCandidate(target_node, target_point, touch_center,
                                    touch_rect,
                                    HeapVector<Member<Node>>(nodes));
}

bool EventHandler::BestContextMenuNodeForHitTestResult(
    const HitTestLocation& location,
    const HitTestResult& result,
    IntPoint& target_point,
    Node*& target_node) {
  DCHECK(location.IsRectBasedTest());
  IntPoint touch_center =
      frame_->View()->ConvertToRootFrame(RoundedIntPoint(location.Point()));
  IntRect touch_rect =
      frame_->View()->ConvertToRootFrame(location.EnclosingIntRect());
  HeapVector<Member<Node>, 11> nodes;
  CopyToVector(result.ListBasedTestResult(), nodes);

  // FIXME: the explicit Vector conversion copies into a temporary and is
  // wasteful.
  return FindBestContextMenuCandidate(target_node, target_point, touch_center,
                                      touch_rect,
                                      HeapVector<Member<Node>>(nodes));
}

// Update the hover and active state across all frames for this gesture.
// This logic is different than the mouse case because mice send MouseLeave
// events to frames as they're exited.  With gestures, a single event
// conceptually both 'leaves' whatever frame currently had hover and enters a
// new frame
void EventHandler::UpdateGestureHoverActiveState(const HitTestRequest& request,
                                                 Element* inner_element) {
  DCHECK_EQ(frame_, &frame_->LocalFrameRoot());

  HeapVector<Member<LocalFrame>> new_hover_frame_chain;
  LocalFrame* new_hover_frame_in_document =
      inner_element ? inner_element->GetDocument().GetFrame() : nullptr;
  // Insert the ancestors of the frame having the new hovered element to the
  // frame chain.  The frame chain doesn't include the main frame to avoid the
  // redundant work that cleans the hover state because the hover state for the
  // main frame is updated by calling Document::updateHoverActiveState.
  while (new_hover_frame_in_document && new_hover_frame_in_document != frame_) {
    new_hover_frame_chain.push_back(new_hover_frame_in_document);
    Frame* parent_frame = new_hover_frame_in_document->Tree().Parent();
    new_hover_frame_in_document = parent_frame && parent_frame->IsLocalFrame()
                                      ? ToLocalFrame(parent_frame)
                                      : nullptr;
  }

  Element* old_hover_element_in_cur_doc = frame_->GetDocument()->HoverElement();
  Element* new_innermost_hover_element = inner_element;

  if (new_innermost_hover_element != old_hover_element_in_cur_doc) {
    wtf_size_t index_frame_chain = new_hover_frame_chain.size();

    // Clear the hover state on any frames which are no longer in the frame
    // chain of the hovered element.
    while (old_hover_element_in_cur_doc &&
           old_hover_element_in_cur_doc->IsFrameOwnerElement()) {
      LocalFrame* new_hover_frame = nullptr;
      // If we can't get the frame from the new hover frame chain,
      // the newHoverFrame will be null and the old hover state will be cleared.
      if (index_frame_chain > 0)
        new_hover_frame = new_hover_frame_chain[--index_frame_chain];

      HTMLFrameOwnerElement* owner =
          ToHTMLFrameOwnerElement(old_hover_element_in_cur_doc);
      if (!owner->ContentFrame() || !owner->ContentFrame()->IsLocalFrame())
        break;

      LocalFrame* old_hover_frame = ToLocalFrame(owner->ContentFrame());
      Document* doc = old_hover_frame->GetDocument();
      if (!doc)
        break;

      old_hover_element_in_cur_doc = doc->HoverElement();
      // If the old hovered frame is different from the new hovered frame.
      // we should clear the old hovered element from the old hovered frame.
      if (new_hover_frame != old_hover_frame)
        doc->UpdateHoverActiveState(request, nullptr);
    }
  }

  // Recursively set the new active/hover states on every frame in the chain of
  // innerElement.
  frame_->GetDocument()->UpdateHoverActiveState(request, inner_element);
}

// Update the mouseover/mouseenter/mouseout/mouseleave events across all frames
// for this gesture, before passing the targeted gesture event directly to a hit
// frame.
void EventHandler::UpdateGestureTargetNodeForMouseEvent(
    const GestureEventWithHitTestResults& targeted_event) {
  DCHECK_EQ(frame_, &frame_->LocalFrameRoot());

  // Behaviour of this function is as follows:
  // - Create the chain of all entered frames.
  // - Compare the last frame chain under the gesture to newly entered frame
  //   chain from the main frame one by one.
  // - If the last frame doesn't match with the entered frame, then create the
  //   chain of exited frames from the last frame chain.
  // - Dispatch mouseout/mouseleave events of the exited frames from the inside
  //   out.
  // - Dispatch mouseover/mouseenter events of the entered frames into the
  //   inside.

  // Insert the ancestors of the frame having the new target node to the entered
  // frame chain.
  HeapVector<Member<LocalFrame>, 2> entered_frame_chain;
  LocalFrame* entered_frame_in_document =
      targeted_event.GetHitTestResult().InnerNodeFrame();
  while (entered_frame_in_document) {
    entered_frame_chain.push_back(entered_frame_in_document);
    Frame* parent_frame = entered_frame_in_document->Tree().Parent();
    entered_frame_in_document = parent_frame && parent_frame->IsLocalFrame()
                                    ? ToLocalFrame(parent_frame)
                                    : nullptr;
  }

  wtf_size_t index_entered_frame_chain = entered_frame_chain.size();
  LocalFrame* exited_frame_in_document = frame_;
  HeapVector<Member<LocalFrame>, 2> exited_frame_chain;
  // Insert the frame from the disagreement between last frames and entered
  // frames.
  while (exited_frame_in_document) {
    Node* last_node_under_tap = exited_frame_in_document->GetEventHandler()
                                    .mouse_event_manager_->GetNodeUnderMouse();
    if (!last_node_under_tap)
      break;

    LocalFrame* next_exited_frame_in_document = nullptr;
    if (last_node_under_tap->IsFrameOwnerElement()) {
      HTMLFrameOwnerElement* owner =
          ToHTMLFrameOwnerElement(last_node_under_tap);
      if (owner->ContentFrame() && owner->ContentFrame()->IsLocalFrame())
        next_exited_frame_in_document = ToLocalFrame(owner->ContentFrame());
    }

    if (exited_frame_chain.size() > 0) {
      exited_frame_chain.push_back(exited_frame_in_document);
    } else {
      LocalFrame* last_entered_frame_in_document =
          index_entered_frame_chain
              ? entered_frame_chain[index_entered_frame_chain - 1]
              : nullptr;
      if (exited_frame_in_document != last_entered_frame_in_document)
        exited_frame_chain.push_back(exited_frame_in_document);
      else if (next_exited_frame_in_document && index_entered_frame_chain)
        --index_entered_frame_chain;
    }
    exited_frame_in_document = next_exited_frame_in_document;
  }

  const WebGestureEvent& gesture_event = targeted_event.Event();
  unsigned modifiers = gesture_event.GetModifiers();
  WebMouseEvent fake_mouse_move(
      WebInputEvent::kMouseMove, gesture_event,
      WebPointerProperties::Button::kNoButton,
      /* clickCount */ 0,
      modifiers | WebInputEvent::Modifiers::kIsCompatibilityEventForTouch,
      gesture_event.TimeStamp());

  // Update the mouseout/mouseleave event
  wtf_size_t index_exited_frame_chain = exited_frame_chain.size();
  while (index_exited_frame_chain) {
    LocalFrame* leave_frame = exited_frame_chain[--index_exited_frame_chain];
    leave_frame->GetEventHandler().mouse_event_manager_->SetNodeUnderMouse(
        EffectiveMouseEventTargetNode(nullptr), String(), fake_mouse_move);
  }

  // update the mouseover/mouseenter event
  while (index_entered_frame_chain) {
    Frame* parent_frame =
        entered_frame_chain[--index_entered_frame_chain]->Tree().Parent();
    if (parent_frame && parent_frame->IsLocalFrame()) {
      ToLocalFrame(parent_frame)
          ->GetEventHandler()
          .mouse_event_manager_->SetNodeUnderMouse(
              EffectiveMouseEventTargetNode(ToHTMLFrameOwnerElement(
                  entered_frame_chain[index_entered_frame_chain]->Owner())),
              String(), fake_mouse_move);
    }
  }
}

GestureEventWithHitTestResults EventHandler::TargetGestureEvent(
    const WebGestureEvent& gesture_event,
    bool read_only) {
  TRACE_EVENT0("input", "EventHandler::targetGestureEvent");

  DCHECK_EQ(frame_, &frame_->LocalFrameRoot());
  // Scrolling events get hit tested per frame (like wheel events do).
  DCHECK(!gesture_event.IsScrollEvent());

  HitTestRequest::HitTestRequestType hit_type =
      gesture_manager_->GetHitTypeForGestureType(gesture_event.GetType());
  TimeDelta active_interval;
  bool should_keep_active_for_min_interval = false;
  if (read_only) {
    hit_type |= HitTestRequest::kReadOnly;
  } else if (gesture_event.GetType() == WebInputEvent::kGestureTap &&
             last_show_press_timestamp_) {
    // If the Tap is received very shortly after ShowPress, we want to
    // delay clearing of the active state so that it's visible to the user
    // for at least a couple of frames.
    active_interval = CurrentTimeTicks() - last_show_press_timestamp_.value();
    should_keep_active_for_min_interval =
        active_interval < kMinimumActiveInterval;
    if (should_keep_active_for_min_interval)
      hit_type |= HitTestRequest::kReadOnly;
  }

  GestureEventWithHitTestResults event_with_hit_test_results =
      HitTestResultForGestureEvent(gesture_event, hit_type);
  // Now apply hover/active state to the final target.
  HitTestRequest request(hit_type | HitTestRequest::kAllowChildFrameContent);
  if (!request.ReadOnly()) {
    UpdateGestureHoverActiveState(
        request, event_with_hit_test_results.GetHitTestResult().InnerElement());
  }

  if (should_keep_active_for_min_interval) {
    last_deferred_tap_element_ =
        event_with_hit_test_results.GetHitTestResult().InnerElement();
    // TODO(https://crbug.com/668758): Use a normal BeginFrame update for this.
    active_interval_timer_.StartOneShot(
        kMinimumActiveInterval - active_interval, FROM_HERE);
  }

  return event_with_hit_test_results;
}

GestureEventWithHitTestResults EventHandler::HitTestResultForGestureEvent(
    const WebGestureEvent& gesture_event,
    HitTestRequest::HitTestRequestType hit_type) {
  // Perform the rect-based hit-test (or point-based if adjustment is
  // disabled). Note that we don't yet apply hover/active state here because
  // we need to resolve touch adjustment first so that we apply hover/active
  // it to the final adjusted node.
  hit_type |= HitTestRequest::kReadOnly;
  WebGestureEvent adjusted_event = gesture_event;
  LayoutSize hit_rect_size;
  if (ShouldApplyTouchAdjustment(gesture_event)) {
    // If gesture_event unique id matches the stored touch event result, do
    // point-base hit test. Otherwise add padding and do rect-based hit test.
    if (GestureCorrespondsToAdjustedTouch(gesture_event)) {
      adjusted_event.ApplyTouchAdjustment(
          touch_adjustment_result_.adjusted_point);
    } else {
      hit_rect_size = GetHitTestRectForAdjustment(
          *frame_, LayoutSize(adjusted_event.TapAreaInRootFrame()));
      if (!hit_rect_size.IsEmpty())
        hit_type |= HitTestRequest::kListBased;
    }
  }

  HitTestLocation location;
  LocalFrame& root_frame = frame_->LocalFrameRoot();
  HitTestResult hit_test_result;
  if (hit_rect_size.IsEmpty()) {
    location = HitTestLocation(adjusted_event.PositionInRootFrame());
    hit_test_result = root_frame.GetEventHandler().HitTestResultAtLocation(
        location, hit_type);
  } else {
    LayoutPoint top_left(adjusted_event.PositionInRootFrame());
    top_left.Move(-hit_rect_size * 0.5f);
    location = HitTestLocation(LayoutRect(top_left, hit_rect_size));
    hit_test_result = root_frame.GetEventHandler().HitTestResultAtLocation(
        location, hit_type);
  }

  if (location.IsRectBasedTest()) {
    // Adjust the location of the gesture to the most likely nearby node, as
    // appropriate for the type of event.
    ApplyTouchAdjustment(&adjusted_event, location, &hit_test_result);
    // Do a new hit-test at the (adjusted) gesture co-ordinates. This is
    // necessary because rect-based hit testing and touch adjustment sometimes
    // return a different node than what a point-based hit test would return for
    // the same point.
    // FIXME: Fix touch adjustment to avoid the need for a redundant hit test.
    // http://crbug.com/398914
    LocalFrame* hit_frame = hit_test_result.InnerNodeFrame();
    if (!hit_frame)
      hit_frame = frame_;
    location = HitTestLocation(adjusted_event.PositionInRootFrame());
    hit_test_result = root_frame.GetEventHandler().HitTestResultAtLocation(
        location,
        (hit_type | HitTestRequest::kReadOnly) & ~HitTestRequest::kListBased);
  }
  // If we did a rect-based hit test it must be resolved to the best single node
  // by now to ensure consumers don't accidentally use one of the other
  // candidates.
  DCHECK(!location.IsRectBasedTest());

  if (ShouldApplyTouchAdjustment(gesture_event) &&
      (gesture_event.GetType() == WebInputEvent::kGestureTap ||
       gesture_event.GetType() == WebInputEvent::kGestureLongPress)) {
    float adjusted_distance = FloatSize(adjusted_event.PositionInRootFrame() -
                                        gesture_event.PositionInRootFrame())
                                  .DiagonalLength();
    UMA_HISTOGRAM_COUNTS_100("Event.Touch.TouchAdjustment.AdjustDistance",
                             static_cast<int>(adjusted_distance));
  }
  return GestureEventWithHitTestResults(adjusted_event, location,
                                        hit_test_result);
}

void EventHandler::ApplyTouchAdjustment(WebGestureEvent* gesture_event,
                                        HitTestLocation& location,
                                        HitTestResult* hit_test_result) {
  Node* adjusted_node = nullptr;
  IntPoint adjusted_point =
      FlooredIntPoint(gesture_event->PositionInRootFrame());
  bool adjusted = false;
  switch (gesture_event->GetType()) {
    case WebInputEvent::kGestureTap:
    case WebInputEvent::kGestureTapUnconfirmed:
    case WebInputEvent::kGestureTapDown:
    case WebInputEvent::kGestureShowPress:
      adjusted = BestClickableNodeForHitTestResult(
          location, *hit_test_result, adjusted_point, adjusted_node);
      break;
    case WebInputEvent::kGestureLongPress:
    case WebInputEvent::kGestureLongTap:
    case WebInputEvent::kGestureTwoFingerTap:
      adjusted = BestContextMenuNodeForHitTestResult(
          location, *hit_test_result, adjusted_point, adjusted_node);
      break;
    default:
      NOTREACHED();
  }

  // Update the hit-test result to be a point-based result instead of a
  // rect-based result.
  // FIXME: We should do this even when no candidate matches the node filter.
  // crbug.com/398914
  if (adjusted) {
    LayoutPoint point = frame_->View()->ConvertFromRootFrame(adjusted_point);
    DCHECK(location.ContainsPoint(FloatPoint(point)));
    DCHECK(location.IsRectBasedTest());
    location = hit_test_result->ResolveRectBasedTest(adjusted_node, point);
    gesture_event->ApplyTouchAdjustment(
        WebFloatPoint(adjusted_point.X(), adjusted_point.Y()));
  }
}

WebInputEventResult EventHandler::SendContextMenuEvent(
    const WebMouseEvent& event,
    Node* override_target_node) {
  LocalFrameView* v = frame_->View();
  if (!v)
    return WebInputEventResult::kNotHandled;

  // Clear mouse press state to avoid initiating a drag while context menu is
  // up.
  mouse_event_manager_->ReleaseMousePress();
  if (last_scrollbar_under_mouse_)
    last_scrollbar_under_mouse_->MouseUp(event);

  LayoutPoint position_in_contents =
      v->ConvertFromRootFrame(FlooredIntPoint(event.PositionInRootFrame()));
  HitTestRequest request(HitTestRequest::kActive);
  MouseEventWithHitTestResults mev =
      frame_->GetDocument()->PerformMouseEventHitTest(
          request, position_in_contents, event);
  // Since |Document::performMouseEventHitTest()| modifies layout tree for
  // setting hover element, we need to update layout tree for requirement of
  // |SelectionController::sendContextMenuEvent()|.
  frame_->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();

  GetSelectionController().SendContextMenuEvent(mev, position_in_contents);

  Node* target_node =
      override_target_node ? override_target_node : mev.InnerNode();
  return mouse_event_manager_->DispatchMouseEvent(
      EffectiveMouseEventTargetNode(target_node),
      event_type_names::kContextmenu, event,
      mev.GetHitTestResult().CanvasRegionId(), nullptr, nullptr);
}

static bool ShouldShowContextMenuAtSelection(const FrameSelection& selection) {
  // TODO(editing-dev): The use of UpdateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  See http://crbug.com/590369 for more details.
  selection.GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();

  const VisibleSelection& visible_selection =
      selection.ComputeVisibleSelectionInDOMTree();
  if (!visible_selection.IsRange() && !visible_selection.RootEditableElement())
    return false;
  return selection.SelectionHasFocus();
}

WebInputEventResult EventHandler::ShowNonLocatedContextMenu(
    Element* override_target_element,
    WebMenuSourceType source_type) {
  LocalFrameView* view = frame_->View();
  if (!view)
    return WebInputEventResult::kNotHandled;

  Document* doc = frame_->GetDocument();
  if (!doc)
    return WebInputEventResult::kNotHandled;

  static const int kContextMenuMargin = 1;

#if defined(OS_WIN)
  int right_aligned = ::GetSystemMetrics(SM_MENUDROPALIGNMENT);
#else
  int right_aligned = 0;
#endif
  IntPoint location_in_root_frame;

  Element* focused_element =
      override_target_element ? override_target_element : doc->FocusedElement();
  FrameSelection& selection = frame_->Selection();
  VisualViewport& visual_viewport = frame_->GetPage()->GetVisualViewport();

  if (!override_target_element && ShouldShowContextMenuAtSelection(selection)) {
    DCHECK(!doc->NeedsLayoutTreeUpdate());

    IntRect first_rect =
        FirstRectForRange(selection.ComputeVisibleSelectionInDOMTree()
                              .ToNormalizedEphemeralRange());

    int x = right_aligned ? first_rect.MaxX() : first_rect.X();
    // In a multiline edit, firstRect.maxY() would end up on the next line, so
    // take the midpoint.
    int y = (first_rect.MaxY() + first_rect.Y()) / 2;
    location_in_root_frame = view->ConvertToRootFrame(IntPoint(x, y));
  } else if (focused_element) {
    IntRect clipped_rect = focused_element->BoundsInViewport();
    location_in_root_frame =
        visual_viewport.ViewportToRootFrame(clipped_rect.Center());
  } else {
    location_in_root_frame = IntPoint(
        right_aligned
            ? visual_viewport.VisibleRect(kIncludeScrollbars).MaxX() -
                  kContextMenuMargin
            : visual_viewport.GetScrollOffset().Width() + kContextMenuMargin,
        visual_viewport.GetScrollOffset().Height() + kContextMenuMargin);
  }

  frame_->View()->SetCursor(PointerCursor());
  IntPoint location_in_viewport =
      visual_viewport.RootFrameToViewport(location_in_root_frame);
  IntPoint global_position =
      view->GetChromeClient()->ViewportToScreen(
          IntRect(location_in_viewport, IntSize()), frame_->View())
          .Location();

  Node* target_node =
      override_target_element ? override_target_element : doc->FocusedElement();
  if (!target_node)
    target_node = doc;

  // Use the focused node as the target for hover and active.
  HitTestRequest request(HitTestRequest::kActive);
  HitTestLocation location(location_in_root_frame);
  HitTestResult result(request, location);
  result.SetInnerNode(target_node);
  doc->UpdateHoverActiveState(request, result.InnerElement());

  // The contextmenu event is a mouse event even when invoked using the
  // keyboard.  This is required for web compatibility.
  WebInputEvent::Type event_type = WebInputEvent::kMouseDown;
  if (frame_->GetSettings() &&
      frame_->GetSettings()->GetShowContextMenuOnMouseUp())
    event_type = WebInputEvent::kMouseUp;

  WebMouseEvent mouse_event(
      event_type,
      WebFloatPoint(location_in_root_frame.X(), location_in_root_frame.Y()),
      WebFloatPoint(global_position.X(), global_position.Y()),
      WebPointerProperties::Button::kNoButton, /* clickCount */ 0,
      WebInputEvent::kNoModifiers, CurrentTimeTicks(), source_type);

  // TODO(dtapuska): Transition the mouseEvent to be created really in viewport
  // coordinates instead of root frame coordinates.
  mouse_event.SetFrameScale(1);

  return SendContextMenuEvent(mouse_event, override_target_element);
}

void EventHandler::ScheduleHoverStateUpdate() {
  // TODO(https://crbug.com/668758): Use a normal BeginFrame update for this.
  if (!hover_timer_.IsActive() &&
      !mouse_event_manager_->IsMousePositionUnknown())
    hover_timer_.StartOneShot(TimeDelta(), FROM_HERE);
}

void EventHandler::ScheduleCursorUpdate() {
  // We only want one timer for the page, rather than each frame having it's own
  // timer competing which eachother (since there's only one mouse cursor).
  DCHECK_EQ(frame_, &frame_->LocalFrameRoot());

  // TODO(https://crbug.com/668758): Use a normal BeginFrame update for this.
  if (!cursor_update_timer_.IsActive())
    cursor_update_timer_.StartOneShot(kCursorUpdateInterval, FROM_HERE);
}

bool EventHandler::CursorUpdatePending() {
  return cursor_update_timer_.IsActive();
}

bool EventHandler::FakeMouseMovePending() const {
  return mouse_event_manager_->FakeMouseMovePending();
}

void EventHandler::MayUpdateHoverWhenContentUnderMouseChanged(
    MouseEventManager::UpdateHoverReason update_hover_reason) {
  if (update_hover_reason ==
          MouseEventManager::UpdateHoverReason::kScrollOffsetChanged &&
      RuntimeEnabledFeatures::NoHoverDuringScrollEnabled()) {
    return;
  }
  mouse_event_manager_->MayUpdateHoverWhenContentUnderMouseChanged(
      update_hover_reason);
}

void EventHandler::MayUpdateHoverAfterScroll(
    const FloatQuad& scroller_rect_in_frame) {
  mouse_event_manager_->MayUpdateHoverAfterScroll(scroller_rect_in_frame);
}

void EventHandler::SetResizingFrameSet(HTMLFrameSetElement* frame_set) {
  CaptureMouseEventsToWidget(true);
  frame_set_being_resized_ = frame_set;
}

void EventHandler::ResizeScrollableAreaDestroyed() {
  scroll_manager_->ClearResizeScrollableArea(true);
}

void EventHandler::HoverTimerFired(TimerBase*) {
  TRACE_EVENT0("input", "EventHandler::hoverTimerFired");

  DCHECK(frame_);
  DCHECK(frame_->GetDocument());

  if (auto* layout_object = frame_->ContentLayoutObject()) {
    if (LocalFrameView* view = frame_->View()) {
      HitTestRequest request(HitTestRequest::kMove);
      HitTestLocation location(view->ViewportToFrame(
          mouse_event_manager_->LastKnownMousePosition()));
      HitTestResult result(request, location);
      layout_object->HitTest(location, result);
      frame_->GetDocument()->UpdateHoverActiveState(request,
                                                    result.InnerElement());
    }
  }
}

void EventHandler::ActiveIntervalTimerFired(TimerBase*) {
  TRACE_EVENT0("input", "EventHandler::activeIntervalTimerFired");

  if (frame_ && frame_->GetDocument() && last_deferred_tap_element_) {
    // FIXME: Enable condition when http://crbug.com/226842 lands
    // m_lastDeferredTapElement.get() == m_frame->document()->activeElement()
    HitTestRequest request(HitTestRequest::kTouchEvent |
                           HitTestRequest::kRelease);
    frame_->GetDocument()->UpdateHoverActiveState(
        request, last_deferred_tap_element_.Get());
  }
  last_deferred_tap_element_ = nullptr;
}

void EventHandler::NotifyElementActivated() {
  // Since another element has been set to active, stop current timer and clear
  // reference.
  active_interval_timer_.Stop();
  last_deferred_tap_element_ = nullptr;
}

bool EventHandler::HandleAccessKey(const WebKeyboardEvent& evt) {
  return keyboard_event_manager_->HandleAccessKey(evt);
}

WebInputEventResult EventHandler::KeyEvent(
    const WebKeyboardEvent& initial_key_event) {
  return keyboard_event_manager_->KeyEvent(initial_key_event);
}

void EventHandler::DefaultKeyboardEventHandler(KeyboardEvent* event) {
  keyboard_event_manager_->DefaultKeyboardEventHandler(
      event, mouse_event_manager_->MousePressNode());
}

void EventHandler::DragSourceEndedAt(const WebMouseEvent& event,
                                     DragOperation operation) {
  // Asides from routing the event to the correct frame, the hit test is also an
  // opportunity for Layer to update the :hover and :active pseudoclasses.
  HitTestRequest request(HitTestRequest::kRelease);
  MouseEventWithHitTestResults mev =
      event_handling_util::PerformMouseEventHitTest(frame_, request, event);

  LocalFrame* target_frame;
  if (TargetIsFrame(mev.InnerNode(), target_frame)) {
    if (target_frame) {
      target_frame->GetEventHandler().DragSourceEndedAt(event, operation);
      return;
    }
  }

  mouse_event_manager_->DragSourceEndedAt(event, operation);
}

void EventHandler::UpdateDragStateAfterEditDragIfNeeded(
    Element* root_editable_element) {
  // If inserting the dragged contents removed the drag source, we still want to
  // fire dragend at the root editble element.
  if (mouse_event_manager_->GetDragState().drag_src_ &&
      !mouse_event_manager_->GetDragState().drag_src_->isConnected())
    mouse_event_manager_->GetDragState().drag_src_ = root_editable_element;
}

bool EventHandler::HandleTextInputEvent(const String& text,
                                        Event* underlying_event,
                                        TextEventInputType input_type) {
  // Platforms should differentiate real commands like selectAll from text input
  // in disguise (like insertNewline), and avoid dispatching text input events
  // from keydown default handlers.
  DCHECK(!underlying_event || !underlying_event->IsKeyboardEvent() ||
         ToKeyboardEvent(underlying_event)->type() ==
             event_type_names::kKeypress);

  if (!frame_)
    return false;

  EventTarget* target;
  if (underlying_event)
    target = underlying_event->target();
  else
    target = EventTargetNodeForDocument(frame_->GetDocument());
  if (!target)
    return false;

  TextEvent* event = TextEvent::Create(frame_->DomWindow(), text, input_type);
  event->SetUnderlyingEvent(underlying_event);

  target->DispatchEvent(*event);
  return event->DefaultHandled() || event->defaultPrevented();
}

void EventHandler::DefaultTextInputEventHandler(TextEvent* event) {
  if (frame_->GetEditor().HandleTextEvent(event))
    event->SetDefaultHandled();
}

void EventHandler::CapsLockStateMayHaveChanged() {
  keyboard_event_manager_->CapsLockStateMayHaveChanged();
}

bool EventHandler::PassMousePressEventToScrollbar(
    MouseEventWithHitTestResults& mev) {
  // Do not pass the mouse press to scrollbar if scrollbar pressed. If the
  // user's left button is down, then the cursor moves outside the scrollbar
  // and presses the middle button , we should not clear
  // last_scrollbar_under_mouse_.
  if (last_scrollbar_under_mouse_ &&
      last_scrollbar_under_mouse_->PressedPart() != ScrollbarPart::kNoPart) {
    return false;
  }

  Scrollbar* scrollbar = mev.GetScrollbar();
  UpdateLastScrollbarUnderMouse(scrollbar, true);

  if (!scrollbar || !scrollbar->Enabled())
    return false;
  scrollbar->MouseDown(mev.Event());
  if (scrollbar->PressedPart() == ScrollbarPart::kThumbPart)
    CaptureMouseEventsToWidget(true);
  return true;
}

// If scrollbar (under mouse) is different from last, send a mouse exited. Set
// last to scrollbar if setLast is true; else set last to 0.
void EventHandler::UpdateLastScrollbarUnderMouse(Scrollbar* scrollbar,
                                                 bool set_last) {
  if (last_scrollbar_under_mouse_ != scrollbar) {
    // Send mouse exited to the old scrollbar.
    if (last_scrollbar_under_mouse_)
      last_scrollbar_under_mouse_->MouseExited();

    // Send mouse entered if we're setting a new scrollbar.
    if (scrollbar && set_last)
      scrollbar->MouseEntered();

    last_scrollbar_under_mouse_ = set_last ? scrollbar : nullptr;
  }
}

WebInputEventResult EventHandler::PassMousePressEventToSubframe(
    MouseEventWithHitTestResults& mev,
    LocalFrame* subframe) {
  GetSelectionController().PassMousePressEventToSubframe(mev);
  WebInputEventResult result =
      subframe->GetEventHandler().HandleMousePressEvent(mev.Event());
  if (result != WebInputEventResult::kNotHandled)
    return result;
  return WebInputEventResult::kHandledSystem;
}

WebInputEventResult EventHandler::PassMouseMoveEventToSubframe(
    MouseEventWithHitTestResults& mev,
    const Vector<WebMouseEvent>& coalesced_events,
    const Vector<WebMouseEvent>& predicted_events,
    LocalFrame* subframe,
    HitTestResult* hovered_node,
    HitTestLocation* hit_test_location) {
  if (mouse_event_manager_->MouseDownMayStartDrag())
    return WebInputEventResult::kNotHandled;
  WebInputEventResult result =
      subframe->GetEventHandler().HandleMouseMoveOrLeaveEvent(
          mev.Event(), coalesced_events, predicted_events, hovered_node,
          hit_test_location);
  if (result != WebInputEventResult::kNotHandled)
    return result;
  return WebInputEventResult::kHandledSystem;
}

WebInputEventResult EventHandler::PassMouseReleaseEventToSubframe(
    MouseEventWithHitTestResults& mev,
    LocalFrame* subframe) {
  WebInputEventResult result =
      subframe->GetEventHandler().HandleMouseReleaseEvent(mev.Event());
  if (result != WebInputEventResult::kNotHandled)
    return result;
  return WebInputEventResult::kHandledSystem;
}

void EventHandler::CaptureMouseEventsToWidget(bool capture) {
  if (!frame_->IsLocalRoot()) {
    frame_->LocalFrameRoot().GetEventHandler().CaptureMouseEventsToWidget(
        capture);
    return;
  }

  if (capture == is_widget_capturing_mouse_events_)
    return;

  frame_->LocalFrameRoot().Client()->SetMouseCapture(capture);
  is_widget_capturing_mouse_events_ = capture;
}

}  // namespace blink
