Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(350)

Side by Side Diff: content/renderer/render_widget_unittest.cc

Issue 1888163003: Articulate the cancel behavior in the WebTouchEvent. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Adjusted comment Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/render_widget.h" 5 #include "content/renderer/render_widget.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/macros.h" 9 #include "base/macros.h"
10 #include "base/test/histogram_tester.h"
10 #include "content/common/input/synthetic_web_input_event_builders.h" 11 #include "content/common/input/synthetic_web_input_event_builders.h"
11 #include "content/common/input/web_input_event_traits.h" 12 #include "content/common/input/web_input_event_traits.h"
12 #include "content/common/input_messages.h" 13 #include "content/common/input_messages.h"
13 #include "content/public/test/mock_render_thread.h" 14 #include "content/public/test/mock_render_thread.h"
14 #include "content/test/fake_compositor_dependencies.h" 15 #include "content/test/fake_compositor_dependencies.h"
15 #include "content/test/mock_render_process.h" 16 #include "content/test/mock_render_process.h"
16 #include "ipc/ipc_test_sink.h" 17 #include "ipc/ipc_test_sink.h"
18 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h" 19 #include "testing/gtest/include/gtest/gtest.h"
18 #include "third_party/WebKit/public/web/WebInputEvent.h" 20 #include "third_party/WebKit/public/web/WebInputEvent.h"
19 #include "ui/gfx/geometry/rect.h" 21 #include "ui/gfx/geometry/rect.h"
20 22
21 namespace content { 23 namespace content {
22 24
25 namespace {
26
27 const char* EVENT_LISTENER_RESULT_HISTOGRAM = "Event.PassiveListeners";
28
29 enum {
30 PASSIVE_LISTENER_UMA_ENUM_PASSIVE,
31 PASSIVE_LISTENER_UMA_ENUM_UNCANCELABLE,
32 PASSIVE_LISTENER_UMA_ENUM_SUPPRESSED,
33 PASSIVE_LISTENER_UMA_ENUM_CANCELABLE,
34 PASSIVE_LISTENER_UMA_ENUM_CANCELABLE_AND_CANCELED,
35 PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING,
36 PASSIVE_LISTENER_UMA_ENUM_COUNT
37 };
38
39 class MockWebWidget : public blink::WebWidget {
40 public:
41 MOCK_METHOD1(handleInputEvent,
42 blink::WebInputEventResult(const blink::WebInputEvent&));
43 };
44
45 } // namespace
46
47 using testing::_;
Charlie Reis 2016/04/20 17:16:25 nit: This goes between the includes and the namesp
dtapuska 2016/04/20 19:38:11 Done.
48
23 class InteractiveRenderWidget : public RenderWidget { 49 class InteractiveRenderWidget : public RenderWidget {
24 public: 50 public:
25 explicit InteractiveRenderWidget(CompositorDependencies* compositor_deps) 51 explicit InteractiveRenderWidget(CompositorDependencies* compositor_deps)
26 : RenderWidget(compositor_deps, 52 : RenderWidget(compositor_deps,
27 blink::WebPopupTypeNone, 53 blink::WebPopupTypeNone,
28 blink::WebScreenInfo(), 54 blink::WebScreenInfo(),
29 false, 55 false,
30 false, 56 false,
31 false), 57 false),
32 always_overscroll_(false) { 58 always_overscroll_(false) {
59 webwidget_ = &mock_webwidget_;
33 // A RenderWidget is not fully initialized until it has a routing ID. 60 // A RenderWidget is not fully initialized until it has a routing ID.
34 SetRoutingID(++next_routing_id_); 61 SetRoutingID(++next_routing_id_);
35 } 62 }
36 63
37 void SetTouchRegion(const std::vector<gfx::Rect>& rects) { 64 void SetTouchRegion(const std::vector<gfx::Rect>& rects) {
38 rects_ = rects; 65 rects_ = rects;
39 } 66 }
40 67
41 void SendInputEvent(const blink::WebInputEvent& event) { 68 void SendInputEvent(const blink::WebInputEvent& event) {
42 OnHandleInputEvent( 69 OnHandleInputEvent(
43 &event, ui::LatencyInfo(), 70 &event, ui::LatencyInfo(),
44 WebInputEventTraits::ShouldBlockEventStream(event) 71 WebInputEventTraits::ShouldBlockEventStream(event)
45 ? InputEventDispatchType::DISPATCH_TYPE_BLOCKING 72 ? InputEventDispatchType::DISPATCH_TYPE_BLOCKING
46 : InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING); 73 : InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING);
47 } 74 }
48 75
49 void set_always_overscroll(bool overscroll) { 76 void set_always_overscroll(bool overscroll) {
50 always_overscroll_ = overscroll; 77 always_overscroll_ = overscroll;
51 } 78 }
52 79
53 IPC::TestSink* sink() { return &sink_; } 80 IPC::TestSink* sink() { return &sink_; }
54 81
82 MockWebWidget& mock_webwidget() { return mock_webwidget_; }
Charlie Reis 2016/04/20 17:16:25 nit: const ref
dtapuska 2016/04/20 19:38:11 The mocks won't accept a const ref so sadly can't
Charlie Reis 2016/04/20 19:53:40 Then you can't use a ref. Can you use a pointer i
Charlie Reis 2016/04/20 19:56:13 Ah, this may be a more relevant link from the styl
dtapuska 2016/04/20 20:09:48 Done.
83
55 protected: 84 protected:
56 ~InteractiveRenderWidget() override {} 85 ~InteractiveRenderWidget() override { webwidget_ = NULL; }
Charlie Reis 2016/04/20 17:16:25 nit: nullptr
dtapuska 2016/04/20 19:38:11 Done.
57 86
58 // Overridden from RenderWidget: 87 // Overridden from RenderWidget:
59 bool HasTouchEventHandlersAt(const gfx::Point& point) const override { 88 bool HasTouchEventHandlersAt(const gfx::Point& point) const override {
60 for (std::vector<gfx::Rect>::const_iterator iter = rects_.begin(); 89 for (std::vector<gfx::Rect>::const_iterator iter = rects_.begin();
61 iter != rects_.end(); ++iter) { 90 iter != rects_.end(); ++iter) {
62 if ((*iter).Contains(point)) 91 if ((*iter).Contains(point))
63 return true; 92 return true;
64 } 93 }
65 return false; 94 return false;
66 } 95 }
(...skipping 17 matching lines...) Expand all
84 bool Send(IPC::Message* msg) override { 113 bool Send(IPC::Message* msg) override {
85 sink_.OnMessageReceived(*msg); 114 sink_.OnMessageReceived(*msg);
86 delete msg; 115 delete msg;
87 return true; 116 return true;
88 } 117 }
89 118
90 private: 119 private:
91 std::vector<gfx::Rect> rects_; 120 std::vector<gfx::Rect> rects_;
92 IPC::TestSink sink_; 121 IPC::TestSink sink_;
93 bool always_overscroll_; 122 bool always_overscroll_;
123 MockWebWidget mock_webwidget_;
94 static int next_routing_id_; 124 static int next_routing_id_;
95 125
96 DISALLOW_COPY_AND_ASSIGN(InteractiveRenderWidget); 126 DISALLOW_COPY_AND_ASSIGN(InteractiveRenderWidget);
97 }; 127 };
98 128
99 int InteractiveRenderWidget::next_routing_id_ = 0; 129 int InteractiveRenderWidget::next_routing_id_ = 0;
100 130
101 class RenderWidgetUnittest : public testing::Test { 131 class RenderWidgetUnittest : public testing::Test {
102 public: 132 public:
103 RenderWidgetUnittest() 133 RenderWidgetUnittest()
104 : widget_(new InteractiveRenderWidget(&compositor_deps_)) {} 134 : widget_(new InteractiveRenderWidget(&compositor_deps_)) {}
105 ~RenderWidgetUnittest() override {} 135 ~RenderWidgetUnittest() override {}
106 136
107 InteractiveRenderWidget* widget() const { return widget_.get(); } 137 InteractiveRenderWidget* widget() const { return widget_.get(); }
108 138
139 const base::HistogramTester& histogram_tester() const {
140 return histogram_tester_;
141 }
142
109 private: 143 private:
110 MockRenderProcess render_process_; 144 MockRenderProcess render_process_;
111 MockRenderThread render_thread_; 145 MockRenderThread render_thread_;
112 FakeCompositorDependencies compositor_deps_; 146 FakeCompositorDependencies compositor_deps_;
113 scoped_refptr<InteractiveRenderWidget> widget_; 147 scoped_refptr<InteractiveRenderWidget> widget_;
148 base::HistogramTester histogram_tester_;
114 149
115 DISALLOW_COPY_AND_ASSIGN(RenderWidgetUnittest); 150 DISALLOW_COPY_AND_ASSIGN(RenderWidgetUnittest);
116 }; 151 };
117 152
118 TEST_F(RenderWidgetUnittest, TouchHitTestSinglePoint) { 153 TEST_F(RenderWidgetUnittest, TouchHitTestSinglePoint) {
119 SyntheticWebTouchEvent touch; 154 SyntheticWebTouchEvent touch;
120 touch.PressPoint(10, 10); 155 touch.PressPoint(10, 10);
121 156
157 EXPECT_CALL(widget()->mock_webwidget(), handleInputEvent(_))
158 .WillRepeatedly(
159 ::testing::Return(blink::WebInputEventResult::NotHandled));
160
122 widget()->SendInputEvent(touch); 161 widget()->SendInputEvent(touch);
123 ASSERT_EQ(1u, widget()->sink()->message_count()); 162 ASSERT_EQ(1u, widget()->sink()->message_count());
124 163
125 // Since there's currently no touch-event handling region, the response should 164 // Since there's currently no touch-event handling region, the response should
126 // be 'no consumer exists'. 165 // be 'no consumer exists'.
127 const IPC::Message* message = widget()->sink()->GetMessageAt(0); 166 const IPC::Message* message = widget()->sink()->GetMessageAt(0);
128 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type()); 167 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
129 InputHostMsg_HandleInputEvent_ACK::Param params; 168 InputHostMsg_HandleInputEvent_ACK::Param params;
130 InputHostMsg_HandleInputEvent_ACK::Read(message, &params); 169 InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
131 InputEventAckState ack_state = base::get<0>(params).state; 170 InputEventAckState ack_state = base::get<0>(params).state;
132 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state); 171 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state);
133 widget()->sink()->ClearMessages(); 172 widget()->sink()->ClearMessages();
134 173
135 std::vector<gfx::Rect> rects; 174 std::vector<gfx::Rect> rects;
136 rects.push_back(gfx::Rect(0, 0, 20, 20)); 175 rects.push_back(gfx::Rect(0, 0, 20, 20));
137 rects.push_back(gfx::Rect(25, 0, 10, 10)); 176 rects.push_back(gfx::Rect(25, 0, 10, 10));
138 widget()->SetTouchRegion(rects); 177 widget()->SetTouchRegion(rects);
139 178
179 EXPECT_CALL(widget()->mock_webwidget(), handleInputEvent(_))
180 .WillRepeatedly(
181 ::testing::Return(blink::WebInputEventResult::NotHandled));
182
140 widget()->SendInputEvent(touch); 183 widget()->SendInputEvent(touch);
141 ASSERT_EQ(1u, widget()->sink()->message_count()); 184 ASSERT_EQ(1u, widget()->sink()->message_count());
142 message = widget()->sink()->GetMessageAt(0); 185 message = widget()->sink()->GetMessageAt(0);
143 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type()); 186 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
144 InputHostMsg_HandleInputEvent_ACK::Read(message, &params); 187 InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
145 ack_state = base::get<0>(params).state; 188 ack_state = base::get<0>(params).state;
146 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state); 189 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state);
147 widget()->sink()->ClearMessages(); 190 widget()->sink()->ClearMessages();
148 } 191 }
149 192
150 TEST_F(RenderWidgetUnittest, TouchHitTestMultiplePoints) { 193 TEST_F(RenderWidgetUnittest, TouchHitTestMultiplePoints) {
151 std::vector<gfx::Rect> rects; 194 std::vector<gfx::Rect> rects;
152 rects.push_back(gfx::Rect(0, 0, 20, 20)); 195 rects.push_back(gfx::Rect(0, 0, 20, 20));
153 rects.push_back(gfx::Rect(25, 0, 10, 10)); 196 rects.push_back(gfx::Rect(25, 0, 10, 10));
154 widget()->SetTouchRegion(rects); 197 widget()->SetTouchRegion(rects);
155 198
156 SyntheticWebTouchEvent touch; 199 SyntheticWebTouchEvent touch;
157 touch.PressPoint(25, 25); 200 touch.PressPoint(25, 25);
158 201
202 EXPECT_CALL(widget()->mock_webwidget(), handleInputEvent(_))
203 .WillRepeatedly(
204 ::testing::Return(blink::WebInputEventResult::NotHandled));
205
159 widget()->SendInputEvent(touch); 206 widget()->SendInputEvent(touch);
160 ASSERT_EQ(1u, widget()->sink()->message_count()); 207 ASSERT_EQ(1u, widget()->sink()->message_count());
161 208
162 // Since there's currently no touch-event handling region, the response should 209 // Since there's currently no touch-event handling region, the response should
163 // be 'no consumer exists'. 210 // be 'no consumer exists'.
164 const IPC::Message* message = widget()->sink()->GetMessageAt(0); 211 const IPC::Message* message = widget()->sink()->GetMessageAt(0);
165 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type()); 212 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
166 InputHostMsg_HandleInputEvent_ACK::Param params; 213 InputHostMsg_HandleInputEvent_ACK::Param params;
167 InputHostMsg_HandleInputEvent_ACK::Read(message, &params); 214 InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
168 InputEventAckState ack_state = base::get<0>(params).state; 215 InputEventAckState ack_state = base::get<0>(params).state;
169 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state); 216 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state);
170 widget()->sink()->ClearMessages(); 217 widget()->sink()->ClearMessages();
171 218
172 // Press a second touch point. This time, on a touch-handling region. 219 // Press a second touch point. This time, on a touch-handling region.
173 touch.PressPoint(10, 10); 220 touch.PressPoint(10, 10);
174 widget()->SendInputEvent(touch); 221 widget()->SendInputEvent(touch);
175 ASSERT_EQ(1u, widget()->sink()->message_count()); 222 ASSERT_EQ(1u, widget()->sink()->message_count());
176 message = widget()->sink()->GetMessageAt(0); 223 message = widget()->sink()->GetMessageAt(0);
177 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type()); 224 EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
178 InputHostMsg_HandleInputEvent_ACK::Read(message, &params); 225 InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
179 ack_state = base::get<0>(params).state; 226 ack_state = base::get<0>(params).state;
180 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state); 227 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state);
181 widget()->sink()->ClearMessages(); 228 widget()->sink()->ClearMessages();
182 } 229 }
183 230
184 TEST_F(RenderWidgetUnittest, EventOverscroll) { 231 TEST_F(RenderWidgetUnittest, EventOverscroll) {
185 widget()->set_always_overscroll(true); 232 widget()->set_always_overscroll(true);
186 233
234 EXPECT_CALL(widget()->mock_webwidget(), handleInputEvent(_))
235 .WillRepeatedly(
236 ::testing::Return(blink::WebInputEventResult::NotHandled));
237
187 blink::WebGestureEvent scroll; 238 blink::WebGestureEvent scroll;
188 scroll.type = blink::WebInputEvent::GestureScrollUpdate; 239 scroll.type = blink::WebInputEvent::GestureScrollUpdate;
189 scroll.x = -10; 240 scroll.x = -10;
190 scroll.data.scrollUpdate.deltaY = 10; 241 scroll.data.scrollUpdate.deltaY = 10;
191 widget()->SendInputEvent(scroll); 242 widget()->SendInputEvent(scroll);
192 243
193 // Overscroll notifications received while handling an input event should 244 // Overscroll notifications received while handling an input event should
194 // be bundled with the event ack IPC. 245 // be bundled with the event ack IPC.
195 ASSERT_EQ(1u, widget()->sink()->message_count()); 246 ASSERT_EQ(1u, widget()->sink()->message_count());
196 const IPC::Message* message = widget()->sink()->GetMessageAt(0); 247 const IPC::Message* message = widget()->sink()->GetMessageAt(0);
(...skipping 22 matching lines...) Expand all
219 InputHostMsg_DidOverscroll::Param params; 270 InputHostMsg_DidOverscroll::Param params;
220 InputHostMsg_DidOverscroll::Read(message, &params); 271 InputHostMsg_DidOverscroll::Read(message, &params);
221 const DidOverscrollParams& overscroll = base::get<0>(params); 272 const DidOverscrollParams& overscroll = base::get<0>(params);
222 EXPECT_EQ(gfx::Vector2dF(10, 5), overscroll.latest_overscroll_delta); 273 EXPECT_EQ(gfx::Vector2dF(10, 5), overscroll.latest_overscroll_delta);
223 EXPECT_EQ(gfx::Vector2dF(5, 5), overscroll.accumulated_overscroll); 274 EXPECT_EQ(gfx::Vector2dF(5, 5), overscroll.accumulated_overscroll);
224 EXPECT_EQ(gfx::PointF(1, 1), overscroll.causal_event_viewport_point); 275 EXPECT_EQ(gfx::PointF(1, 1), overscroll.causal_event_viewport_point);
225 EXPECT_EQ(gfx::Vector2dF(-10, -5), overscroll.current_fling_velocity); 276 EXPECT_EQ(gfx::Vector2dF(-10, -5), overscroll.current_fling_velocity);
226 widget()->sink()->ClearMessages(); 277 widget()->sink()->ClearMessages();
227 } 278 }
228 279
280 TEST_F(RenderWidgetUnittest, RenderWidgetInputEventUmaMetrics) {
281 SyntheticWebTouchEvent touch;
282 touch.PressPoint(10, 10);
283
284 EXPECT_CALL(widget()->mock_webwidget(), handleInputEvent(_))
285 .Times(4)
286 .WillRepeatedly(
287 ::testing::Return(blink::WebInputEventResult::NotHandled));
288
289 widget()->SendInputEvent(touch);
290 histogram_tester().ExpectBucketCount(EVENT_LISTENER_RESULT_HISTOGRAM,
291 PASSIVE_LISTENER_UMA_ENUM_CANCELABLE, 1);
292
293 touch.dispatchType = blink::WebInputEvent::DispatchType::EventNonBlocking;
294 widget()->SendInputEvent(touch);
295 histogram_tester().ExpectBucketCount(EVENT_LISTENER_RESULT_HISTOGRAM,
296 PASSIVE_LISTENER_UMA_ENUM_UNCANCELABLE,
297 1);
298
299 touch.dispatchType =
300 blink::WebInputEvent::DispatchType::ListenersNonBlockingPassive;
301 widget()->SendInputEvent(touch);
302 histogram_tester().ExpectBucketCount(EVENT_LISTENER_RESULT_HISTOGRAM,
303 PASSIVE_LISTENER_UMA_ENUM_PASSIVE, 1);
304
305 touch.dispatchType =
306 blink::WebInputEvent::DispatchType::ListenersForcedNonBlockingPassive;
307 widget()->SendInputEvent(touch);
308 histogram_tester().ExpectBucketCount(
309 EVENT_LISTENER_RESULT_HISTOGRAM,
310 PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING, 1);
311
312 EXPECT_CALL(widget()->mock_webwidget(), handleInputEvent(_))
313 .WillOnce(
314 ::testing::Return(blink::WebInputEventResult::HandledSuppressed));
315 touch.dispatchType = blink::WebInputEvent::DispatchType::Blocking;
316 widget()->SendInputEvent(touch);
317 histogram_tester().ExpectBucketCount(EVENT_LISTENER_RESULT_HISTOGRAM,
318 PASSIVE_LISTENER_UMA_ENUM_SUPPRESSED, 1);
319
320 EXPECT_CALL(widget()->mock_webwidget(), handleInputEvent(_))
321 .WillOnce(
322 ::testing::Return(blink::WebInputEventResult::HandledApplication));
323 touch.dispatchType = blink::WebInputEvent::DispatchType::Blocking;
324 widget()->SendInputEvent(touch);
325 histogram_tester().ExpectBucketCount(
326 EVENT_LISTENER_RESULT_HISTOGRAM,
327 PASSIVE_LISTENER_UMA_ENUM_CANCELABLE_AND_CANCELED, 1);
328 }
329
229 } // namespace content 330 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698