blob: e4319f56cd141da7bdbb0d3ef5be45775e2acd19 [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"
dcheng35d31c112015-07-22 00:17:3612#include "content/test/fake_compositor_dependencies.h"
[email protected]f8ed4722013-12-03 03:27:2513#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"
tfarina3b0452d2014-12-31 15:20:0917#include "ui/gfx/geometry/rect.h"
[email protected]f8ed4722013-12-03 03:27:2518
19namespace content {
20
jddukec05612b2015-06-25 23:13:1821class InteractiveRenderWidget : public RenderWidget {
[email protected]f8ed4722013-12-03 03:27:2522 public:
dcheng35d31c112015-07-22 00:17:3623 explicit InteractiveRenderWidget(CompositorDependencies* compositor_deps)
24 : RenderWidget(compositor_deps,
25 blink::WebPopupTypeNone,
[email protected]7912e822014-04-16 02:37:0326 blink::WebScreenInfo(),
27 false,
28 false,
jddukec05612b2015-06-25 23:13:1829 false),
30 always_overscroll_(false) {}
[email protected]f8ed4722013-12-03 03:27:2531
32 void SetTouchRegion(const std::vector<gfx::Rect>& rects) {
33 rects_ = rects;
34 }
35
36 void SendInputEvent(const blink::WebInputEvent& event) {
jdduke0cf1e662015-10-15 22:43:2837 OnHandleInputEvent(&event, ui::LatencyInfo());
[email protected]f8ed4722013-12-03 03:27:2538 }
39
jddukec05612b2015-06-25 23:13:1840 void set_always_overscroll(bool overscroll) {
41 always_overscroll_ = overscroll;
42 }
43
[email protected]f8ed4722013-12-03 03:27:2544 IPC::TestSink* sink() { return &sink_; }
45
46 protected:
jddukec05612b2015-06-25 23:13:1847 ~InteractiveRenderWidget() override {}
[email protected]f8ed4722013-12-03 03:27:2548
49 // Overridden from RenderWidget:
dcheng6d18e402014-10-21 12:32:5250 bool HasTouchEventHandlersAt(const gfx::Point& point) const override {
[email protected]f8ed4722013-12-03 03:27:2551 for (std::vector<gfx::Rect>::const_iterator iter = rects_.begin();
52 iter != rects_.end(); ++iter) {
53 if ((*iter).Contains(point))
54 return true;
55 }
56 return false;
57 }
58
jddukec05612b2015-06-25 23:13:1859 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));
69 return true;
70 }
71
72 return false;
73 }
74
dcheng6d18e402014-10-21 12:32:5275 bool Send(IPC::Message* msg) override {
[email protected]f8ed4722013-12-03 03:27:2576 sink_.OnMessageReceived(*msg);
77 delete msg;
78 return true;
79 }
80
81 private:
82 std::vector<gfx::Rect> rects_;
83 IPC::TestSink sink_;
jddukec05612b2015-06-25 23:13:1884 bool always_overscroll_;
[email protected]f8ed4722013-12-03 03:27:2585
jddukec05612b2015-06-25 23:13:1886 DISALLOW_COPY_AND_ASSIGN(InteractiveRenderWidget);
[email protected]f8ed4722013-12-03 03:27:2587};
88
dcheng35d31c112015-07-22 00:17:3689class RenderWidgetUnittest : public testing::Test {
90 public:
91 RenderWidgetUnittest()
92 : widget_(new InteractiveRenderWidget(&compositor_deps_)) {}
93 ~RenderWidgetUnittest() override {}
[email protected]f8ed4722013-12-03 03:27:2594
dcheng35d31c112015-07-22 00:17:3695 InteractiveRenderWidget* widget() const { return widget_.get(); }
96
97 private:
98 MockRenderProcess render_process_;
99 MockRenderThread render_thread_;
100 FakeCompositorDependencies compositor_deps_;
101 scoped_refptr<InteractiveRenderWidget> widget_;
102
103 DISALLOW_COPY_AND_ASSIGN(RenderWidgetUnittest);
104};
105
106TEST_F(RenderWidgetUnittest, TouchHitTestSinglePoint) {
[email protected]f8ed4722013-12-03 03:27:25107 SyntheticWebTouchEvent touch;
108 touch.PressPoint(10, 10);
109
dcheng35d31c112015-07-22 00:17:36110 widget()->SendInputEvent(touch);
111 ASSERT_EQ(1u, widget()->sink()->message_count());
[email protected]f8ed4722013-12-03 03:27:25112
113 // Since there's currently no touch-event handling region, the response should
114 // be 'no consumer exists'.
dcheng35d31c112015-07-22 00:17:36115 const IPC::Message* message = widget()->sink()->GetMessageAt(0);
[email protected]f8ed4722013-12-03 03:27:25116 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
[email protected]5636d902014-05-13 23:19:10117 InputHostMsg_HandleInputEvent_ACK::Param params;
118 InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
brettwd5ca2bc2015-05-29 22:15:47119 InputEventAckState ack_state = base::get<0>(params).state;
[email protected]f8ed4722013-12-03 03:27:25120 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state);
dcheng35d31c112015-07-22 00:17:36121 widget()->sink()->ClearMessages();
[email protected]f8ed4722013-12-03 03:27:25122
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));
dcheng35d31c112015-07-22 00:17:36126 widget()->SetTouchRegion(rects);
[email protected]f8ed4722013-12-03 03:27:25127
dcheng35d31c112015-07-22 00:17:36128 widget()->SendInputEvent(touch);
129 ASSERT_EQ(1u, widget()->sink()->message_count());
130 message = widget()->sink()->GetMessageAt(0);
[email protected]f8ed4722013-12-03 03:27:25131 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
[email protected]5636d902014-05-13 23:19:10132 InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
brettwd5ca2bc2015-05-29 22:15:47133 ack_state = base::get<0>(params).state;
[email protected]f8ed4722013-12-03 03:27:25134 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state);
dcheng35d31c112015-07-22 00:17:36135 widget()->sink()->ClearMessages();
[email protected]f8ed4722013-12-03 03:27:25136}
137
138TEST_F(RenderWidgetUnittest, TouchHitTestMultiplePoints) {
[email protected]f8ed4722013-12-03 03:27:25139 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));
dcheng35d31c112015-07-22 00:17:36142 widget()->SetTouchRegion(rects);
[email protected]f8ed4722013-12-03 03:27:25143
[email protected]f8ed4722013-12-03 03:27:25144 SyntheticWebTouchEvent touch;
145 touch.PressPoint(25, 25);
146
dcheng35d31c112015-07-22 00:17:36147 widget()->SendInputEvent(touch);
148 ASSERT_EQ(1u, widget()->sink()->message_count());
[email protected]f8ed4722013-12-03 03:27:25149
150 // Since there's currently no touch-event handling region, the response should
151 // be 'no consumer exists'.
dcheng35d31c112015-07-22 00:17:36152 const IPC::Message* message = widget()->sink()->GetMessageAt(0);
[email protected]f8ed4722013-12-03 03:27:25153 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
[email protected]5636d902014-05-13 23:19:10154 InputHostMsg_HandleInputEvent_ACK::Param params;
155 InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
brettwd5ca2bc2015-05-29 22:15:47156 InputEventAckState ack_state = base::get<0>(params).state;
[email protected]f8ed4722013-12-03 03:27:25157 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state);
dcheng35d31c112015-07-22 00:17:36158 widget()->sink()->ClearMessages();
[email protected]f8ed4722013-12-03 03:27:25159
160 // Press a second touch point. This time, on a touch-handling region.
161 touch.PressPoint(10, 10);
dcheng35d31c112015-07-22 00:17:36162 widget()->SendInputEvent(touch);
163 ASSERT_EQ(1u, widget()->sink()->message_count());
164 message = widget()->sink()->GetMessageAt(0);
[email protected]f8ed4722013-12-03 03:27:25165 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
[email protected]5636d902014-05-13 23:19:10166 InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
brettwd5ca2bc2015-05-29 22:15:47167 ack_state = base::get<0>(params).state;
[email protected]f8ed4722013-12-03 03:27:25168 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state);
dcheng35d31c112015-07-22 00:17:36169 widget()->sink()->ClearMessages();
[email protected]f8ed4722013-12-03 03:27:25170}
171
jddukec05612b2015-06-25 23:13:18172TEST_F(RenderWidgetUnittest, EventOverscroll) {
dcheng35d31c112015-07-22 00:17:36173 widget()->set_always_overscroll(true);
jddukec05612b2015-06-25 23:13:18174
175 blink::WebGestureEvent scroll;
176 scroll.type = blink::WebInputEvent::GestureScrollUpdate;
177 scroll.x = -10;
178 scroll.data.scrollUpdate.deltaY = 10;
dcheng35d31c112015-07-22 00:17:36179 widget()->SendInputEvent(scroll);
jddukec05612b2015-06-25 23:13:18180
181 // Overscroll notifications received while handling an input event should
182 // be bundled with the event ack IPC.
dcheng35d31c112015-07-22 00:17:36183 ASSERT_EQ(1u, widget()->sink()->message_count());
184 const IPC::Message* message = widget()->sink()->GetMessageAt(0);
jddukec05612b2015-06-25 23:13:18185 ASSERT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
186 InputHostMsg_HandleInputEvent_ACK::Param params;
187 InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
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);
dcheng35d31c112015-07-22 00:17:36195 widget()->sink()->ClearMessages();
jddukec05612b2015-06-25 23:13:18196}
197
198TEST_F(RenderWidgetUnittest, FlingOverscroll) {
jddukec05612b2015-06-25 23:13:18199 // Overscroll notifications received outside of handling an input event should
200 // be sent as a separate IPC.
dcheng35d31c112015-07-22 00:17:36201 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);
jddukec05612b2015-06-25 23:13:18206 ASSERT_EQ(InputHostMsg_DidOverscroll::ID, message->type());
207 InputHostMsg_DidOverscroll::Param params;
208 InputHostMsg_DidOverscroll::Read(message, &params);
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);
dcheng35d31c112015-07-22 00:17:36214 widget()->sink()->ClearMessages();
jddukec05612b2015-06-25 23:13:18215}
216
[email protected]f8ed4722013-12-03 03:27:25217} // namespace content