Revert 268405 "Make sure that ScratchBuffer::Allocate() always r..."
[chromium-blink-merge.git] / content / browser / renderer_host / input / touch_input_browsertest.cc
bloba92fd26781c8430ac6871e8b5ec5603e58398493
1 // Copyright 2013 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/auto_reset.h"
6 #include "base/command_line.h"
7 #include "base/run_loop.h"
8 #include "content/browser/gpu/compositor_util.h"
9 #include "content/browser/renderer_host/render_widget_host_impl.h"
10 #include "content/browser/web_contents/web_contents_impl.h"
11 #include "content/common/input/synthetic_web_input_event_builders.h"
12 #include "content/common/input_messages.h"
13 #include "content/public/browser/browser_message_filter.h"
14 #include "content/public/browser/render_view_host.h"
15 #include "content/public/browser/render_widget_host_view.h"
16 #include "content/public/common/content_switches.h"
17 #include "content/public/test/content_browser_test.h"
18 #include "content/public/test/content_browser_test_utils.h"
19 #include "content/shell/browser/shell.h"
20 #include "third_party/WebKit/public/web/WebInputEvent.h"
21 #include "ui/events/event_switches.h"
22 #include "ui/events/latency_info.h"
24 using blink::WebInputEvent;
26 namespace {
28 void GiveItSomeTime() {
29 base::RunLoop run_loop;
30 base::MessageLoop::current()->PostDelayedTask(
31 FROM_HERE,
32 run_loop.QuitClosure(),
33 base::TimeDelta::FromMilliseconds(10));
34 run_loop.Run();
37 const char kTouchEventDataURL[] =
38 "data:text/html;charset=utf-8,"
39 "<body onload='setup();'>"
40 "<div id='first'></div><div id='second'></div><div id='third'></div>"
41 "<style>"
42 " #first {"
43 " position: absolute;"
44 " width: 100px;"
45 " height: 100px;"
46 " top: 0px;"
47 " left: 0px;"
48 " background-color: green;"
49 " -webkit-transform: translate3d(0, 0, 0);"
50 " }"
51 " #second {"
52 " position: absolute;"
53 " width: 100px;"
54 " height: 100px;"
55 " top: 0px;"
56 " left: 110px;"
57 " background-color: blue;"
58 " -webkit-transform: translate3d(0, 0, 0);"
59 " }"
60 " #third {"
61 " position: absolute;"
62 " width: 100px;"
63 " height: 100px;"
64 " top: 110px;"
65 " left: 0px;"
66 " background-color: yellow;"
67 " -webkit-transform: translate3d(0, 0, 0);"
68 " }"
69 "</style>"
70 "<script>"
71 " function setup() {"
72 " second.ontouchstart = function() {};"
73 " third.ontouchstart = function(e) {"
74 " e.preventDefault();"
75 " };"
76 " }"
77 "</script>";
79 } // namespace
81 namespace content {
83 class InputEventMessageFilter : public BrowserMessageFilter {
84 public:
85 InputEventMessageFilter()
86 : BrowserMessageFilter(InputMsgStart),
87 type_(WebInputEvent::Undefined),
88 state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {}
90 void WaitForAck(WebInputEvent::Type type) {
91 base::RunLoop run_loop;
92 base::AutoReset<base::Closure> reset_quit(&quit_, run_loop.QuitClosure());
93 base::AutoReset<WebInputEvent::Type> reset_type(&type_, type);
94 run_loop.Run();
97 InputEventAckState last_ack_state() const { return state_; }
99 protected:
100 virtual ~InputEventMessageFilter() {}
102 private:
103 void ReceivedEventAck(WebInputEvent::Type type, InputEventAckState state) {
104 if (type_ == type) {
105 state_ = state;
106 quit_.Run();
110 // BrowserMessageFilter:
111 virtual bool OnMessageReceived(const IPC::Message& message,
112 bool* message_was_ok) OVERRIDE {
113 if (message.type() == InputHostMsg_HandleInputEvent_ACK::ID) {
114 ui::LatencyInfo latency;
115 WebInputEvent::Type type = WebInputEvent::Undefined;
116 InputEventAckState ack = INPUT_EVENT_ACK_STATE_UNKNOWN;
117 InputHostMsg_HandleInputEvent_ACK::Read(&message, &type, &ack, &latency);
118 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
119 base::Bind(&InputEventMessageFilter::ReceivedEventAck,
120 this, type, ack));
122 return false;
125 base::Closure quit_;
126 WebInputEvent::Type type_;
127 InputEventAckState state_;
129 DISALLOW_COPY_AND_ASSIGN(InputEventMessageFilter);
132 class TouchInputBrowserTest : public ContentBrowserTest {
133 public:
134 TouchInputBrowserTest() {}
135 virtual ~TouchInputBrowserTest() {}
137 RenderWidgetHostImpl* GetWidgetHost() {
138 return RenderWidgetHostImpl::From(shell()->web_contents()->
139 GetRenderViewHost());
142 InputEventMessageFilter* filter() { return filter_.get(); }
144 protected:
145 void LoadURLAndAddFilter() {
146 const GURL data_url(kTouchEventDataURL);
147 NavigateToURL(shell(), data_url);
149 WebContentsImpl* web_contents =
150 static_cast<WebContentsImpl*>(shell()->web_contents());
151 RenderWidgetHostImpl* host =
152 RenderWidgetHostImpl::From(web_contents->GetRenderViewHost());
153 host->GetView()->SetSize(gfx::Size(400, 400));
155 // The page is loaded in the renderer, wait for a new frame to arrive.
156 while (!host->ScheduleComposite())
157 GiveItSomeTime();
159 filter_ = new InputEventMessageFilter();
160 host->GetProcess()->AddFilter(filter_);
163 virtual void SetUpCommandLine(CommandLine* cmd) OVERRIDE {
164 cmd->AppendSwitchASCII(switches::kTouchEvents,
165 switches::kTouchEventsEnabled);
168 scoped_refptr<InputEventMessageFilter> filter_;
171 #if defined(OS_MACOSX)
172 // TODO(ccameron): Failing on mac: crbug.com/346363
173 #define MAYBE_TouchNoHandler DISABLED_TouchNoHandler
174 #else
175 #define MAYBE_TouchNoHandler TouchNoHandler
176 #endif
177 IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_TouchNoHandler) {
178 LoadURLAndAddFilter();
179 SyntheticWebTouchEvent touch;
181 // A press on |first| should be acked with NO_CONSUMER_EXISTS since there is
182 // no touch-handler on it.
183 touch.PressPoint(25, 25);
184 GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
185 filter()->WaitForAck(WebInputEvent::TouchStart);
187 if (content::IsThreadedCompositingEnabled()) {
188 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
189 filter()->last_ack_state());
190 } else {
191 // http://crbug.com/326232: This should be NO_CONSUMER_EXISTS once
192 // WebViewImpl::hasTouchEventHandlersAt() is implemented.
193 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state());
196 // If a touch-press is acked with NO_CONSUMER_EXISTS, then subsequent
197 // touch-points don't need to be dispatched until the touch point is released.
198 touch.ReleasePoint(0);
199 GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
200 touch.ResetPoints();
203 IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, TouchHandlerNoConsume) {
204 LoadURLAndAddFilter();
205 SyntheticWebTouchEvent touch;
207 // Press on |second| should be acked with NOT_CONSUMED since there is a
208 // touch-handler on |second|, but it doesn't consume the event.
209 touch.PressPoint(125, 25);
210 GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
211 filter()->WaitForAck(WebInputEvent::TouchStart);
212 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state());
214 touch.ReleasePoint(0);
215 GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
216 filter()->WaitForAck(WebInputEvent::TouchEnd);
217 touch.ResetPoints();
220 IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, TouchHandlerConsume) {
221 LoadURLAndAddFilter();
222 SyntheticWebTouchEvent touch;
224 // Press on |third| should be acked with CONSUMED since the touch-handler on
225 // |third| consimes the event.
226 touch.PressPoint(25, 125);
227 GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
228 filter()->WaitForAck(WebInputEvent::TouchStart);
229 EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, filter()->last_ack_state());
231 touch.ReleasePoint(0);
232 GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
233 filter()->WaitForAck(WebInputEvent::TouchEnd);
236 #if defined(OS_MACOSX)
237 // TODO(ccameron): Failing on mac: crbug.com/346363
238 #define MAYBE_MultiPointTouchPress DISABLED_MultiPointTouchPress
239 #else
240 #define MAYBE_MultiPointTouchPress MultiPointTouchPress
241 #endif
242 IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_MultiPointTouchPress) {
243 LoadURLAndAddFilter();
244 SyntheticWebTouchEvent touch;
246 // Press on |first|, which sould be acked with NO_CONSUMER_EXISTS. Then press
247 // on |third|. That point should be acked with CONSUMED.
248 touch.PressPoint(25, 25);
249 GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
250 filter()->WaitForAck(WebInputEvent::TouchStart);
251 if (content::IsThreadedCompositingEnabled()) {
252 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
253 filter()->last_ack_state());
254 } else {
255 // http://crbug.com/326232: This should be NO_CONSUMER_EXISTS once
256 // WebViewImpl::hasTouchEventHandlersAt() is implemented.
257 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state());
260 touch.PressPoint(25, 125);
261 GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
262 filter()->WaitForAck(WebInputEvent::TouchStart);
263 EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, filter()->last_ack_state());
266 } // namespace content