blob: b9749e54dcfcb68b3d63e94f6b7586d3aeaa6d52 [file] [log] [blame]
// Copyright 2014 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/bind.h"
#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/renderer_host/input/synthetic_gesture.h"
#include "content/browser/renderer_host/input/synthetic_gesture_controller.h"
#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h"
#include "content/browser/renderer_host/input/touch_event_queue.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/input/synthetic_gesture_params.h"
#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
#include "content/common/input_messages.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/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.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 {
const char kTouchActionDataURL[] =
"data:text/html;charset=utf-8,"
"<!DOCTYPE html>"
"<meta name='viewport' content='width=device-width'/>"
"<style>"
"html, body {"
" margin: 0;"
"}"
".box {"
" height: 96px;"
" width: 96px;"
" border: 2px solid blue;"
"}"
".spacer { height: 1000px; }"
".ta-none { touch-action: none; }"
"</style>"
"<div class=box></div>"
"<div class='box ta-none'></div>"
"<div class=spacer></div>"
"<script>"
" window.eventCounts = "
" {touchstart:0, touchmove:0, touchend: 0, touchcancel:0};"
" function countEvent(e) { eventCounts[e.type]++; }"
" for (var evt in eventCounts) { "
" document.addEventListener(evt, countEvent); "
" }"
" document.title='ready';"
"</script>";
} // namespace
namespace content {
class TouchActionBrowserTest : public ContentBrowserTest {
public:
TouchActionBrowserTest() {}
virtual ~TouchActionBrowserTest() {}
RenderWidgetHostImpl* GetWidgetHost() {
return RenderWidgetHostImpl::From(shell()->web_contents()->
GetRenderViewHost());
}
void OnSyntheticGestureCompleted(SyntheticGesture::Result result) {
EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
runner_->Quit();
}
protected:
void LoadURL() {
const GURL data_url(kTouchActionDataURL);
NavigateToURL(shell(), data_url);
RenderWidgetHostImpl* host = GetWidgetHost();
host->GetView()->SetSize(gfx::Size(400, 400));
base::string16 ready_title(base::ASCIIToUTF16("ready"));
TitleWatcher watcher(shell()->web_contents(), ready_title);
ignore_result(watcher.WaitAndGetTitle());
}
// ContentBrowserTest:
virtual void SetUpCommandLine(CommandLine* cmd) OVERRIDE {
cmd->AppendSwitchASCII(switches::kTouchEvents,
switches::kTouchEventsEnabled);
// TODO(rbyers): Remove this switch once touch-action ships.
// http://crbug.com/241964
cmd->AppendSwitch(switches::kEnableExperimentalWebPlatformFeatures);
}
int ExecuteScriptAndExtractInt(const std::string& script) {
int value = 0;
EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
shell()->web_contents(),
"domAutomationController.send(" + script + ")",
&value));
return value;
}
int GetScrollTop() {
return ExecuteScriptAndExtractInt("document.documentElement.scrollTop");
}
// Generate touch events for a synthetic scroll from |point| for |distance|.
// Returns true if the page scrolled by the desired amount, and false if
// it didn't scroll at all.
bool DoTouchScroll(const gfx::Point& point, const gfx::Vector2d& distance) {
EXPECT_EQ(0, GetScrollTop());
int scrollHeight = ExecuteScriptAndExtractInt(
"document.documentElement.scrollHeight");
EXPECT_EQ(1200, scrollHeight);
SyntheticSmoothScrollGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
params.anchor = point;
params.distances.push_back(-distance);
runner_ = new MessageLoopRunner();
scoped_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
GetWidgetHost()->QueueSyntheticGesture(
gesture.PassAs<SyntheticGesture>(),
base::Bind(&TouchActionBrowserTest::OnSyntheticGestureCompleted,
base::Unretained(this)));
// Runs until we get the OnSyntheticGestureCompleted callback
runner_->Run();
runner_ = NULL;
// Check the scroll offset
int scrollTop = GetScrollTop();
if (scrollTop == 0)
return false;
EXPECT_EQ(distance.y(), scrollTop);
return true;
}
private:
scoped_refptr<MessageLoopRunner> runner_;
DISALLOW_COPY_AND_ASSIGN(TouchActionBrowserTest);
};
// TouchActionBrowserTest.DefaultAuto fails under ThreadSanitizer v2, see
// http://crbug.com/348539 and is flaky on XP, see
// http://crbug.com/354763
//
// Mac doesn't yet have a gesture recognizer, so can't support turning touch
// events into scroll gestures.
// Will be fixed with http://crbug.com/337142
//
// Verify the test infrastructure works - we can touch-scroll the page and get a
// touchcancel as expected.
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, DISABLED_DefaultAuto) {
LoadURL();
bool scrolled = DoTouchScroll(gfx::Point(50, 50), gfx::Vector2d(0, 45));
EXPECT_TRUE(scrolled);
EXPECT_EQ(1, ExecuteScriptAndExtractInt("eventCounts.touchstart"));
EXPECT_EQ(1, ExecuteScriptAndExtractInt("eventCounts.touchmove"));
if (TouchEventQueue::TOUCH_SCROLLING_MODE_DEFAULT ==
TouchEventQueue::TOUCH_SCROLLING_MODE_TOUCHCANCEL) {
EXPECT_EQ(0, ExecuteScriptAndExtractInt("eventCounts.touchend"));
EXPECT_EQ(1, ExecuteScriptAndExtractInt("eventCounts.touchcancel"));
} else {
EXPECT_EQ(1, ExecuteScriptAndExtractInt("eventCounts.touchend"));
EXPECT_EQ(0, ExecuteScriptAndExtractInt("eventCounts.touchcancel"));
}
}
// Verify that touching a touch-action: none region disables scrolling and
// enables all touch events to be sent.
// Disabled on MacOS because it doesn't support touch input.
// It's just flaky everywhere.
IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, DISABLED_TouchActionNone) {
LoadURL();
bool scrolled = DoTouchScroll(gfx::Point(50, 150), gfx::Vector2d(0, 45));
EXPECT_FALSE(scrolled);
EXPECT_EQ(1, ExecuteScriptAndExtractInt("eventCounts.touchstart"));
EXPECT_GT(ExecuteScriptAndExtractInt("eventCounts.touchmove"), 1);
EXPECT_EQ(1, ExecuteScriptAndExtractInt("eventCounts.touchend"));
EXPECT_EQ(0, ExecuteScriptAndExtractInt("eventCounts.touchcancel"));
}
} // namespace content