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