| 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/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 |
| OLD | NEW |