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

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

Powered by Google App Engine
This is Rietveld 408576698