Index: trunk/src/content/browser/renderer_host/render_widget_host_unittest.cc |
=================================================================== |
--- trunk/src/content/browser/renderer_host/render_widget_host_unittest.cc (revision 263805) |
+++ trunk/src/content/browser/renderer_host/render_widget_host_unittest.cc (working copy) |
@@ -48,6 +48,7 @@ |
using blink::WebGestureEvent; |
using blink::WebInputEvent; |
using blink::WebKeyboardEvent; |
+using blink::WebMouseEvent; |
using blink::WebMouseWheelEvent; |
using blink::WebTouchEvent; |
using blink::WebTouchPoint; |
@@ -199,6 +200,7 @@ |
: RenderWidgetHostImpl(delegate, process, routing_id, false), |
unresponsive_timer_fired_(false) { |
input_router_impl_ = static_cast<InputRouterImpl*>(input_router_.get()); |
+ acked_touch_event_type_ = blink::WebInputEvent::Undefined; |
} |
// Allow poking at a few private members. |
@@ -261,6 +263,18 @@ |
return touch_event_queue().empty(); |
} |
+ virtual void OnTouchEventAck( |
+ const TouchEventWithLatencyInfo& event, |
+ InputEventAckState ack_result) OVERRIDE { |
+ // Sniff touch acks. |
+ acked_touch_event_type_ = event.event.type; |
+ RenderWidgetHostImpl::OnTouchEventAck(event, ack_result); |
+ } |
+ |
+ WebInputEvent::Type acked_touch_event_type() const { |
+ return acked_touch_event_type_; |
+ } |
+ |
bool ScrollStateIsContentScrolling() const { |
return scroll_state() == OverscrollController::STATE_CONTENT_SCROLLING; |
} |
@@ -321,6 +335,7 @@ |
private: |
bool unresponsive_timer_fired_; |
+ WebInputEvent::Type acked_touch_event_type_; |
// |input_router_impl_| and |mock_input_router_| are owned by |
// RenderWidgetHostImpl. The handles below are provided for convenience so |
@@ -582,7 +597,10 @@ |
RenderWidgetHostTest() |
: process_(NULL), |
handle_key_press_event_(false), |
- handle_mouse_event_(false) { |
+ handle_mouse_event_(false), |
+ simulated_event_time_delta_seconds_(0) { |
+ last_simulated_event_time_seconds_ = |
+ (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); |
} |
virtual ~RenderWidgetHostTest() { |
} |
@@ -645,10 +663,20 @@ |
host_->OnMessageReceived(*response); |
} |
+ double GetNextSimulatedEventTimeSeconds() { |
+ last_simulated_event_time_seconds_ += simulated_event_time_delta_seconds_; |
+ return last_simulated_event_time_seconds_; |
+ } |
+ |
void SimulateKeyboardEvent(WebInputEvent::Type type) { |
- WebKeyboardEvent event = SyntheticWebKeyboardEventBuilder::Build(type); |
- NativeWebKeyboardEvent native_event; |
- memcpy(&native_event, &event, sizeof(event)); |
+ SimulateKeyboardEvent(type, 0); |
+ } |
+ |
+ void SimulateKeyboardEvent(WebInputEvent::Type type, int modifiers) { |
+ WebKeyboardEvent event = SyntheticWebKeyboardEventBuilder::Build(type); |
+ event.modifiers = modifiers; |
+ NativeWebKeyboardEvent native_event; |
+ memcpy(&native_event, &event, sizeof(event)); |
host_->ForwardKeyboardEvent(native_event); |
} |
@@ -679,13 +707,19 @@ |
} |
void SimulateMouseMove(int x, int y, int modifiers) { |
- host_->ForwardMouseEvent( |
- SyntheticWebMouseEventBuilder::Build(WebInputEvent::MouseMove, |
- x, |
- y, |
- modifiers)); |
+ SimulateMouseEvent(WebInputEvent::MouseMove, x, y, modifiers, false); |
} |
+ void SimulateMouseEvent( |
+ WebInputEvent::Type type, int x, int y, int modifiers, bool pressed) { |
+ WebMouseEvent event = |
+ SyntheticWebMouseEventBuilder::Build(type, x, y, modifiers); |
+ if (pressed) |
+ event.button = WebMouseEvent::ButtonLeft; |
+ event.timeStampSeconds = GetNextSimulatedEventTimeSeconds(); |
+ host_->ForwardMouseEvent(event); |
+ } |
+ |
void SimulateWheelEventWithPhase(WebMouseWheelEvent::Phase phase) { |
host_->ForwardWheelEvent(SyntheticWebMouseWheelEventBuilder::Build(phase)); |
} |
@@ -788,6 +822,8 @@ |
scoped_ptr<gfx::Screen> screen_; |
bool handle_key_press_event_; |
bool handle_mouse_event_; |
+ double last_simulated_event_time_seconds_; |
+ double simulated_event_time_delta_seconds_; |
private: |
SyntheticWebTouchEvent touch_event_; |
@@ -2381,6 +2417,203 @@ |
process_->sink().ClearMessages(); |
} |
+std::string GetInputMessageTypes(RenderWidgetHostProcess* process) { |
+ const WebInputEvent* event = NULL; |
+ ui::LatencyInfo latency_info; |
+ bool is_keyboard_shortcut; |
+ std::string result; |
+ for (size_t i = 0; i < process->sink().message_count(); ++i) { |
+ const IPC::Message *message = process->sink().GetMessageAt(i); |
+ EXPECT_EQ(InputMsg_HandleInputEvent::ID, message->type()); |
+ EXPECT_TRUE(InputMsg_HandleInputEvent::Read( |
+ message, &event, &latency_info, &is_keyboard_shortcut)); |
+ if (i != 0) |
+ result += " "; |
+ result += WebInputEventTraits::GetName(event->type); |
+ } |
+ process->sink().ClearMessages(); |
+ return result; |
+} |
+ |
+TEST_F(RenderWidgetHostTest, TouchEmulator) { |
+ simulated_event_time_delta_seconds_ = 0.1; |
+ host_->DisableGestureDebounce(); |
+ // Immediately ack all touches instead of sending them to the renderer. |
+ host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false)); |
+ host_->OnMessageReceived( |
+ ViewHostMsg_SetTouchEventEmulationEnabled(0, true, true)); |
+ process_->sink().ClearMessages(); |
+ view_->set_bounds(gfx::Rect(0, 0, 400, 200)); |
+ view_->Show(); |
+ |
+ SimulateMouseEvent(WebInputEvent::MouseMove, 10, 10, 0, false); |
+ EXPECT_EQ(0U, process_->sink().message_count()); |
+ |
+ // Mouse press becomes touch start which in turn becomes tap. |
+ SimulateMouseEvent(WebInputEvent::MouseDown, 10, 10, 0, true); |
+ EXPECT_EQ(WebInputEvent::TouchStart, host_->acked_touch_event_type()); |
+ EXPECT_EQ("GestureTapDown", GetInputMessageTypes(process_)); |
+ SendInputEventACK(WebInputEvent::GestureTapDown, |
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
+ |
+ // Mouse drag generates touch move, cancels tap and starts scroll. |
+ SimulateMouseEvent(WebInputEvent::MouseMove, 10, 30, 0, true); |
+ EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); |
+ EXPECT_EQ( |
+ "GestureTapCancel GestureScrollBegin GestureScrollUpdate", |
+ GetInputMessageTypes(process_)); |
+ SendInputEventACK(WebInputEvent::GestureTapCancel, |
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
+ SendInputEventACK(WebInputEvent::GestureScrollBegin, |
+ INPUT_EVENT_ACK_STATE_CONSUMED); |
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate, |
+ INPUT_EVENT_ACK_STATE_CONSUMED); |
+ EXPECT_EQ(0U, process_->sink().message_count()); |
+ |
+ // Mouse drag with shift becomes pinch. |
+ SimulateMouseEvent( |
+ WebInputEvent::MouseMove, 10, 40, WebInputEvent::ShiftKey, true); |
+ EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); |
+ EXPECT_EQ("GesturePinchBegin", |
+ GetInputMessageTypes(process_)); |
+ SendInputEventACK(WebInputEvent::GesturePinchBegin, |
+ INPUT_EVENT_ACK_STATE_CONSUMED); |
+ EXPECT_EQ(0U, process_->sink().message_count()); |
+ |
+ SimulateMouseEvent( |
+ WebInputEvent::MouseMove, 10, 50, WebInputEvent::ShiftKey, true); |
+ EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); |
+ EXPECT_EQ("GesturePinchUpdate", |
+ GetInputMessageTypes(process_)); |
+ SendInputEventACK(WebInputEvent::GesturePinchUpdate, |
+ INPUT_EVENT_ACK_STATE_CONSUMED); |
+ EXPECT_EQ(0U, process_->sink().message_count()); |
+ |
+ // Mouse drag without shift becomes scroll again. |
+ SimulateMouseEvent(WebInputEvent::MouseMove, 10, 60, 0, true); |
+ EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); |
+ EXPECT_EQ("GesturePinchEnd GestureScrollUpdate", |
+ GetInputMessageTypes(process_)); |
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate, |
+ INPUT_EVENT_ACK_STATE_CONSUMED); |
+ EXPECT_EQ(0U, process_->sink().message_count()); |
+ |
+ SimulateMouseEvent(WebInputEvent::MouseMove, 10, 70, 0, true); |
+ EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); |
+ EXPECT_EQ("GestureScrollUpdate", |
+ GetInputMessageTypes(process_)); |
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate, |
+ INPUT_EVENT_ACK_STATE_CONSUMED); |
+ EXPECT_EQ(0U, process_->sink().message_count()); |
+ |
+ SimulateMouseEvent(WebInputEvent::MouseUp, 10, 70, 0, true); |
+ EXPECT_EQ(WebInputEvent::TouchEnd, host_->acked_touch_event_type()); |
+ EXPECT_EQ("GestureScrollEnd", GetInputMessageTypes(process_)); |
+ SendInputEventACK(WebInputEvent::GestureScrollEnd, |
+ INPUT_EVENT_ACK_STATE_CONSUMED); |
+ EXPECT_EQ(0U, process_->sink().message_count()); |
+ |
+ // Mouse move does nothing. |
+ SimulateMouseEvent(WebInputEvent::MouseMove, 10, 80, 0, false); |
+ EXPECT_EQ(0U, process_->sink().message_count()); |
+ |
+ // Another mouse down continues scroll. |
+ SimulateMouseEvent(WebInputEvent::MouseDown, 10, 80, 0, true); |
+ EXPECT_EQ(WebInputEvent::TouchStart, host_->acked_touch_event_type()); |
+ EXPECT_EQ("GestureTapDown", GetInputMessageTypes(process_)); |
+ SendInputEventACK(WebInputEvent::GestureTapDown, |
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
+ EXPECT_EQ(0U, process_->sink().message_count()); |
+ |
+ SimulateMouseEvent(WebInputEvent::MouseMove, 10, 100, 0, true); |
+ EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); |
+ EXPECT_EQ( |
+ "GestureTapCancel GestureScrollBegin GestureScrollUpdate", |
+ GetInputMessageTypes(process_)); |
+ SendInputEventACK(WebInputEvent::GestureTapCancel, |
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
+ SendInputEventACK(WebInputEvent::GestureScrollBegin, |
+ INPUT_EVENT_ACK_STATE_CONSUMED); |
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate, |
+ INPUT_EVENT_ACK_STATE_CONSUMED); |
+ EXPECT_EQ(0U, process_->sink().message_count()); |
+ |
+ // Another pinch. |
+ SimulateMouseEvent( |
+ WebInputEvent::MouseMove, 10, 110, WebInputEvent::ShiftKey, true); |
+ EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); |
+ EXPECT_EQ("GesturePinchBegin", |
+ GetInputMessageTypes(process_)); |
+ SendInputEventACK(WebInputEvent::GesturePinchBegin, |
+ INPUT_EVENT_ACK_STATE_CONSUMED); |
+ EXPECT_EQ(0U, process_->sink().message_count()); |
+ |
+ SimulateMouseEvent( |
+ WebInputEvent::MouseMove, 10, 120, WebInputEvent::ShiftKey, true); |
+ EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); |
+ EXPECT_EQ("GesturePinchUpdate", |
+ GetInputMessageTypes(process_)); |
+ SendInputEventACK(WebInputEvent::GesturePinchUpdate, |
+ INPUT_EVENT_ACK_STATE_CONSUMED); |
+ EXPECT_EQ(0U, process_->sink().message_count()); |
+ |
+ // Turn off emulation during a pinch. |
+ host_->OnMessageReceived( |
+ ViewHostMsg_SetTouchEventEmulationEnabled(0, false, false)); |
+ EXPECT_EQ(WebInputEvent::TouchCancel, host_->acked_touch_event_type()); |
+ EXPECT_EQ("GesturePinchEnd GestureScrollEnd", |
+ GetInputMessageTypes(process_)); |
+ SendInputEventACK(WebInputEvent::GesturePinchEnd, |
+ INPUT_EVENT_ACK_STATE_CONSUMED); |
+ SendInputEventACK(WebInputEvent::GestureScrollEnd, |
+ INPUT_EVENT_ACK_STATE_CONSUMED); |
+ EXPECT_EQ(0U, process_->sink().message_count()); |
+ |
+ // Mouse event should pass untouched. |
+ SimulateMouseEvent( |
+ WebInputEvent::MouseMove, 10, 10, WebInputEvent::ShiftKey, true); |
+ EXPECT_EQ("MouseMove", GetInputMessageTypes(process_)); |
+ SendInputEventACK(WebInputEvent::MouseMove, |
+ INPUT_EVENT_ACK_STATE_CONSUMED); |
+ EXPECT_EQ(0U, process_->sink().message_count()); |
+ |
+ // Turn on emulation. |
+ host_->OnMessageReceived( |
+ ViewHostMsg_SetTouchEventEmulationEnabled(0, true, true)); |
+ EXPECT_EQ(0U, process_->sink().message_count()); |
+ |
+ // Another touch. |
+ SimulateMouseEvent(WebInputEvent::MouseDown, 10, 10, 0, true); |
+ EXPECT_EQ(WebInputEvent::TouchStart, host_->acked_touch_event_type()); |
+ EXPECT_EQ("GestureTapDown", GetInputMessageTypes(process_)); |
+ SendInputEventACK(WebInputEvent::GestureTapDown, |
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
+ EXPECT_EQ(0U, process_->sink().message_count()); |
+ |
+ // Scroll. |
+ SimulateMouseEvent(WebInputEvent::MouseMove, 10, 30, 0, true); |
+ EXPECT_EQ(WebInputEvent::TouchMove, host_->acked_touch_event_type()); |
+ EXPECT_EQ( |
+ "GestureTapCancel GestureScrollBegin GestureScrollUpdate", |
+ GetInputMessageTypes(process_)); |
+ SendInputEventACK(WebInputEvent::GestureTapCancel, |
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
+ SendInputEventACK(WebInputEvent::GestureScrollBegin, |
+ INPUT_EVENT_ACK_STATE_CONSUMED); |
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate, |
+ INPUT_EVENT_ACK_STATE_CONSUMED); |
+ |
+ // Turn off emulation during a scroll. |
+ host_->OnMessageReceived( |
+ ViewHostMsg_SetTouchEventEmulationEnabled(0, false, false)); |
+ EXPECT_EQ(WebInputEvent::TouchCancel, host_->acked_touch_event_type()); |
+ |
+ EXPECT_EQ("GestureScrollEnd", GetInputMessageTypes(process_)); |
+ SendInputEventACK(WebInputEvent::GestureScrollEnd, |
+ INPUT_EVENT_ACK_STATE_CONSUMED); |
+ EXPECT_EQ(0U, process_->sink().message_count()); |
+} |
+ |
#define TEST_InputRouterRoutes_NOARGS(INPUTMSG) \ |
TEST_F(RenderWidgetHostTest, InputRouterRoutes##INPUTMSG) { \ |
host_->SetupForInputRouterTest(); \ |