Add ICU message format support
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_unittest.cc
bloba33a0cb410c9a8f414c5c65121b16062da53ab0b
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/location.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/memory/shared_memory.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "base/timer/timer.h"
14 #include "content/browser/browser_thread_impl.h"
15 #include "content/browser/gpu/compositor_util.h"
16 #include "content/browser/renderer_host/input/input_router_impl.h"
17 #include "content/browser/renderer_host/render_widget_host_delegate.h"
18 #include "content/browser/renderer_host/render_widget_host_view_base.h"
19 #include "content/common/input/synthetic_web_input_event_builders.h"
20 #include "content/common/input_messages.h"
21 #include "content/common/view_messages.h"
22 #include "content/public/common/content_switches.h"
23 #include "content/public/test/mock_render_process_host.h"
24 #include "content/public/test/test_browser_context.h"
25 #include "content/test/test_render_view_host.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "ui/events/keycodes/keyboard_codes.h"
28 #include "ui/gfx/canvas.h"
29 #include "ui/gfx/screen.h"
31 #if defined(OS_ANDROID)
32 #include "content/browser/renderer_host/render_widget_host_view_android.h"
33 #endif
35 #if defined(USE_AURA) || (defined(OS_MACOSX) && !defined(OS_IOS))
36 #include "content/browser/compositor/test/no_transport_image_transport_factory.h"
37 #endif
39 #if defined(USE_AURA)
40 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
41 #include "content/browser/renderer_host/ui_events_helper.h"
42 #include "ui/aura/test/test_screen.h"
43 #include "ui/events/event.h"
44 #endif
46 using base::TimeDelta;
47 using blink::WebGestureDevice;
48 using blink::WebGestureEvent;
49 using blink::WebInputEvent;
50 using blink::WebKeyboardEvent;
51 using blink::WebMouseEvent;
52 using blink::WebMouseWheelEvent;
53 using blink::WebTouchEvent;
54 using blink::WebTouchPoint;
56 namespace content {
58 // MockInputRouter -------------------------------------------------------------
60 class MockInputRouter : public InputRouter {
61 public:
62 explicit MockInputRouter(InputRouterClient* client)
63 : send_event_called_(false),
64 sent_mouse_event_(false),
65 sent_wheel_event_(false),
66 sent_keyboard_event_(false),
67 sent_gesture_event_(false),
68 send_touch_event_not_cancelled_(false),
69 message_received_(false),
70 client_(client) {
72 ~MockInputRouter() override {}
74 // InputRouter
75 bool SendInput(scoped_ptr<IPC::Message> message) override {
76 send_event_called_ = true;
77 return true;
79 void SendMouseEvent(const MouseEventWithLatencyInfo& mouse_event) override {
80 sent_mouse_event_ = true;
82 void SendWheelEvent(
83 const MouseWheelEventWithLatencyInfo& wheel_event) override {
84 sent_wheel_event_ = true;
86 void SendKeyboardEvent(const NativeWebKeyboardEventWithLatencyInfo& key_event,
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 void NotifySiteIsMobileOptimized(bool is_mobile_optimized) override {}
104 void RequestNotificationWhenFlushed() 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 send_event_called_;
114 bool sent_mouse_event_;
115 bool sent_wheel_event_;
116 bool sent_keyboard_event_;
117 bool sent_gesture_event_;
118 bool send_touch_event_not_cancelled_;
119 bool message_received_;
121 private:
122 InputRouterClient* client_;
124 DISALLOW_COPY_AND_ASSIGN(MockInputRouter);
127 // MockRenderWidgetHost ----------------------------------------------------
129 class MockRenderWidgetHost : public RenderWidgetHostImpl {
130 public:
131 MockRenderWidgetHost(
132 RenderWidgetHostDelegate* delegate,
133 RenderProcessHost* process,
134 int routing_id)
135 : RenderWidgetHostImpl(delegate, process, routing_id, false),
136 unresponsive_timer_fired_(false) {
137 acked_touch_event_type_ = blink::WebInputEvent::Undefined;
140 // Allow poking at a few private members.
141 using RenderWidgetHostImpl::GetResizeParams;
142 using RenderWidgetHostImpl::OnUpdateRect;
143 using RenderWidgetHostImpl::RendererExited;
144 using RenderWidgetHostImpl::SetInitialRenderSizeParams;
145 using RenderWidgetHostImpl::old_resize_params_;
146 using RenderWidgetHostImpl::is_hidden_;
147 using RenderWidgetHostImpl::resize_ack_pending_;
148 using RenderWidgetHostImpl::input_router_;
150 void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
151 InputEventAckState ack_result) override {
152 // Sniff touch acks.
153 acked_touch_event_type_ = event.event.type;
154 RenderWidgetHostImpl::OnTouchEventAck(event, ack_result);
157 bool unresponsive_timer_fired() const {
158 return unresponsive_timer_fired_;
161 void DisableGestureDebounce() {
162 input_router_.reset(new InputRouterImpl(
163 process_, this, this, routing_id_, InputRouterImpl::Config()));
166 WebInputEvent::Type acked_touch_event_type() const {
167 return acked_touch_event_type_;
170 void SetupForInputRouterTest() {
171 input_router_.reset(new MockInputRouter(this));
174 MockInputRouter* mock_input_router() {
175 return static_cast<MockInputRouter*>(input_router_.get());
178 protected:
179 void NotifyRendererUnresponsive() override {
180 unresponsive_timer_fired_ = true;
183 bool unresponsive_timer_fired_;
184 WebInputEvent::Type acked_touch_event_type_;
186 DISALLOW_COPY_AND_ASSIGN(MockRenderWidgetHost);
189 namespace {
191 // RenderWidgetHostProcess -----------------------------------------------------
193 class RenderWidgetHostProcess : public MockRenderProcessHost {
194 public:
195 explicit RenderWidgetHostProcess(BrowserContext* browser_context)
196 : MockRenderProcessHost(browser_context) {
198 ~RenderWidgetHostProcess() override {}
200 bool HasConnection() const override { return true; }
202 protected:
203 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostProcess);
206 // TestView --------------------------------------------------------------------
208 // This test view allows us to specify the size, and keep track of acked
209 // touch-events.
210 class TestView : public TestRenderWidgetHostView {
211 public:
212 explicit TestView(RenderWidgetHostImpl* rwh)
213 : TestRenderWidgetHostView(rwh),
214 unhandled_wheel_event_count_(0),
215 acked_event_count_(0),
216 gesture_event_type_(-1),
217 use_fake_physical_backing_size_(false),
218 ack_result_(INPUT_EVENT_ACK_STATE_UNKNOWN) {
221 // Sets the bounds returned by GetViewBounds.
222 void set_bounds(const gfx::Rect& bounds) {
223 bounds_ = bounds;
226 const WebTouchEvent& acked_event() const { return acked_event_; }
227 int acked_event_count() const { return acked_event_count_; }
228 void ClearAckedEvent() {
229 acked_event_.type = blink::WebInputEvent::Undefined;
230 acked_event_count_ = 0;
233 const WebMouseWheelEvent& unhandled_wheel_event() const {
234 return unhandled_wheel_event_;
236 int unhandled_wheel_event_count() const {
237 return unhandled_wheel_event_count_;
239 int gesture_event_type() const { return gesture_event_type_; }
240 InputEventAckState ack_result() const { return ack_result_; }
242 void SetMockPhysicalBackingSize(const gfx::Size& mock_physical_backing_size) {
243 use_fake_physical_backing_size_ = true;
244 mock_physical_backing_size_ = mock_physical_backing_size;
246 void ClearMockPhysicalBackingSize() {
247 use_fake_physical_backing_size_ = false;
249 void SetScreenInfo(const blink::WebScreenInfo& screen_info) {
250 screen_info_ = screen_info;
253 // RenderWidgetHostView override.
254 gfx::Rect GetViewBounds() const override { return bounds_; }
255 void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
256 InputEventAckState ack_result) override {
257 acked_event_ = touch.event;
258 ++acked_event_count_;
260 void WheelEventAck(const WebMouseWheelEvent& event,
261 InputEventAckState ack_result) override {
262 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
263 return;
264 unhandled_wheel_event_count_++;
265 unhandled_wheel_event_ = event;
267 void GestureEventAck(const WebGestureEvent& event,
268 InputEventAckState ack_result) override {
269 gesture_event_type_ = event.type;
270 ack_result_ = ack_result;
272 gfx::Size GetPhysicalBackingSize() const override {
273 if (use_fake_physical_backing_size_)
274 return mock_physical_backing_size_;
275 return TestRenderWidgetHostView::GetPhysicalBackingSize();
277 void GetScreenInfo(blink::WebScreenInfo* screen_info) override {
278 *screen_info = screen_info_;
280 #if defined(USE_AURA)
281 ~TestView() override {
282 // Simulate the mouse exit event dispatched when an aura window is
283 // destroyed. (MakeWebMouseEventFromAuraEvent translates ET_MOUSE_EXITED
284 // into WebInputEvent::MouseMove.)
285 rwh_->input_router()->SendMouseEvent(
286 MouseEventWithLatencyInfo(
287 SyntheticWebMouseEventBuilder::Build(WebInputEvent::MouseMove),
288 ui::LatencyInfo()));
290 #endif
292 protected:
293 WebMouseWheelEvent unhandled_wheel_event_;
294 int unhandled_wheel_event_count_;
295 WebTouchEvent acked_event_;
296 int acked_event_count_;
297 int gesture_event_type_;
298 gfx::Rect bounds_;
299 bool use_fake_physical_backing_size_;
300 gfx::Size mock_physical_backing_size_;
301 InputEventAckState ack_result_;
302 blink::WebScreenInfo screen_info_;
304 DISALLOW_COPY_AND_ASSIGN(TestView);
307 // MockRenderWidgetHostDelegate --------------------------------------------
309 class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
310 public:
311 MockRenderWidgetHostDelegate()
312 : prehandle_keyboard_event_(false),
313 prehandle_keyboard_event_called_(false),
314 prehandle_keyboard_event_type_(WebInputEvent::Undefined),
315 unhandled_keyboard_event_called_(false),
316 unhandled_keyboard_event_type_(WebInputEvent::Undefined),
317 handle_wheel_event_(false),
318 handle_wheel_event_called_(false) {
320 ~MockRenderWidgetHostDelegate() override {}
322 // Tests that make sure we ignore keyboard event acknowledgments to events we
323 // didn't send work by making sure we didn't call UnhandledKeyboardEvent().
324 bool unhandled_keyboard_event_called() const {
325 return unhandled_keyboard_event_called_;
328 WebInputEvent::Type unhandled_keyboard_event_type() const {
329 return unhandled_keyboard_event_type_;
332 bool prehandle_keyboard_event_called() const {
333 return prehandle_keyboard_event_called_;
336 WebInputEvent::Type prehandle_keyboard_event_type() const {
337 return prehandle_keyboard_event_type_;
340 void set_prehandle_keyboard_event(bool handle) {
341 prehandle_keyboard_event_ = handle;
344 void set_handle_wheel_event(bool handle) {
345 handle_wheel_event_ = handle;
348 bool handle_wheel_event_called() {
349 return handle_wheel_event_called_;
352 protected:
353 bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
354 bool* is_keyboard_shortcut) override {
355 prehandle_keyboard_event_type_ = event.type;
356 prehandle_keyboard_event_called_ = true;
357 return prehandle_keyboard_event_;
360 void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) override {
361 unhandled_keyboard_event_type_ = event.type;
362 unhandled_keyboard_event_called_ = true;
365 bool HandleWheelEvent(const blink::WebMouseWheelEvent& event) override {
366 handle_wheel_event_called_ = true;
367 return handle_wheel_event_;
370 void Cut() override {}
371 void Copy() override {}
372 void Paste() override {}
373 void SelectAll() override {}
375 private:
376 bool prehandle_keyboard_event_;
377 bool prehandle_keyboard_event_called_;
378 WebInputEvent::Type prehandle_keyboard_event_type_;
380 bool unhandled_keyboard_event_called_;
381 WebInputEvent::Type unhandled_keyboard_event_type_;
383 bool handle_wheel_event_;
384 bool handle_wheel_event_called_;
387 // RenderWidgetHostTest --------------------------------------------------------
389 class RenderWidgetHostTest : public testing::Test {
390 public:
391 RenderWidgetHostTest()
392 : process_(NULL),
393 handle_key_press_event_(false),
394 handle_mouse_event_(false),
395 simulated_event_time_delta_seconds_(0) {
396 last_simulated_event_time_seconds_ =
397 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
399 ~RenderWidgetHostTest() override {}
401 bool KeyPressEventCallback(const NativeWebKeyboardEvent& /* event */) {
402 return handle_key_press_event_;
404 bool MouseEventCallback(const blink::WebMouseEvent& /* event */) {
405 return handle_mouse_event_;
408 protected:
409 // testing::Test
410 void SetUp() override {
411 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
412 command_line->AppendSwitch(switches::kValidateInputEventStream);
414 browser_context_.reset(new TestBrowserContext());
415 delegate_.reset(new MockRenderWidgetHostDelegate());
416 process_ = new RenderWidgetHostProcess(browser_context_.get());
417 #if defined(USE_AURA) || (defined(OS_MACOSX) && !defined(OS_IOS))
418 if (IsDelegatedRendererEnabled()) {
419 ImageTransportFactory::InitializeForUnitTests(
420 scoped_ptr<ImageTransportFactory>(
421 new NoTransportImageTransportFactory));
423 #endif
424 #if defined(USE_AURA)
425 screen_.reset(aura::TestScreen::Create(gfx::Size()));
426 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
427 #endif
428 host_.reset(
429 new MockRenderWidgetHost(delegate_.get(), process_, MSG_ROUTING_NONE));
430 view_.reset(new TestView(host_.get()));
431 ConfigureView(view_.get());
432 host_->SetView(view_.get());
433 SetInitialRenderSizeParams();
434 host_->Init();
435 host_->DisableGestureDebounce();
438 void TearDown() override {
439 view_.reset();
440 host_.reset();
441 delegate_.reset();
442 process_ = NULL;
443 browser_context_.reset();
445 #if defined(USE_AURA)
446 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, nullptr);
447 screen_.reset();
448 #endif
449 #if defined(USE_AURA) || (defined(OS_MACOSX) && !defined(OS_IOS))
450 if (IsDelegatedRendererEnabled())
451 ImageTransportFactory::Terminate();
452 #endif
454 // Process all pending tasks to avoid leaks.
455 base::MessageLoop::current()->RunUntilIdle();
458 void SetInitialRenderSizeParams() {
459 ViewMsg_Resize_Params render_size_params;
460 host_->GetResizeParams(&render_size_params);
461 host_->SetInitialRenderSizeParams(render_size_params);
464 virtual void ConfigureView(TestView* view) {
467 int64 GetLatencyComponentId() {
468 return host_->GetLatencyComponentId();
471 void SendInputEventACK(WebInputEvent::Type type,
472 InputEventAckState ack_result) {
473 DCHECK(!WebInputEvent::isTouchEventType(type));
474 InputEventAck ack(type, ack_result);
475 host_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
478 double GetNextSimulatedEventTimeSeconds() {
479 last_simulated_event_time_seconds_ += simulated_event_time_delta_seconds_;
480 return last_simulated_event_time_seconds_;
483 void SimulateKeyboardEvent(WebInputEvent::Type type) {
484 SimulateKeyboardEvent(type, 0);
487 void SimulateKeyboardEvent(WebInputEvent::Type type, int modifiers) {
488 WebKeyboardEvent event = SyntheticWebKeyboardEventBuilder::Build(type);
489 event.modifiers = modifiers;
490 NativeWebKeyboardEvent native_event;
491 memcpy(&native_event, &event, sizeof(event));
492 host_->ForwardKeyboardEvent(native_event);
495 void SimulateMouseEvent(WebInputEvent::Type type) {
496 host_->ForwardMouseEvent(SyntheticWebMouseEventBuilder::Build(type));
499 void SimulateMouseEventWithLatencyInfo(WebInputEvent::Type type,
500 const ui::LatencyInfo& ui_latency) {
501 host_->ForwardMouseEventWithLatencyInfo(
502 SyntheticWebMouseEventBuilder::Build(type),
503 ui_latency);
506 void SimulateWheelEvent(float dX, float dY, int modifiers, bool precise) {
507 host_->ForwardWheelEvent(
508 SyntheticWebMouseWheelEventBuilder::Build(dX, dY, modifiers, precise));
511 void SimulateWheelEventWithLatencyInfo(float dX,
512 float dY,
513 int modifiers,
514 bool precise,
515 const ui::LatencyInfo& ui_latency) {
516 host_->ForwardWheelEventWithLatencyInfo(
517 SyntheticWebMouseWheelEventBuilder::Build(dX, dY, modifiers, precise),
518 ui_latency);
521 void SimulateMouseMove(int x, int y, int modifiers) {
522 SimulateMouseEvent(WebInputEvent::MouseMove, x, y, modifiers, false);
525 void SimulateMouseEvent(
526 WebInputEvent::Type type, int x, int y, int modifiers, bool pressed) {
527 WebMouseEvent event =
528 SyntheticWebMouseEventBuilder::Build(type, x, y, modifiers);
529 if (pressed)
530 event.button = WebMouseEvent::ButtonLeft;
531 event.timeStampSeconds = GetNextSimulatedEventTimeSeconds();
532 host_->ForwardMouseEvent(event);
535 // Inject simple synthetic WebGestureEvent instances.
536 void SimulateGestureEvent(WebInputEvent::Type type,
537 WebGestureDevice sourceDevice) {
538 host_->ForwardGestureEvent(
539 SyntheticWebGestureEventBuilder::Build(type, sourceDevice));
542 void SimulateGestureEventWithLatencyInfo(WebInputEvent::Type type,
543 WebGestureDevice sourceDevice,
544 const ui::LatencyInfo& ui_latency) {
545 host_->ForwardGestureEventWithLatencyInfo(
546 SyntheticWebGestureEventBuilder::Build(type, sourceDevice),
547 ui_latency);
550 // Set the timestamp for the touch-event.
551 void SetTouchTimestamp(base::TimeDelta timestamp) {
552 touch_event_.SetTimestamp(timestamp);
555 // Sends a touch event (irrespective of whether the page has a touch-event
556 // handler or not).
557 uint32 SendTouchEvent() {
558 uint32 touch_event_id = touch_event_.uniqueTouchEventId;
559 host_->ForwardTouchEventWithLatencyInfo(touch_event_, ui::LatencyInfo());
561 touch_event_.ResetPoints();
562 return touch_event_id;
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 base::PickleIterator iter(message);
579 const char* data;
580 int data_length;
581 if (!iter.ReadData(&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, so setting it to the same thing
620 // 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 // No resize ack if the physical backing gets set, but the view bounds are
627 // zero.
628 view_->SetMockPhysicalBackingSize(gfx::Size(200, 200));
629 host_->WasResized();
630 EXPECT_FALSE(host_->resize_ack_pending_);
632 // Setting the view bounds to nonzero should send out the notification.
633 // but should not expect ack for empty physical backing size.
634 gfx::Rect original_size(0, 0, 100, 100);
635 process_->sink().ClearMessages();
636 view_->set_bounds(original_size);
637 view_->SetMockPhysicalBackingSize(gfx::Size());
638 host_->WasResized();
639 EXPECT_FALSE(host_->resize_ack_pending_);
640 EXPECT_EQ(original_size.size(), host_->old_resize_params_->new_size);
641 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
643 // Setting the bounds and physical backing size to nonzero should send out
644 // the notification and expect an ack.
645 process_->sink().ClearMessages();
646 view_->ClearMockPhysicalBackingSize();
647 host_->WasResized();
648 EXPECT_TRUE(host_->resize_ack_pending_);
649 EXPECT_EQ(original_size.size(), host_->old_resize_params_->new_size);
650 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
651 ViewHostMsg_UpdateRect_Params params;
652 params.flags = ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK;
653 params.view_size = original_size.size();
654 host_->OnUpdateRect(params);
655 EXPECT_FALSE(host_->resize_ack_pending_);
657 // Send out a update that's not a resize ack after setting resize ack pending
658 // flag. This should not clean the resize ack pending flag.
659 process_->sink().ClearMessages();
660 gfx::Rect second_size(0, 0, 110, 110);
661 EXPECT_FALSE(host_->resize_ack_pending_);
662 view_->set_bounds(second_size);
663 host_->WasResized();
664 EXPECT_TRUE(host_->resize_ack_pending_);
665 params.flags = 0;
666 params.view_size = gfx::Size(100, 100);
667 host_->OnUpdateRect(params);
668 EXPECT_TRUE(host_->resize_ack_pending_);
669 EXPECT_EQ(second_size.size(), host_->old_resize_params_->new_size);
671 // Sending out a new notification should NOT send out a new IPC message since
672 // a resize ACK is pending.
673 gfx::Rect third_size(0, 0, 120, 120);
674 process_->sink().ClearMessages();
675 view_->set_bounds(third_size);
676 host_->WasResized();
677 EXPECT_TRUE(host_->resize_ack_pending_);
678 EXPECT_EQ(second_size.size(), host_->old_resize_params_->new_size);
679 EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
681 // Send a update that's a resize ack, but for the original_size we sent. Since
682 // this isn't the second_size, the message handler should immediately send
683 // a new resize message for the new size to the renderer.
684 process_->sink().ClearMessages();
685 params.flags = ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK;
686 params.view_size = original_size.size();
687 host_->OnUpdateRect(params);
688 EXPECT_TRUE(host_->resize_ack_pending_);
689 EXPECT_EQ(third_size.size(), host_->old_resize_params_->new_size);
690 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
692 // Send the resize ack for the latest size.
693 process_->sink().ClearMessages();
694 params.flags = ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK;
695 params.view_size = third_size.size();
696 host_->OnUpdateRect(params);
697 EXPECT_FALSE(host_->resize_ack_pending_);
698 EXPECT_EQ(third_size.size(), host_->old_resize_params_->new_size);
699 EXPECT_FALSE(process_->sink().GetFirstMessageMatching(ViewMsg_Resize::ID));
701 // Now clearing the bounds should send out a notification but we shouldn't
702 // expect a resize ack (since the renderer won't ack empty sizes). The message
703 // should contain the new size (0x0) and not the previous one that we skipped
704 process_->sink().ClearMessages();
705 view_->set_bounds(gfx::Rect());
706 host_->WasResized();
707 EXPECT_FALSE(host_->resize_ack_pending_);
708 EXPECT_EQ(gfx::Size(), host_->old_resize_params_->new_size);
709 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
711 // Send a rect that has no area but has either width or height set.
712 process_->sink().ClearMessages();
713 view_->set_bounds(gfx::Rect(0, 0, 0, 30));
714 host_->WasResized();
715 EXPECT_FALSE(host_->resize_ack_pending_);
716 EXPECT_EQ(gfx::Size(0, 30), host_->old_resize_params_->new_size);
717 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
719 // Set the same size again. It should not be sent again.
720 process_->sink().ClearMessages();
721 host_->WasResized();
722 EXPECT_FALSE(host_->resize_ack_pending_);
723 EXPECT_EQ(gfx::Size(0, 30), host_->old_resize_params_->new_size);
724 EXPECT_FALSE(process_->sink().GetFirstMessageMatching(ViewMsg_Resize::ID));
726 // A different size should be sent again, however.
727 view_->set_bounds(gfx::Rect(0, 0, 0, 31));
728 host_->WasResized();
729 EXPECT_FALSE(host_->resize_ack_pending_);
730 EXPECT_EQ(gfx::Size(0, 31), host_->old_resize_params_->new_size);
731 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
734 // Test that a resize event is sent if WasResized() is called after a
735 // WebScreenInfo change.
736 TEST_F(RenderWidgetHostTest, ResizeScreenInfo) {
737 blink::WebScreenInfo screen_info;
738 screen_info.deviceScaleFactor = 1.f;
739 screen_info.rect = blink::WebRect(0, 0, 800, 600);
740 screen_info.availableRect = blink::WebRect(0, 0, 800, 600);
741 screen_info.orientationAngle = 0;
742 screen_info.orientationType = blink::WebScreenOrientationPortraitPrimary;
744 view_->SetScreenInfo(screen_info);
745 host_->WasResized();
746 EXPECT_FALSE(host_->resize_ack_pending_);
747 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
748 process_->sink().ClearMessages();
750 screen_info.orientationAngle = 180;
751 screen_info.orientationType = blink::WebScreenOrientationLandscapePrimary;
753 view_->SetScreenInfo(screen_info);
754 host_->WasResized();
755 EXPECT_FALSE(host_->resize_ack_pending_);
756 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
757 process_->sink().ClearMessages();
759 screen_info.deviceScaleFactor = 2.f;
761 view_->SetScreenInfo(screen_info);
762 host_->WasResized();
763 EXPECT_FALSE(host_->resize_ack_pending_);
764 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
765 process_->sink().ClearMessages();
767 // No screen change.
768 view_->SetScreenInfo(screen_info);
769 host_->WasResized();
770 EXPECT_FALSE(host_->resize_ack_pending_);
771 EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
774 // Test for crbug.com/25097. If a renderer crashes between a resize and the
775 // corresponding update message, we must be sure to clear the resize ack logic.
776 TEST_F(RenderWidgetHostTest, ResizeThenCrash) {
777 // Clear the first Resize message that carried screen info.
778 process_->sink().ClearMessages();
780 // Setting the bounds to a "real" rect should send out the notification.
781 gfx::Rect original_size(0, 0, 100, 100);
782 view_->set_bounds(original_size);
783 host_->WasResized();
784 EXPECT_TRUE(host_->resize_ack_pending_);
785 EXPECT_EQ(original_size.size(), host_->old_resize_params_->new_size);
786 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
788 // Simulate a renderer crash before the update message. Ensure all the
789 // resize ack logic is cleared. Must clear the view first so it doesn't get
790 // deleted.
791 host_->SetView(NULL);
792 host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
793 EXPECT_FALSE(host_->resize_ack_pending_);
794 EXPECT_EQ(gfx::Size(), host_->old_resize_params_->new_size);
796 // Reset the view so we can exit the test cleanly.
797 host_->SetView(view_.get());
800 // Unable to include render_widget_host_view_mac.h and compile.
801 #if !defined(OS_MACOSX)
802 // Tests setting background transparency.
803 TEST_F(RenderWidgetHostTest, Background) {
804 scoped_ptr<RenderWidgetHostViewBase> view;
805 #if defined(USE_AURA)
806 view.reset(new RenderWidgetHostViewAura(host_.get(), false));
807 // TODO(derat): Call this on all platforms: http://crbug.com/102450.
808 view->InitAsChild(NULL);
809 #elif defined(OS_ANDROID)
810 view.reset(new RenderWidgetHostViewAndroid(host_.get(), NULL));
811 #endif
812 host_->SetView(view.get());
814 EXPECT_TRUE(view->GetBackgroundOpaque());
815 view->SetBackgroundColor(SK_ColorTRANSPARENT);
816 EXPECT_FALSE(view->GetBackgroundOpaque());
818 const IPC::Message* set_background =
819 process_->sink().GetUniqueMessageMatching(
820 ViewMsg_SetBackgroundOpaque::ID);
821 ASSERT_TRUE(set_background);
822 base::Tuple<bool> sent_background;
823 ViewMsg_SetBackgroundOpaque::Read(set_background, &sent_background);
824 EXPECT_FALSE(base::get<0>(sent_background));
826 #if defined(USE_AURA)
827 // See the comment above |InitAsChild(NULL)|.
828 host_->SetView(NULL);
829 static_cast<RenderWidgetHostViewBase*>(view.release())->Destroy();
830 #endif
832 #endif
834 // Test that we don't paint when we're hidden, but we still send the ACK. Most
835 // of the rest of the painting is tested in the GetBackingStore* ones.
836 TEST_F(RenderWidgetHostTest, HiddenPaint) {
837 BrowserThreadImpl ui_thread(BrowserThread::UI, base::MessageLoop::current());
838 // Hide the widget, it should have sent out a message to the renderer.
839 EXPECT_FALSE(host_->is_hidden_);
840 host_->WasHidden();
841 EXPECT_TRUE(host_->is_hidden_);
842 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_WasHidden::ID));
844 // Send it an update as from the renderer.
845 process_->sink().ClearMessages();
846 ViewHostMsg_UpdateRect_Params params;
847 params.view_size = gfx::Size(100, 100);
848 host_->OnUpdateRect(params);
850 // Now unhide.
851 process_->sink().ClearMessages();
852 host_->WasShown(ui::LatencyInfo());
853 EXPECT_FALSE(host_->is_hidden_);
855 // It should have sent out a restored message with a request to paint.
856 const IPC::Message* restored = process_->sink().GetUniqueMessageMatching(
857 ViewMsg_WasShown::ID);
858 ASSERT_TRUE(restored);
859 base::Tuple<bool, ui::LatencyInfo> needs_repaint;
860 ViewMsg_WasShown::Read(restored, &needs_repaint);
861 EXPECT_TRUE(base::get<0>(needs_repaint));
864 TEST_F(RenderWidgetHostTest, IgnoreKeyEventsHandledByRenderer) {
865 // Simulate a keyboard event.
866 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
868 // Make sure we sent the input event to the renderer.
869 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
870 InputMsg_HandleInputEvent::ID));
871 process_->sink().ClearMessages();
873 // Send the simulated response from the renderer back.
874 SendInputEventACK(WebInputEvent::RawKeyDown,
875 INPUT_EVENT_ACK_STATE_CONSUMED);
876 EXPECT_FALSE(delegate_->unhandled_keyboard_event_called());
879 TEST_F(RenderWidgetHostTest, PreHandleRawKeyDownEvent) {
880 // Simluate the situation that the browser handled the key down event during
881 // pre-handle phrase.
882 delegate_->set_prehandle_keyboard_event(true);
883 process_->sink().ClearMessages();
885 // Simulate a keyboard event.
886 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
888 EXPECT_TRUE(delegate_->prehandle_keyboard_event_called());
889 EXPECT_EQ(WebInputEvent::RawKeyDown,
890 delegate_->prehandle_keyboard_event_type());
892 // Make sure the RawKeyDown event is not sent to the renderer.
893 EXPECT_EQ(0U, process_->sink().message_count());
895 // The browser won't pre-handle a Char event.
896 delegate_->set_prehandle_keyboard_event(false);
898 // Forward the Char event.
899 SimulateKeyboardEvent(WebInputEvent::Char);
901 // Make sure the Char event is suppressed.
902 EXPECT_EQ(0U, process_->sink().message_count());
904 // Forward the KeyUp event.
905 SimulateKeyboardEvent(WebInputEvent::KeyUp);
907 // Make sure only KeyUp was sent to the renderer.
908 EXPECT_EQ(1U, process_->sink().message_count());
909 EXPECT_EQ(InputMsg_HandleInputEvent::ID,
910 process_->sink().GetMessageAt(0)->type());
911 process_->sink().ClearMessages();
913 // Send the simulated response from the renderer back.
914 SendInputEventACK(WebInputEvent::KeyUp,
915 INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
917 EXPECT_TRUE(delegate_->unhandled_keyboard_event_called());
918 EXPECT_EQ(WebInputEvent::KeyUp, delegate_->unhandled_keyboard_event_type());
921 TEST_F(RenderWidgetHostTest, UnhandledWheelEvent) {
922 SimulateWheelEvent(-5, 0, 0, true);
924 // Make sure we sent the input event to the renderer.
925 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
926 InputMsg_HandleInputEvent::ID));
927 process_->sink().ClearMessages();
929 // Send the simulated response from the renderer back.
930 SendInputEventACK(WebInputEvent::MouseWheel,
931 INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
932 EXPECT_TRUE(delegate_->handle_wheel_event_called());
933 EXPECT_EQ(1, view_->unhandled_wheel_event_count());
934 EXPECT_EQ(-5, view_->unhandled_wheel_event().deltaX);
937 TEST_F(RenderWidgetHostTest, HandleWheelEvent) {
938 // Indicate that we're going to handle this wheel event
939 delegate_->set_handle_wheel_event(true);
941 SimulateWheelEvent(-5, 0, 0, true);
943 // Make sure we sent the input event to the renderer.
944 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
945 InputMsg_HandleInputEvent::ID));
946 process_->sink().ClearMessages();
948 // Send the simulated response from the renderer back.
949 SendInputEventACK(WebInputEvent::MouseWheel,
950 INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
952 // ensure the wheel event handler was invoked
953 EXPECT_TRUE(delegate_->handle_wheel_event_called());
955 // and that it suppressed the unhandled wheel event handler.
956 EXPECT_EQ(0, view_->unhandled_wheel_event_count());
959 TEST_F(RenderWidgetHostTest, UnhandledGestureEvent) {
960 SimulateGestureEvent(WebInputEvent::GestureTwoFingerTap,
961 blink::WebGestureDeviceTouchscreen);
963 // Make sure we sent the input event to the renderer.
964 EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
965 InputMsg_HandleInputEvent::ID));
966 process_->sink().ClearMessages();
968 // Send the simulated response from the renderer back.
969 SendInputEventACK(WebInputEvent::GestureTwoFingerTap,
970 INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
971 EXPECT_EQ(WebInputEvent::GestureTwoFingerTap, view_->gesture_event_type());
972 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, view_->ack_result());
975 // Test that the hang monitor timer expires properly if a new timer is started
976 // while one is in progress (see crbug.com/11007).
977 TEST_F(RenderWidgetHostTest, DontPostponeHangMonitorTimeout) {
978 // Start with a short timeout.
979 host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10));
981 // Immediately try to add a long 30 second timeout.
982 EXPECT_FALSE(host_->unresponsive_timer_fired());
983 host_->StartHangMonitorTimeout(TimeDelta::FromSeconds(30));
985 // Wait long enough for first timeout and see if it fired.
986 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
987 FROM_HERE, base::MessageLoop::QuitClosure(),
988 TimeDelta::FromMilliseconds(10));
989 base::MessageLoop::current()->Run();
990 EXPECT_TRUE(host_->unresponsive_timer_fired());
993 // Test that the hang monitor timer expires properly if it is started, stopped,
994 // and then started again.
995 TEST_F(RenderWidgetHostTest, StopAndStartHangMonitorTimeout) {
996 // Start with a short timeout, then stop it.
997 host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10));
998 host_->StopHangMonitorTimeout();
1000 // Start it again to ensure it still works.
1001 EXPECT_FALSE(host_->unresponsive_timer_fired());
1002 host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10));
1004 // Wait long enough for first timeout and see if it fired.
1005 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1006 FROM_HERE, base::MessageLoop::QuitClosure(),
1007 TimeDelta::FromMilliseconds(40));
1008 base::MessageLoop::current()->Run();
1009 EXPECT_TRUE(host_->unresponsive_timer_fired());
1012 // Test that the hang monitor timer expires properly if it is started, then
1013 // updated to a shorter duration.
1014 TEST_F(RenderWidgetHostTest, ShorterDelayHangMonitorTimeout) {
1015 // Start with a timeout.
1016 host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(100));
1018 // Start it again with shorter delay.
1019 EXPECT_FALSE(host_->unresponsive_timer_fired());
1020 host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(20));
1022 // Wait long enough for the second timeout and see if it fired.
1023 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1024 FROM_HERE, base::MessageLoop::QuitClosure(),
1025 TimeDelta::FromMilliseconds(25));
1026 base::MessageLoop::current()->Run();
1027 EXPECT_TRUE(host_->unresponsive_timer_fired());
1030 // Test that the hang monitor timer is effectively disabled when the widget is
1031 // hidden.
1032 TEST_F(RenderWidgetHostTest, HangMonitorTimeoutDisabledForInputWhenHidden) {
1033 host_->set_hung_renderer_delay(base::TimeDelta::FromMicroseconds(1));
1034 SimulateMouseEvent(WebInputEvent::MouseMove, 10, 10, 0, false);
1036 // Hiding the widget should deactivate the timeout.
1037 host_->WasHidden();
1039 // The timeout should not fire.
1040 EXPECT_FALSE(host_->unresponsive_timer_fired());
1041 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1042 FROM_HERE, base::MessageLoop::QuitClosure(),
1043 TimeDelta::FromMicroseconds(2));
1044 base::MessageLoop::current()->Run();
1045 EXPECT_FALSE(host_->unresponsive_timer_fired());
1047 // The timeout should never reactivate while hidden.
1048 SimulateMouseEvent(WebInputEvent::MouseMove, 10, 10, 0, false);
1049 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1050 FROM_HERE, base::MessageLoop::QuitClosure(),
1051 TimeDelta::FromMicroseconds(2));
1052 base::MessageLoop::current()->Run();
1053 EXPECT_FALSE(host_->unresponsive_timer_fired());
1055 // Showing the widget should restore the timeout, as the events have
1056 // not yet been ack'ed.
1057 host_->WasShown(ui::LatencyInfo());
1058 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1059 FROM_HERE, base::MessageLoop::QuitClosure(),
1060 TimeDelta::FromMicroseconds(2));
1061 base::MessageLoop::current()->Run();
1062 EXPECT_TRUE(host_->unresponsive_timer_fired());
1065 // Test that the hang monitor catches two input events but only one ack.
1066 // This can happen if the second input event causes the renderer to hang.
1067 // This test will catch a regression of crbug.com/111185.
1068 TEST_F(RenderWidgetHostTest, MultipleInputEvents) {
1069 // Configure the host to wait 10ms before considering
1070 // the renderer hung.
1071 host_->set_hung_renderer_delay(base::TimeDelta::FromMicroseconds(10));
1073 // Send two events but only one ack.
1074 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
1075 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
1076 SendInputEventACK(WebInputEvent::RawKeyDown,
1077 INPUT_EVENT_ACK_STATE_CONSUMED);
1079 // Wait long enough for first timeout and see if it fired.
1080 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1081 FROM_HERE, base::MessageLoop::QuitClosure(),
1082 TimeDelta::FromMicroseconds(20));
1083 base::MessageLoop::current()->Run();
1084 EXPECT_TRUE(host_->unresponsive_timer_fired());
1087 std::string GetInputMessageTypes(RenderWidgetHostProcess* process) {
1088 std::string result;
1089 for (size_t i = 0; i < process->sink().message_count(); ++i) {
1090 const IPC::Message *message = process->sink().GetMessageAt(i);
1091 EXPECT_EQ(InputMsg_HandleInputEvent::ID, message->type());
1092 InputMsg_HandleInputEvent::Param params;
1093 EXPECT_TRUE(InputMsg_HandleInputEvent::Read(message, &params));
1094 const WebInputEvent* event = base::get<0>(params);
1095 if (i != 0)
1096 result += " ";
1097 result += WebInputEventTraits::GetName(event->type);
1099 process->sink().ClearMessages();
1100 return result;
1103 TEST_F(RenderWidgetHostTest, TouchEmulator) {
1104 simulated_event_time_delta_seconds_ = 0.1;
1105 // Immediately ack all touches instead of sending them to the renderer.
1106 host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
1107 host_->SetTouchEventEmulationEnabled(
1108 true, ui::GestureProviderConfigType::GENERIC_MOBILE);
1109 process_->sink().ClearMessages();
1110 view_->set_bounds(gfx::Rect(0, 0, 400, 200));
1111 view_->Show();
1113 SimulateMouseEvent(WebInputEvent::MouseMove, 10, 10, 0, false);
1114 EXPECT_EQ(0U, process_->sink().message_count());
1116 // Mouse press becomes touch start which in turn becomes tap.
1117 SimulateMouseEvent(WebInputEvent::MouseDown, 10, 10, 0, true);
1118 EXPECT_EQ(WebInputEvent::TouchStart, host_->acked_touch_event_type());
1119 EXPECT_EQ("GestureTapDown", GetInputMessageTypes(process_));
1121 // Mouse drag generates touch move, cancels tap and starts scroll.
1122 SimulateMouseEvent(WebInputEvent::MouseMove, 10, 30, 0, true);
1123 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type());
1124 EXPECT_EQ(
1125 "GestureTapCancel GestureScrollBegin GestureScrollUpdate",
1126 GetInputMessageTypes(process_));
1127 SendInputEventACK(WebInputEvent::GestureScrollUpdate,
1128 INPUT_EVENT_ACK_STATE_CONSUMED);
1129 EXPECT_EQ(0U, process_->sink().message_count());
1131 // Mouse drag with shift becomes pinch.
1132 SimulateMouseEvent(
1133 WebInputEvent::MouseMove, 10, 40, WebInputEvent::ShiftKey, true);
1134 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type());
1135 EXPECT_EQ("GesturePinchBegin",
1136 GetInputMessageTypes(process_));
1137 EXPECT_EQ(0U, process_->sink().message_count());
1139 SimulateMouseEvent(
1140 WebInputEvent::MouseMove, 10, 50, WebInputEvent::ShiftKey, true);
1141 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type());
1142 EXPECT_EQ("GesturePinchUpdate",
1143 GetInputMessageTypes(process_));
1144 SendInputEventACK(WebInputEvent::GesturePinchUpdate,
1145 INPUT_EVENT_ACK_STATE_CONSUMED);
1146 EXPECT_EQ(0U, process_->sink().message_count());
1148 // Mouse drag without shift becomes scroll again.
1149 SimulateMouseEvent(WebInputEvent::MouseMove, 10, 60, 0, true);
1150 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type());
1151 EXPECT_EQ("GesturePinchEnd GestureScrollUpdate",
1152 GetInputMessageTypes(process_));
1153 SendInputEventACK(WebInputEvent::GestureScrollUpdate,
1154 INPUT_EVENT_ACK_STATE_CONSUMED);
1155 EXPECT_EQ(0U, process_->sink().message_count());
1157 SimulateMouseEvent(WebInputEvent::MouseMove, 10, 70, 0, true);
1158 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type());
1159 EXPECT_EQ("GestureScrollUpdate",
1160 GetInputMessageTypes(process_));
1161 SendInputEventACK(WebInputEvent::GestureScrollUpdate,
1162 INPUT_EVENT_ACK_STATE_CONSUMED);
1163 EXPECT_EQ(0U, process_->sink().message_count());
1165 SimulateMouseEvent(WebInputEvent::MouseUp, 10, 70, 0, true);
1166 EXPECT_EQ(WebInputEvent::TouchEnd, host_->acked_touch_event_type());
1167 EXPECT_EQ("GestureScrollEnd", GetInputMessageTypes(process_));
1168 EXPECT_EQ(0U, process_->sink().message_count());
1170 // Mouse move does nothing.
1171 SimulateMouseEvent(WebInputEvent::MouseMove, 10, 80, 0, false);
1172 EXPECT_EQ(0U, process_->sink().message_count());
1174 // Another mouse down continues scroll.
1175 SimulateMouseEvent(WebInputEvent::MouseDown, 10, 80, 0, true);
1176 EXPECT_EQ(WebInputEvent::TouchStart, host_->acked_touch_event_type());
1177 EXPECT_EQ("GestureTapDown", GetInputMessageTypes(process_));
1178 EXPECT_EQ(0U, process_->sink().message_count());
1180 SimulateMouseEvent(WebInputEvent::MouseMove, 10, 100, 0, true);
1181 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type());
1182 EXPECT_EQ(
1183 "GestureTapCancel GestureScrollBegin GestureScrollUpdate",
1184 GetInputMessageTypes(process_));
1185 SendInputEventACK(WebInputEvent::GestureScrollUpdate,
1186 INPUT_EVENT_ACK_STATE_CONSUMED);
1187 EXPECT_EQ(0U, process_->sink().message_count());
1189 // Another pinch.
1190 SimulateMouseEvent(
1191 WebInputEvent::MouseMove, 10, 110, WebInputEvent::ShiftKey, true);
1192 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type());
1193 EXPECT_EQ("GesturePinchBegin",
1194 GetInputMessageTypes(process_));
1195 EXPECT_EQ(0U, process_->sink().message_count());
1197 SimulateMouseEvent(
1198 WebInputEvent::MouseMove, 10, 120, WebInputEvent::ShiftKey, true);
1199 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type());
1200 EXPECT_EQ("GesturePinchUpdate",
1201 GetInputMessageTypes(process_));
1202 SendInputEventACK(WebInputEvent::GesturePinchUpdate,
1203 INPUT_EVENT_ACK_STATE_CONSUMED);
1204 EXPECT_EQ(0U, process_->sink().message_count());
1206 // Turn off emulation during a pinch.
1207 host_->SetTouchEventEmulationEnabled(
1208 false, ui::GestureProviderConfigType::GENERIC_MOBILE);
1209 EXPECT_EQ(WebInputEvent::TouchCancel, host_->acked_touch_event_type());
1210 EXPECT_EQ("GesturePinchEnd GestureScrollEnd",
1211 GetInputMessageTypes(process_));
1212 EXPECT_EQ(0U, process_->sink().message_count());
1214 // Mouse event should pass untouched.
1215 SimulateMouseEvent(
1216 WebInputEvent::MouseMove, 10, 10, WebInputEvent::ShiftKey, true);
1217 EXPECT_EQ("MouseMove", GetInputMessageTypes(process_));
1218 SendInputEventACK(WebInputEvent::MouseMove,
1219 INPUT_EVENT_ACK_STATE_CONSUMED);
1220 EXPECT_EQ(0U, process_->sink().message_count());
1222 // Turn on emulation.
1223 host_->SetTouchEventEmulationEnabled(
1224 true, ui::GestureProviderConfigType::GENERIC_MOBILE);
1225 EXPECT_EQ(0U, process_->sink().message_count());
1227 // Another touch.
1228 SimulateMouseEvent(WebInputEvent::MouseDown, 10, 10, 0, true);
1229 EXPECT_EQ(WebInputEvent::TouchStart, host_->acked_touch_event_type());
1230 EXPECT_EQ("GestureTapDown", GetInputMessageTypes(process_));
1231 EXPECT_EQ(0U, process_->sink().message_count());
1233 // Scroll.
1234 SimulateMouseEvent(WebInputEvent::MouseMove, 10, 30, 0, true);
1235 EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type());
1236 EXPECT_EQ(
1237 "GestureTapCancel GestureScrollBegin GestureScrollUpdate",
1238 GetInputMessageTypes(process_));
1239 SendInputEventACK(WebInputEvent::GestureScrollUpdate,
1240 INPUT_EVENT_ACK_STATE_CONSUMED);
1242 // Turn off emulation during a scroll.
1243 host_->SetTouchEventEmulationEnabled(
1244 false, ui::GestureProviderConfigType::GENERIC_MOBILE);
1245 EXPECT_EQ(WebInputEvent::TouchCancel, host_->acked_touch_event_type());
1247 EXPECT_EQ("GestureScrollEnd", GetInputMessageTypes(process_));
1248 EXPECT_EQ(0U, process_->sink().message_count());
1251 #define TEST_InputRouterRoutes_NOARGS(INPUTMSG) \
1252 TEST_F(RenderWidgetHostTest, InputRouterRoutes##INPUTMSG) { \
1253 host_->SetupForInputRouterTest(); \
1254 host_->INPUTMSG(); \
1255 EXPECT_TRUE(host_->mock_input_router()->send_event_called_); \
1258 TEST_InputRouterRoutes_NOARGS(Focus);
1259 TEST_InputRouterRoutes_NOARGS(Blur);
1260 TEST_InputRouterRoutes_NOARGS(LostCapture);
1262 #undef TEST_InputRouterRoutes_NOARGS
1264 #define TEST_InputRouterRoutes_NOARGS_FromRFH(INPUTMSG) \
1265 TEST_F(RenderWidgetHostTest, InputRouterRoutes##INPUTMSG) { \
1266 host_->SetupForInputRouterTest(); \
1267 host_->Send(new INPUTMSG(host_->GetRoutingID())); \
1268 EXPECT_TRUE(host_->mock_input_router()->send_event_called_); \
1271 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Undo);
1272 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Redo);
1273 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Cut);
1274 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Copy);
1275 #if defined(OS_MACOSX)
1276 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_CopyToFindPboard);
1277 #endif
1278 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Paste);
1279 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_PasteAndMatchStyle);
1280 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Delete);
1281 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_SelectAll);
1282 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Unselect);
1284 #undef TEST_InputRouterRoutes_NOARGS_FromRFH
1286 TEST_F(RenderWidgetHostTest, InputRouterRoutesReplace) {
1287 host_->SetupForInputRouterTest();
1288 host_->Send(new InputMsg_Replace(host_->GetRoutingID(), base::string16()));
1289 EXPECT_TRUE(host_->mock_input_router()->send_event_called_);
1292 TEST_F(RenderWidgetHostTest, InputRouterRoutesReplaceMisspelling) {
1293 host_->SetupForInputRouterTest();
1294 host_->Send(new InputMsg_ReplaceMisspelling(host_->GetRoutingID(),
1295 base::string16()));
1296 EXPECT_TRUE(host_->mock_input_router()->send_event_called_);
1299 TEST_F(RenderWidgetHostTest, IgnoreInputEvent) {
1300 host_->SetupForInputRouterTest();
1302 host_->SetIgnoreInputEvents(true);
1304 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
1305 EXPECT_FALSE(host_->mock_input_router()->sent_keyboard_event_);
1307 SimulateMouseEvent(WebInputEvent::MouseMove);
1308 EXPECT_FALSE(host_->mock_input_router()->sent_mouse_event_);
1310 SimulateWheelEvent(0, 100, 0, true);
1311 EXPECT_FALSE(host_->mock_input_router()->sent_wheel_event_);
1313 SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
1314 blink::WebGestureDeviceTouchpad);
1315 EXPECT_FALSE(host_->mock_input_router()->sent_gesture_event_);
1317 PressTouchPoint(100, 100);
1318 SendTouchEvent();
1319 EXPECT_FALSE(host_->mock_input_router()->send_touch_event_not_cancelled_);
1322 TEST_F(RenderWidgetHostTest, KeyboardListenerIgnoresEvent) {
1323 host_->SetupForInputRouterTest();
1324 host_->AddKeyPressEventCallback(
1325 base::Bind(&RenderWidgetHostTest::KeyPressEventCallback,
1326 base::Unretained(this)));
1327 handle_key_press_event_ = false;
1328 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
1330 EXPECT_TRUE(host_->mock_input_router()->sent_keyboard_event_);
1333 TEST_F(RenderWidgetHostTest, KeyboardListenerSuppressFollowingEvents) {
1334 host_->SetupForInputRouterTest();
1336 host_->AddKeyPressEventCallback(
1337 base::Bind(&RenderWidgetHostTest::KeyPressEventCallback,
1338 base::Unretained(this)));
1340 // The callback handles the first event
1341 handle_key_press_event_ = true;
1342 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
1344 EXPECT_FALSE(host_->mock_input_router()->sent_keyboard_event_);
1346 // Following Char events should be suppressed
1347 handle_key_press_event_ = false;
1348 SimulateKeyboardEvent(WebInputEvent::Char);
1349 EXPECT_FALSE(host_->mock_input_router()->sent_keyboard_event_);
1350 SimulateKeyboardEvent(WebInputEvent::Char);
1351 EXPECT_FALSE(host_->mock_input_router()->sent_keyboard_event_);
1353 // Sending RawKeyDown event should stop suppression
1354 SimulateKeyboardEvent(WebInputEvent::RawKeyDown);
1355 EXPECT_TRUE(host_->mock_input_router()->sent_keyboard_event_);
1357 host_->mock_input_router()->sent_keyboard_event_ = false;
1358 SimulateKeyboardEvent(WebInputEvent::Char);
1359 EXPECT_TRUE(host_->mock_input_router()->sent_keyboard_event_);
1362 TEST_F(RenderWidgetHostTest, MouseEventCallbackCanHandleEvent) {
1363 host_->SetupForInputRouterTest();
1365 host_->AddMouseEventCallback(
1366 base::Bind(&RenderWidgetHostTest::MouseEventCallback,
1367 base::Unretained(this)));
1369 handle_mouse_event_ = true;
1370 SimulateMouseEvent(WebInputEvent::MouseDown);
1372 EXPECT_FALSE(host_->mock_input_router()->sent_mouse_event_);
1374 handle_mouse_event_ = false;
1375 SimulateMouseEvent(WebInputEvent::MouseDown);
1377 EXPECT_TRUE(host_->mock_input_router()->sent_mouse_event_);
1380 TEST_F(RenderWidgetHostTest, InputRouterReceivesHandleInputEvent_ACK) {
1381 host_->SetupForInputRouterTest();
1383 SendInputEventACK(WebInputEvent::RawKeyDown,
1384 INPUT_EVENT_ACK_STATE_CONSUMED);
1386 EXPECT_TRUE(host_->mock_input_router()->message_received_);
1389 TEST_F(RenderWidgetHostTest, InputRouterReceivesMoveCaret_ACK) {
1390 host_->SetupForInputRouterTest();
1392 host_->OnMessageReceived(InputHostMsg_MoveCaret_ACK(0));
1394 EXPECT_TRUE(host_->mock_input_router()->message_received_);
1397 TEST_F(RenderWidgetHostTest, InputRouterReceivesSelectRange_ACK) {
1398 host_->SetupForInputRouterTest();
1400 host_->OnMessageReceived(InputHostMsg_SelectRange_ACK(0));
1402 EXPECT_TRUE(host_->mock_input_router()->message_received_);
1405 TEST_F(RenderWidgetHostTest, InputRouterReceivesHasTouchEventHandlers) {
1406 host_->SetupForInputRouterTest();
1408 host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
1410 EXPECT_TRUE(host_->mock_input_router()->message_received_);
1413 ui::LatencyInfo GetLatencyInfoFromInputEvent(RenderWidgetHostProcess* process) {
1414 const IPC::Message* message = process->sink().GetUniqueMessageMatching(
1415 InputMsg_HandleInputEvent::ID);
1416 EXPECT_TRUE(message);
1417 InputMsg_HandleInputEvent::Param params;
1418 EXPECT_TRUE(InputMsg_HandleInputEvent::Read(message, &params));
1419 process->sink().ClearMessages();
1420 return base::get<1>(params);
1423 void CheckLatencyInfoComponentInMessage(RenderWidgetHostProcess* process,
1424 int64 component_id,
1425 WebInputEvent::Type input_type) {
1426 ui::LatencyInfo latency_info = GetLatencyInfoFromInputEvent(process);
1427 EXPECT_TRUE(latency_info.FindLatency(
1428 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
1429 component_id,
1430 NULL));
1433 // Tests that after input event passes through RWHI through ForwardXXXEvent()
1434 // or ForwardXXXEventWithLatencyInfo(), LatencyInfo component
1435 // ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT will always present in the
1436 // event's LatencyInfo.
1437 TEST_F(RenderWidgetHostTest, InputEventRWHLatencyComponent) {
1438 host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
1439 process_->sink().ClearMessages();
1441 // Tests RWHI::ForwardWheelEvent().
1442 SimulateWheelEvent(-5, 0, 0, true);
1443 CheckLatencyInfoComponentInMessage(
1444 process_, GetLatencyComponentId(), WebInputEvent::MouseWheel);
1445 SendInputEventACK(WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
1447 // Tests RWHI::ForwardWheelEventWithLatencyInfo().
1448 SimulateWheelEventWithLatencyInfo(-5, 0, 0, true, ui::LatencyInfo());
1449 CheckLatencyInfoComponentInMessage(
1450 process_, GetLatencyComponentId(), WebInputEvent::MouseWheel);
1451 SendInputEventACK(WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
1453 // Tests RWHI::ForwardMouseEvent().
1454 SimulateMouseEvent(WebInputEvent::MouseMove);
1455 CheckLatencyInfoComponentInMessage(
1456 process_, GetLatencyComponentId(), WebInputEvent::MouseMove);
1457 SendInputEventACK(WebInputEvent::MouseMove, INPUT_EVENT_ACK_STATE_CONSUMED);
1459 // Tests RWHI::ForwardMouseEventWithLatencyInfo().
1460 SimulateMouseEventWithLatencyInfo(WebInputEvent::MouseMove,
1461 ui::LatencyInfo());
1462 CheckLatencyInfoComponentInMessage(
1463 process_, GetLatencyComponentId(), WebInputEvent::MouseMove);
1464 SendInputEventACK(WebInputEvent::MouseMove, INPUT_EVENT_ACK_STATE_CONSUMED);
1466 // Tests RWHI::ForwardGestureEvent().
1467 SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
1468 blink::WebGestureDeviceTouchscreen);
1469 CheckLatencyInfoComponentInMessage(
1470 process_, GetLatencyComponentId(), WebInputEvent::GestureScrollBegin);
1472 // Tests RWHI::ForwardGestureEventWithLatencyInfo().
1473 SimulateGestureEventWithLatencyInfo(WebInputEvent::GestureScrollUpdate,
1474 blink::WebGestureDeviceTouchscreen,
1475 ui::LatencyInfo());
1476 CheckLatencyInfoComponentInMessage(
1477 process_, GetLatencyComponentId(), WebInputEvent::GestureScrollUpdate);
1478 SendInputEventACK(WebInputEvent::GestureScrollUpdate,
1479 INPUT_EVENT_ACK_STATE_CONSUMED);
1481 // Tests RWHI::ForwardTouchEventWithLatencyInfo().
1482 PressTouchPoint(0, 1);
1483 uint32 touch_event_id = SendTouchEvent();
1484 InputEventAck ack(WebInputEvent::TouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
1485 touch_event_id);
1486 host_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
1487 CheckLatencyInfoComponentInMessage(
1488 process_, GetLatencyComponentId(), WebInputEvent::TouchStart);
1491 TEST_F(RenderWidgetHostTest, RendererExitedResetsInputRouter) {
1492 // RendererExited will delete the view.
1493 host_->SetView(new TestView(host_.get()));
1494 host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
1496 // Make sure the input router is in a fresh state.
1497 ASSERT_FALSE(host_->input_router()->HasPendingEvents());
1500 // Regression test for http://crbug.com/401859.
1501 TEST_F(RenderWidgetHostTest, RendererExitedResetsIsHidden) {
1502 // RendererExited will delete the view.
1503 host_->SetView(new TestView(host_.get()));
1504 host_->WasHidden();
1506 ASSERT_TRUE(host_->is_hidden());
1507 host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
1508 ASSERT_FALSE(host_->is_hidden());
1510 // Make sure the input router is in a fresh state.
1511 ASSERT_FALSE(host_->input_router()->HasPendingEvents());
1514 TEST_F(RenderWidgetHostTest, ResizeParams) {
1515 gfx::Rect bounds(0, 0, 100, 100);
1516 gfx::Size physical_backing_size(40, 50);
1517 view_->set_bounds(bounds);
1518 view_->SetMockPhysicalBackingSize(physical_backing_size);
1520 ViewMsg_Resize_Params resize_params;
1521 host_->GetResizeParams(&resize_params);
1522 EXPECT_EQ(bounds.size(), resize_params.new_size);
1523 EXPECT_EQ(physical_backing_size, resize_params.physical_backing_size);
1526 class RenderWidgetHostInitialSizeTest : public RenderWidgetHostTest {
1527 public:
1528 RenderWidgetHostInitialSizeTest()
1529 : RenderWidgetHostTest(), initial_size_(200, 100) {}
1531 void ConfigureView(TestView* view) override {
1532 view->set_bounds(gfx::Rect(initial_size_));
1535 protected:
1536 gfx::Size initial_size_;
1539 TEST_F(RenderWidgetHostInitialSizeTest, InitialSize) {
1540 // Having an initial size set means that the size information had been sent
1541 // with the reqiest to new up the RenderView and so subsequent WasResized
1542 // calls should not result in new IPC (unless the size has actually changed).
1543 host_->WasResized();
1544 EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
1545 EXPECT_EQ(initial_size_, host_->old_resize_params_->new_size);
1546 EXPECT_TRUE(host_->resize_ack_pending_);
1549 } // namespace content