Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / content / browser / renderer_host / input / touch_input_browsertest.cc
blob3324d236f26ee658a3c11729478bfefbff136ffd
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 #if defined(OS_ANDROID)
40 "<head>"
41 "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
42 "</head>"
43 #endif
44 "<body onload='setup();'>"
45 "<div id='first'></div><div id='second'></div><div id='third'></div>"
46 "<style>"
47 " #first {"
48 " position: absolute;"
49 " width: 100px;"
50 " height: 100px;"
51 " top: 0px;"
52 " left: 0px;"
53 " background-color: green;"
54 " -webkit-transform: translate3d(0, 0, 0);"
55 " }"
56 " #second {"
57 " position: absolute;"
58 " width: 100px;"
59 " height: 100px;"
60 " top: 0px;"
61 " left: 110px;"
62 " background-color: blue;"
63 " -webkit-transform: translate3d(0, 0, 0);"
64 " }"
65 " #third {"
66 " position: absolute;"
67 " width: 100px;"
68 " height: 100px;"
69 " top: 110px;"
70 " left: 0px;"
71 " background-color: yellow;"
72 " -webkit-transform: translate3d(0, 0, 0);"
73 " }"
74 "</style>"
75 "<script>"
76 " function setup() {"
77 " second.ontouchstart = function() {};"
78 " third.ontouchstart = function(e) {"
79 " e.preventDefault();"
80 " };"
81 " }"
82 "</script>";
84 } // namespace
86 namespace content {
88 class InputEventMessageFilter : public BrowserMessageFilter {
89 public:
90 InputEventMessageFilter()
91 : BrowserMessageFilter(InputMsgStart),
92 type_(WebInputEvent::Undefined),
93 state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {}
95 void WaitForAck(WebInputEvent::Type type) {
96 base::RunLoop run_loop;
97 base::AutoReset<base::Closure> reset_quit(&quit_, run_loop.QuitClosure());
98 base::AutoReset<WebInputEvent::Type> reset_type(&type_, type);
99 run_loop.Run();
102 InputEventAckState last_ack_state() const { return state_; }
104 protected:
105 ~InputEventMessageFilter() override {}
107 private:
108 void ReceivedEventAck(WebInputEvent::Type type, InputEventAckState state) {
109 if (type_ == type) {
110 state_ = state;
111 quit_.Run();
115 // BrowserMessageFilter:
116 bool OnMessageReceived(const IPC::Message& message) override {
117 if (message.type() == InputHostMsg_HandleInputEvent_ACK::ID) {
118 InputHostMsg_HandleInputEvent_ACK::Param params;
119 InputHostMsg_HandleInputEvent_ACK::Read(&message, &params);
120 WebInputEvent::Type type = get<0>(params).type;
121 InputEventAckState ack = get<0>(params).state;
122 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
123 base::Bind(&InputEventMessageFilter::ReceivedEventAck,
124 this, type, ack));
126 return false;
129 base::Closure quit_;
130 WebInputEvent::Type type_;
131 InputEventAckState state_;
133 DISALLOW_COPY_AND_ASSIGN(InputEventMessageFilter);
136 class TouchInputBrowserTest : public ContentBrowserTest {
137 public:
138 TouchInputBrowserTest() {}
139 ~TouchInputBrowserTest() override {}
141 RenderWidgetHostImpl* GetWidgetHost() {
142 return RenderWidgetHostImpl::From(shell()->web_contents()->
143 GetRenderViewHost());
146 InputEventMessageFilter* filter() { return filter_.get(); }
148 protected:
149 void LoadURLAndAddFilter() {
150 const GURL data_url(kTouchEventDataURL);
151 NavigateToURL(shell(), data_url);
153 WebContentsImpl* web_contents =
154 static_cast<WebContentsImpl*>(shell()->web_contents());
155 RenderWidgetHostImpl* host =
156 RenderWidgetHostImpl::From(web_contents->GetRenderViewHost());
157 host->GetView()->SetSize(gfx::Size(400, 400));
159 // The page is loaded in the renderer, wait for a new frame to arrive.
160 while (!host->ScheduleComposite())
161 GiveItSomeTime();
163 filter_ = new InputEventMessageFilter();
164 host->GetProcess()->AddFilter(filter_.get());
167 void SetUpCommandLine(base::CommandLine* cmd) override {
168 cmd->AppendSwitchASCII(switches::kTouchEvents,
169 switches::kTouchEventsEnabled);
172 scoped_refptr<InputEventMessageFilter> filter_;
175 #if defined(OS_MACOSX)
176 // TODO(ccameron): Failing on mac: crbug.com/346363
177 #define MAYBE_TouchNoHandler DISABLED_TouchNoHandler
178 #else
179 #define MAYBE_TouchNoHandler TouchNoHandler
180 #endif
181 IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_TouchNoHandler) {
182 LoadURLAndAddFilter();
183 SyntheticWebTouchEvent touch;
185 // A press on |first| should be acked with NO_CONSUMER_EXISTS since there is
186 // no touch-handler on it.
187 touch.PressPoint(25, 25);
188 GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
189 filter()->WaitForAck(WebInputEvent::TouchStart);
191 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
192 filter()->last_ack_state());
194 // If a touch-press is acked with NO_CONSUMER_EXISTS, then subsequent
195 // touch-points don't need to be dispatched until the touch point is released.
196 touch.ReleasePoint(0);
197 GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
198 touch.ResetPoints();
201 IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, TouchHandlerNoConsume) {
202 LoadURLAndAddFilter();
203 SyntheticWebTouchEvent touch;
205 // Press on |second| should be acked with NOT_CONSUMED since there is a
206 // touch-handler on |second|, but it doesn't consume the event.
207 touch.PressPoint(125, 25);
208 GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
209 filter()->WaitForAck(WebInputEvent::TouchStart);
210 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state());
212 touch.ReleasePoint(0);
213 GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
214 filter()->WaitForAck(WebInputEvent::TouchEnd);
215 touch.ResetPoints();
218 IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, TouchHandlerConsume) {
219 LoadURLAndAddFilter();
220 SyntheticWebTouchEvent touch;
222 // Press on |third| should be acked with CONSUMED since the touch-handler on
223 // |third| consimes the event.
224 touch.PressPoint(25, 125);
225 GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
226 filter()->WaitForAck(WebInputEvent::TouchStart);
227 EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, filter()->last_ack_state());
229 touch.ReleasePoint(0);
230 GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
231 filter()->WaitForAck(WebInputEvent::TouchEnd);
234 #if defined(OS_MACOSX)
235 // TODO(ccameron): Failing on mac: crbug.com/346363
236 #define MAYBE_MultiPointTouchPress DISABLED_MultiPointTouchPress
237 #else
238 #define MAYBE_MultiPointTouchPress MultiPointTouchPress
239 #endif
240 IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_MultiPointTouchPress) {
241 LoadURLAndAddFilter();
242 SyntheticWebTouchEvent touch;
244 // Press on |first|, which sould be acked with NO_CONSUMER_EXISTS. Then press
245 // on |third|. That point should be acked with CONSUMED.
246 touch.PressPoint(25, 25);
247 GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
248 filter()->WaitForAck(WebInputEvent::TouchStart);
249 EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
250 filter()->last_ack_state());
252 touch.PressPoint(25, 125);
253 GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
254 filter()->WaitForAck(WebInputEvent::TouchStart);
255 EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, filter()->last_ack_state());
258 } // namespace content