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 3 // found in the LICENSE file. 4 5 #include "base/basictypes.h" 6 #include "base/bind.h" 7 #include "base/command_line.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/shared_memory.h" 10 #include "base/timer/timer.h" 11 #include "content/browser/browser_thread_impl.h" 12 #include "content/browser/renderer_host/input/input_router_impl.h" 13 #include "content/browser/renderer_host/render_widget_host_delegate.h" 14 #include "content/browser/renderer_host/render_widget_host_view_base.h" 15 #include "content/common/input/synthetic_web_input_event_builders.h" 16 #include "content/common/input_messages.h" 17 #include "content/common/view_messages.h" 18 #include "content/public/common/content_switches.h" 19 #include "content/public/test/mock_render_process_host.h" 20 #include "content/public/test/test_browser_context.h" 21 #include "content/test/test_render_view_host.h" 22 #include "testing/gtest/include/gtest/gtest.h" 23 #include "ui/events/keycodes/keyboard_codes.h" 24 #include "ui/gfx/canvas.h" 25 #include "ui/gfx/screen.h" 26 27 #if defined(OS_ANDROID) 28 #include "content/browser/renderer_host/render_widget_host_view_android.h" 29 #endif 30 31 #if defined(USE_AURA) 32 #include "content/browser/compositor/image_transport_factory.h" 33 #include "content/browser/renderer_host/render_widget_host_view_aura.h" 34 #include "content/browser/renderer_host/ui_events_helper.h" 35 #include "ui/aura/env.h" 36 #include "ui/aura/test/test_screen.h" 37 #include "ui/compositor/test/in_process_context_factory.h" 38 #include "ui/events/event.h" 39 #endif 40 41 using base::TimeDelta; 42 using blink::WebGestureDevice; 43 using blink::WebGestureEvent; 44 using blink::WebInputEvent; 45 using blink::WebKeyboardEvent; 46 using blink::WebMouseEvent; 47 using blink::WebMouseWheelEvent; 48 using blink::WebTouchEvent; 49 using blink::WebTouchPoint; 50 51 namespace content { 52 53 // MockInputRouter ------------------------------------------------------------- 54 55 class MockInputRouter : public InputRouter { 56 public: 57 explicit MockInputRouter(InputRouterClient* client) 58 : send_event_called_(false), 59 sent_mouse_event_(false), 60 sent_wheel_event_(false), 61 sent_keyboard_event_(false), 62 sent_gesture_event_(false), 63 send_touch_event_not_cancelled_(false), 64 message_received_(false), 65 client_(client) { 66 } 67 virtual ~MockInputRouter() {} 68 69 // InputRouter 70 virtual void Flush() OVERRIDE { 71 flush_called_ = true; 72 } 73 virtual bool SendInput(scoped_ptr<IPC::Message> message) OVERRIDE { 74 send_event_called_ = true; 75 return true; 76 } 77 virtual void SendMouseEvent( 78 const MouseEventWithLatencyInfo& mouse_event) OVERRIDE { 79 sent_mouse_event_ = true; 80 } 81 virtual void SendWheelEvent( 82 const MouseWheelEventWithLatencyInfo& wheel_event) OVERRIDE { 83 sent_wheel_event_ = true; 84 } 85 virtual void SendKeyboardEvent( 86 const NativeWebKeyboardEvent& key_event, 87 const ui::LatencyInfo& latency_info, 88 bool is_shortcut) OVERRIDE { 89 sent_keyboard_event_ = true; 90 } 91 virtual void SendGestureEvent( 92 const GestureEventWithLatencyInfo& gesture_event) OVERRIDE { 93 sent_gesture_event_ = true; 94 } 95 virtual void SendTouchEvent( 96 const TouchEventWithLatencyInfo& touch_event) OVERRIDE { 97 send_touch_event_not_cancelled_ = 98 client_->FilterInputEvent(touch_event.event, touch_event.latency) == 99 INPUT_EVENT_ACK_STATE_NOT_CONSUMED; 100 } 101 virtual const NativeWebKeyboardEvent* GetLastKeyboardEvent() const OVERRIDE { 102 NOTREACHED(); 103 return NULL; 104 } 105 virtual bool ShouldForwardTouchEvent() const OVERRIDE { return true; } 106 virtual void OnViewUpdated(int view_flags) OVERRIDE {} 107 virtual bool HasPendingEvents() const OVERRIDE { return false; } 108 109 // IPC::Listener 110 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { 111 message_received_ = true; 112 return false; 113 } 114 115 bool flush_called_; 116 bool send_event_called_; 117 bool sent_mouse_event_; 118 bool sent_wheel_event_; 119 bool sent_keyboard_event_; 120 bool sent_gesture_event_; 121 bool send_touch_event_not_cancelled_; 122 bool message_received_; 123 124 private: 125 InputRouterClient* client_; 126 127 DISALLOW_COPY_AND_ASSIGN(MockInputRouter); 128 }; 129 130 // MockRenderWidgetHost ---------------------------------------------------- 131 132 class MockRenderWidgetHost : public RenderWidgetHostImpl { 133 public: 134 MockRenderWidgetHost( 135 RenderWidgetHostDelegate* delegate, 136 RenderProcessHost* process, 137 int routing_id) 138 : RenderWidgetHostImpl(delegate, process, routing_id, false), 139 unresponsive_timer_fired_(false) { 140 acked_touch_event_type_ = blink::WebInputEvent::Undefined; 141 } 142 143 // Allow poking at a few private members. 144 using RenderWidgetHostImpl::OnUpdateRect; 145 using RenderWidgetHostImpl::RendererExited; 146 using RenderWidgetHostImpl::last_requested_size_; 147 using RenderWidgetHostImpl::is_hidden_; 148 using RenderWidgetHostImpl::resize_ack_pending_; 149 using RenderWidgetHostImpl::input_router_; 150 151 virtual void OnTouchEventAck( 152 const TouchEventWithLatencyInfo& event, 153 InputEventAckState ack_result) OVERRIDE { 154 // Sniff touch acks. 155 acked_touch_event_type_ = event.event.type; 156 RenderWidgetHostImpl::OnTouchEventAck(event, ack_result); 157 } 158 159 bool unresponsive_timer_fired() const { 160 return unresponsive_timer_fired_; 161 } 162 163 void set_hung_renderer_delay_ms(int delay_ms) { 164 hung_renderer_delay_ms_ = delay_ms; 165 } 166 167 void DisableGestureDebounce() { 168 input_router_.reset(new InputRouterImpl( 169 process_, this, this, routing_id_, InputRouterImpl::Config())); 170 } 171 172 WebInputEvent::Type acked_touch_event_type() const { 173 return acked_touch_event_type_; 174 } 175 176 void SetupForInputRouterTest() { 177 input_router_.reset(new MockInputRouter(this)); 178 } 179 180 MockInputRouter* mock_input_router() { 181 return static_cast<MockInputRouter*>(input_router_.get()); 182 } 183 184 protected: 185 virtual void NotifyRendererUnresponsive() OVERRIDE { 186 unresponsive_timer_fired_ = true; 187 } 188 189 bool unresponsive_timer_fired_; 190 WebInputEvent::Type acked_touch_event_type_; 191 192 DISALLOW_COPY_AND_ASSIGN(MockRenderWidgetHost); 193 }; 194 195 namespace { 196 197 // RenderWidgetHostProcess ----------------------------------------------------- 198 199 class RenderWidgetHostProcess : public MockRenderProcessHost { 200 public: 201 explicit RenderWidgetHostProcess(BrowserContext* browser_context) 202 : MockRenderProcessHost(browser_context), 203 update_msg_should_reply_(false), 204 update_msg_reply_flags_(0) { 205 } 206 virtual ~RenderWidgetHostProcess() { 207 } 208 209 void set_update_msg_should_reply(bool reply) { 210 update_msg_should_reply_ = reply; 211 } 212 void set_update_msg_reply_flags(int flags) { 213 update_msg_reply_flags_ = flags; 214 } 215 216 // Fills the given update parameters with resonable default values. 217 void InitUpdateRectParams(ViewHostMsg_UpdateRect_Params* params); 218 219 virtual bool HasConnection() const OVERRIDE { return true; } 220 221 protected: 222 virtual bool WaitForBackingStoreMsg(int render_widget_id, 223 const base::TimeDelta& max_delay, 224 IPC::Message* msg) OVERRIDE; 225 226 // Set to true when WaitForBackingStoreMsg should return a successful update 227 // message reply. False implies timeout. 228 bool update_msg_should_reply_; 229 230 // Indicates the flags that should be sent with a repaint request. This 231 // only has an effect when update_msg_should_reply_ is true. 232 int update_msg_reply_flags_; 233 234 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostProcess); 235 }; 236 237 void RenderWidgetHostProcess::InitUpdateRectParams( 238 ViewHostMsg_UpdateRect_Params* params) { 239 const int w = 100, h = 100; 240 241 params->view_size = gfx::Size(w, h); 242 params->flags = update_msg_reply_flags_; 243 } 244 245 bool RenderWidgetHostProcess::WaitForBackingStoreMsg( 246 int render_widget_id, 247 const base::TimeDelta& max_delay, 248 IPC::Message* msg) { 249 if (!update_msg_should_reply_) 250 return false; 251 252 // Construct a fake update reply. 253 ViewHostMsg_UpdateRect_Params params; 254 InitUpdateRectParams(¶ms); 255 256 ViewHostMsg_UpdateRect message(render_widget_id, params); 257 *msg = message; 258 return true; 259 } 260 261 // TestView -------------------------------------------------------------------- 262 263 // This test view allows us to specify the size, and keep track of acked 264 // touch-events. 265 class TestView : public TestRenderWidgetHostView { 266 public: 267 explicit TestView(RenderWidgetHostImpl* rwh) 268 : TestRenderWidgetHostView(rwh), 269 unhandled_wheel_event_count_(0), 270 acked_event_count_(0), 271 gesture_event_type_(-1), 272 use_fake_physical_backing_size_(false), 273 ack_result_(INPUT_EVENT_ACK_STATE_UNKNOWN) { 274 } 275 276 // Sets the bounds returned by GetViewBounds. 277 void set_bounds(const gfx::Rect& bounds) { 278 bounds_ = bounds; 279 } 280 281 const WebTouchEvent& acked_event() const { return acked_event_; } 282 int acked_event_count() const { return acked_event_count_; } 283 void ClearAckedEvent() { 284 acked_event_.type = blink::WebInputEvent::Undefined; 285 acked_event_count_ = 0; 286 } 287 288 const WebMouseWheelEvent& unhandled_wheel_event() const { 289 return unhandled_wheel_event_; 290 } 291 int unhandled_wheel_event_count() const { 292 return unhandled_wheel_event_count_; 293 } 294 int gesture_event_type() const { return gesture_event_type_; } 295 InputEventAckState ack_result() const { return ack_result_; } 296 297 void SetMockPhysicalBackingSize(const gfx::Size& mock_physical_backing_size) { 298 use_fake_physical_backing_size_ = true; 299 mock_physical_backing_size_ = mock_physical_backing_size; 300 } 301 void ClearMockPhysicalBackingSize() { 302 use_fake_physical_backing_size_ = false; 303 } 304 305 // RenderWidgetHostView override. 306 virtual gfx::Rect GetViewBounds() const OVERRIDE { 307 return bounds_; 308 } 309 virtual void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch, 310 InputEventAckState ack_result) OVERRIDE { 311 acked_event_ = touch.event; 312 ++acked_event_count_; 313 } 314 virtual void WheelEventAck(const WebMouseWheelEvent& event, 315 InputEventAckState ack_result) OVERRIDE { 316 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) 317 return; 318 unhandled_wheel_event_count_++; 319 unhandled_wheel_event_ = event; 320 } 321 virtual void GestureEventAck(const WebGestureEvent& event, 322 InputEventAckState ack_result) OVERRIDE { 323 gesture_event_type_ = event.type; 324 ack_result_ = ack_result; 325 } 326 virtual gfx::Size GetPhysicalBackingSize() const OVERRIDE { 327 if (use_fake_physical_backing_size_) 328 return mock_physical_backing_size_; 329 return TestRenderWidgetHostView::GetPhysicalBackingSize(); 330 } 331 #if defined(USE_AURA) 332 virtual ~TestView() { 333 // Simulate the mouse exit event dispatched when an aura window is 334 // destroyed. (MakeWebMouseEventFromAuraEvent translates ET_MOUSE_EXITED 335 // into WebInputEvent::MouseMove.) 336 rwh_->input_router()->SendMouseEvent( 337 MouseEventWithLatencyInfo( 338 SyntheticWebMouseEventBuilder::Build(WebInputEvent::MouseMove), 339 ui::LatencyInfo())); 340 } 341 #endif 342 343 protected: 344 WebMouseWheelEvent unhandled_wheel_event_; 345 int unhandled_wheel_event_count_; 346 WebTouchEvent acked_event_; 347 int acked_event_count_; 348 int gesture_event_type_; 349 gfx::Rect bounds_; 350 bool use_fake_physical_backing_size_; 351 gfx::Size mock_physical_backing_size_; 352 InputEventAckState ack_result_; 353 354 DISALLOW_COPY_AND_ASSIGN(TestView); 355 }; 356 357 // MockRenderWidgetHostDelegate -------------------------------------------- 358 359 class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate { 360 public: 361 MockRenderWidgetHostDelegate() 362 : prehandle_keyboard_event_(false), 363 prehandle_keyboard_event_called_(false), 364 prehandle_keyboard_event_type_(WebInputEvent::Undefined), 365 unhandled_keyboard_event_called_(false), 366 unhandled_keyboard_event_type_(WebInputEvent::Undefined), 367 handle_wheel_event_(false), 368 handle_wheel_event_called_(false) { 369 } 370 virtual ~MockRenderWidgetHostDelegate() {} 371 372 // Tests that make sure we ignore keyboard event acknowledgments to events we 373 // didn't send work by making sure we didn't call UnhandledKeyboardEvent(). 374 bool unhandled_keyboard_event_called() const { 375 return unhandled_keyboard_event_called_; 376 } 377 378 WebInputEvent::Type unhandled_keyboard_event_type() const { 379 return unhandled_keyboard_event_type_; 380 } 381 382 bool prehandle_keyboard_event_called() const { 383 return prehandle_keyboard_event_called_; 384 } 385 386 WebInputEvent::Type prehandle_keyboard_event_type() const { 387 return prehandle_keyboard_event_type_; 388 } 389 390 void set_prehandle_keyboard_event(bool handle) { 391 prehandle_keyboard_event_ = handle; 392 } 393 394 void set_handle_wheel_event(bool handle) { 395 handle_wheel_event_ = handle; 396 } 397 398 bool handle_wheel_event_called() { 399 return handle_wheel_event_called_; 400 } 401 402 protected: 403 virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, 404 bool* is_keyboard_shortcut) OVERRIDE { 405 prehandle_keyboard_event_type_ = event.type; 406 prehandle_keyboard_event_called_ = true; 407 return prehandle_keyboard_event_; 408 } 409 410 virtual void HandleKeyboardEvent( 411 const NativeWebKeyboardEvent& event) OVERRIDE { 412 unhandled_keyboard_event_type_ = event.type; 413 unhandled_keyboard_event_called_ = true; 414 } 415 416 virtual bool HandleWheelEvent( 417 const blink::WebMouseWheelEvent& event) OVERRIDE { 418 handle_wheel_event_called_ = true; 419 return handle_wheel_event_; 420 } 421 422 private: 423 bool prehandle_keyboard_event_; 424 bool prehandle_keyboard_event_called_; 425 WebInputEvent::Type prehandle_keyboard_event_type_; 426 427 bool unhandled_keyboard_event_called_; 428 WebInputEvent::Type unhandled_keyboard_event_type_; 429 430 bool handle_wheel_event_; 431 bool handle_wheel_event_called_; 432 }; 433 434 // RenderWidgetHostTest -------------------------------------------------------- 435 436 class RenderWidgetHostTest : public testing::Test { 437 public: 438 RenderWidgetHostTest() 439 : process_(NULL), 440 handle_key_press_event_(false), 441 handle_mouse_event_(false), 442 simulated_event_time_delta_seconds_(0) { 443 last_simulated_event_time_seconds_ = 444 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); 445 } 446 virtual ~RenderWidgetHostTest() { 447 } 448 449 bool KeyPressEventCallback(const NativeWebKeyboardEvent& /* event */) { 450 return handle_key_press_event_; 451 } 452 bool MouseEventCallback(const blink::WebMouseEvent& /* event */) { 453 return handle_mouse_event_; 454 } 455 456 protected: 457 // testing::Test 458 virtual void SetUp() { 459 CommandLine* command_line = CommandLine::ForCurrentProcess(); 460 command_line->AppendSwitch(switches::kValidateInputEventStream); 461 462 browser_context_.reset(new TestBrowserContext()); 463 delegate_.reset(new MockRenderWidgetHostDelegate()); 464 process_ = new RenderWidgetHostProcess(browser_context_.get()); 465 #if defined(USE_AURA) 466 ImageTransportFactory::InitializeForUnitTests( 467 scoped_ptr<ui::ContextFactory>(new ui::InProcessContextFactory)); 468 aura::Env::CreateInstance(true); 469 screen_.reset(aura::TestScreen::Create(gfx::Size())); 470 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get()); 471 #endif 472 host_.reset( 473 new MockRenderWidgetHost(delegate_.get(), process_, MSG_ROUTING_NONE)); 474 view_.reset(new TestView(host_.get())); 475 host_->SetView(view_.get()); 476 host_->Init(); 477 host_->DisableGestureDebounce(); 478 } 479 virtual void TearDown() { 480 view_.reset(); 481 host_.reset(); 482 delegate_.reset(); 483 process_ = NULL; 484 browser_context_.reset(); 485 486 #if defined(USE_AURA) 487 aura::Env::DeleteInstance(); 488 screen_.reset(); 489 ImageTransportFactory::Terminate(); 490 #endif 491 492 // Process all pending tasks to avoid leaks. 493 base::MessageLoop::current()->RunUntilIdle(); 494 } 495 496 int64 GetLatencyComponentId() { 497 return host_->GetLatencyComponentId(); 498 } 499 500 void SendInputEventACK(WebInputEvent::Type type, 501 InputEventAckState ack_result) { 502 InputHostMsg_HandleInputEvent_ACK_Params ack; 503 ack.type = type; 504 ack.state = ack_result; 505 host_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack)); 506 } 507 508 double GetNextSimulatedEventTimeSeconds() { 509 last_simulated_event_time_seconds_ += simulated_event_time_delta_seconds_; 510 return last_simulated_event_time_seconds_; 511 } 512 513 void SimulateKeyboardEvent(WebInputEvent::Type type) { 514 SimulateKeyboardEvent(type, 0); 515 } 516 517 void SimulateKeyboardEvent(WebInputEvent::Type type, int modifiers) { 518 WebKeyboardEvent event = SyntheticWebKeyboardEventBuilder::Build(type); 519 event.modifiers = modifiers; 520 NativeWebKeyboardEvent native_event; 521 memcpy(&native_event, &event, sizeof(event)); 522 host_->ForwardKeyboardEvent(native_event); 523 } 524 525 void SimulateMouseEvent(WebInputEvent::Type type) { 526 host_->ForwardMouseEvent(SyntheticWebMouseEventBuilder::Build(type)); 527 } 528 529 void SimulateMouseEventWithLatencyInfo(WebInputEvent::Type type, 530 const ui::LatencyInfo& ui_latency) { 531 host_->ForwardMouseEventWithLatencyInfo( 532 SyntheticWebMouseEventBuilder::Build(type), 533 ui_latency); 534 } 535 536 void SimulateWheelEvent(float dX, float dY, int modifiers, bool precise) { 537 host_->ForwardWheelEvent( 538 SyntheticWebMouseWheelEventBuilder::Build(dX, dY, modifiers, precise)); 539 } 540 541 void SimulateWheelEventWithLatencyInfo(float dX, 542 float dY, 543 int modifiers, 544 bool precise, 545 const ui::LatencyInfo& ui_latency) { 546 host_->ForwardWheelEventWithLatencyInfo( 547 SyntheticWebMouseWheelEventBuilder::Build(dX, dY, modifiers, precise), 548 ui_latency); 549 } 550 551 void SimulateMouseMove(int x, int y, int modifiers) { 552 SimulateMouseEvent(WebInputEvent::MouseMove, x, y, modifiers, false); 553 } 554 555 void SimulateMouseEvent( 556 WebInputEvent::Type type, int x, int y, int modifiers, bool pressed) { 557 WebMouseEvent event = 558 SyntheticWebMouseEventBuilder::Build(type, x, y, modifiers); 559 if (pressed) 560 event.button = WebMouseEvent::ButtonLeft; 561 event.timeStampSeconds = GetNextSimulatedEventTimeSeconds(); 562 host_->ForwardMouseEvent(event); 563 } 564 565 // Inject simple synthetic WebGestureEvent instances. 566 void SimulateGestureEvent(WebInputEvent::Type type, 567 WebGestureDevice sourceDevice) { 568 host_->ForwardGestureEvent( 569 SyntheticWebGestureEventBuilder::Build(type, sourceDevice)); 570 } 571 572 void SimulateGestureEventWithLatencyInfo(WebInputEvent::Type type, 573 WebGestureDevice sourceDevice, 574 const ui::LatencyInfo& ui_latency) { 575 host_->ForwardGestureEventWithLatencyInfo( 576 SyntheticWebGestureEventBuilder::Build(type, sourceDevice), 577 ui_latency); 578 } 579 580 // Set the timestamp for the touch-event. 581 void SetTouchTimestamp(base::TimeDelta timestamp) { 582 touch_event_.SetTimestamp(timestamp); 583 } 584 585 // Sends a touch event (irrespective of whether the page has a touch-event 586 // handler or not). 587 void SendTouchEvent() { 588 host_->ForwardTouchEventWithLatencyInfo(touch_event_, ui::LatencyInfo()); 589 590 touch_event_.ResetPoints(); 591 } 592 593 int PressTouchPoint(int x, int y) { 594 return touch_event_.PressPoint(x, y); 595 } 596 597 void MoveTouchPoint(int index, int x, int y) { 598 touch_event_.MovePoint(index, x, y); 599 } 600 601 void ReleaseTouchPoint(int index) { 602 touch_event_.ReleasePoint(index); 603 } 604 605 const WebInputEvent* GetInputEventFromMessage(const IPC::Message& message) { 606 PickleIterator iter(message); 607 const char* data; 608 int data_length; 609 if (!message.ReadData(&iter, &data, &data_length)) 610 return NULL; 611 return reinterpret_cast<const WebInputEvent*>(data); 612 } 613 614 base::MessageLoopForUI message_loop_; 615 616 scoped_ptr<TestBrowserContext> browser_context_; 617 RenderWidgetHostProcess* process_; // Deleted automatically by the widget. 618 scoped_ptr<MockRenderWidgetHostDelegate> delegate_; 619 scoped_ptr<MockRenderWidgetHost> host_; 620 scoped_ptr<TestView> view_; 621 scoped_ptr<gfx::Screen> screen_; 622 bool handle_key_press_event_; 623 bool handle_mouse_event_; 624 double last_simulated_event_time_seconds_; 625 double simulated_event_time_delta_seconds_; 626 627 private: 628 SyntheticWebTouchEvent touch_event_; 629 630 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostTest); 631 }; 632 633 #if GTEST_HAS_PARAM_TEST 634 // RenderWidgetHostWithSourceTest ---------------------------------------------- 635 636 // This is for tests that are to be run for all source devices. 637 class RenderWidgetHostWithSourceTest 638 : public RenderWidgetHostTest, 639 public testing::WithParamInterface<WebGestureDevice> {}; 640 #endif // GTEST_HAS_PARAM_TEST 641 642 } // namespace 643 644 // ----------------------------------------------------------------------------- 645 646 TEST_F(RenderWidgetHostTest, Resize) { 647 // The initial bounds is the empty rect, and the screen info hasn't been sent 648 // yet, so setting it to the same thing shouldn't send the resize message. 649 view_->set_bounds(gfx::Rect()); 650 host_->WasResized(); 651 EXPECT_FALSE(host_->resize_ack_pending_); 652 EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); 653 654 // Setting the bounds to a "real" rect should send out the notification. 655 // but should not expect ack for empty physical backing size. 656 gfx::Rect original_size(0, 0, 100, 100); 657 process_->sink().ClearMessages(); 658 view_->set_bounds(original_size); 659 view_->SetMockPhysicalBackingSize(gfx::Size()); 660 host_->WasResized(); 661 EXPECT_FALSE(host_->resize_ack_pending_); 662 EXPECT_EQ(original_size.size(), host_->last_requested_size_); 663 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); 664 665 // Setting the bounds to a "real" rect should send out the notification. 666 // but should not expect ack for only physical backing size change. 667 process_->sink().ClearMessages(); 668 view_->ClearMockPhysicalBackingSize(); 669 host_->WasResized(); 670 EXPECT_FALSE(host_->resize_ack_pending_); 671 EXPECT_EQ(original_size.size(), host_->last_requested_size_); 672 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); 673 674 // Send out a update that's not a resize ack after setting resize ack pending 675 // flag. This should not clean the resize ack pending flag. 676 process_->sink().ClearMessages(); 677 gfx::Rect second_size(0, 0, 110, 110); 678 EXPECT_FALSE(host_->resize_ack_pending_); 679 view_->set_bounds(second_size); 680 host_->WasResized(); 681 EXPECT_TRUE(host_->resize_ack_pending_); 682 ViewHostMsg_UpdateRect_Params params; 683 process_->InitUpdateRectParams(¶ms); 684 host_->OnUpdateRect(params); 685 EXPECT_TRUE(host_->resize_ack_pending_); 686 EXPECT_EQ(second_size.size(), host_->last_requested_size_); 687 688 // Sending out a new notification should NOT send out a new IPC message since 689 // a resize ACK is pending. 690 gfx::Rect third_size(0, 0, 120, 120); 691 process_->sink().ClearMessages(); 692 view_->set_bounds(third_size); 693 host_->WasResized(); 694 EXPECT_TRUE(host_->resize_ack_pending_); 695 EXPECT_EQ(second_size.size(), host_->last_requested_size_); 696 EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); 697 698 // Send a update that's a resize ack, but for the original_size we sent. Since 699 // this isn't the second_size, the message handler should immediately send 700 // a new resize message for the new size to the renderer. 701 process_->sink().ClearMessages(); 702 params.flags = ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK; 703 params.view_size = original_size.size(); 704 host_->OnUpdateRect(params); 705 EXPECT_TRUE(host_->resize_ack_pending_); 706 EXPECT_EQ(third_size.size(), host_->last_requested_size_); 707 ASSERT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); 708 709 // Send the resize ack for the latest size. 710 process_->sink().ClearMessages(); 711 params.view_size = third_size.size(); 712 host_->OnUpdateRect(params); 713 EXPECT_FALSE(host_->resize_ack_pending_); 714 EXPECT_EQ(third_size.size(), host_->last_requested_size_); 715 ASSERT_FALSE(process_->sink().GetFirstMessageMatching(ViewMsg_Resize::ID)); 716 717 // Now clearing the bounds should send out a notification but we shouldn't 718 // expect a resize ack (since the renderer won't ack empty sizes). The message 719 // should contain the new size (0x0) and not the previous one that we skipped 720 process_->sink().ClearMessages(); 721 view_->set_bounds(gfx::Rect()); 722 host_->WasResized(); 723 EXPECT_FALSE(host_->resize_ack_pending_); 724 EXPECT_EQ(gfx::Size(), host_->last_requested_size_); 725 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); 726 727 // Send a rect that has no area but has either width or height set. 728 process_->sink().ClearMessages(); 729 view_->set_bounds(gfx::Rect(0, 0, 0, 30)); 730 host_->WasResized(); 731 EXPECT_FALSE(host_->resize_ack_pending_); 732 EXPECT_EQ(gfx::Size(0, 30), host_->last_requested_size_); 733 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); 734 735 // Set the same size again. It should not be sent again. 736 process_->sink().ClearMessages(); 737 host_->WasResized(); 738 EXPECT_FALSE(host_->resize_ack_pending_); 739 EXPECT_EQ(gfx::Size(0, 30), host_->last_requested_size_); 740 EXPECT_FALSE(process_->sink().GetFirstMessageMatching(ViewMsg_Resize::ID)); 741 742 // A different size should be sent again, however. 743 view_->set_bounds(gfx::Rect(0, 0, 0, 31)); 744 host_->WasResized(); 745 EXPECT_FALSE(host_->resize_ack_pending_); 746 EXPECT_EQ(gfx::Size(0, 31), host_->last_requested_size_); 747 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); 748 } 749 750 // Test for crbug.com/25097. If a renderer crashes between a resize and the 751 // corresponding update message, we must be sure to clear the resize ack logic. 752 TEST_F(RenderWidgetHostTest, ResizeThenCrash) { 753 // Clear the first Resize message that carried screen info. 754 process_->sink().ClearMessages(); 755 756 // Setting the bounds to a "real" rect should send out the notification. 757 gfx::Rect original_size(0, 0, 100, 100); 758 view_->set_bounds(original_size); 759 host_->WasResized(); 760 EXPECT_TRUE(host_->resize_ack_pending_); 761 EXPECT_EQ(original_size.size(), host_->last_requested_size_); 762 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); 763 764 // Simulate a renderer crash before the update message. Ensure all the 765 // resize ack logic is cleared. Must clear the view first so it doesn't get 766 // deleted. 767 host_->SetView(NULL); 768 host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1); 769 EXPECT_FALSE(host_->resize_ack_pending_); 770 EXPECT_EQ(gfx::Size(), host_->last_requested_size_); 771 772 // Reset the view so we can exit the test cleanly. 773 host_->SetView(view_.get()); 774 } 775 776 // Unable to include render_widget_host_view_mac.h and compile. 777 #if !defined(OS_MACOSX) 778 // Tests setting background transparency. 779 TEST_F(RenderWidgetHostTest, Background) { 780 scoped_ptr<RenderWidgetHostViewBase> view; 781 #if defined(USE_AURA) 782 view.reset(new RenderWidgetHostViewAura(host_.get())); 783 // TODO(derat): Call this on all platforms: http://crbug.com/102450. 784 view->InitAsChild(NULL); 785 #elif defined(OS_ANDROID) 786 view.reset(new RenderWidgetHostViewAndroid(host_.get(), NULL)); 787 #endif 788 host_->SetView(view.get()); 789 790 EXPECT_TRUE(view->GetBackgroundOpaque()); 791 view->SetBackgroundOpaque(false); 792 EXPECT_FALSE(view->GetBackgroundOpaque()); 793 794 const IPC::Message* set_background = 795 process_->sink().GetUniqueMessageMatching( 796 ViewMsg_SetBackgroundOpaque::ID); 797 ASSERT_TRUE(set_background); 798 Tuple1<bool> sent_background; 799 ViewMsg_SetBackgroundOpaque::Read(set_background, &sent_background); 800 EXPECT_FALSE(sent_background.a); 801 802 #if defined(USE_AURA) 803 // See the comment above |InitAsChild(NULL)|. 804 host_->SetView(NULL); 805 static_cast<RenderWidgetHostViewBase*>(view.release())->Destroy(); 806 #endif 807 } 808 #endif 809 810 // Test that we don't paint when we're hidden, but we still send the ACK. Most 811 // of the rest of the painting is tested in the GetBackingStore* ones. 812 TEST_F(RenderWidgetHostTest, HiddenPaint) { 813 BrowserThreadImpl ui_thread(BrowserThread::UI, base::MessageLoop::current()); 814 // Hide the widget, it should have sent out a message to the renderer. 815 EXPECT_FALSE(host_->is_hidden_); 816 host_->WasHidden(); 817 EXPECT_TRUE(host_->is_hidden_); 818 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_WasHidden::ID)); 819 820 // Send it an update as from the renderer. 821 process_->sink().ClearMessages(); 822 ViewHostMsg_UpdateRect_Params params; 823 process_->InitUpdateRectParams(¶ms); 824 host_->OnUpdateRect(params); 825 826 // Now unhide. 827 process_->sink().ClearMessages(); 828 host_->WasShown(); 829 EXPECT_FALSE(host_->is_hidden_); 830 831 // It should have sent out a restored message with a request to paint. 832 const IPC::Message* restored = process_->sink().GetUniqueMessageMatching( 833 ViewMsg_WasShown::ID); 834 ASSERT_TRUE(restored); 835 Tuple1<bool> needs_repaint; 836 ViewMsg_WasShown::Read(restored, &needs_repaint); 837 EXPECT_TRUE(needs_repaint.a); 838 } 839 840 TEST_F(RenderWidgetHostTest, IgnoreKeyEventsHandledByRenderer) { 841 // Simulate a keyboard event. 842 SimulateKeyboardEvent(WebInputEvent::RawKeyDown); 843 844 // Make sure we sent the input event to the renderer. 845 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching( 846 InputMsg_HandleInputEvent::ID)); 847 process_->sink().ClearMessages(); 848 849 // Send the simulated response from the renderer back. 850 SendInputEventACK(WebInputEvent::RawKeyDown, 851 INPUT_EVENT_ACK_STATE_CONSUMED); 852 EXPECT_FALSE(delegate_->unhandled_keyboard_event_called()); 853 } 854 855 TEST_F(RenderWidgetHostTest, PreHandleRawKeyDownEvent) { 856 // Simluate the situation that the browser handled the key down event during 857 // pre-handle phrase. 858 delegate_->set_prehandle_keyboard_event(true); 859 process_->sink().ClearMessages(); 860 861 // Simulate a keyboard event. 862 SimulateKeyboardEvent(WebInputEvent::RawKeyDown); 863 864 EXPECT_TRUE(delegate_->prehandle_keyboard_event_called()); 865 EXPECT_EQ(WebInputEvent::RawKeyDown, 866 delegate_->prehandle_keyboard_event_type()); 867 868 // Make sure the RawKeyDown event is not sent to the renderer. 869 EXPECT_EQ(0U, process_->sink().message_count()); 870 871 // The browser won't pre-handle a Char event. 872 delegate_->set_prehandle_keyboard_event(false); 873 874 // Forward the Char event. 875 SimulateKeyboardEvent(WebInputEvent::Char); 876 877 // Make sure the Char event is suppressed. 878 EXPECT_EQ(0U, process_->sink().message_count()); 879 880 // Forward the KeyUp event. 881 SimulateKeyboardEvent(WebInputEvent::KeyUp); 882 883 // Make sure only KeyUp was sent to the renderer. 884 EXPECT_EQ(1U, process_->sink().message_count()); 885 EXPECT_EQ(InputMsg_HandleInputEvent::ID, 886 process_->sink().GetMessageAt(0)->type()); 887 process_->sink().ClearMessages(); 888 889 // Send the simulated response from the renderer back. 890 SendInputEventACK(WebInputEvent::KeyUp, 891 INPUT_EVENT_ACK_STATE_NOT_CONSUMED); 892 893 EXPECT_TRUE(delegate_->unhandled_keyboard_event_called()); 894 EXPECT_EQ(WebInputEvent::KeyUp, delegate_->unhandled_keyboard_event_type()); 895 } 896 897 TEST_F(RenderWidgetHostTest, UnhandledWheelEvent) { 898 SimulateWheelEvent(-5, 0, 0, true); 899 900 // Make sure we sent the input event to the renderer. 901 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching( 902 InputMsg_HandleInputEvent::ID)); 903 process_->sink().ClearMessages(); 904 905 // Send the simulated response from the renderer back. 906 SendInputEventACK(WebInputEvent::MouseWheel, 907 INPUT_EVENT_ACK_STATE_NOT_CONSUMED); 908 EXPECT_TRUE(delegate_->handle_wheel_event_called()); 909 EXPECT_EQ(1, view_->unhandled_wheel_event_count()); 910 EXPECT_EQ(-5, view_->unhandled_wheel_event().deltaX); 911 } 912 913 TEST_F(RenderWidgetHostTest, HandleWheelEvent) { 914 // Indicate that we're going to handle this wheel event 915 delegate_->set_handle_wheel_event(true); 916 917 SimulateWheelEvent(-5, 0, 0, true); 918 919 // Make sure we sent the input event to the renderer. 920 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching( 921 InputMsg_HandleInputEvent::ID)); 922 process_->sink().ClearMessages(); 923 924 // Send the simulated response from the renderer back. 925 SendInputEventACK(WebInputEvent::MouseWheel, 926 INPUT_EVENT_ACK_STATE_NOT_CONSUMED); 927 928 // ensure the wheel event handler was invoked 929 EXPECT_TRUE(delegate_->handle_wheel_event_called()); 930 931 // and that it suppressed the unhandled wheel event handler. 932 EXPECT_EQ(0, view_->unhandled_wheel_event_count()); 933 } 934 935 TEST_F(RenderWidgetHostTest, UnhandledGestureEvent) { 936 SimulateGestureEvent(WebInputEvent::GestureTwoFingerTap, 937 blink::WebGestureDeviceTouchscreen); 938 939 // Make sure we sent the input event to the renderer. 940 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching( 941 InputMsg_HandleInputEvent::ID)); 942 process_->sink().ClearMessages(); 943 944 // Send the simulated response from the renderer back. 945 SendInputEventACK(WebInputEvent::GestureTwoFingerTap, 946 INPUT_EVENT_ACK_STATE_NOT_CONSUMED); 947 EXPECT_EQ(WebInputEvent::GestureTwoFingerTap, view_->gesture_event_type()); 948 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, view_->ack_result()); 949 } 950 951 // Test that the hang monitor timer expires properly if a new timer is started 952 // while one is in progress (see crbug.com/11007). 953 TEST_F(RenderWidgetHostTest, DontPostponeHangMonitorTimeout) { 954 // Start with a short timeout. 955 host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10)); 956 957 // Immediately try to add a long 30 second timeout. 958 EXPECT_FALSE(host_->unresponsive_timer_fired()); 959 host_->StartHangMonitorTimeout(TimeDelta::FromSeconds(30)); 960 961 // Wait long enough for first timeout and see if it fired. 962 base::MessageLoop::current()->PostDelayedTask( 963 FROM_HERE, 964 base::MessageLoop::QuitClosure(), 965 TimeDelta::FromMilliseconds(10)); 966 base::MessageLoop::current()->Run(); 967 EXPECT_TRUE(host_->unresponsive_timer_fired()); 968 } 969 970 // Test that the hang monitor timer expires properly if it is started, stopped, 971 // and then started again. 972 TEST_F(RenderWidgetHostTest, StopAndStartHangMonitorTimeout) { 973 // Start with a short timeout, then stop it. 974 host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10)); 975 host_->StopHangMonitorTimeout(); 976 977 // Start it again to ensure it still works. 978 EXPECT_FALSE(host_->unresponsive_timer_fired()); 979 host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10)); 980 981 // Wait long enough for first timeout and see if it fired. 982 base::MessageLoop::current()->PostDelayedTask( 983 FROM_HERE, 984 base::MessageLoop::QuitClosure(), 985 TimeDelta::FromMilliseconds(40)); 986 base::MessageLoop::current()->Run(); 987 EXPECT_TRUE(host_->unresponsive_timer_fired()); 988 } 989 990 // Test that the hang monitor timer expires properly if it is started, then 991 // updated to a shorter duration. 992 TEST_F(RenderWidgetHostTest, ShorterDelayHangMonitorTimeout) { 993 // Start with a timeout. 994 host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(100)); 995 996 // Start it again with shorter delay. 997 EXPECT_FALSE(host_->unresponsive_timer_fired()); 998 host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(20)); 999 1000 // Wait long enough for the second timeout and see if it fired. 1001 base::MessageLoop::current()->PostDelayedTask( 1002 FROM_HERE, 1003 base::MessageLoop::QuitClosure(), 1004 TimeDelta::FromMilliseconds(25)); 1005 base::MessageLoop::current()->Run(); 1006 EXPECT_TRUE(host_->unresponsive_timer_fired()); 1007 } 1008 1009 // Test that the hang monitor catches two input events but only one ack. 1010 // This can happen if the second input event causes the renderer to hang. 1011 // This test will catch a regression of crbug.com/111185. 1012 TEST_F(RenderWidgetHostTest, MultipleInputEvents) { 1013 // Configure the host to wait 10ms before considering 1014 // the renderer hung. 1015 host_->set_hung_renderer_delay_ms(10); 1016 1017 // Send two events but only one ack. 1018 SimulateKeyboardEvent(WebInputEvent::RawKeyDown); 1019 SimulateKeyboardEvent(WebInputEvent::RawKeyDown); 1020 SendInputEventACK(WebInputEvent::RawKeyDown, 1021 INPUT_EVENT_ACK_STATE_CONSUMED); 1022 1023 // Wait long enough for first timeout and see if it fired. 1024 base::MessageLoop::current()->PostDelayedTask( 1025 FROM_HERE, 1026 base::MessageLoop::QuitClosure(), 1027 TimeDelta::FromMilliseconds(40)); 1028 base::MessageLoop::current()->Run(); 1029 EXPECT_TRUE(host_->unresponsive_timer_fired()); 1030 } 1031 1032 std::string GetInputMessageTypes(RenderWidgetHostProcess* process) { 1033 std::string result; 1034 for (size_t i = 0; i < process->sink().message_count(); ++i) { 1035 const IPC::Message *message = process->sink().GetMessageAt(i); 1036 EXPECT_EQ(InputMsg_HandleInputEvent::ID, message->type()); 1037 InputMsg_HandleInputEvent::Param params; 1038 EXPECT_TRUE(InputMsg_HandleInputEvent::Read(message, ¶ms)); 1039 const WebInputEvent* event = params.a; 1040 if (i != 0) 1041 result += " "; 1042 result += WebInputEventTraits::GetName(event->type); 1043 } 1044 process->sink().ClearMessages(); 1045 return result; 1046 } 1047 1048 TEST_F(RenderWidgetHostTest, TouchEmulator) { 1049 simulated_event_time_delta_seconds_ = 0.1; 1050 // Immediately ack all touches instead of sending them to the renderer. 1051 host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false)); 1052 host_->OnMessageReceived( 1053 ViewHostMsg_SetTouchEventEmulationEnabled(0, true, true)); 1054 process_->sink().ClearMessages(); 1055 view_->set_bounds(gfx::Rect(0, 0, 400, 200)); 1056 view_->Show(); 1057 1058 SimulateMouseEvent(WebInputEvent::MouseMove, 10, 10, 0, false); 1059 EXPECT_EQ(0U, process_->sink().message_count()); 1060 1061 // Mouse press becomes touch start which in turn becomes tap. 1062 SimulateMouseEvent(WebInputEvent::MouseDown, 10, 10, 0, true); 1063 EXPECT_EQ(WebInputEvent::TouchStart, host_->acked_touch_event_type()); 1064 EXPECT_EQ("GestureTapDown", GetInputMessageTypes(process_)); 1065 1066 // Mouse drag generates touch move, cancels tap and starts scroll. 1067 SimulateMouseEvent(WebInputEvent::MouseMove, 10, 30, 0, true); 1068 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); 1069 EXPECT_EQ( 1070 "GestureTapCancel GestureScrollBegin GestureScrollUpdate", 1071 GetInputMessageTypes(process_)); 1072 SendInputEventACK(WebInputEvent::GestureScrollUpdate, 1073 INPUT_EVENT_ACK_STATE_CONSUMED); 1074 EXPECT_EQ(0U, process_->sink().message_count()); 1075 1076 // Mouse drag with shift becomes pinch. 1077 SimulateMouseEvent( 1078 WebInputEvent::MouseMove, 10, 40, WebInputEvent::ShiftKey, true); 1079 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); 1080 EXPECT_EQ("GesturePinchBegin", 1081 GetInputMessageTypes(process_)); 1082 EXPECT_EQ(0U, process_->sink().message_count()); 1083 1084 SimulateMouseEvent( 1085 WebInputEvent::MouseMove, 10, 50, WebInputEvent::ShiftKey, true); 1086 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); 1087 EXPECT_EQ("GesturePinchUpdate", 1088 GetInputMessageTypes(process_)); 1089 SendInputEventACK(WebInputEvent::GesturePinchUpdate, 1090 INPUT_EVENT_ACK_STATE_CONSUMED); 1091 EXPECT_EQ(0U, process_->sink().message_count()); 1092 1093 // Mouse drag without shift becomes scroll again. 1094 SimulateMouseEvent(WebInputEvent::MouseMove, 10, 60, 0, true); 1095 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); 1096 EXPECT_EQ("GesturePinchEnd GestureScrollUpdate", 1097 GetInputMessageTypes(process_)); 1098 SendInputEventACK(WebInputEvent::GestureScrollUpdate, 1099 INPUT_EVENT_ACK_STATE_CONSUMED); 1100 EXPECT_EQ(0U, process_->sink().message_count()); 1101 1102 SimulateMouseEvent(WebInputEvent::MouseMove, 10, 70, 0, true); 1103 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); 1104 EXPECT_EQ("GestureScrollUpdate", 1105 GetInputMessageTypes(process_)); 1106 SendInputEventACK(WebInputEvent::GestureScrollUpdate, 1107 INPUT_EVENT_ACK_STATE_CONSUMED); 1108 EXPECT_EQ(0U, process_->sink().message_count()); 1109 1110 SimulateMouseEvent(WebInputEvent::MouseUp, 10, 70, 0, true); 1111 EXPECT_EQ(WebInputEvent::TouchEnd, host_->acked_touch_event_type()); 1112 EXPECT_EQ("GestureScrollEnd", GetInputMessageTypes(process_)); 1113 EXPECT_EQ(0U, process_->sink().message_count()); 1114 1115 // Mouse move does nothing. 1116 SimulateMouseEvent(WebInputEvent::MouseMove, 10, 80, 0, false); 1117 EXPECT_EQ(0U, process_->sink().message_count()); 1118 1119 // Another mouse down continues scroll. 1120 SimulateMouseEvent(WebInputEvent::MouseDown, 10, 80, 0, true); 1121 EXPECT_EQ(WebInputEvent::TouchStart, host_->acked_touch_event_type()); 1122 EXPECT_EQ("GestureTapDown", GetInputMessageTypes(process_)); 1123 EXPECT_EQ(0U, process_->sink().message_count()); 1124 1125 SimulateMouseEvent(WebInputEvent::MouseMove, 10, 100, 0, true); 1126 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); 1127 EXPECT_EQ( 1128 "GestureTapCancel GestureScrollBegin GestureScrollUpdate", 1129 GetInputMessageTypes(process_)); 1130 SendInputEventACK(WebInputEvent::GestureScrollUpdate, 1131 INPUT_EVENT_ACK_STATE_CONSUMED); 1132 EXPECT_EQ(0U, process_->sink().message_count()); 1133 1134 // Another pinch. 1135 SimulateMouseEvent( 1136 WebInputEvent::MouseMove, 10, 110, WebInputEvent::ShiftKey, true); 1137 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); 1138 EXPECT_EQ("GesturePinchBegin", 1139 GetInputMessageTypes(process_)); 1140 EXPECT_EQ(0U, process_->sink().message_count()); 1141 1142 SimulateMouseEvent( 1143 WebInputEvent::MouseMove, 10, 120, WebInputEvent::ShiftKey, true); 1144 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); 1145 EXPECT_EQ("GesturePinchUpdate", 1146 GetInputMessageTypes(process_)); 1147 SendInputEventACK(WebInputEvent::GesturePinchUpdate, 1148 INPUT_EVENT_ACK_STATE_CONSUMED); 1149 EXPECT_EQ(0U, process_->sink().message_count()); 1150 1151 // Turn off emulation during a pinch. 1152 host_->OnMessageReceived( 1153 ViewHostMsg_SetTouchEventEmulationEnabled(0, false, false)); 1154 EXPECT_EQ(WebInputEvent::TouchCancel, host_->acked_touch_event_type()); 1155 EXPECT_EQ("GesturePinchEnd GestureScrollEnd", 1156 GetInputMessageTypes(process_)); 1157 EXPECT_EQ(0U, process_->sink().message_count()); 1158 1159 // Mouse event should pass untouched. 1160 SimulateMouseEvent( 1161 WebInputEvent::MouseMove, 10, 10, WebInputEvent::ShiftKey, true); 1162 EXPECT_EQ("MouseMove", GetInputMessageTypes(process_)); 1163 SendInputEventACK(WebInputEvent::MouseMove, 1164 INPUT_EVENT_ACK_STATE_CONSUMED); 1165 EXPECT_EQ(0U, process_->sink().message_count()); 1166 1167 // Turn on emulation. 1168 host_->OnMessageReceived( 1169 ViewHostMsg_SetTouchEventEmulationEnabled(0, true, true)); 1170 EXPECT_EQ(0U, process_->sink().message_count()); 1171 1172 // Another touch. 1173 SimulateMouseEvent(WebInputEvent::MouseDown, 10, 10, 0, true); 1174 EXPECT_EQ(WebInputEvent::TouchStart, host_->acked_touch_event_type()); 1175 EXPECT_EQ("GestureTapDown", GetInputMessageTypes(process_)); 1176 EXPECT_EQ(0U, process_->sink().message_count()); 1177 1178 // Scroll. 1179 SimulateMouseEvent(WebInputEvent::MouseMove, 10, 30, 0, true); 1180 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); 1181 EXPECT_EQ( 1182 "GestureTapCancel GestureScrollBegin GestureScrollUpdate", 1183 GetInputMessageTypes(process_)); 1184 SendInputEventACK(WebInputEvent::GestureScrollUpdate, 1185 INPUT_EVENT_ACK_STATE_CONSUMED); 1186 1187 // Turn off emulation during a scroll. 1188 host_->OnMessageReceived( 1189 ViewHostMsg_SetTouchEventEmulationEnabled(0, false, false)); 1190 EXPECT_EQ(WebInputEvent::TouchCancel, host_->acked_touch_event_type()); 1191 1192 EXPECT_EQ("GestureScrollEnd", GetInputMessageTypes(process_)); 1193 EXPECT_EQ(0U, process_->sink().message_count()); 1194 } 1195 1196 #define TEST_InputRouterRoutes_NOARGS(INPUTMSG) \ 1197 TEST_F(RenderWidgetHostTest, InputRouterRoutes##INPUTMSG) { \ 1198 host_->SetupForInputRouterTest(); \ 1199 host_->INPUTMSG(); \ 1200 EXPECT_TRUE(host_->mock_input_router()->send_event_called_); \ 1201 } 1202 1203 TEST_InputRouterRoutes_NOARGS(Focus); 1204 TEST_InputRouterRoutes_NOARGS(Blur); 1205 TEST_InputRouterRoutes_NOARGS(LostCapture); 1206 1207 #undef TEST_InputRouterRoutes_NOARGS 1208 1209 #define TEST_InputRouterRoutes_NOARGS_FromRFH(INPUTMSG) \ 1210 TEST_F(RenderWidgetHostTest, InputRouterRoutes##INPUTMSG) { \ 1211 host_->SetupForInputRouterTest(); \ 1212 host_->Send(new INPUTMSG(host_->GetRoutingID())); \ 1213 EXPECT_TRUE(host_->mock_input_router()->send_event_called_); \ 1214 } 1215 1216 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Undo); 1217 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Redo); 1218 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Cut); 1219 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Copy); 1220 #if defined(OS_MACOSX) 1221 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_CopyToFindPboard); 1222 #endif 1223 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Paste); 1224 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_PasteAndMatchStyle); 1225 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Delete); 1226 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_SelectAll); 1227 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Unselect); 1228 1229 #undef TEST_InputRouterRoutes_NOARGS_FromRFH 1230 1231 TEST_F(RenderWidgetHostTest, InputRouterRoutesReplace) { 1232 host_->SetupForInputRouterTest(); 1233 host_->Send(new InputMsg_Replace(host_->GetRoutingID(), base::string16())); 1234 EXPECT_TRUE(host_->mock_input_router()->send_event_called_); 1235 } 1236 1237 TEST_F(RenderWidgetHostTest, InputRouterRoutesReplaceMisspelling) { 1238 host_->SetupForInputRouterTest(); 1239 host_->Send(new InputMsg_ReplaceMisspelling(host_->GetRoutingID(), 1240 base::string16())); 1241 EXPECT_TRUE(host_->mock_input_router()->send_event_called_); 1242 } 1243 1244 TEST_F(RenderWidgetHostTest, IgnoreInputEvent) { 1245 host_->SetupForInputRouterTest(); 1246 1247 host_->SetIgnoreInputEvents(true); 1248 1249 SimulateKeyboardEvent(WebInputEvent::RawKeyDown); 1250 EXPECT_FALSE(host_->mock_input_router()->sent_keyboard_event_); 1251 1252 SimulateMouseEvent(WebInputEvent::MouseMove); 1253 EXPECT_FALSE(host_->mock_input_router()->sent_mouse_event_); 1254 1255 SimulateWheelEvent(0, 100, 0, true); 1256 EXPECT_FALSE(host_->mock_input_router()->sent_wheel_event_); 1257 1258 SimulateGestureEvent(WebInputEvent::GestureScrollBegin, 1259 blink::WebGestureDeviceTouchpad); 1260 EXPECT_FALSE(host_->mock_input_router()->sent_gesture_event_); 1261 1262 PressTouchPoint(100, 100); 1263 SendTouchEvent(); 1264 EXPECT_FALSE(host_->mock_input_router()->send_touch_event_not_cancelled_); 1265 } 1266 1267 TEST_F(RenderWidgetHostTest, KeyboardListenerIgnoresEvent) { 1268 host_->SetupForInputRouterTest(); 1269 host_->AddKeyPressEventCallback( 1270 base::Bind(&RenderWidgetHostTest::KeyPressEventCallback, 1271 base::Unretained(this))); 1272 handle_key_press_event_ = false; 1273 SimulateKeyboardEvent(WebInputEvent::RawKeyDown); 1274 1275 EXPECT_TRUE(host_->mock_input_router()->sent_keyboard_event_); 1276 } 1277 1278 TEST_F(RenderWidgetHostTest, KeyboardListenerSuppressFollowingEvents) { 1279 host_->SetupForInputRouterTest(); 1280 1281 host_->AddKeyPressEventCallback( 1282 base::Bind(&RenderWidgetHostTest::KeyPressEventCallback, 1283 base::Unretained(this))); 1284 1285 // The callback handles the first event 1286 handle_key_press_event_ = true; 1287 SimulateKeyboardEvent(WebInputEvent::RawKeyDown); 1288 1289 EXPECT_FALSE(host_->mock_input_router()->sent_keyboard_event_); 1290 1291 // Following Char events should be suppressed 1292 handle_key_press_event_ = false; 1293 SimulateKeyboardEvent(WebInputEvent::Char); 1294 EXPECT_FALSE(host_->mock_input_router()->sent_keyboard_event_); 1295 SimulateKeyboardEvent(WebInputEvent::Char); 1296 EXPECT_FALSE(host_->mock_input_router()->sent_keyboard_event_); 1297 1298 // Sending RawKeyDown event should stop suppression 1299 SimulateKeyboardEvent(WebInputEvent::RawKeyDown); 1300 EXPECT_TRUE(host_->mock_input_router()->sent_keyboard_event_); 1301 1302 host_->mock_input_router()->sent_keyboard_event_ = false; 1303 SimulateKeyboardEvent(WebInputEvent::Char); 1304 EXPECT_TRUE(host_->mock_input_router()->sent_keyboard_event_); 1305 } 1306 1307 TEST_F(RenderWidgetHostTest, MouseEventCallbackCanHandleEvent) { 1308 host_->SetupForInputRouterTest(); 1309 1310 host_->AddMouseEventCallback( 1311 base::Bind(&RenderWidgetHostTest::MouseEventCallback, 1312 base::Unretained(this))); 1313 1314 handle_mouse_event_ = true; 1315 SimulateMouseEvent(WebInputEvent::MouseDown); 1316 1317 EXPECT_FALSE(host_->mock_input_router()->sent_mouse_event_); 1318 1319 handle_mouse_event_ = false; 1320 SimulateMouseEvent(WebInputEvent::MouseDown); 1321 1322 EXPECT_TRUE(host_->mock_input_router()->sent_mouse_event_); 1323 } 1324 1325 TEST_F(RenderWidgetHostTest, InputRouterReceivesHandleInputEvent_ACK) { 1326 host_->SetupForInputRouterTest(); 1327 1328 SendInputEventACK(WebInputEvent::RawKeyDown, 1329 INPUT_EVENT_ACK_STATE_CONSUMED); 1330 1331 EXPECT_TRUE(host_->mock_input_router()->message_received_); 1332 } 1333 1334 TEST_F(RenderWidgetHostTest, InputRouterReceivesMoveCaret_ACK) { 1335 host_->SetupForInputRouterTest(); 1336 1337 host_->OnMessageReceived(ViewHostMsg_MoveCaret_ACK(0)); 1338 1339 EXPECT_TRUE(host_->mock_input_router()->message_received_); 1340 } 1341 1342 TEST_F(RenderWidgetHostTest, InputRouterReceivesSelectRange_ACK) { 1343 host_->SetupForInputRouterTest(); 1344 1345 host_->OnMessageReceived(ViewHostMsg_SelectRange_ACK(0)); 1346 1347 EXPECT_TRUE(host_->mock_input_router()->message_received_); 1348 } 1349 1350 TEST_F(RenderWidgetHostTest, InputRouterReceivesHasTouchEventHandlers) { 1351 host_->SetupForInputRouterTest(); 1352 1353 host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true)); 1354 1355 EXPECT_TRUE(host_->mock_input_router()->message_received_); 1356 } 1357 1358 1359 void CheckLatencyInfoComponentInMessage(RenderWidgetHostProcess* process, 1360 int64 component_id, 1361 WebInputEvent::Type input_type) { 1362 const IPC::Message* message = process->sink().GetUniqueMessageMatching( 1363 InputMsg_HandleInputEvent::ID); 1364 ASSERT_TRUE(message); 1365 InputMsg_HandleInputEvent::Param params; 1366 EXPECT_TRUE(InputMsg_HandleInputEvent::Read(message, ¶ms)); 1367 ui::LatencyInfo latency_info = params.b; 1368 EXPECT_TRUE(latency_info.FindLatency( 1369 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 1370 component_id, 1371 NULL)); 1372 process->sink().ClearMessages(); 1373 } 1374 1375 // Tests that after input event passes through RWHI through ForwardXXXEvent() 1376 // or ForwardXXXEventWithLatencyInfo(), LatencyInfo component 1377 // ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT will always present in the 1378 // event's LatencyInfo. 1379 TEST_F(RenderWidgetHostTest, InputEventRWHLatencyComponent) { 1380 host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true)); 1381 process_->sink().ClearMessages(); 1382 1383 // Tests RWHI::ForwardWheelEvent(). 1384 SimulateWheelEvent(-5, 0, 0, true); 1385 CheckLatencyInfoComponentInMessage( 1386 process_, GetLatencyComponentId(), WebInputEvent::MouseWheel); 1387 SendInputEventACK(WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED); 1388 1389 // Tests RWHI::ForwardWheelEventWithLatencyInfo(). 1390 SimulateWheelEventWithLatencyInfo(-5, 0, 0, true, ui::LatencyInfo()); 1391 CheckLatencyInfoComponentInMessage( 1392 process_, GetLatencyComponentId(), WebInputEvent::MouseWheel); 1393 SendInputEventACK(WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED); 1394 1395 // Tests RWHI::ForwardMouseEvent(). 1396 SimulateMouseEvent(WebInputEvent::MouseMove); 1397 CheckLatencyInfoComponentInMessage( 1398 process_, GetLatencyComponentId(), WebInputEvent::MouseMove); 1399 SendInputEventACK(WebInputEvent::MouseMove, INPUT_EVENT_ACK_STATE_CONSUMED); 1400 1401 // Tests RWHI::ForwardMouseEventWithLatencyInfo(). 1402 SimulateMouseEventWithLatencyInfo(WebInputEvent::MouseMove, 1403 ui::LatencyInfo()); 1404 CheckLatencyInfoComponentInMessage( 1405 process_, GetLatencyComponentId(), WebInputEvent::MouseMove); 1406 SendInputEventACK(WebInputEvent::MouseMove, INPUT_EVENT_ACK_STATE_CONSUMED); 1407 1408 // Tests RWHI::ForwardGestureEvent(). 1409 SimulateGestureEvent(WebInputEvent::GestureScrollBegin, 1410 blink::WebGestureDeviceTouchscreen); 1411 CheckLatencyInfoComponentInMessage( 1412 process_, GetLatencyComponentId(), WebInputEvent::GestureScrollBegin); 1413 1414 // Tests RWHI::ForwardGestureEventWithLatencyInfo(). 1415 SimulateGestureEventWithLatencyInfo(WebInputEvent::GestureScrollUpdate, 1416 blink::WebGestureDeviceTouchscreen, 1417 ui::LatencyInfo()); 1418 CheckLatencyInfoComponentInMessage( 1419 process_, GetLatencyComponentId(), WebInputEvent::GestureScrollUpdate); 1420 SendInputEventACK(WebInputEvent::GestureScrollUpdate, 1421 INPUT_EVENT_ACK_STATE_CONSUMED); 1422 1423 // Tests RWHI::ForwardTouchEventWithLatencyInfo(). 1424 PressTouchPoint(0, 1); 1425 SendTouchEvent(); 1426 CheckLatencyInfoComponentInMessage( 1427 process_, GetLatencyComponentId(), WebInputEvent::TouchStart); 1428 SendInputEventACK(WebInputEvent::TouchStart, INPUT_EVENT_ACK_STATE_CONSUMED); 1429 } 1430 1431 TEST_F(RenderWidgetHostTest, RendererExitedResetsInputRouter) { 1432 // RendererExited will delete the view. 1433 host_->SetView(new TestView(host_.get())); 1434 host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1); 1435 1436 // Make sure the input router is in a fresh state. 1437 ASSERT_FALSE(host_->input_router()->HasPendingEvents()); 1438 } 1439 1440 // Regression test for http://crbug.com/401859. 1441 TEST_F(RenderWidgetHostTest, RendererExitedResetsIsHidden) { 1442 // RendererExited will delete the view. 1443 host_->SetView(new TestView(host_.get())); 1444 host_->WasHidden(); 1445 1446 ASSERT_TRUE(host_->is_hidden()); 1447 host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1); 1448 ASSERT_FALSE(host_->is_hidden()); 1449 1450 // Make sure the input router is in a fresh state. 1451 ASSERT_FALSE(host_->input_router()->HasPendingEvents()); 1452 } 1453 1454 } // namespace content 1455