From 4a6e69b3a6effb0c8a9cb5a1011283723d6bff0f Mon Sep 17 00:00:00 2001 From: "sadrul@chromium.org" Date: Fri, 6 Dec 2013 04:12:17 +0000 Subject: input: Add some touch-event related browser-tests. The tests added verify that the touch-events are acked correctly, for both single and multi-touch points. The tests run both with and without the compositor thread event-handler, to ensure that the event acks are the same in both cases. BUG=321457 R=jdduke@chromium.org TBR=jochen@chromium.org for content_tests.gypi Review URL: https://codereview.chromium.org/105903002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@239115 0039d316-1c4b-4281-b951-d872f2087c98 --- .../renderer_host/input/touch_input_browsertest.cc | 275 +++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 content/browser/renderer_host/input/touch_input_browsertest.cc (limited to 'content/browser/renderer_host/input') diff --git a/content/browser/renderer_host/input/touch_input_browsertest.cc b/content/browser/renderer_host/input/touch_input_browsertest.cc new file mode 100644 index 0000000..ca4f455 --- /dev/null +++ b/content/browser/renderer_host/input/touch_input_browsertest.cc @@ -0,0 +1,275 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/auto_reset.h" +#include "base/command_line.h" +#include "base/run_loop.h" +#include "content/browser/renderer_host/render_widget_host_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/input/synthetic_web_input_event_builders.h" +#include "content/common/input_messages.h" +#include "content/public/browser/browser_message_filter.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_widget_host_view.h" +#include "content/public/common/content_switches.h" +#include "content/shell/browser/shell.h" +#include "content/test/content_browser_test.h" +#include "content/test/content_browser_test_utils.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/events/event_switches.h" +#include "ui/events/latency_info.h" + +using blink::WebInputEvent; + +namespace { + +void GiveItSomeTime() { + base::RunLoop run_loop; + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + run_loop.QuitClosure(), + base::TimeDelta::FromMilliseconds(10)); + run_loop.Run(); +} + +const char kTouchEventDataURL[] = + "data:text/html;charset=utf-8," + "" + "
" + "" + ""; + +} // namespace + +namespace content { + +class InputEventMessageFilter : public BrowserMessageFilter { + public: + InputEventMessageFilter() + : type_(WebInputEvent::Undefined), + state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {} + + void WaitForAck(WebInputEvent::Type type) { + base::RunLoop run_loop; + base::AutoReset reset_quit(&quit_, run_loop.QuitClosure()); + base::AutoReset reset_type(&type_, type); + run_loop.Run(); + } + + InputEventAckState last_ack_state() const { return state_; } + + protected: + virtual ~InputEventMessageFilter() {} + + private: + void ReceivedEventAck(WebInputEvent::Type type, InputEventAckState state) { + if (type_ == type) { + state_ = state; + quit_.Run(); + } + } + + // BrowserMessageFilter: + virtual bool OnMessageReceived(const IPC::Message& message, + bool* message_was_ok) OVERRIDE { + if (message.type() == InputHostMsg_HandleInputEvent_ACK::ID) { + ui::LatencyInfo latency; + WebInputEvent::Type type = WebInputEvent::Undefined; + InputEventAckState ack = INPUT_EVENT_ACK_STATE_UNKNOWN; + InputHostMsg_HandleInputEvent_ACK::Read(&message, &type, &ack, &latency); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&InputEventMessageFilter::ReceivedEventAck, + this, type, ack)); + } + return false; + } + + base::Closure quit_; + WebInputEvent::Type type_; + InputEventAckState state_; + + DISALLOW_COPY_AND_ASSIGN(InputEventMessageFilter); +}; + +class TouchInputBrowserTest : public ContentBrowserTest, + public testing::WithParamInterface { + public: + TouchInputBrowserTest() {} + virtual ~TouchInputBrowserTest() {} + + RenderWidgetHostImpl* GetWidgetHost() { + return RenderWidgetHostImpl::From(shell()->web_contents()-> + GetRenderViewHost()); + } + + InputEventMessageFilter* filter() { return filter_.get(); } + + protected: + void LoadURLAndAddFilter() { + const GURL data_url(kTouchEventDataURL); + NavigateToURL(shell(), data_url); + + WebContentsImpl* web_contents = + static_cast(shell()->web_contents()); + RenderWidgetHostImpl* host = + RenderWidgetHostImpl::From(web_contents->GetRenderViewHost()); + host->GetView()->SetSize(gfx::Size(400, 400)); + + // The page is loaded in the renderer, wait for a new frame to arrive. + while (!host->ScheduleComposite()) + GiveItSomeTime(); + + filter_ = new InputEventMessageFilter(); + host->GetProcess()->AddFilter(filter_); + } + + // ContentBrowserTest: + virtual void SetUp() OVERRIDE { + // We expect real pixel output for these tests. + UseRealGLContexts(); + + // On legacy windows, these tests need real GL bindings to pass. +#if defined(OS_WIN) && !defined(USE_AURA) + UseRealGLBindings(); +#endif + + ContentBrowserTest::SetUp(); + } + + virtual void SetUpCommandLine(CommandLine* cmd) OVERRIDE { + cmd->AppendSwitchASCII(switches::kTouchEvents, + switches::kTouchEventsEnabled); + cmd->AppendSwitch(GetParam()); + } + + scoped_refptr filter_; +}; + +IN_PROC_BROWSER_TEST_P(TouchInputBrowserTest, TouchNoHandler) { + LoadURLAndAddFilter(); + SyntheticWebTouchEvent touch; + + // A press on |first| should be acked with NO_CONSUMER_EXISTS since there is + // no touch-handler on it. + touch.PressPoint(25, 25); + GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo()); + filter()->WaitForAck(WebInputEvent::TouchStart); + + if (GetParam() == std::string(switches::kEnableThreadedCompositing)) { + EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, + filter()->last_ack_state()); + } else { + // http://crbug.com/326232: This should be NO_CONSUMER_EXISTS once + // WebViewImpl::hasTouchEventHandlersAt() is implemented. + EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state()); + } + + // If a touch-press is acked with NO_CONSUMER_EXISTS, then subsequent + // touch-points don't need to be dispatched until the touch point is released. + touch.ReleasePoint(0); + GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo()); + touch.ResetPoints(); +} + +IN_PROC_BROWSER_TEST_P(TouchInputBrowserTest, TouchHandlerNoConsume) { + LoadURLAndAddFilter(); + SyntheticWebTouchEvent touch; + + // Press on |second| should be acked with NOT_CONSUMED since there is a + // touch-handler on |second|, but it doesn't consume the event. + touch.PressPoint(125, 25); + GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo()); + filter()->WaitForAck(WebInputEvent::TouchStart); + EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state()); + + touch.ReleasePoint(0); + GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo()); + filter()->WaitForAck(WebInputEvent::TouchEnd); + touch.ResetPoints(); +} + +IN_PROC_BROWSER_TEST_P(TouchInputBrowserTest, TouchHandlerConsume) { + LoadURLAndAddFilter(); + SyntheticWebTouchEvent touch; + + // Press on |third| should be acked with CONSUMED since the touch-handler on + // |third| consimes the event. + touch.PressPoint(25, 125); + GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo()); + filter()->WaitForAck(WebInputEvent::TouchStart); + EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, filter()->last_ack_state()); + + touch.ReleasePoint(0); + GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo()); + filter()->WaitForAck(WebInputEvent::TouchEnd); +} + +IN_PROC_BROWSER_TEST_P(TouchInputBrowserTest, MultiPointTouchPress) { + LoadURLAndAddFilter(); + SyntheticWebTouchEvent touch; + + // Press on |first|, which sould be acked with NO_CONSUMER_EXISTS. Then press + // on |third|. That point should be acked with CONSUMED. + touch.PressPoint(25, 25); + GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo()); + filter()->WaitForAck(WebInputEvent::TouchStart); + if (GetParam() == std::string(switches::kEnableThreadedCompositing)) { + EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, + filter()->last_ack_state()); + } else { + // http://crbug.com/326232: This should be NO_CONSUMER_EXISTS once + // WebViewImpl::hasTouchEventHandlersAt() is implemented. + EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state()); + } + + touch.PressPoint(25, 125); + GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo()); + filter()->WaitForAck(WebInputEvent::TouchStart); + EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, filter()->last_ack_state()); +} + +INSTANTIATE_TEST_CASE_P(WithoutInputHandlerProxy, TouchInputBrowserTest, + ::testing::Values(std::string(switches::kDisableThreadedCompositing))); + +#if !defined(OS_MACOSX) +INSTANTIATE_TEST_CASE_P(WithInputHandlerProxy, TouchInputBrowserTest, + ::testing::Values(std::string(switches::kEnableThreadedCompositing))); +#endif + +} // namespace content -- cgit v1.1