OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/basictypes.h" | 5 #include "base/basictypes.h" |
6 #include "base/memory/scoped_ptr.h" | 6 #include "base/memory/scoped_ptr.h" |
7 #include "base/shared_memory.h" | 7 #include "base/shared_memory.h" |
8 #include "base/timer.h" | 8 #include "base/timer.h" |
9 #include "content/browser/browser_thread_impl.h" | 9 #include "content/browser/browser_thread_impl.h" |
10 #include "content/browser/renderer_host/backing_store.h" | 10 #include "content/browser/renderer_host/backing_store.h" |
11 #include "content/browser/renderer_host/render_widget_host_delegate.h" | 11 #include "content/browser/renderer_host/render_widget_host_delegate.h" |
12 #include "content/browser/renderer_host/gesture_event_filter.h" | 12 #include "content/browser/renderer_host/gesture_event_filter.h" |
13 #include "content/browser/renderer_host/test_render_view_host.h" | 13 #include "content/browser/renderer_host/test_render_view_host.h" |
| 14 #include "content/browser/renderer_host/touch_event_queue.h" |
14 #include "content/common/view_messages.h" | 15 #include "content/common/view_messages.h" |
15 #include "content/port/browser/render_widget_host_view_port.h" | 16 #include "content/port/browser/render_widget_host_view_port.h" |
16 #include "content/public/browser/notification_details.h" | 17 #include "content/public/browser/notification_details.h" |
17 #include "content/public/browser/notification_observer.h" | 18 #include "content/public/browser/notification_observer.h" |
18 #include "content/public/browser/notification_registrar.h" | 19 #include "content/public/browser/notification_registrar.h" |
19 #include "content/public/browser/notification_source.h" | 20 #include "content/public/browser/notification_source.h" |
20 #include "content/public/browser/notification_types.h" | 21 #include "content/public/browser/notification_types.h" |
21 #include "content/public/test/mock_render_process_host.h" | 22 #include "content/public/test/mock_render_process_host.h" |
22 #include "content/public/test/test_browser_context.h" | 23 #include "content/public/test/test_browser_context.h" |
23 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 ViewHostMsg_UpdateRect_Params params; | 121 ViewHostMsg_UpdateRect_Params params; |
121 InitUpdateRectParams(¶ms); | 122 InitUpdateRectParams(¶ms); |
122 | 123 |
123 ViewHostMsg_UpdateRect message(render_widget_id, params); | 124 ViewHostMsg_UpdateRect message(render_widget_id, params); |
124 *msg = message; | 125 *msg = message; |
125 return true; | 126 return true; |
126 } | 127 } |
127 | 128 |
128 // TestView -------------------------------------------------------------------- | 129 // TestView -------------------------------------------------------------------- |
129 | 130 |
130 // This test view allows us to specify the size. | 131 // This test view allows us to specify the size, and keep track of acked |
| 132 // touch-events. |
131 class TestView : public content::TestRenderWidgetHostView { | 133 class TestView : public content::TestRenderWidgetHostView { |
132 public: | 134 public: |
133 explicit TestView(RenderWidgetHostImpl* rwh) | 135 explicit TestView(RenderWidgetHostImpl* rwh) |
134 : content::TestRenderWidgetHostView(rwh) { | 136 : content::TestRenderWidgetHostView(rwh) { |
135 } | 137 } |
136 | 138 |
137 // Sets the bounds returned by GetViewBounds. | 139 // Sets the bounds returned by GetViewBounds. |
138 void set_bounds(const gfx::Rect& bounds) { | 140 void set_bounds(const gfx::Rect& bounds) { |
139 bounds_ = bounds; | 141 bounds_ = bounds; |
140 } | 142 } |
141 | 143 |
| 144 const WebKit::WebTouchEvent& acked_event() const { return acked_event_; } |
| 145 void ClearAckedEvent() { |
| 146 acked_event_.type = WebKit::WebInputEvent::Undefined; |
| 147 } |
| 148 |
142 // RenderWidgetHostView override. | 149 // RenderWidgetHostView override. |
143 virtual gfx::Rect GetViewBounds() const { | 150 virtual gfx::Rect GetViewBounds() const OVERRIDE { |
144 return bounds_; | 151 return bounds_; |
145 } | 152 } |
146 | 153 |
| 154 virtual void ProcessAckedTouchEvent(const WebKit::WebTouchEvent& touch, |
| 155 bool processed) OVERRIDE { |
| 156 acked_event_ = touch; |
| 157 } |
| 158 |
147 protected: | 159 protected: |
| 160 WebKit::WebTouchEvent acked_event_; |
148 gfx::Rect bounds_; | 161 gfx::Rect bounds_; |
149 DISALLOW_COPY_AND_ASSIGN(TestView); | 162 DISALLOW_COPY_AND_ASSIGN(TestView); |
150 }; | 163 }; |
151 | 164 |
152 // MockRenderWidgetHostDelegate -------------------------------------------- | 165 // MockRenderWidgetHostDelegate -------------------------------------------- |
153 | 166 |
154 class MockRenderWidgetHostDelegate : public content::RenderWidgetHostDelegate { | 167 class MockRenderWidgetHostDelegate : public content::RenderWidgetHostDelegate { |
155 public: | 168 public: |
156 MockRenderWidgetHostDelegate() | 169 MockRenderWidgetHostDelegate() |
157 : prehandle_keyboard_event_(false), | 170 : prehandle_keyboard_event_(false), |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 } | 233 } |
221 | 234 |
222 // Allow poking at a few private members. | 235 // Allow poking at a few private members. |
223 using RenderWidgetHostImpl::OnMsgPaintAtSizeAck; | 236 using RenderWidgetHostImpl::OnMsgPaintAtSizeAck; |
224 using RenderWidgetHostImpl::OnMsgUpdateRect; | 237 using RenderWidgetHostImpl::OnMsgUpdateRect; |
225 using RenderWidgetHostImpl::RendererExited; | 238 using RenderWidgetHostImpl::RendererExited; |
226 using RenderWidgetHostImpl::in_flight_size_; | 239 using RenderWidgetHostImpl::in_flight_size_; |
227 using RenderWidgetHostImpl::is_hidden_; | 240 using RenderWidgetHostImpl::is_hidden_; |
228 using RenderWidgetHostImpl::resize_ack_pending_; | 241 using RenderWidgetHostImpl::resize_ack_pending_; |
229 using RenderWidgetHostImpl::gesture_event_filter_; | 242 using RenderWidgetHostImpl::gesture_event_filter_; |
| 243 using RenderWidgetHostImpl::touch_event_queue_; |
230 | 244 |
231 bool unresponsive_timer_fired() const { | 245 bool unresponsive_timer_fired() const { |
232 return unresponsive_timer_fired_; | 246 return unresponsive_timer_fired_; |
233 } | 247 } |
234 | 248 |
235 void set_hung_renderer_delay_ms(int delay_ms) { | 249 void set_hung_renderer_delay_ms(int delay_ms) { |
236 hung_renderer_delay_ms_ = delay_ms; | 250 hung_renderer_delay_ms_ = delay_ms; |
237 } | 251 } |
238 | 252 |
239 WebGestureEvent GestureEventLastQueueEvent() { | 253 WebGestureEvent GestureEventLastQueueEvent() { |
(...skipping 21 matching lines...) Expand all Loading... |
261 } | 275 } |
262 | 276 |
263 void set_maximum_tap_gap_time_ms(int delay_ms) { | 277 void set_maximum_tap_gap_time_ms(int delay_ms) { |
264 gesture_event_filter_->maximum_tap_gap_time_ms_ = delay_ms; | 278 gesture_event_filter_->maximum_tap_gap_time_ms_ = delay_ms; |
265 } | 279 } |
266 | 280 |
267 void set_debounce_interval_time_ms(int delay_ms) { | 281 void set_debounce_interval_time_ms(int delay_ms) { |
268 gesture_event_filter_->debounce_interval_time_ms_ = delay_ms; | 282 gesture_event_filter_->debounce_interval_time_ms_ = delay_ms; |
269 } | 283 } |
270 | 284 |
| 285 size_t TouchEventQueueSize() { |
| 286 return touch_event_queue_->touch_queue_.size(); |
| 287 } |
| 288 |
271 protected: | 289 protected: |
272 virtual void NotifyRendererUnresponsive() OVERRIDE { | 290 virtual void NotifyRendererUnresponsive() OVERRIDE { |
273 unresponsive_timer_fired_ = true; | 291 unresponsive_timer_fired_ = true; |
274 } | 292 } |
275 | 293 |
276 private: | 294 private: |
277 bool unresponsive_timer_fired_; | 295 bool unresponsive_timer_fired_; |
278 }; | 296 }; |
279 | 297 |
280 // MockPaintingObserver -------------------------------------------------------- | 298 // MockPaintingObserver -------------------------------------------------------- |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 | 409 |
392 // Inject simple synthetic WebGestureEvent instances. | 410 // Inject simple synthetic WebGestureEvent instances. |
393 void SimulateGestureFlingStartEvent(float velocityX, float velocityY) { | 411 void SimulateGestureFlingStartEvent(float velocityX, float velocityY) { |
394 WebGestureEvent gesture_event; | 412 WebGestureEvent gesture_event; |
395 gesture_event.type = WebInputEvent::GestureFlingStart; | 413 gesture_event.type = WebInputEvent::GestureFlingStart; |
396 gesture_event.data.flingStart.velocityX = velocityX; | 414 gesture_event.data.flingStart.velocityX = velocityX; |
397 gesture_event.data.flingStart.velocityY = velocityY; | 415 gesture_event.data.flingStart.velocityY = velocityY; |
398 host_->ForwardGestureEvent(gesture_event); | 416 host_->ForwardGestureEvent(gesture_event); |
399 } | 417 } |
400 | 418 |
| 419 // Sends a touch event (irrespective of whether the page has a touch-event |
| 420 // handler or not). |
| 421 void SendTouchEvent() { |
| 422 host_->ForwardTouchEvent(touch_event_); |
| 423 |
| 424 // Mark all the points as stationary. And remove the points that have been |
| 425 // released. |
| 426 int point = 0; |
| 427 for (unsigned int i = 0; i < touch_event_.touchesLength; ++i) { |
| 428 if (touch_event_.touches[i].state == WebKit::WebTouchPoint::StateReleased) |
| 429 continue; |
| 430 |
| 431 touch_event_.touches[point] = touch_event_.touches[i]; |
| 432 touch_event_.touches[point].state = |
| 433 WebKit::WebTouchPoint::StateStationary; |
| 434 ++point; |
| 435 } |
| 436 touch_event_.touchesLength = point; |
| 437 touch_event_.type = WebInputEvent::Undefined; |
| 438 } |
| 439 |
| 440 int PressTouchPoint(int x, int y) { |
| 441 if (touch_event_.touchesLength == touch_event_.touchesLengthCap) |
| 442 return -1; |
| 443 WebKit::WebTouchPoint& point = |
| 444 touch_event_.touches[touch_event_.touchesLength]; |
| 445 point.id = touch_event_.touchesLength; |
| 446 point.position.x = point.screenPosition.x = x; |
| 447 point.position.y = point.screenPosition.y = y; |
| 448 point.state = WebKit::WebTouchPoint::StatePressed; |
| 449 point.radiusX = point.radiusY = 1.f; |
| 450 ++touch_event_.touchesLength; |
| 451 touch_event_.type = WebInputEvent::TouchStart; |
| 452 return point.id; |
| 453 } |
| 454 |
| 455 void MoveTouchPoint(int index, int x, int y) { |
| 456 CHECK(index >= 0 && index < touch_event_.touchesLengthCap); |
| 457 WebKit::WebTouchPoint& point = touch_event_.touches[index]; |
| 458 point.position.x = point.screenPosition.x = x; |
| 459 point.position.y = point.screenPosition.y = y; |
| 460 touch_event_.touches[index].state = WebKit::WebTouchPoint::StateMoved; |
| 461 touch_event_.type = WebInputEvent::TouchMove; |
| 462 } |
| 463 |
| 464 void ReleaseTouchPoint(int index) { |
| 465 CHECK(index >= 0 && index < touch_event_.touchesLengthCap); |
| 466 touch_event_.touches[index].state = WebKit::WebTouchPoint::StateReleased; |
| 467 touch_event_.type = WebInputEvent::TouchEnd; |
| 468 } |
| 469 |
401 MessageLoopForUI message_loop_; | 470 MessageLoopForUI message_loop_; |
402 | 471 |
403 scoped_ptr<content::TestBrowserContext> browser_context_; | 472 scoped_ptr<content::TestBrowserContext> browser_context_; |
404 RenderWidgetHostProcess* process_; // Deleted automatically by the widget. | 473 RenderWidgetHostProcess* process_; // Deleted automatically by the widget. |
405 scoped_ptr<MockRenderWidgetHostDelegate> delegate_; | 474 scoped_ptr<MockRenderWidgetHostDelegate> delegate_; |
406 scoped_ptr<MockRenderWidgetHost> host_; | 475 scoped_ptr<MockRenderWidgetHost> host_; |
407 scoped_ptr<TestView> view_; | 476 scoped_ptr<TestView> view_; |
408 | 477 |
| 478 private: |
| 479 WebKit::WebTouchEvent touch_event_; |
| 480 |
409 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostTest); | 481 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostTest); |
410 }; | 482 }; |
411 | 483 |
412 // ----------------------------------------------------------------------------- | 484 // ----------------------------------------------------------------------------- |
413 | 485 |
414 TEST_F(RenderWidgetHostTest, Resize) { | 486 TEST_F(RenderWidgetHostTest, Resize) { |
415 // The initial bounds is the empty rect, so setting it to the same thing | 487 // The initial bounds is the empty rect, so setting it to the same thing |
416 // should do nothing. | 488 // should do nothing. |
417 view_->set_bounds(gfx::Rect()); | 489 view_->set_bounds(gfx::Rect()); |
418 host_->WasResized(); | 490 host_->WasResized(); |
(...skipping 812 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1231 WebInputEvent::GestureScrollUpdate, | 1303 WebInputEvent::GestureScrollUpdate, |
1232 WebInputEvent::GestureScrollUpdate}; | 1304 WebInputEvent::GestureScrollUpdate}; |
1233 | 1305 |
1234 for (unsigned i = 0; i < sizeof(expected) / sizeof(WebInputEvent::Type); | 1306 for (unsigned i = 0; i < sizeof(expected) / sizeof(WebInputEvent::Type); |
1235 i++) { | 1307 i++) { |
1236 WebGestureEvent merged_event = host_->GestureEventQueueEventAt(i); | 1308 WebGestureEvent merged_event = host_->GestureEventQueueEventAt(i); |
1237 EXPECT_EQ(expected[i], merged_event.type); | 1309 EXPECT_EQ(expected[i], merged_event.type); |
1238 } | 1310 } |
1239 } | 1311 } |
1240 | 1312 |
| 1313 // Tests that touch-events are queued properly. |
| 1314 TEST_F(RenderWidgetHostTest, TouchEventQueue) { |
| 1315 process_->sink().ClearMessages(); |
| 1316 |
| 1317 PressTouchPoint(1, 1); |
| 1318 SendTouchEvent(); |
| 1319 EXPECT_EQ(1U, process_->sink().message_count()); |
| 1320 process_->sink().ClearMessages(); |
| 1321 |
| 1322 // The second touch should not be sent since one is already in queue. |
| 1323 MoveTouchPoint(0, 5, 5); |
| 1324 SendTouchEvent(); |
| 1325 EXPECT_EQ(0U, process_->sink().message_count()); |
| 1326 |
| 1327 EXPECT_EQ(2U, host_->TouchEventQueueSize()); |
| 1328 |
| 1329 // Receive an ACK for the first touch-event. |
| 1330 SendInputEventACK(WebInputEvent::TouchStart, true); |
| 1331 EXPECT_EQ(1U, host_->TouchEventQueueSize()); |
| 1332 EXPECT_EQ(WebKit::WebInputEvent::TouchStart, view_->acked_event().type); |
| 1333 EXPECT_EQ(1U, process_->sink().message_count()); |
| 1334 process_->sink().ClearMessages(); |
| 1335 |
| 1336 SendInputEventACK(WebInputEvent::TouchMove, true); |
| 1337 EXPECT_EQ(0U, host_->TouchEventQueueSize()); |
| 1338 EXPECT_EQ(WebKit::WebInputEvent::TouchMove, view_->acked_event().type); |
| 1339 EXPECT_EQ(0U, process_->sink().message_count()); |
| 1340 } |
| 1341 |
| 1342 // Tests that the touch-queue is emptied if a page stops listening for touch |
| 1343 // events. |
| 1344 TEST_F(RenderWidgetHostTest, TouchEventQueueFlush) { |
| 1345 process_->sink().ClearMessages(); |
| 1346 |
| 1347 host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true)); |
| 1348 EXPECT_EQ(0U, process_->sink().message_count()); |
| 1349 EXPECT_EQ(0U, host_->TouchEventQueueSize()); |
| 1350 |
| 1351 EXPECT_EQ(0U, host_->TouchEventQueueSize()); |
| 1352 EXPECT_TRUE(host_->ShouldForwardTouchEvent()); |
| 1353 |
| 1354 // Send a touch-press event. |
| 1355 PressTouchPoint(1, 1); |
| 1356 SendTouchEvent(); |
| 1357 EXPECT_EQ(1U, process_->sink().message_count()); |
| 1358 process_->sink().ClearMessages(); |
| 1359 |
| 1360 ReleaseTouchPoint(0); |
| 1361 SendTouchEvent(); |
| 1362 |
| 1363 for (int i = 5; i < 15; ++i) { |
| 1364 PressTouchPoint(1, 1); |
| 1365 SendTouchEvent(); |
| 1366 MoveTouchPoint(0, i, i); |
| 1367 SendTouchEvent(); |
| 1368 ReleaseTouchPoint(0); |
| 1369 SendTouchEvent(); |
| 1370 } |
| 1371 EXPECT_EQ(0U, process_->sink().message_count()); |
| 1372 EXPECT_EQ(32U, host_->TouchEventQueueSize()); |
| 1373 |
| 1374 // Receive an ACK for the first touch-event. One of the queued touch-event |
| 1375 // should be forwarded. |
| 1376 SendInputEventACK(WebInputEvent::TouchStart, true); |
| 1377 EXPECT_EQ(31U, host_->TouchEventQueueSize()); |
| 1378 EXPECT_EQ(WebKit::WebInputEvent::TouchStart, view_->acked_event().type); |
| 1379 EXPECT_EQ(1U, process_->sink().message_count()); |
| 1380 process_->sink().ClearMessages(); |
| 1381 |
| 1382 // The page stops listening for touch-events. The touch-event queue should now |
| 1383 // be emptied, but none of the queued touch-events should be sent to the |
| 1384 // renderer. |
| 1385 host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false)); |
| 1386 EXPECT_EQ(0U, process_->sink().message_count()); |
| 1387 EXPECT_EQ(0U, host_->TouchEventQueueSize()); |
| 1388 EXPECT_FALSE(host_->ShouldForwardTouchEvent()); |
| 1389 } |
| 1390 |
| 1391 // Tests that touch-events are coalesced properly in the queue. |
| 1392 TEST_F(RenderWidgetHostTest, TouchEventQueueCoalesce) { |
| 1393 process_->sink().ClearMessages(); |
| 1394 |
| 1395 host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true)); |
| 1396 EXPECT_EQ(0U, process_->sink().message_count()); |
| 1397 EXPECT_EQ(0U, host_->TouchEventQueueSize()); |
| 1398 |
| 1399 EXPECT_EQ(0U, host_->TouchEventQueueSize()); |
| 1400 EXPECT_TRUE(host_->ShouldForwardTouchEvent()); |
| 1401 |
| 1402 // Send a touch-press event. |
| 1403 PressTouchPoint(1, 1); |
| 1404 SendTouchEvent(); |
| 1405 EXPECT_EQ(1U, process_->sink().message_count()); |
| 1406 process_->sink().ClearMessages(); |
| 1407 |
| 1408 // Send a few touch-move events, followed by a touch-release event. All the |
| 1409 // touch-move events should be coalesced into a single event. |
| 1410 for (int i = 5; i < 15; ++i) { |
| 1411 MoveTouchPoint(0, i, i); |
| 1412 SendTouchEvent(); |
| 1413 } |
| 1414 ReleaseTouchPoint(0); |
| 1415 SendTouchEvent(); |
| 1416 EXPECT_EQ(0U, process_->sink().message_count()); |
| 1417 EXPECT_EQ(3U, host_->TouchEventQueueSize()); |
| 1418 } |
| 1419 |
1241 // Test that the hang monitor timer expires properly if a new timer is started | 1420 // Test that the hang monitor timer expires properly if a new timer is started |
1242 // while one is in progress (see crbug.com/11007). | 1421 // while one is in progress (see crbug.com/11007). |
1243 TEST_F(RenderWidgetHostTest, DontPostponeHangMonitorTimeout) { | 1422 TEST_F(RenderWidgetHostTest, DontPostponeHangMonitorTimeout) { |
1244 // Start with a short timeout. | 1423 // Start with a short timeout. |
1245 host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10)); | 1424 host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10)); |
1246 | 1425 |
1247 // Immediately try to add a long 30 second timeout. | 1426 // Immediately try to add a long 30 second timeout. |
1248 EXPECT_FALSE(host_->unresponsive_timer_fired()); | 1427 EXPECT_FALSE(host_->unresponsive_timer_fired()); |
1249 host_->StartHangMonitorTimeout(TimeDelta::FromSeconds(30)); | 1428 host_->StartHangMonitorTimeout(TimeDelta::FromSeconds(30)); |
1250 | 1429 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1316 TEST_F(RenderWidgetHostTest, IncorrectBitmapScaleFactor) { | 1495 TEST_F(RenderWidgetHostTest, IncorrectBitmapScaleFactor) { |
1317 ViewHostMsg_UpdateRect_Params params; | 1496 ViewHostMsg_UpdateRect_Params params; |
1318 process_->InitUpdateRectParams(¶ms); | 1497 process_->InitUpdateRectParams(¶ms); |
1319 params.scale_factor = params.scale_factor * 2; | 1498 params.scale_factor = params.scale_factor * 2; |
1320 | 1499 |
1321 EXPECT_EQ(0, process_->bad_msg_count()); | 1500 EXPECT_EQ(0, process_->bad_msg_count()); |
1322 host_->OnMsgUpdateRect(params); | 1501 host_->OnMsgUpdateRect(params); |
1323 EXPECT_EQ(1, process_->bad_msg_count()); | 1502 EXPECT_EQ(1, process_->bad_msg_count()); |
1324 } | 1503 } |
1325 #endif | 1504 #endif |
OLD | NEW |