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

Side by Side Diff: content/browser/renderer_host/input/buffered_input_router_unittest.cc

Issue 20356003: Provided batched input delivery with a BufferedInputRouter (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Code review Created 7 years, 4 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
(Empty)
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.
4
5 #include "base/basictypes.h"
6 #include "content/browser/renderer_host/input/buffered_input_router.h"
7 #include "content/browser/renderer_host/input/input_router_unittest.h"
8 #include "content/common/input/event_packet.h"
9 #include "content/common/input/input_event_utils.h"
10 #include "content/common/input_messages.h"
11 #include "content/common/view_messages.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 using WebKit::WebGestureEvent;
15 using WebKit::WebInputEvent;
16 using WebKit::WebMouseEvent;
17 using WebKit::WebMouseWheelEvent;
18 using WebKit::WebTouchEvent;
19 using WebKit::WebTouchPoint;
20
21 namespace content {
22
23 class TestBufferedInputRouter : public BufferedInputRouter {
24 public:
25 TestBufferedInputRouter(IPC::Sender* sender,
26 InputRouterClient* client,
27 InputAckHandler* ack_handler,
28 int routing_id)
29 : BufferedInputRouter(sender, client, ack_handler, routing_id) {}
30
31
32 size_t QueuedEventCount() const {
33 return input_queue()->QueuedEventCount();
34 }
35 };
36
37 class BufferedInputRouterTest : public InputRouterTest {
38 public:
39 BufferedInputRouterTest() {}
40 virtual ~BufferedInputRouterTest() {}
41
42 protected:
43 // InputRouterTest
44 virtual scoped_ptr<InputRouter> CreateInputRouter(RenderProcessHost* process,
45 InputRouterClient* client,
46 InputAckHandler* handler,
47 int routing_id) OVERRIDE {
48 return scoped_ptr<InputRouter>(
49 new TestBufferedInputRouter(process, client, handler, routing_id));
50 }
51
52 bool FinishFlush(InputEventState ack_state) {
53 if (!process_->sink().message_count())
54 return false;
55 IPC::Message message(*process_->sink().GetMessageAt(0));
56 process_->sink().ClearMessages();
57 SendEventPacketACK(message, ack_state);
58 return true;
59 }
60
61 void SendEventPacketACK(const IPC::Message& message,
62 InputEventState ack_state) {
63 EventPacket packet;
64 ASSERT_TRUE(CrackEventPacketMessage(message, &packet));
65
66 for (size_t i = 0; i < packet.events.size(); ++i)
67 packet.events[i].state = ack_state;
68
69 input_router_->OnMessageReceived(
70 InputHostMsg_HandleEventPacket_ACK(0, packet));
71 }
72
73 size_t QueuedEventCount() const {
74 return buffered_input_router()->QueuedEventCount();
75 }
76
77 TestBufferedInputRouter* buffered_input_router() const {
78 return static_cast<TestBufferedInputRouter*>(input_router_.get());
79 }
80 };
81
82 TEST_F(BufferedInputRouterTest, InputEventsProperlyQueued) {
83 EXPECT_TRUE(input_router_->SendInput(
84 scoped_ptr<IPC::Message>(new InputMsg_Redo(MSG_ROUTING_NONE))));
85 EXPECT_EQ(1U, QueuedEventCount());
86
87 EXPECT_TRUE(input_router_->SendInput(
88 scoped_ptr<IPC::Message>(new InputMsg_Cut(MSG_ROUTING_NONE))));
89 EXPECT_EQ(2U, QueuedEventCount());
90
91 EXPECT_TRUE(input_router_->SendInput(
92 scoped_ptr<IPC::Message>(new InputMsg_Copy(MSG_ROUTING_NONE))));
93 EXPECT_EQ(3U, QueuedEventCount());
94
95 EXPECT_TRUE(input_router_->SendInput(
96 scoped_ptr<IPC::Message>(new InputMsg_Paste(MSG_ROUTING_NONE))));
97 EXPECT_EQ(4U, QueuedEventCount());
98
99 #ifdef NDEBUG
100 // Non-input messages not queued (this will DCHECK).
101 EXPECT_FALSE(input_router_->SendInput(scoped_ptr<IPC::Message>(
102 new ViewMsg_ChangeResizeRect(MSG_ROUTING_NONE, gfx::Rect()))));
103 EXPECT_EQ(4U, QueuedEventCount());
104 #endif
105 }
106
107 #define SCOPED_EXPECT(CALL, MESSAGE) { SCOPED_TRACE(MESSAGE); CALL; }
108
109 TEST_F(BufferedInputRouterTest, ClientOnSendEventCalled) {
110 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
111 EXPECT_EQ(1U, QueuedEventCount());
112
113 SimulateWheelEvent(5, 0, 0, false);
114 EXPECT_EQ(2U, QueuedEventCount());
115
116 SimulateMouseMove(5, 0, 0);
117 EXPECT_EQ(3U, QueuedEventCount());
118
119 SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
120 WebGestureEvent::Touchpad);
121 EXPECT_EQ(4U, QueuedEventCount());
122
123 SimulateTouchEvent(1, 1);
124 EXPECT_EQ(5U, QueuedEventCount());
125 }
126
127 TEST_F(BufferedInputRouterTest, ClientOnSendEventHonored) {
128 client_->set_allow_send_event(false);
129
130 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
131 EXPECT_EQ(0U, QueuedEventCount());
132
133 SimulateWheelEvent(5, 0, 0, false);
134 EXPECT_EQ(0U, QueuedEventCount());
135
136 SimulateMouseMove(5, 0, 0);
137 EXPECT_EQ(0U, QueuedEventCount());
138
139 SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
140 WebGestureEvent::Touchpad);
141 EXPECT_EQ(0U, QueuedEventCount());
142
143 SimulateTouchEvent(1, 1);
144 EXPECT_EQ(0U, QueuedEventCount());
145 }
146
147 TEST_F(BufferedInputRouterTest, FlightCountIncrementedOnDeliver) {
148 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
149 EXPECT_EQ(0, client_->in_flight_event_count());
150
151 input_router_->Flush();
152 EXPECT_EQ(1, client_->in_flight_event_count());
153 }
154
155 TEST_F(BufferedInputRouterTest, FlightCountDecrementedOnAck) {
156 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
157 EXPECT_EQ(0, client_->in_flight_event_count());
158
159 input_router_->Flush();
160 EXPECT_EQ(1, client_->in_flight_event_count());
161
162 // The in-flight count should continue until the flush has finished.
163 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_COULD_NOT_DELIVER));
164 EXPECT_EQ(1, client_->in_flight_event_count());
165
166 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_ABSORBED));
167 EXPECT_EQ(0, client_->in_flight_event_count());
168 }
169
170 TEST_F(BufferedInputRouterTest, FilteredEventsNeverQueued) {
171 // Event should not be queued, but should be ack'ed.
172 client_->set_filter_state(INPUT_EVENT_ACK_STATE_CONSUMED);
173 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
174 SCOPED_EXPECT(ack_handler_->ExpectAckCalled(1), "AckCalled");
175 EXPECT_EQ(0U, QueuedEventCount());
176 ASSERT_EQ(NULL, input_router_->GetLastKeyboardEvent());
177
178 // Event should not be queued, but should be ack'ed.
179 client_->set_filter_state(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
180 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
181 SCOPED_EXPECT(ack_handler_->ExpectAckCalled(1), "AckCalled");
182 EXPECT_EQ(0U, QueuedEventCount());
183 ASSERT_EQ(NULL, input_router_->GetLastKeyboardEvent());
184
185 // |INPUT_EVENT_ACK_STATE_UNKNOWN| should drop the event without ack'ing.
186 client_->set_filter_state(INPUT_EVENT_ACK_STATE_UNKNOWN);
187 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
188 SCOPED_EXPECT(ack_handler_->ExpectAckCalled(0), "AckNotCalled");
189 EXPECT_EQ(0U, QueuedEventCount());
190 ASSERT_EQ(NULL, input_router_->GetLastKeyboardEvent());
191
192 // Event should be queued.
193 client_->set_filter_state(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
194 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
195 SCOPED_EXPECT(ack_handler_->ExpectAckCalled(0), "AckNotCalled");
196 EXPECT_EQ(1U, QueuedEventCount());
197 }
198
199 TEST_F(BufferedInputRouterTest, FollowupEventsInjected) {
200 // Enable a followup gesture event.
201 WebGestureEvent followup_event;
202 followup_event.type = WebInputEvent::GestureScrollBegin;
203 followup_event.data.scrollUpdate.deltaX = 10;
204 ack_handler_->set_followup_touch_event(make_scoped_ptr(
205 new GestureEventWithLatencyInfo(followup_event, ui::LatencyInfo())));
206
207 // Create an initial packet of { Touch, Key } and start flushing.
208 SimulateTouchEvent(1, 1);
209 EXPECT_EQ(1U, QueuedEventCount());
210 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
211 EXPECT_EQ(2U, QueuedEventCount());
212 input_router_->Flush();
213
214 // Followup only triggered when event handled.
215 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_COULD_NOT_DELIVER));
216 SCOPED_EXPECT(client_->ExpectDidFlushCalled(false), "DidFlushNotCalled");
217 EXPECT_EQ(2U, QueuedEventCount());
218
219 // Ack the touch event.
220 EventPacket packet;
221 ASSERT_EQ(1U, process_->sink().message_count());
222 ASSERT_TRUE(CrackEventPacketMessage(*process_->sink().GetMessageAt(0),
223 &packet));
224 process_->sink().ClearMessages();
225 ASSERT_EQ(2U, packet.events.size());
226 packet.events[0].state = INPUT_EVENT_IMPL_THREAD_ABSORBED;
227 packet.events[1].state = INPUT_EVENT_IMPL_THREAD_COULD_NOT_DELIVER;
228 input_router_->OnMessageReceived(
229 InputHostMsg_HandleEventPacket_ACK(0, packet));
230
231 // Ack'ing the touch event will triggered the followup gesture event.
232 // However, the flush is not complete until the followup event is ack'ed.
233 SCOPED_EXPECT(client_->ExpectDidFlushCalled(false), "DidFlushNotCalled");
234 SCOPED_EXPECT(client_->ExpectSendCalled(true), "SendGestureCalled");
235 EXPECT_EQ(followup_event.type, client_->sent_gesture_event().event.type);
236 EXPECT_EQ(2U, QueuedEventCount());
237
238 // Our packet is now { Gesture, Key }.
239 EventPacket followup_packet;
240 ASSERT_EQ(1U, process_->sink().message_count());
241 ASSERT_TRUE(CrackEventPacketMessage(*process_->sink().GetMessageAt(0),
242 &followup_packet));
243 ui::LatencyInfo latency;
244 const WebInputEvent* web_event = NULL;
245 ASSERT_TRUE(CrackWebInputEventMessage(followup_packet.events[0].message,
246 &web_event,
247 &latency,
248 NULL));
249 EXPECT_EQ(followup_event.type, web_event->type);
250 ASSERT_TRUE(CrackWebInputEventMessage(followup_packet.events[1].message,
251 &web_event,
252 &latency,
253 NULL));
254 EXPECT_EQ(WebInputEvent::RawKeyDown, web_event->type);
255
256 // Complete the flush; the gesture should have been ack'ed.
257 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_ABSORBED));
258 SCOPED_EXPECT(client_->ExpectDidFlushCalled(true), "DidFlushCalled");
259 EXPECT_EQ(followup_event.type, ack_handler_->acked_gesture_event().type);
260 EXPECT_EQ(0U, QueuedEventCount());
261 }
262
263 TEST_F(BufferedInputRouterTest, FlushRequestedOnQueue) {
264 // The first queued event should trigger a flush request.
265 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
266 EXPECT_EQ(1U, QueuedEventCount());
267 SCOPED_EXPECT(client_->ExpectNeedsFlushCalled(true), "SetNeedsFlushCalled");
268
269 // Subsequently queued events will not trigger another flush request.
270 SimulateWheelEvent(5, 0, 0, false);
271 EXPECT_EQ(2U, QueuedEventCount());
272 SCOPED_EXPECT(client_->ExpectNeedsFlushCalled(false), "SetNeedsFlushCalled");
273 }
274
275 TEST_F(BufferedInputRouterTest, HasQueuedGestureEvents) {
276 EXPECT_FALSE(input_router_->HasQueuedGestureEvents());
277 SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
278 WebGestureEvent::Touchpad);
279 EXPECT_TRUE(input_router_->HasQueuedGestureEvents());
280
281 // Only an ack'ed gesture should clear it from the queue.
282 input_router_->Flush();
283 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_COULD_NOT_DELIVER));
284 EXPECT_TRUE(input_router_->HasQueuedGestureEvents());
285
286 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_ABSORBED));
287 EXPECT_FALSE(input_router_->HasQueuedGestureEvents());
288 }
289
290 TEST_F(BufferedInputRouterTest, GetLastKeyboardEvent) {
291 EXPECT_EQ(NULL, input_router_->GetLastKeyboardEvent());
292
293 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
294 EXPECT_EQ(WebInputEvent::RawKeyDown,
295 input_router_->GetLastKeyboardEvent()->type);
296
297 // Queueing another key event does not effect the "last" event.
298 SimulateKeyboardEvent(WebInputEvent::KeyUp);
299 EXPECT_EQ(WebInputEvent::RawKeyDown,
300 input_router_->GetLastKeyboardEvent()->type);
301
302 input_router_->Flush();
303
304 // Ack'ing the first event should make the second event the "last" event.
305 EventPacket packet;
306 ASSERT_TRUE(CrackEventPacketMessage(*process_->sink().GetMessageAt(0),
307 &packet));
308 process_->sink().ClearMessages();
309 packet.events[0].state = INPUT_EVENT_IMPL_THREAD_ABSORBED;
310 packet.events[1].state = INPUT_EVENT_IMPL_THREAD_COULD_NOT_DELIVER;
311 input_router_->OnMessageReceived(
312 InputHostMsg_HandleEventPacket_ACK(0, packet));
313 EXPECT_EQ(WebInputEvent::KeyUp,
314 input_router_->GetLastKeyboardEvent()->type);
315
316 // A key event queued during a flush becomes "last" upon flush completion.
317 SimulateKeyboardEvent(WebInputEvent::Char);
318 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_ABSORBED));
319 EXPECT_EQ(WebInputEvent::Char,
320 input_router_->GetLastKeyboardEvent()->type);
321
322 // An empty queue should produce a null "last" event.
323 input_router_->Flush();
324 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_ABSORBED));
325 EXPECT_EQ(NULL, input_router_->GetLastKeyboardEvent());
326 }
327
328 TEST_F(BufferedInputRouterTest, UnexpectedAck) {
329 ASSERT_FALSE(ack_handler_->unexpected_event_ack_called());
330 input_router_->OnMessageReceived(
331 InputHostMsg_HandleEventPacket_ACK(0, EventPacket()));
332 EXPECT_TRUE(ack_handler_->unexpected_event_ack_called());
333 }
334
335 TEST_F(BufferedInputRouterTest, BadAck) {
336 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
337 input_router_->Flush();
338
339 ASSERT_FALSE(ack_handler_->unexpected_event_ack_called());
340 EventPacket packet;
341 input_router_->OnMessageReceived(
342 InputHostMsg_HandleEventPacket_ACK(0, EventPacket()));
343 EXPECT_TRUE(ack_handler_->unexpected_event_ack_called());
344 }
345
346 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698