1 // Copyright 2014 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"
7 #include "base/command_line.h"
8 #include "base/run_loop.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "content/browser/renderer_host/input/synthetic_gesture.h"
11 #include "content/browser/renderer_host/input/synthetic_gesture_controller.h"
12 #include "content/browser/renderer_host/input/synthetic_gesture_target.h"
13 #include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h"
14 #include "content/browser/renderer_host/input/touch_event_queue.h"
15 #include "content/browser/renderer_host/render_widget_host_impl.h"
16 #include "content/browser/renderer_host/render_widget_host_view_base.h"
17 #include "content/browser/web_contents/web_contents_impl.h"
18 #include "content/common/input/synthetic_gesture_params.h"
19 #include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
20 #include "content/common/input_messages.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "content/public/browser/render_widget_host_view.h"
23 #include "content/public/common/content_switches.h"
24 #include "content/public/test/browser_test_utils.h"
25 #include "content/public/test/content_browser_test.h"
26 #include "content/public/test/content_browser_test_utils.h"
27 #include "content/public/test/test_utils.h"
28 #include "content/shell/browser/shell.h"
29 #include "third_party/WebKit/public/web/WebInputEvent.h"
30 #include "ui/events/event_switches.h"
31 #include "ui/events/latency_info.h"
33 using blink::WebInputEvent
;
37 const char kTouchActionDataURL
[] =
38 "data:text/html;charset=utf-8,"
40 "<meta name='viewport' content='width=device-width'/>"
48 " border: 2px solid blue;"
50 ".spacer { height: 1000px; }"
51 ".ta-none { touch-action: none; }"
53 "<div class=box></div>"
54 "<div class='box ta-none'></div>"
55 "<div class=spacer></div>"
57 " window.eventCounts = "
58 " {touchstart:0, touchmove:0, touchend: 0, touchcancel:0};"
59 " function countEvent(e) { eventCounts[e.type]++; }"
60 " for (var evt in eventCounts) { "
61 " document.addEventListener(evt, countEvent); "
63 " document.title='ready';"
71 class TouchActionBrowserTest
: public ContentBrowserTest
{
73 TouchActionBrowserTest() {}
74 virtual ~TouchActionBrowserTest() {}
76 RenderWidgetHostImpl
* GetWidgetHost() {
77 return RenderWidgetHostImpl::From(shell()->web_contents()->
81 void OnSyntheticGestureCompleted(SyntheticGesture::Result result
) {
82 EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED
, result
);
88 const GURL
data_url(kTouchActionDataURL
);
89 NavigateToURL(shell(), data_url
);
91 RenderWidgetHostImpl
* host
= GetWidgetHost();
92 host
->GetView()->SetSize(gfx::Size(400, 400));
94 base::string16
ready_title(base::ASCIIToUTF16("ready"));
95 TitleWatcher
watcher(shell()->web_contents(), ready_title
);
96 ignore_result(watcher
.WaitAndGetTitle());
99 // ContentBrowserTest:
100 virtual void SetUpCommandLine(CommandLine
* cmd
) OVERRIDE
{
101 cmd
->AppendSwitchASCII(switches::kTouchEvents
,
102 switches::kTouchEventsEnabled
);
103 // TODO(rbyers): Remove this switch once touch-action ships.
104 // http://crbug.com/241964
105 cmd
->AppendSwitch(switches::kEnableExperimentalWebPlatformFeatures
);
108 int ExecuteScriptAndExtractInt(const std::string
& script
) {
110 EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
111 shell()->web_contents(),
112 "domAutomationController.send(" + script
+ ")",
118 return ExecuteScriptAndExtractInt("document.documentElement.scrollTop");
121 // Generate touch events for a synthetic scroll from |point| for |distance|.
122 // Returns true if the page scrolled by the desired amount, and false if
123 // it didn't scroll at all.
124 bool DoTouchScroll(const gfx::Point
& point
, const gfx::Vector2d
& distance
) {
125 EXPECT_EQ(0, GetScrollTop());
127 int scrollHeight
= ExecuteScriptAndExtractInt(
128 "document.documentElement.scrollHeight");
129 EXPECT_EQ(1200, scrollHeight
);
131 SyntheticSmoothScrollGestureParams params
;
132 params
.gesture_source_type
= SyntheticGestureParams::TOUCH_INPUT
;
133 params
.anchor
= point
;
134 params
.distances
.push_back(-distance
);
136 runner_
= new MessageLoopRunner();
138 scoped_ptr
<SyntheticSmoothScrollGesture
> gesture(
139 new SyntheticSmoothScrollGesture(params
));
140 GetWidgetHost()->QueueSyntheticGesture(
141 gesture
.PassAs
<SyntheticGesture
>(),
142 base::Bind(&TouchActionBrowserTest::OnSyntheticGestureCompleted
,
143 base::Unretained(this)));
145 // Runs until we get the OnSyntheticGestureCompleted callback
149 // Check the scroll offset
150 int scrollTop
= GetScrollTop();
154 EXPECT_EQ(distance
.y(), scrollTop
);
159 scoped_refptr
<MessageLoopRunner
> runner_
;
161 DISALLOW_COPY_AND_ASSIGN(TouchActionBrowserTest
);
164 // TouchActionBrowserTest.DefaultAuto fails under ThreadSanitizer v2, see
165 // http://crbug.com/348539 and is flaky on XP, see
166 // http://crbug.com/354763
168 // Mac doesn't yet have a gesture recognizer, so can't support turning touch
169 // events into scroll gestures.
170 // Will be fixed with http://crbug.com/337142
172 // Verify the test infrastructure works - we can touch-scroll the page and get a
173 // touchcancel as expected.
174 IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest
, DISABLED_DefaultAuto
) {
177 bool scrolled
= DoTouchScroll(gfx::Point(50, 50), gfx::Vector2d(0, 45));
178 EXPECT_TRUE(scrolled
);
180 EXPECT_EQ(1, ExecuteScriptAndExtractInt("eventCounts.touchstart"));
181 EXPECT_EQ(1, ExecuteScriptAndExtractInt("eventCounts.touchmove"));
182 if (TouchEventQueue::TOUCH_SCROLLING_MODE_DEFAULT
==
183 TouchEventQueue::TOUCH_SCROLLING_MODE_TOUCHCANCEL
) {
184 EXPECT_EQ(0, ExecuteScriptAndExtractInt("eventCounts.touchend"));
185 EXPECT_EQ(1, ExecuteScriptAndExtractInt("eventCounts.touchcancel"));
187 EXPECT_EQ(1, ExecuteScriptAndExtractInt("eventCounts.touchend"));
188 EXPECT_EQ(0, ExecuteScriptAndExtractInt("eventCounts.touchcancel"));
192 // Verify that touching a touch-action: none region disables scrolling and
193 // enables all touch events to be sent.
194 // Disabled on MacOS because it doesn't support touch input.
195 // It's just flaky everywhere.
196 IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest
, DISABLED_TouchActionNone
) {
199 bool scrolled
= DoTouchScroll(gfx::Point(50, 150), gfx::Vector2d(0, 45));
200 EXPECT_FALSE(scrolled
);
202 EXPECT_EQ(1, ExecuteScriptAndExtractInt("eventCounts.touchstart"));
203 EXPECT_GT(ExecuteScriptAndExtractInt("eventCounts.touchmove"), 1);
204 EXPECT_EQ(1, ExecuteScriptAndExtractInt("eventCounts.touchend"));
205 EXPECT_EQ(0, ExecuteScriptAndExtractInt("eventCounts.touchcancel"));
208 } // namespace content