#include "base/memory/shared_memory.h"
#include "base/timer/timer.h"
#include "content/browser/browser_thread_impl.h"
-#include "content/browser/renderer_host/backing_store.h"
#include "content/browser/renderer_host/input/gesture_event_queue.h"
#include "content/browser/renderer_host/input/input_router_impl.h"
-#include "content/browser/renderer_host/input/tap_suppression_controller.h"
-#include "content/browser/renderer_host/input/tap_suppression_controller_client.h"
#include "content/browser/renderer_host/input/touch_event_queue.h"
#include "content/browser/renderer_host/overscroll_controller.h"
#include "content/browser/renderer_host/overscroll_controller_delegate.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
+#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
-#include "content/port/browser/render_widget_host_view_port.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/screen.h"
+#if defined(OS_ANDROID)
+#include "content/browser/renderer_host/render_widget_host_view_android.h"
+#endif
+
#if defined(USE_AURA)
#include "content/browser/compositor/image_transport_factory.h"
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#include "content/browser/renderer_host/ui_events_helper.h"
#include "ui/aura/env.h"
#include "ui/aura/test/test_screen.h"
#include "ui/compositor/test/in_process_context_factory.h"
-#endif
-
-#if defined(OS_WIN) || defined(USE_AURA)
-#include "content/browser/renderer_host/ui_events_helper.h"
#include "ui/events/event.h"
#endif
using blink::WebGestureEvent;
using blink::WebInputEvent;
using blink::WebKeyboardEvent;
+using blink::WebMouseEvent;
using blink::WebMouseWheelEvent;
using blink::WebTouchEvent;
using blink::WebTouchPoint;
int routing_id)
: 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.
}
unsigned GestureEventLastQueueEventSize() const {
- return gesture_event_queue()->coalesced_gesture_events_.size();
+ return gesture_event_queue().coalesced_gesture_events_.size();
}
WebGestureEvent GestureEventSecondFromLastQueueEvent() const {
- return gesture_event_queue()->coalesced_gesture_events_.at(
+ return gesture_event_queue().coalesced_gesture_events_.at(
GestureEventLastQueueEventSize() - 2).event;
}
WebGestureEvent GestureEventLastQueueEvent() const {
- return gesture_event_queue()->coalesced_gesture_events_.back().event;
+ return gesture_event_queue().coalesced_gesture_events_.back().event;
}
unsigned GestureEventDebouncingQueueSize() const {
- return gesture_event_queue()->debouncing_deferral_queue_.size();
+ return gesture_event_queue().debouncing_deferral_queue_.size();
}
WebGestureEvent GestureEventQueueEventAt(int i) const {
- return gesture_event_queue()->coalesced_gesture_events_.at(i).event;
+ return gesture_event_queue().coalesced_gesture_events_.at(i).event;
}
bool ScrollingInProgress() const {
- return gesture_event_queue()->scrolling_in_progress_;
- }
-
- bool FlingInProgress() const {
- return gesture_event_queue()->fling_in_progress_;
- }
-
- bool WillIgnoreNextACK() const {
- return gesture_event_queue()->ignore_next_ack_;
+ return gesture_event_queue().scrolling_in_progress_;
}
void SetupForOverscrollControllerTest() {
overscroll_controller_->set_delegate(overscroll_delegate_.get());
}
- void DisableGestureDebounce() {
- gesture_event_queue()->set_debounce_enabled_for_testing(false);
- }
+ void DisableGestureDebounce() { set_debounce_interval_time_ms(0); }
void set_debounce_interval_time_ms(int delay_ms) {
- gesture_event_queue()->
- set_debounce_interval_time_ms_for_testing(delay_ms);
+ gesture_event_queue().set_debounce_interval_time_ms_for_testing(delay_ms);
}
bool TouchEventQueueEmpty() const {
- return touch_event_queue()->empty();
+ 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 {
}
void SetupForInputRouterTest() {
- mock_input_router_ = new MockInputRouter(this);
- input_router_.reset(mock_input_router_);
+ input_router_.reset(new MockInputRouter(this));
}
MockInputRouter* mock_input_router() {
- return mock_input_router_;
+ return static_cast<MockInputRouter*>(input_router_.get());
}
protected:
unresponsive_timer_fired_ = true;
}
- const TouchEventQueue* touch_event_queue() const {
- return input_router_impl_->touch_event_queue_.get();
+ const TouchEventQueue& touch_event_queue() const {
+ return input_router_impl()->touch_event_queue_;
}
- const GestureEventQueue* gesture_event_queue() const {
- return input_router_impl_->gesture_event_queue_.get();
+ const GestureEventQueue& gesture_event_queue() const {
+ return input_router_impl()->gesture_event_queue_;
}
- GestureEventQueue* gesture_event_queue() {
- return input_router_impl_->gesture_event_queue_.get();
+ GestureEventQueue& gesture_event_queue() {
+ return input_router_impl()->gesture_event_queue_;
}
private:
- bool unresponsive_timer_fired_;
+ const InputRouterImpl* input_router_impl() const {
+ return static_cast<InputRouterImpl*>(input_router_.get());
+ }
- // |input_router_impl_| and |mock_input_router_| are owned by
- // RenderWidgetHostImpl. The handles below are provided for convenience so
- // that we don't have to reinterpret_cast it all the time.
- InputRouterImpl* input_router_impl_;
- MockInputRouter* mock_input_router_;
+ InputRouterImpl* input_router_impl() {
+ return static_cast<InputRouterImpl*>(input_router_.get());
+ }
+
+ bool unresponsive_timer_fired_;
+ WebInputEvent::Type acked_touch_event_type_;
scoped_ptr<TestOverscrollDelegate> overscroll_delegate_;
public:
explicit RenderWidgetHostProcess(BrowserContext* browser_context)
: MockRenderProcessHost(browser_context),
- current_update_buf_(NULL),
update_msg_should_reply_(false),
update_msg_reply_flags_(0) {
}
virtual ~RenderWidgetHostProcess() {
- delete current_update_buf_;
}
void set_update_msg_should_reply(bool reply) {
const base::TimeDelta& max_delay,
IPC::Message* msg) OVERRIDE;
- TransportDIB* current_update_buf_;
-
// Set to true when WaitForBackingStoreMsg should return a successful update
// message reply. False implies timeout.
bool update_msg_should_reply_;
void RenderWidgetHostProcess::InitUpdateRectParams(
ViewHostMsg_UpdateRect_Params* params) {
- // Create the shared backing store.
const int w = 100, h = 100;
- const size_t pixel_size = w * h * 4;
-
- if (!current_update_buf_)
- current_update_buf_ = TransportDIB::Create(pixel_size, 0);
- params->bitmap = current_update_buf_->id();
- params->bitmap_rect = gfx::Rect(0, 0, w, h);
- params->scroll_delta = gfx::Vector2d();
- params->copy_rects.push_back(params->bitmap_rect);
+
params->view_size = gfx::Size(w, h);
params->flags = update_msg_reply_flags_;
- params->needs_ack = true;
- params->scale_factor = 1;
}
bool RenderWidgetHostProcess::WaitForBackingStoreMsg(
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() {
}
#if defined(USE_AURA)
ImageTransportFactory::InitializeForUnitTests(
scoped_ptr<ui::ContextFactory>(new ui::InProcessContextFactory));
- aura::Env::CreateInstance();
+ aura::Env::CreateInstance(true);
screen_.reset(aura::TestScreen::Create());
gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
#endif
view_.reset(new TestView(host_.get()));
host_->SetView(view_.get());
host_->Init();
+
+ // Tests for debounce-related behavior will explicitly enable debouncing.
+ host_->DisableGestureDebounce();
}
virtual void TearDown() {
view_.reset();
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);
}
}
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) {
float anchorX,
float anchorY,
int modifiers) {
- SimulateGestureEventCore(
- SyntheticWebGestureEventBuilder::BuildPinchUpdate(scale,
- anchorX,
- anchorY,
- modifiers));
+ SimulateGestureEventCore(SyntheticWebGestureEventBuilder::BuildPinchUpdate(
+ scale, anchorX, anchorY, modifiers, WebGestureEvent::Touchscreen));
}
// Inject synthetic GestureFlingStart events.
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_;
// Tests setting custom background
TEST_F(RenderWidgetHostTest, Background) {
#if !defined(OS_MACOSX)
- scoped_ptr<RenderWidgetHostView> view(
- RenderWidgetHostView::CreateViewForWidget(host_.get()));
-#if defined(OS_LINUX) || defined(USE_AURA)
+ scoped_ptr<RenderWidgetHostViewBase> view;
+#if defined(USE_AURA)
+ view.reset(new RenderWidgetHostViewAura(host_.get()));
// TODO(derat): Call this on all platforms: http://crbug.com/102450.
- // InitAsChild doesn't seem to work if NULL parent is passed on Windows,
- // which leads to DCHECK failure in RenderWidgetHostView::Destroy.
- // When you enable this for OS_WIN, enable |view.release()->Destroy()|
- // below.
view->InitAsChild(NULL);
+#elif defined(OS_ANDROID)
+ view.reset(new RenderWidgetHostViewAndroid(host_.get(), NULL));
#endif
host_->SetView(view.get());
sent_background.a.unlockPixels();
background.unlockPixels();
-#if defined(OS_LINUX) || defined(USE_AURA)
+#if defined(USE_AURA)
// See the comment above |InitAsChild(NULL)|.
host_->SetView(NULL);
- static_cast<RenderWidgetHostViewPort*>(view.release())->Destroy();
+ static_cast<RenderWidgetHostViewBase*>(view.release())->Destroy();
#endif
#else
// since windows HDC structures are opaque.
}
-// Tests getting the backing store with the renderer not setting repaint ack
-// flags.
-TEST_F(RenderWidgetHostTest, GetBackingStore_NoRepaintAck) {
- // First set the view size to match what the renderer is rendering.
- ViewHostMsg_UpdateRect_Params params;
- process_->InitUpdateRectParams(¶ms);
- view_->set_bounds(gfx::Rect(params.view_size));
-
- // We don't currently have a backing store, and if the renderer doesn't send
- // one in time, we should get nothing.
- process_->set_update_msg_should_reply(false);
- BackingStore* backing = host_->GetBackingStore(true);
- EXPECT_FALSE(backing);
- // The widget host should have sent a request for a repaint, and there should
- // be no paint ACK.
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID));
- EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_UpdateRect_ACK::ID));
-
- // Allowing the renderer to reply in time should give is a backing store.
- process_->sink().ClearMessages();
- process_->set_update_msg_should_reply(true);
- process_->set_update_msg_reply_flags(0);
- backing = host_->GetBackingStore(true);
- EXPECT_TRUE(backing);
- // The widget host should NOT have sent a request for a repaint, since there
- // was an ACK already pending.
- EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID));
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_UpdateRect_ACK::ID));
-}
-
-// Tests getting the backing store with the renderer sending a repaint ack.
-TEST_F(RenderWidgetHostTest, GetBackingStore_RepaintAck) {
- // First set the view size to match what the renderer is rendering.
- ViewHostMsg_UpdateRect_Params params;
- process_->InitUpdateRectParams(¶ms);
- view_->set_bounds(gfx::Rect(params.view_size));
-
- // Doing a request request with the update message allowed should work and
- // the repaint ack should work.
- process_->set_update_msg_should_reply(true);
- process_->set_update_msg_reply_flags(
- ViewHostMsg_UpdateRect_Flags::IS_REPAINT_ACK);
- BackingStore* backing = host_->GetBackingStore(true);
- EXPECT_TRUE(backing);
- // We still should not have sent out a repaint request since the last flags
- // didn't have the repaint ack set, and the pending flag will still be set.
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID));
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_UpdateRect_ACK::ID));
-
- // Asking again for the backing store should just re-use the existing one
- // and not send any messagse.
- process_->sink().ClearMessages();
- backing = host_->GetBackingStore(true);
- EXPECT_TRUE(backing);
- EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID));
- EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_UpdateRect_ACK::ID));
-}
-
// Test that we don't paint when we're hidden, but we still send the ACK. Most
// of the rest of the painting is tested in the GetBackingStore* ones.
TEST_F(RenderWidgetHostTest, HiddenPaint) {
process_->InitUpdateRectParams(¶ms);
host_->OnUpdateRect(params);
- // It should have sent out the ACK.
- EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_UpdateRect_ACK::ID));
-
// Now unhide.
process_->sink().ClearMessages();
host_->WasShown();
EXPECT_TRUE(host_->unresponsive_timer_fired());
}
-// This test is not valid for Windows because getting the shared memory
-// size doesn't work.
-#if !defined(OS_WIN)
-TEST_F(RenderWidgetHostTest, IncorrectBitmapScaleFactor) {
- ViewHostMsg_UpdateRect_Params params;
- process_->InitUpdateRectParams(¶ms);
- params.scale_factor = params.scale_factor * 2;
-
- EXPECT_EQ(0, process_->bad_msg_count());
- host_->OnUpdateRect(params);
- EXPECT_EQ(1, process_->bad_msg_count());
-}
-#endif
-
// Tests that scroll ACKs are correctly handled by the overscroll-navigation
// controller.
TEST_F(RenderWidgetHostTest, WheelScrollEventOverscrolls) {
// overscroll nav instead of completing it.
TEST_F(RenderWidgetHostTest, ReverseFlingCancelsOverscroll) {
host_->SetupForOverscrollControllerTest();
- host_->DisableGestureDebounce();
process_->sink().ClearMessages();
view_->set_bounds(gfx::Rect(0, 0, 400, 200));
view_->Show();
SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
WebGestureEvent::Touchscreen);
SimulateGestureScrollUpdateEvent(300, -5, 0);
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_CONSUMED);
SendInputEventACK(WebInputEvent::GestureScrollUpdate,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_delegate()->completed_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
EXPECT_EQ(1U, process_->sink().message_count());
- SendInputEventACK(WebInputEvent::GestureScrollEnd,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
}
{
SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
WebGestureEvent::Touchscreen);
SimulateGestureScrollUpdateEvent(-300, -5, 0);
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_CONSUMED);
SendInputEventACK(WebInputEvent::GestureScrollUpdate,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(OVERSCROLL_WEST, host_->overscroll_mode());
TEST_F(RenderWidgetHostTest, GestureScrollOverscrolls) {
// Turn off debounce handling for test isolation.
host_->SetupForOverscrollControllerTest();
- host_->DisableGestureDebounce();
process_->sink().ClearMessages();
SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
WebGestureEvent::Touchscreen);
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
TEST_F(RenderWidgetHostTest, GestureScrollConsumedHorizontal) {
// Turn off debounce handling for test isolation.
host_->SetupForOverscrollControllerTest();
- host_->DisableGestureDebounce();
process_->sink().ClearMessages();
SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
SimulateGestureScrollUpdateEvent(10, 0, 0);
// Start scrolling on content. ACK both events as being processed.
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_CONSUMED);
SendInputEventACK(WebInputEvent::GestureScrollUpdate,
INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
WebGestureEvent::Touchscreen);
EXPECT_EQ(1U, process_->sink().message_count());
process_->sink().ClearMessages();
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_CONSUMED);
// Send update events.
SimulateGestureScrollUpdateEvent(25, 0, 0);
WebGestureEvent::Touchscreen);
EXPECT_EQ(1U, process_->sink().message_count());
process_->sink().ClearMessages();
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_CONSUMED);
// Send update events.
SimulateGestureScrollUpdateEvent(55, 0, 0);
SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
WebGestureEvent::Touchscreen);
SimulateGestureScrollUpdateEvent(20, 0, 0);
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
SendInputEventACK(WebInputEvent::GestureScrollUpdate,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
// router.
EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
process_->sink().ClearMessages();
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
EXPECT_EQ(0U, process_->sink().message_count());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
// router.
EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
EXPECT_EQ(0U, host_->GestureEventDebouncingQueueSize());
-
- SendInputEventACK(blink::WebInputEvent::GestureScrollEnd,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
- EXPECT_EQ(0U, host_->GestureEventDebouncingQueueSize());
// Start scrolling. Receive ACK as it being processed.
SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
// router.
EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
process_->sink().ClearMessages();
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
EXPECT_EQ(0U, process_->sink().message_count());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
// router.
EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
EXPECT_EQ(0U, host_->GestureEventDebouncingQueueSize());
-
- SendInputEventACK(blink::WebInputEvent::GestureScrollEnd,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(0U, process_->sink().message_count());
- EXPECT_EQ(0U, host_->GestureEventLastQueueEventSize());
- EXPECT_EQ(0U, host_->GestureEventDebouncingQueueSize());
}
TEST_F(RenderWidgetHostTest, OverscrollDirectionChange) {
WebGestureEvent::Touchscreen);
EXPECT_EQ(1U, process_->sink().message_count());
process_->sink().ClearMessages();
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_CONSUMED);
// Send update events and receive ack as not consumed.
SimulateGestureScrollUpdateEvent(125, -5, 0);
// move events do reach the renderer.
TEST_F(RenderWidgetHostTest, OverscrollMouseMoveCompletion) {
host_->SetupForOverscrollControllerTest();
- host_->DisableGestureDebounce();
process_->sink().ClearMessages();
view_->set_bounds(gfx::Rect(0, 0, 400, 200));
view_->Show();
SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
WebGestureEvent::Touchscreen);
SimulateGestureScrollUpdateEvent(300, -5, 0);
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_CONSUMED);
SendInputEventACK(WebInputEvent::GestureScrollUpdate,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
EXPECT_EQ(1U, process_->sink().message_count());
process_->sink().ClearMessages();
- SendInputEventACK(WebInputEvent::GestureScrollEnd,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
// Move mouse some more. The mouse-move events should reach the renderer.
SimulateMouseMove(5, 10, 0);
// reset after the end of the scroll.
TEST_F(RenderWidgetHostTest, OverscrollStateResetsAfterScroll) {
host_->SetupForOverscrollControllerTest();
- host_->DisableGestureDebounce();
process_->sink().ClearMessages();
view_->set_bounds(gfx::Rect(0, 0, 400, 200));
view_->Show();
SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
WebGestureEvent::Touchscreen);
SimulateGestureScrollUpdateEvent(300, -5, 0);
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_CONSUMED);
SendInputEventACK(WebInputEvent::GestureScrollUpdate,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_mode());
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_delegate()->current_mode());
+ EXPECT_EQ(2U, process_->sink().message_count());
host_->Blur();
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_mode());
SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
WebGestureEvent::Touchscreen);
- EXPECT_EQ(0U, process_->sink().message_count());
+ EXPECT_EQ(1U, process_->sink().message_count());
+ process_->sink().ClearMessages();
// Start a scroll gesture again. This should correctly start the overscroll
// after the threshold.
WebGestureEvent::Touchscreen);
EXPECT_EQ(OVERSCROLL_NONE, host_->overscroll_delegate()->current_mode());
EXPECT_EQ(OVERSCROLL_EAST, host_->overscroll_delegate()->completed_mode());
+ EXPECT_EQ(3U, process_->sink().message_count());
+}
+
+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;
+ // 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_));
+
+ // 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::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_));
+ 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_));
+ 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_));
+ 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::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_));
+ 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_));
+ 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_));
+ 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::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_));
+ EXPECT_EQ(0U, process_->sink().message_count());
}
#define TEST_InputRouterRoutes_NOARGS(INPUTMSG) \
TEST_F(RenderWidgetHostTest, InputRouterRoutesReplace) {
host_->SetupForInputRouterTest();
- host_->Replace(base::string16());
+ host_->Send(new InputMsg_Replace(host_->GetRoutingID(), base::string16()));
EXPECT_TRUE(host_->mock_input_router()->send_event_called_);
}
TEST_F(RenderWidgetHostTest, InputRouterRoutesReplaceMisspelling) {
host_->SetupForInputRouterTest();
- host_->ReplaceMisspelling(base::string16());
+ host_->Send(new InputMsg_ReplaceMisspelling(host_->GetRoutingID(),
+ base::string16()));
EXPECT_TRUE(host_->mock_input_router()->send_event_called_);
}
WebGestureEvent::Touchscreen);
CheckLatencyInfoComponentInMessage(
process_, GetLatencyComponentId(), WebInputEvent::GestureScrollBegin);
- SendInputEventACK(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_CONSUMED);
// Tests RWHI::ForwardGestureEventWithLatencyInfo().
SimulateGestureEventWithLatencyInfo(WebInputEvent::GestureScrollUpdate,