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