blob: 508ebc181b21d5c933cd3b6d08053955f34d2bbf [file] [log] [blame]
[email protected]f8ed4722013-12-03 03:27:251// 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.
4
5#include "content/renderer/render_widget.h"
6
7#include <vector>
8
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/mock_render_process.h"
13#include "ipc/ipc_test_sink.h"
14#include "testing/gtest/include/gtest/gtest.h"
15#include "third_party/WebKit/public/web/WebInputEvent.h"
tfarina3b0452d2014-12-31 15:20:0916#include "ui/gfx/geometry/rect.h"
[email protected]f8ed4722013-12-03 03:27:2517
18namespace content {
19
20class RenderWidgetUnittest : public testing::Test {
21 public:
22 RenderWidgetUnittest() {}
dchengf5762152014-10-29 02:12:0623 ~RenderWidgetUnittest() override {}
[email protected]f8ed4722013-12-03 03:27:2524
25 private:
26 MockRenderProcess render_process_;
27 MockRenderThread render_thread_;
28
29 DISALLOW_COPY_AND_ASSIGN(RenderWidgetUnittest);
30};
31
jddukec05612b2015-06-25 23:13:1832class InteractiveRenderWidget : public RenderWidget {
[email protected]f8ed4722013-12-03 03:27:2533 public:
jddukec05612b2015-06-25 23:13:1834 InteractiveRenderWidget()
[email protected]7912e822014-04-16 02:37:0335 : RenderWidget(blink::WebPopupTypeNone,
36 blink::WebScreenInfo(),
37 false,
38 false,
jddukec05612b2015-06-25 23:13:1839 false),
40 always_overscroll_(false) {}
[email protected]f8ed4722013-12-03 03:27:2541
42 void SetTouchRegion(const std::vector<gfx::Rect>& rects) {
43 rects_ = rects;
44 }
45
46 void SendInputEvent(const blink::WebInputEvent& event) {
47 OnHandleInputEvent(&event, ui::LatencyInfo(), false);
48 }
49
jddukec05612b2015-06-25 23:13:1850 void set_always_overscroll(bool overscroll) {
51 always_overscroll_ = overscroll;
52 }
53
[email protected]f8ed4722013-12-03 03:27:2554 IPC::TestSink* sink() { return &sink_; }
55
56 protected:
jddukec05612b2015-06-25 23:13:1857 ~InteractiveRenderWidget() override {}
[email protected]f8ed4722013-12-03 03:27:2558
59 // Overridden from RenderWidget:
dcheng6d18e402014-10-21 12:32:5260 bool HasTouchEventHandlersAt(const gfx::Point& point) const override {
[email protected]f8ed4722013-12-03 03:27:2561 for (std::vector<gfx::Rect>::const_iterator iter = rects_.begin();
62 iter != rects_.end(); ++iter) {
63 if ((*iter).Contains(point))
64 return true;
65 }
66 return false;
67 }
68
jddukec05612b2015-06-25 23:13:1869 bool WillHandleGestureEvent(const blink::WebGestureEvent& event) override {
70 if (always_overscroll_ &&
71 event.type == blink::WebInputEvent::GestureScrollUpdate) {
72 didOverscroll(blink::WebFloatSize(event.data.scrollUpdate.deltaX,
73 event.data.scrollUpdate.deltaY),
74 blink::WebFloatSize(event.data.scrollUpdate.deltaX,
75 event.data.scrollUpdate.deltaY),
76 blink::WebFloatPoint(event.x, event.y),
77 blink::WebFloatSize(event.data.scrollUpdate.velocityX,
78 event.data.scrollUpdate.velocityY));
79 return true;
80 }
81
82 return false;
83 }
84
dcheng6d18e402014-10-21 12:32:5285 bool Send(IPC::Message* msg) override {
[email protected]f8ed4722013-12-03 03:27:2586 sink_.OnMessageReceived(*msg);
87 delete msg;
88 return true;
89 }
90
91 private:
92 std::vector<gfx::Rect> rects_;
93 IPC::TestSink sink_;
jddukec05612b2015-06-25 23:13:1894 bool always_overscroll_;
[email protected]f8ed4722013-12-03 03:27:2595
jddukec05612b2015-06-25 23:13:1896 DISALLOW_COPY_AND_ASSIGN(InteractiveRenderWidget);
[email protected]f8ed4722013-12-03 03:27:2597};
98
99TEST_F(RenderWidgetUnittest, TouchHitTestSinglePoint) {
jddukec05612b2015-06-25 23:13:18100 scoped_refptr<InteractiveRenderWidget> widget = new InteractiveRenderWidget();
[email protected]f8ed4722013-12-03 03:27:25101
[email protected]f8ed4722013-12-03 03:27:25102 SyntheticWebTouchEvent touch;
103 touch.PressPoint(10, 10);
104
105 widget->SendInputEvent(touch);
106 ASSERT_EQ(1u, widget->sink()->message_count());
107
108 // Since there's currently no touch-event handling region, the response should
109 // be 'no consumer exists'.
110 const IPC::Message* message = widget->sink()->GetMessageAt(0);
111 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
[email protected]5636d902014-05-13 23:19:10112 InputHostMsg_HandleInputEvent_ACK::Param params;
113 InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
brettwd5ca2bc2015-05-29 22:15:47114 InputEventAckState ack_state = base::get<0>(params).state;
[email protected]f8ed4722013-12-03 03:27:25115 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state);
116 widget->sink()->ClearMessages();
117
118 std::vector<gfx::Rect> rects;
119 rects.push_back(gfx::Rect(0, 0, 20, 20));
120 rects.push_back(gfx::Rect(25, 0, 10, 10));
121 widget->SetTouchRegion(rects);
122
123 widget->SendInputEvent(touch);
124 ASSERT_EQ(1u, widget->sink()->message_count());
125 message = widget->sink()->GetMessageAt(0);
126 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
[email protected]5636d902014-05-13 23:19:10127 InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
brettwd5ca2bc2015-05-29 22:15:47128 ack_state = base::get<0>(params).state;
[email protected]f8ed4722013-12-03 03:27:25129 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state);
130 widget->sink()->ClearMessages();
131}
132
133TEST_F(RenderWidgetUnittest, TouchHitTestMultiplePoints) {
jddukec05612b2015-06-25 23:13:18134 scoped_refptr<InteractiveRenderWidget> widget = new InteractiveRenderWidget();
[email protected]f8ed4722013-12-03 03:27:25135 std::vector<gfx::Rect> rects;
136 rects.push_back(gfx::Rect(0, 0, 20, 20));
137 rects.push_back(gfx::Rect(25, 0, 10, 10));
138 widget->SetTouchRegion(rects);
139
[email protected]f8ed4722013-12-03 03:27:25140 SyntheticWebTouchEvent touch;
141 touch.PressPoint(25, 25);
142
143 widget->SendInputEvent(touch);
144 ASSERT_EQ(1u, widget->sink()->message_count());
145
146 // Since there's currently no touch-event handling region, the response should
147 // be 'no consumer exists'.
148 const IPC::Message* message = widget->sink()->GetMessageAt(0);
149 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
[email protected]5636d902014-05-13 23:19:10150 InputHostMsg_HandleInputEvent_ACK::Param params;
151 InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
brettwd5ca2bc2015-05-29 22:15:47152 InputEventAckState ack_state = base::get<0>(params).state;
[email protected]f8ed4722013-12-03 03:27:25153 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state);
154 widget->sink()->ClearMessages();
155
156 // Press a second touch point. This time, on a touch-handling region.
157 touch.PressPoint(10, 10);
158 widget->SendInputEvent(touch);
159 ASSERT_EQ(1u, widget->sink()->message_count());
160 message = widget->sink()->GetMessageAt(0);
161 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
[email protected]5636d902014-05-13 23:19:10162 InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
brettwd5ca2bc2015-05-29 22:15:47163 ack_state = base::get<0>(params).state;
[email protected]f8ed4722013-12-03 03:27:25164 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state);
165 widget->sink()->ClearMessages();
166}
167
jddukec05612b2015-06-25 23:13:18168TEST_F(RenderWidgetUnittest, EventOverscroll) {
169 scoped_refptr<InteractiveRenderWidget> widget = new InteractiveRenderWidget();
170 widget->set_always_overscroll(true);
171
172 blink::WebGestureEvent scroll;
173 scroll.type = blink::WebInputEvent::GestureScrollUpdate;
174 scroll.x = -10;
175 scroll.data.scrollUpdate.deltaY = 10;
176 widget->SendInputEvent(scroll);
177
178 // Overscroll notifications received while handling an input event should
179 // be bundled with the event ack IPC.
180 ASSERT_EQ(1u, widget->sink()->message_count());
181 const IPC::Message* message = widget->sink()->GetMessageAt(0);
182 ASSERT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
183 InputHostMsg_HandleInputEvent_ACK::Param params;
184 InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
185 const InputEventAck& ack = base::get<0>(params);
186 ASSERT_EQ(ack.type, scroll.type);
187 ASSERT_TRUE(ack.overscroll);
188 EXPECT_EQ(gfx::Vector2dF(0, 10), ack.overscroll->accumulated_overscroll);
189 EXPECT_EQ(gfx::Vector2dF(0, 10), ack.overscroll->latest_overscroll_delta);
190 EXPECT_EQ(gfx::Vector2dF(), ack.overscroll->current_fling_velocity);
191 EXPECT_EQ(gfx::PointF(-10, 0), ack.overscroll->causal_event_viewport_point);
192 widget->sink()->ClearMessages();
193}
194
195TEST_F(RenderWidgetUnittest, FlingOverscroll) {
196 scoped_refptr<InteractiveRenderWidget> widget = new InteractiveRenderWidget();
197
198 // Overscroll notifications received outside of handling an input event should
199 // be sent as a separate IPC.
200 widget->didOverscroll(blink::WebFloatSize(10, 5), blink::WebFloatSize(5, 5),
201 blink::WebFloatPoint(1, 1), blink::WebFloatSize(10, 5));
202 ASSERT_EQ(1u, widget->sink()->message_count());
203 const IPC::Message* message = widget->sink()->GetMessageAt(0);
204 ASSERT_EQ(InputHostMsg_DidOverscroll::ID, message->type());
205 InputHostMsg_DidOverscroll::Param params;
206 InputHostMsg_DidOverscroll::Read(message, &params);
207 const DidOverscrollParams& overscroll = base::get<0>(params);
208 EXPECT_EQ(gfx::Vector2dF(10, 5), overscroll.latest_overscroll_delta);
209 EXPECT_EQ(gfx::Vector2dF(5, 5), overscroll.accumulated_overscroll);
210 EXPECT_EQ(gfx::PointF(1, 1), overscroll.causal_event_viewport_point);
211 EXPECT_EQ(gfx::Vector2dF(-10, -5), overscroll.current_fling_velocity);
212 widget->sink()->ClearMessages();
213}
214
[email protected]f8ed4722013-12-03 03:27:25215} // namespace content