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

#ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_INPUT_EVENT_ROUTER_H_
#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_INPUT_EVENT_ROUTER_H_

#include <stdint.h>

#include <map>
#include <unordered_map>
#include <vector>

#include "base/containers/hash_tables.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/host/hit_test/hit_test_query.h"
#include "components/viz/service/surfaces/surface_hittest_delegate.h"
#include "content/browser/renderer_host/input/touch_emulator_client.h"
#include "content/browser/renderer_host/render_widget_host_view_base_observer.h"
#include "content/browser/renderer_host/render_widget_targeter.h"
#include "content/common/content_export.h"
#include "ui/gfx/geometry/vector2d_conversions.h"

struct FrameHostMsg_HittestData_Params;

#if defined(OS_WIN)
// Flaky on Windows. https://crbug.com/868308
#define MAYBE_TouchpadPinchOverOOPIF DISABLED_TouchpadPinchOverOOPIF
#else
#define MAYBE_TouchpadPinchOverOOPIF TouchpadPinchOverOOPIF
#endif  // OS_WIN

namespace blink {
class WebGestureEvent;
class WebInputEvent;
class WebMouseEvent;
class WebMouseWheelEvent;
class WebTouchEvent;
}

namespace gfx {
class Point;
class PointF;
}

namespace ui {
class LatencyInfo;
}

namespace content {

class RenderWidgetHostImpl;
class RenderWidgetHostView;
class RenderWidgetHostViewBase;
class RenderWidgetTargeter;
class TouchEmulator;

// Class owned by WebContentsImpl for the purpose of directing input events
// to the correct RenderWidgetHost on pages with multiple RenderWidgetHosts.
// It maintains a mapping of RenderWidgetHostViews to Surface IDs that they
// own. When an input event requires routing based on window coordinates,
// this class requests a Surface hit test from the provided |root_view| and
// forwards the event to the owning RWHV of the returned Surface ID.
class CONTENT_EXPORT RenderWidgetHostInputEventRouter
    : public RenderWidgetHostViewBaseObserver,
      public RenderWidgetTargeter::Delegate,
      public TouchEmulatorClient {
 public:
  RenderWidgetHostInputEventRouter();
  ~RenderWidgetHostInputEventRouter() final;

  void OnRenderWidgetHostViewBaseDestroyed(
      RenderWidgetHostViewBase* view) override;

  void RouteMouseEvent(RenderWidgetHostViewBase* root_view,
                       blink::WebMouseEvent* event,
                       const ui::LatencyInfo& latency);
  void RouteMouseWheelEvent(RenderWidgetHostViewBase* root_view,
                            blink::WebMouseWheelEvent* event,
                            const ui::LatencyInfo& latency);
  void RouteGestureEvent(RenderWidgetHostViewBase* root_view,
                         blink::WebGestureEvent* event,
                         const ui::LatencyInfo& latency);
  void OnHandledTouchStartOrFirstTouchMove(uint32_t unique_touch_event_id);
  void RouteTouchEvent(RenderWidgetHostViewBase* root_view,
                       blink::WebTouchEvent *event,
                       const ui::LatencyInfo& latency);

  // |event| is in root coordinates.
  void BubbleScrollEvent(RenderWidgetHostViewBase* target_view,
                         const blink::WebGestureEvent& event,
                         const RenderWidgetHostViewBase* resending_view);
  void CancelScrollBubbling(RenderWidgetHostViewBase* target_view);

  void AddFrameSinkIdOwner(const viz::FrameSinkId& id,
                           RenderWidgetHostViewBase* owner);
  void RemoveFrameSinkIdOwner(const viz::FrameSinkId& id);

  bool is_registered(const viz::FrameSinkId& id) {
    return owner_map_.find(id) != owner_map_.end();
  }

  void OnHittestData(const FrameHostMsg_HittestData_Params& params);

  TouchEmulator* GetTouchEmulator();
  // Since GetTouchEmulator will lazily create a touch emulator, the following
  // accessor allows testing for its existence without causing it to be created.
  bool has_touch_emulator() const { return touch_emulator_.get(); }

  // Returns the RenderWidgetHostImpl inside the |root_view| at |point| where
  // |point| is with respect to |root_view|'s coordinates. If a RWHI is found,
  // the value of |transformed_point| is the coordinate of the point with
  // respect to the RWHI's coordinates. If |root_view| is nullptr, this method
  // will return nullptr and will not modify |transformed_point|.
  RenderWidgetHostImpl* GetRenderWidgetHostAtPoint(
      RenderWidgetHostViewBase* root_view,
      const gfx::PointF& point,
      gfx::PointF* transformed_point);

  // RenderWidgetTargeter::Delegate:
  RenderWidgetHostViewBase* FindViewFromFrameSinkId(
      const viz::FrameSinkId& frame_sink_id) const override;

  // Allows a target to claim or release capture of mouse events.
  void SetMouseCaptureTarget(RenderWidgetHostViewBase* target,
                             bool captures_dragging);

  std::vector<RenderWidgetHostView*> GetRenderWidgetHostViewsForTests() const;
  RenderWidgetTargeter* GetRenderWidgetTargeterForTests();

  // TouchEmulatorClient:
  void ForwardEmulatedGestureEvent(
      const blink::WebGestureEvent& event) override;
  void ForwardEmulatedTouchEvent(const blink::WebTouchEvent& event,
                                 RenderWidgetHostViewBase* target) override;
  void SetCursor(const WebCursor& cursor) override;
  void ShowContextMenuAtPoint(const gfx::Point& point,
                              const ui::MenuSourceType source_type) override;

 private:
  struct HittestData {
    bool ignored_for_hittest;
  };

  class HittestDelegate : public viz::SurfaceHittestDelegate {
   public:
    HittestDelegate(const std::unordered_map<viz::SurfaceId,
                                             HittestData,
                                             viz::SurfaceIdHash>& hittest_data);
    bool RejectHitTarget(const viz::SurfaceDrawQuad* surface_quad,
                         const gfx::Point& point_in_quad_space) override;
    bool AcceptHitTarget(const viz::SurfaceDrawQuad* surface_quad,
                         const gfx::Point& point_in_quad_space) override;

    const std::unordered_map<viz::SurfaceId, HittestData, viz::SurfaceIdHash>&
        hittest_data_;
  };

  using FrameSinkIdOwnerMap = std::unordered_map<viz::FrameSinkId,
                                                 RenderWidgetHostViewBase*,
                                                 viz::FrameSinkIdHash>;
  struct TargetData {
    RenderWidgetHostViewBase* target;
    gfx::Vector2dF delta;

    TargetData() : target(nullptr) {}
  };
  using TargetMap = std::map<uint32_t, TargetData>;

  void ClearAllObserverRegistrations();
  RenderWidgetTargetResult FindViewAtLocation(
      RenderWidgetHostViewBase* root_view,
      const gfx::PointF& point,
      const gfx::PointF& point_in_screen,
      viz::EventSource source,
      gfx::PointF* transformed_point) const;

  bool IsViewInMap(const RenderWidgetHostViewBase* view) const;
  void RouteTouchscreenGestureEvent(RenderWidgetHostViewBase* root_view,
                                    blink::WebGestureEvent* event,
                                    const ui::LatencyInfo& latency);

  RenderWidgetTargetResult FindTouchpadGestureEventTarget(
      RenderWidgetHostViewBase* root_view,
      const blink::WebGestureEvent& event) const;
  void RouteTouchpadGestureEvent(RenderWidgetHostViewBase* root_view,
                                 blink::WebGestureEvent* event,
                                 const ui::LatencyInfo& latency);
  void DispatchTouchpadGestureEvent(
      RenderWidgetHostViewBase* root_view,
      RenderWidgetHostViewBase* target,
      const blink::WebGestureEvent& touchpad_gesture_event,
      const ui::LatencyInfo& latency,
      const base::Optional<gfx::PointF>& target_location);

  // MouseMove/Enter/Leave events might need to be processed by multiple frames
  // in different processes for MouseEnter and MouseLeave event handlers to
  // properly fire. This method determines which RenderWidgetHostViews other
  // than the actual target require notification, and sends the appropriate
  // events to them. |event| should be in |root_view|'s coordinate space.
  void SendMouseEnterOrLeaveEvents(const blink::WebMouseEvent& event,
                                   RenderWidgetHostViewBase* target,
                                   RenderWidgetHostViewBase* root_view);

  // The following methods take a GestureScrollUpdate event and send a
  // GestureScrollBegin or GestureScrollEnd for wrapping it. This is needed
  // when GestureScrollUpdates are being forwarded for scroll bubbling.
  void SendGestureScrollBegin(RenderWidgetHostViewBase* view,
                              const blink::WebGestureEvent& event);
  void SendGestureScrollEnd(RenderWidgetHostViewBase* view,
                            const blink::WebGestureEvent& event);

  // Helper functions to implement RenderWidgetTargeter::Delegate functions.
  RenderWidgetTargetResult FindMouseEventTarget(
      RenderWidgetHostViewBase* root_view,
      const blink::WebMouseEvent& event) const;
  RenderWidgetTargetResult FindMouseWheelEventTarget(
      RenderWidgetHostViewBase* root_view,
      const blink::WebMouseWheelEvent& event) const;
  // Returns target for first TouchStart in a sequence, or a null target
  // otherwise.
  RenderWidgetTargetResult FindTouchEventTarget(
      RenderWidgetHostViewBase* root_view,
      const blink::WebTouchEvent& event);
  RenderWidgetTargetResult FindTouchscreenGestureEventTarget(
      RenderWidgetHostViewBase* root_view,
      const blink::WebGestureEvent& gesture_event);

  // |mouse_event| is in the coord-space of |root_view|.
  void DispatchMouseEvent(RenderWidgetHostViewBase* root_view,
                          RenderWidgetHostViewBase* target,
                          const blink::WebMouseEvent& mouse_event,
                          const ui::LatencyInfo& latency,
                          const base::Optional<gfx::PointF>& target_location);
  // |mouse_wheel_event| is in the coord-space of |root_view|.
  void DispatchMouseWheelEvent(
      RenderWidgetHostViewBase* root_view,
      RenderWidgetHostViewBase* target,
      const blink::WebMouseWheelEvent& mouse_wheel_event,
      const ui::LatencyInfo& latency,
      const base::Optional<gfx::PointF>& target_location);
  // Assumes |touch_event| has coordinates in the root view's coordinate space.
  void DispatchTouchEvent(RenderWidgetHostViewBase* root_view,
                          RenderWidgetHostViewBase* target,
                          const blink::WebTouchEvent& touch_event,
                          const ui::LatencyInfo& latency,
                          const base::Optional<gfx::PointF>& target_location);
  // Assumes |gesture_event| has coordinates in root view's coordinate space.
  void DispatchTouchscreenGestureEvent(
      RenderWidgetHostViewBase* root_view,
      RenderWidgetHostViewBase* target,
      const blink::WebGestureEvent& gesture_event,
      const ui::LatencyInfo& latency,
      const base::Optional<gfx::PointF>& target_location);

  // Transforms |point| from |root_view| coord space to |target| coord space.
  // Result is stored in |transformed_point|. Returns true if the transform
  // is successful, false otherwise.
  bool TransformPointToTargetCoordSpace(RenderWidgetHostViewBase* root_view,
                                        RenderWidgetHostViewBase* target,
                                        const gfx::PointF& point,
                                        gfx::PointF* transformed_point,
                                        viz::EventSource source) const;

  // TODO(828422): Remove once this issue no longer occurs.
  void ReportBubblingScrollToSameView(const blink::WebGestureEvent& event,
                                      const RenderWidgetHostViewBase* view);

  // RenderWidgetTargeter::Delegate:
  RenderWidgetTargetResult FindTargetSynchronously(
      RenderWidgetHostViewBase* root_view,
      const blink::WebInputEvent& event) override;
  void DispatchEventToTarget(
      RenderWidgetHostViewBase* root_view,
      RenderWidgetHostViewBase* target,
      const blink::WebInputEvent& event,
      const ui::LatencyInfo& latency,
      const base::Optional<gfx::PointF>& target_location) override;
  // Notify whether the events in the queue are being flushed due to touch ack
  // timeout, or the flushing has completed.
  void SetEventsBeingFlushed(bool events_being_flushed) override;

  FrameSinkIdOwnerMap owner_map_;
  TargetMap touchscreen_gesture_target_map_;
  TargetData touch_target_;
  TargetData touchscreen_gesture_target_;
  // The following variable is temporary, for diagnosis of
  // https://crbug.com/824774.
  bool touchscreen_gesture_target_in_map_;
  TargetData touchpad_gesture_target_;
  TargetData bubbling_gesture_scroll_target_;
  TargetData first_bubbling_scroll_target_;
  // Used to target wheel events for the duration of a scroll.
  TargetData wheel_target_;
  // Maintains the same target between mouse down and mouse up.
  TargetData mouse_capture_target_;

  // Tracked for the purpose of generating MouseEnter and MouseLeave events.
  RenderWidgetHostViewBase* last_mouse_move_target_;
  RenderWidgetHostViewBase* last_mouse_move_root_view_;

  // Tracked for the purpose of targeting subsequent fling cancel events.
  RenderWidgetHostViewBase* last_fling_start_target_ = nullptr;

  // Tracked for the purpose of providing a root_view when dispatching emulated
  // touch/gesture events.
  RenderWidgetHostViewBase* last_emulated_event_root_view_;
  float last_device_scale_factor_;

  int active_touches_;
  // Keep track of when we are between GesturePinchBegin and GesturePinchEnd
  // inclusive, as we need to route these events (and anything in between) to
  // the main frame.
  bool in_touchscreen_gesture_pinch_;
  bool gesture_pinch_did_send_scroll_begin_;
  std::unordered_map<viz::SurfaceId, HittestData, viz::SurfaceIdHash>
      hittest_data_;

  std::unique_ptr<RenderWidgetTargeter> event_targeter_;
  bool use_viz_hit_test_ = false;
  bool events_being_flushed_ = false;

  std::unique_ptr<TouchEmulator> touch_emulator_;

  base::WeakPtrFactory<RenderWidgetHostInputEventRouter> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostInputEventRouter);
  friend class RenderWidgetHostInputEventRouterTest;
  FRIEND_TEST_ALL_PREFIXES(SitePerProcessHitTestBrowserTest,
                           HitTestStaleDataDeletedView);
  FRIEND_TEST_ALL_PREFIXES(SitePerProcessHitTestBrowserTest,
                           InputEventRouterGestureTargetMapTest);
  FRIEND_TEST_ALL_PREFIXES(SitePerProcessHitTestBrowserTest,
                           InputEventRouterGesturePreventDefaultTargetMapTest);
  FRIEND_TEST_ALL_PREFIXES(SitePerProcessHitTestBrowserTest,
                           InputEventRouterTouchpadGestureTargetTest);
  FRIEND_TEST_ALL_PREFIXES(SitePerProcessHitTestBrowserTest,
                           MAYBE_TouchpadPinchOverOOPIF);
  FRIEND_TEST_ALL_PREFIXES(SitePerProcessMouseWheelHitTestBrowserTest,
                           InputEventRouterWheelTargetTest);
  FRIEND_TEST_ALL_PREFIXES(SitePerProcessMacBrowserTest,
                           InputEventRouterTouchpadGestureTargetTest);
};

}  // namespace content

#endif  // CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_INPUT_EVENT_ROUTER_H_
