1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/render_widget.h"
9 #include "content/common/input/synthetic_web_input_event_builders.h"
10 #include "content/common/input_messages.h"
11 #include "content/public/test/mock_render_thread.h"
12 #include "content/test/fake_compositor_dependencies.h"
13 #include "content/test/mock_render_process.h"
14 #include "ipc/ipc_test_sink.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/WebKit/public/web/WebInputEvent.h"
17 #include "ui/gfx/geometry/rect.h"
21 class InteractiveRenderWidget
: public RenderWidget
{
23 explicit InteractiveRenderWidget(CompositorDependencies
* compositor_deps
)
24 : RenderWidget(compositor_deps
,
25 blink::WebPopupTypeNone
,
26 blink::WebScreenInfo(),
30 always_overscroll_(false) {}
32 void SetTouchRegion(const std::vector
<gfx::Rect
>& rects
) {
36 void SendInputEvent(const blink::WebInputEvent
& event
) {
37 OnHandleInputEvent(&event
, ui::LatencyInfo(), false);
40 void set_always_overscroll(bool overscroll
) {
41 always_overscroll_
= overscroll
;
44 IPC::TestSink
* sink() { return &sink_
; }
47 ~InteractiveRenderWidget() override
{}
49 // Overridden from RenderWidget:
50 bool HasTouchEventHandlersAt(const gfx::Point
& point
) const override
{
51 for (std::vector
<gfx::Rect
>::const_iterator iter
= rects_
.begin();
52 iter
!= rects_
.end(); ++iter
) {
53 if ((*iter
).Contains(point
))
59 bool WillHandleGestureEvent(const blink::WebGestureEvent
& event
) override
{
60 if (always_overscroll_
&&
61 event
.type
== blink::WebInputEvent::GestureScrollUpdate
) {
62 didOverscroll(blink::WebFloatSize(event
.data
.scrollUpdate
.deltaX
,
63 event
.data
.scrollUpdate
.deltaY
),
64 blink::WebFloatSize(event
.data
.scrollUpdate
.deltaX
,
65 event
.data
.scrollUpdate
.deltaY
),
66 blink::WebFloatPoint(event
.x
, event
.y
),
67 blink::WebFloatSize(event
.data
.scrollUpdate
.velocityX
,
68 event
.data
.scrollUpdate
.velocityY
));
75 bool Send(IPC::Message
* msg
) override
{
76 sink_
.OnMessageReceived(*msg
);
82 std::vector
<gfx::Rect
> rects_
;
84 bool always_overscroll_
;
86 DISALLOW_COPY_AND_ASSIGN(InteractiveRenderWidget
);
89 class RenderWidgetUnittest
: public testing::Test
{
91 RenderWidgetUnittest()
92 : widget_(new InteractiveRenderWidget(&compositor_deps_
)) {}
93 ~RenderWidgetUnittest() override
{}
95 InteractiveRenderWidget
* widget() const { return widget_
.get(); }
98 MockRenderProcess render_process_
;
99 MockRenderThread render_thread_
;
100 FakeCompositorDependencies compositor_deps_
;
101 scoped_refptr
<InteractiveRenderWidget
> widget_
;
103 DISALLOW_COPY_AND_ASSIGN(RenderWidgetUnittest
);
106 TEST_F(RenderWidgetUnittest
, TouchHitTestSinglePoint
) {
107 SyntheticWebTouchEvent touch
;
108 touch
.PressPoint(10, 10);
110 widget()->SendInputEvent(touch
);
111 ASSERT_EQ(1u, widget()->sink()->message_count());
113 // Since there's currently no touch-event handling region, the response should
114 // be 'no consumer exists'.
115 const IPC::Message
* message
= widget()->sink()->GetMessageAt(0);
116 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID
, message
->type());
117 InputHostMsg_HandleInputEvent_ACK::Param params
;
118 InputHostMsg_HandleInputEvent_ACK::Read(message
, ¶ms
);
119 InputEventAckState ack_state
= base::get
<0>(params
).state
;
120 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS
, ack_state
);
121 widget()->sink()->ClearMessages();
123 std::vector
<gfx::Rect
> rects
;
124 rects
.push_back(gfx::Rect(0, 0, 20, 20));
125 rects
.push_back(gfx::Rect(25, 0, 10, 10));
126 widget()->SetTouchRegion(rects
);
128 widget()->SendInputEvent(touch
);
129 ASSERT_EQ(1u, widget()->sink()->message_count());
130 message
= widget()->sink()->GetMessageAt(0);
131 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID
, message
->type());
132 InputHostMsg_HandleInputEvent_ACK::Read(message
, ¶ms
);
133 ack_state
= base::get
<0>(params
).state
;
134 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED
, ack_state
);
135 widget()->sink()->ClearMessages();
138 TEST_F(RenderWidgetUnittest
, TouchHitTestMultiplePoints
) {
139 std::vector
<gfx::Rect
> rects
;
140 rects
.push_back(gfx::Rect(0, 0, 20, 20));
141 rects
.push_back(gfx::Rect(25, 0, 10, 10));
142 widget()->SetTouchRegion(rects
);
144 SyntheticWebTouchEvent touch
;
145 touch
.PressPoint(25, 25);
147 widget()->SendInputEvent(touch
);
148 ASSERT_EQ(1u, widget()->sink()->message_count());
150 // Since there's currently no touch-event handling region, the response should
151 // be 'no consumer exists'.
152 const IPC::Message
* message
= widget()->sink()->GetMessageAt(0);
153 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID
, message
->type());
154 InputHostMsg_HandleInputEvent_ACK::Param params
;
155 InputHostMsg_HandleInputEvent_ACK::Read(message
, ¶ms
);
156 InputEventAckState ack_state
= base::get
<0>(params
).state
;
157 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS
, ack_state
);
158 widget()->sink()->ClearMessages();
160 // Press a second touch point. This time, on a touch-handling region.
161 touch
.PressPoint(10, 10);
162 widget()->SendInputEvent(touch
);
163 ASSERT_EQ(1u, widget()->sink()->message_count());
164 message
= widget()->sink()->GetMessageAt(0);
165 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID
, message
->type());
166 InputHostMsg_HandleInputEvent_ACK::Read(message
, ¶ms
);
167 ack_state
= base::get
<0>(params
).state
;
168 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED
, ack_state
);
169 widget()->sink()->ClearMessages();
172 TEST_F(RenderWidgetUnittest
, EventOverscroll
) {
173 widget()->set_always_overscroll(true);
175 blink::WebGestureEvent scroll
;
176 scroll
.type
= blink::WebInputEvent::GestureScrollUpdate
;
178 scroll
.data
.scrollUpdate
.deltaY
= 10;
179 widget()->SendInputEvent(scroll
);
181 // Overscroll notifications received while handling an input event should
182 // be bundled with the event ack IPC.
183 ASSERT_EQ(1u, widget()->sink()->message_count());
184 const IPC::Message
* message
= widget()->sink()->GetMessageAt(0);
185 ASSERT_EQ(InputHostMsg_HandleInputEvent_ACK::ID
, message
->type());
186 InputHostMsg_HandleInputEvent_ACK::Param params
;
187 InputHostMsg_HandleInputEvent_ACK::Read(message
, ¶ms
);
188 const InputEventAck
& ack
= base::get
<0>(params
);
189 ASSERT_EQ(ack
.type
, scroll
.type
);
190 ASSERT_TRUE(ack
.overscroll
);
191 EXPECT_EQ(gfx::Vector2dF(0, 10), ack
.overscroll
->accumulated_overscroll
);
192 EXPECT_EQ(gfx::Vector2dF(0, 10), ack
.overscroll
->latest_overscroll_delta
);
193 EXPECT_EQ(gfx::Vector2dF(), ack
.overscroll
->current_fling_velocity
);
194 EXPECT_EQ(gfx::PointF(-10, 0), ack
.overscroll
->causal_event_viewport_point
);
195 widget()->sink()->ClearMessages();
198 TEST_F(RenderWidgetUnittest
, FlingOverscroll
) {
199 // Overscroll notifications received outside of handling an input event should
200 // be sent as a separate IPC.
201 widget()->didOverscroll(blink::WebFloatSize(10, 5), blink::WebFloatSize(5, 5),
202 blink::WebFloatPoint(1, 1),
203 blink::WebFloatSize(10, 5));
204 ASSERT_EQ(1u, widget()->sink()->message_count());
205 const IPC::Message
* message
= widget()->sink()->GetMessageAt(0);
206 ASSERT_EQ(InputHostMsg_DidOverscroll::ID
, message
->type());
207 InputHostMsg_DidOverscroll::Param params
;
208 InputHostMsg_DidOverscroll::Read(message
, ¶ms
);
209 const DidOverscrollParams
& overscroll
= base::get
<0>(params
);
210 EXPECT_EQ(gfx::Vector2dF(10, 5), overscroll
.latest_overscroll_delta
);
211 EXPECT_EQ(gfx::Vector2dF(5, 5), overscroll
.accumulated_overscroll
);
212 EXPECT_EQ(gfx::PointF(1, 1), overscroll
.causal_event_viewport_point
);
213 EXPECT_EQ(gfx::Vector2dF(-10, -5), overscroll
.current_fling_velocity
);
214 widget()->sink()->ClearMessages();
217 } // namespace content