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

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: BufferedInputRouter unit tests 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 BufferedInputRouterTest : public InputRouterTest {
24 public:
25 BufferedInputRouterTest()
26 : sync_flush_ack_(false),
27 sync_flush_state_(INPUT_EVENT_UNHANDLED) {}
28 virtual ~BufferedInputRouterTest() {}
29
30 protected:
31 // InputRouterTest
32 virtual scoped_ptr<InputRouter> CreateInputRouter(RenderProcessHost* process,
33 InputRouterClient* client,
34 int routing_id) OVERRIDE {
35 return scoped_ptr<InputRouter>(
36 new BufferedInputRouter(process, client, routing_id));
37 }
38
39 // IPC::Listener
40 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
41 if (!sync_flush_ack_)
42 return false;
43
44 SendEventPacketACK(message, sync_flush_state_);
45 return true;
46 }
47
48 bool FinishFlush(InputEventState ack_state) {
49 if (!process_->sink().message_count())
50 return false;
51 IPC::Message message(*process_->sink().GetMessageAt(0));
52 process_->sink().ClearMessages();
53 SendEventPacketACK(message, ack_state);
54 return true;
55 }
56
57 void SendEventPacketACK(const IPC::Message& message,
58 InputEventState ack_state) {
59 EventPacket packet;
60 ASSERT_TRUE(CrackEventPacketMessage(message, &packet));
61
62 for (size_t i = 0; i < packet.events.size(); ++i)
63 packet.events[i].state = ack_state;
64
65 input_router_->OnMessageReceived(
66 InputHostMsg_HandleEventPacket_ACK(0, packet));
67 }
68
69 void CheckShouldSignalDelayedPacket() {
70 buffered_input_router()->CheckShouldSignalDelayedPacket();
71 }
72
73 void SetSyncFlushAck(bool sync, InputEventState state) {
74 sync_flush_ack_ = sync;
75 sync_flush_state_ = state;
76 }
77
78 size_t QueuedEventCount() const {
79 return buffered_input_router()->input_queue_->QueuedEventCount();
80 }
81
82 bool IsFlushTimeoutRunning() const {
83 return buffered_input_router()->delayed_packet_timer_.IsRunning();
84 }
85
86 BufferedInputRouter* buffered_input_router() const {
87 return static_cast<BufferedInputRouter*>(input_router_.get());
88 }
89
90 private:
91 bool sync_flush_ack_;
92 InputEventState sync_flush_state_;
93 };
94
95 TEST_F(BufferedInputRouterTest, InputEventsProperlyQueued) {
96 EXPECT_TRUE(input_router_->SendInput(new InputMsg_Redo(MSG_ROUTING_NONE)));
97 EXPECT_EQ(1U, QueuedEventCount());
98
99 EXPECT_TRUE(input_router_->SendInput(new InputMsg_Cut(MSG_ROUTING_NONE)));
100 EXPECT_EQ(2U, QueuedEventCount());
101
102 EXPECT_TRUE(input_router_->SendInput(new InputMsg_Copy(MSG_ROUTING_NONE)));
103 EXPECT_EQ(3U, QueuedEventCount());
104
105 EXPECT_TRUE(input_router_->SendInput(new InputMsg_Paste(MSG_ROUTING_NONE)));
106 EXPECT_EQ(4U, QueuedEventCount());
107
108 #ifdef NDEBUG
109 // Non-input messages not queued (this will DCHECK).
110 EXPECT_FALSE(input_router_->SendInput(
111 new ViewMsg_ChangeResizeRect(MSG_ROUTING_NONE, gfx::Rect())));
112 EXPECT_EQ(4U, QueuedEventCount());
113 #endif
114 }
115
116 #define SCOPED_EXPECT(CALL, MESSAGE) { SCOPED_TRACE(MESSAGE); CALL; }
117
118 TEST_F(BufferedInputRouterTest, ClientOnSendEventCalled) {
119 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
120 EXPECT_EQ(1U, QueuedEventCount());
121
122 SimulateWheelEvent(5, 0, 0, false);
123 EXPECT_EQ(2U, QueuedEventCount());
124
125 SimulateMouseMove(5, 0, 0);
126 EXPECT_EQ(3U, QueuedEventCount());
127
128 SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
129 WebGestureEvent::Touchpad);
130 EXPECT_EQ(4U, QueuedEventCount());
131
132 SimulateTouchEvent(1, 1);
133 EXPECT_EQ(5U, QueuedEventCount());
134 }
135
136 TEST_F(BufferedInputRouterTest, ClientOnSendEventHonored) {
137 client_->set_allow_send_event(false);
138
139 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
140 EXPECT_EQ(0U, QueuedEventCount());
141
142 SimulateWheelEvent(5, 0, 0, false);
143 EXPECT_EQ(0U, QueuedEventCount());
144
145 SimulateMouseMove(5, 0, 0);
146 EXPECT_EQ(0U, QueuedEventCount());
147
148 SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
149 WebGestureEvent::Touchpad);
150 EXPECT_EQ(0U, QueuedEventCount());
151
152 SimulateTouchEvent(1, 1);
153 EXPECT_EQ(0U, QueuedEventCount());
154 }
155
156 TEST_F(BufferedInputRouterTest, FlightCountIncrementedOnDeliver) {
157 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
158 EXPECT_EQ(0, client_->in_flight_event_count());
159
160 input_router_->Flush();
161 EXPECT_EQ(1, client_->in_flight_event_count());
162 }
163
164 TEST_F(BufferedInputRouterTest, FlightCountNotIncrementedOnSyncAck) {
165 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
166 EXPECT_EQ(0, client_->in_flight_event_count());
167
168 SetSyncFlushAck(true, INPUT_EVENT_IMPL_THREAD_ABSORBED);
169 input_router_->Flush();
170 EXPECT_EQ(0, client_->in_flight_event_count());
171 }
172
173 TEST_F(BufferedInputRouterTest, FlightCountDecrementedOnAck) {
174 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
175 EXPECT_EQ(0, client_->in_flight_event_count());
176
177 input_router_->Flush();
178 EXPECT_EQ(1, client_->in_flight_event_count());
179
180 // The in-flight count should continue until the flush has finished.
181 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_COULD_NOT_DELIVER));
182 EXPECT_EQ(1, client_->in_flight_event_count());
183
184 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_ABSORBED));
185 EXPECT_EQ(0, client_->in_flight_event_count());
186 }
187
188 TEST_F(BufferedInputRouterTest, FilteredEventsNeverQueued) {
189 // Event should not be queued, but should be ack'ed.
190 client_->set_filter_state(INPUT_EVENT_ACK_STATE_CONSUMED);
191 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
192 SCOPED_EXPECT(client_->ExpectAckCalled(1), "AckCalled");
193 EXPECT_EQ(0U, QueuedEventCount());
194 ASSERT_EQ(NULL, input_router_->GetLastKeyboardEvent());
195
196 // Event should not be queued, but should be ack'ed.
197 client_->set_filter_state(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
198 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
199 SCOPED_EXPECT(client_->ExpectAckCalled(1), "AckCalled");
200 EXPECT_EQ(0U, QueuedEventCount());
201 ASSERT_EQ(NULL, input_router_->GetLastKeyboardEvent());
202
203 // |INPUT_EVENT_ACK_STATE_UNKNOWN| should drop the event without ack'ing.
204 client_->set_filter_state(INPUT_EVENT_ACK_STATE_UNKNOWN);
205 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
206 SCOPED_EXPECT(client_->ExpectAckCalled(0), "AckNotCalled");
207 EXPECT_EQ(0U, QueuedEventCount());
208 ASSERT_EQ(NULL, input_router_->GetLastKeyboardEvent());
209
210 // Event should be queued.
211 client_->set_filter_state(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
212 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
213 SCOPED_EXPECT(client_->ExpectAckCalled(0), "AckNotCalled");
214 EXPECT_EQ(1U, QueuedEventCount());
215 }
216
217 TEST_F(BufferedInputRouterTest, FollowupEventsInjected) {
218 // Enable a followup gesture event.
219 WebGestureEvent followup_event;
220 followup_event.type = WebInputEvent::GestureScrollBegin;
221 followup_event.data.scrollUpdate.deltaX = 10;
222 client_->set_followup_touch_event(make_scoped_ptr(
223 new GestureEventWithLatencyInfo(followup_event, ui::LatencyInfo())));
224
225 // Create an initial packet of { Touch, Key } and start flushing.
226 SimulateTouchEvent(1, 1);
227 EXPECT_EQ(1U, QueuedEventCount());
228 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
229 EXPECT_EQ(2U, QueuedEventCount());
230 input_router_->Flush();
231
232 // Followup only triggered when event handled.
233 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_COULD_NOT_DELIVER));
234 SCOPED_EXPECT(client_->ExpectDidFlushCalled(false), "DidFlushNotCalled");
235 EXPECT_EQ(2U, QueuedEventCount());
236
237 // Ack the touch event.
238 EventPacket packet;
239 ASSERT_EQ(1U, process_->sink().message_count());
240 ASSERT_TRUE(CrackEventPacketMessage(*process_->sink().GetMessageAt(0),
241 &packet));
242 process_->sink().ClearMessages();
243 packet.events[0].state = INPUT_EVENT_IMPL_THREAD_ABSORBED;
244 packet.events[1].state = INPUT_EVENT_IMPL_THREAD_COULD_NOT_DELIVER;
245 input_router_->OnMessageReceived(
246 InputHostMsg_HandleEventPacket_ACK(0, packet));
247
248 // Ack'ing the touch event will triggered the followup gesture event.
249 // However, the flush is not complete until the followup event is ack'ed.
250 SCOPED_EXPECT(client_->ExpectDidFlushCalled(false), "DidFlushNotCalled");
251 SCOPED_EXPECT(client_->ExpectSendCalled(true), "SendGestureCalled");
252 EXPECT_EQ(followup_event.type, client_->sent_gesture_event().event.type);
253 EXPECT_EQ(2U, QueuedEventCount());
254
255 // Our packet is now { Gesture, Key }.
256 EventPacket followup_packet;
257 ASSERT_EQ(1U, process_->sink().message_count());
258 ASSERT_TRUE(CrackEventPacketMessage(*process_->sink().GetMessageAt(0),
259 &followup_packet));
260 ui::LatencyInfo latency;
261 const WebInputEvent* web_event = NULL;
262 ASSERT_TRUE(CrackWebInputEventMessage(followup_packet.events[0].message,
263 &web_event,
264 &latency,
265 NULL));
266 EXPECT_EQ(followup_event.type, web_event->type);
267 ASSERT_TRUE(CrackWebInputEventMessage(followup_packet.events[1].message,
268 &web_event,
269 &latency,
270 NULL));
271 EXPECT_EQ(WebInputEvent::RawKeyDown, web_event->type);
272
273 // Complete the flush; the gesture should have been ack'ed.
274 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_ABSORBED));
275 SCOPED_EXPECT(client_->ExpectDidFlushCalled(true), "DidFlushCalled");
276 EXPECT_EQ(followup_event.type, client_->acked_gesture_event().type);
277 EXPECT_EQ(0U, QueuedEventCount());
278 }
279
280 TEST_F(BufferedInputRouterTest, FlushRequestedOnQueue) {
281 // The first queued event should trigger a flush request.
282 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
283 EXPECT_EQ(1U, QueuedEventCount());
284 SCOPED_EXPECT(client_->ExpectNeedsFlushCalled(true), "SetNeedsFlushCalled");
285
286 // Subsequently queued events will not trigger another flush request.
287 SimulateWheelEvent(5, 0, 0, false);
288 EXPECT_EQ(2U, QueuedEventCount());
289 SCOPED_EXPECT(client_->ExpectNeedsFlushCalled(false), "SetNeedsFlushCalled");
290 }
291
292 TEST_F(BufferedInputRouterTest, FlushTriggersTimeout) {
293 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
294 EXPECT_FALSE(IsFlushTimeoutRunning());
295
296 input_router_->Flush();
297 EXPECT_TRUE(IsFlushTimeoutRunning());
298 SCOPED_EXPECT(client_->ExpectDidFlushCalled(false), "DidFlushNotCalled");
299 }
300
301 TEST_F(BufferedInputRouterTest, SyncFlushDoesntTriggerTimeout) {
302 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
303 EXPECT_FALSE(IsFlushTimeoutRunning());
304 SetSyncFlushAck(true, INPUT_EVENT_IMPL_THREAD_ABSORBED);
305
306 input_router_->Flush();
307 EXPECT_FALSE(IsFlushTimeoutRunning());
308 SCOPED_EXPECT(client_->ExpectDidFlushCalled(true), "DidFlushCalled");
309 }
310
311 TEST_F(BufferedInputRouterTest, DidFlushStopsTimeout) {
312 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
313 EXPECT_FALSE(IsFlushTimeoutRunning());
314 input_router_->Flush();
315 EXPECT_TRUE(IsFlushTimeoutRunning());
316
317 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_ABSORBED));
318 SCOPED_EXPECT(client_->ExpectDidFlushCalled(true), "DidFlushCalled");
319 EXPECT_FALSE(IsFlushTimeoutRunning());
320 }
321
322 TEST_F(BufferedInputRouterTest, TimeoutSignalsDidFlush) {
323 base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(10);
324 buffered_input_router()->set_delayed_packet_timeout_ms(timeout);
325
326 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
327 EXPECT_EQ(1U, QueuedEventCount());
328 input_router_->Flush();
329 EXPECT_TRUE(IsFlushTimeoutRunning());
330
331 // The delayed signal should trigger a DidFlush, but the queue keeps flushing.
332 base::PlatformThread::Sleep(timeout * 2);
333 CheckShouldSignalDelayedPacket();
334 SCOPED_EXPECT(client_->ExpectDidFlushCalled(true), "DidFlushCalled");
335 EXPECT_EQ(1U, QueuedEventCount());
336 EXPECT_FALSE(IsFlushTimeoutRunning());
337 }
338
339 TEST_F(BufferedInputRouterTest, HasQueuedGestureEvents) {
340 EXPECT_FALSE(input_router_->HasQueuedGestureEvents());
341 SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
342 WebGestureEvent::Touchpad);
343 EXPECT_TRUE(input_router_->HasQueuedGestureEvents());
344
345 // Only an ack'ed gesture should clear it from the queue.
346 input_router_->Flush();
347 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_COULD_NOT_DELIVER));
348 EXPECT_TRUE(input_router_->HasQueuedGestureEvents());
349
350 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_ABSORBED));
351 EXPECT_FALSE(input_router_->HasQueuedGestureEvents());
352 }
353
354 TEST_F(BufferedInputRouterTest, GetLastKeyboardEvent) {
355 EXPECT_EQ(NULL, input_router_->GetLastKeyboardEvent());
356
357 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
358 EXPECT_EQ(WebInputEvent::RawKeyDown,
359 input_router_->GetLastKeyboardEvent()->type);
360
361 // Queueing another key event does not effect the "last" event.
362 SimulateKeyboardEvent(WebInputEvent::KeyUp);
363 EXPECT_EQ(WebInputEvent::RawKeyDown,
364 input_router_->GetLastKeyboardEvent()->type);
365
366 input_router_->Flush();
367
368 // Ack'ing the first event should make the second event the "last" event.
369 EventPacket packet;
370 ASSERT_TRUE(CrackEventPacketMessage(*process_->sink().GetMessageAt(0),
371 &packet));
372 process_->sink().ClearMessages();
373 packet.events[0].state = INPUT_EVENT_IMPL_THREAD_ABSORBED;
374 packet.events[1].state = INPUT_EVENT_IMPL_THREAD_COULD_NOT_DELIVER;
375 input_router_->OnMessageReceived(
376 InputHostMsg_HandleEventPacket_ACK(0, packet));
377 EXPECT_EQ(WebInputEvent::KeyUp,
378 input_router_->GetLastKeyboardEvent()->type);
379
380 // A key event queued during a flush becomes "last" upon flush completion.
381 SimulateKeyboardEvent(WebInputEvent::Char);
382 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_ABSORBED));
383 EXPECT_EQ(WebInputEvent::Char,
384 input_router_->GetLastKeyboardEvent()->type);
385
386 // An empty queue should produce a null "last" event.
387 input_router_->Flush();
388 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_ABSORBED));
389 EXPECT_EQ(NULL, input_router_->GetLastKeyboardEvent());
390 }
391
392 TEST_F(BufferedInputRouterTest, UnexpectedAck) {
393 ASSERT_FALSE(client_->unexpected_event_ack_called());
394 input_router_->OnMessageReceived(
395 InputHostMsg_HandleEventPacket_ACK(0, EventPacket()));
396 EXPECT_TRUE(client_->unexpected_event_ack_called());
397 }
398
399 TEST_F(BufferedInputRouterTest, BadAck) {
400 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
401 input_router_->Flush();
402
403 ASSERT_FALSE(client_->unexpected_event_ack_called());
404 EventPacket packet;
405 input_router_->OnMessageReceived(
406 InputHostMsg_HandleEventPacket_ACK(0, EventPacket()));
407 EXPECT_TRUE(client_->unexpected_event_ack_called());
408 }
409
410 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698