Index: content/browser/renderer_host/input/composited_scrolling_browsertest.cc |
diff --git a/content/browser/renderer_host/input/composited_scrolling_browsertest.cc b/content/browser/renderer_host/input/composited_scrolling_browsertest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e776a8ee44653eac3d83c201bf64fbf7cac87018 |
--- /dev/null |
+++ b/content/browser/renderer_host/input/composited_scrolling_browsertest.cc |
@@ -0,0 +1,167 @@ |
+// Copyright 2015 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/bind.h" |
+#include "base/command_line.h" |
+#include "base/run_loop.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "cc/base/math_util.h" |
+#include "content/browser/renderer_host/input/synthetic_gesture.h" |
+#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.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_gesture_params.h" |
+#include "content/common/input/synthetic_smooth_scroll_gesture_params.h" |
+#include "content/public/browser/render_view_host.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" |
+ |
+namespace { |
+ |
+const char kCompositedScrollingDataURL[] = |
+ "data:text/html;charset=utf-8," |
+ "<!DOCTYPE html>" |
+ "<meta name='viewport' content='width=device-width'/>" |
+ "<style>" |
+ "#scroller {" |
+ " width:500px;" |
+ " height:500px;" |
+ " overflow:scroll;" |
+ " transform: rotateX(-30deg);" |
+ "}" |
+ |
+ "#content {" |
+ " background-color:red;" |
+ " width:1000px;" |
+ " height:1000px;" |
+ "}" |
+ "</style>" |
+ "<div id='scroller'>" |
+ " <div id='content'>" |
+ " </div>" |
+ "</div>" |
+ "<script>" |
+ " document.title='ready';" |
+ "</script>"; |
+ |
+} // namespace |
+ |
+namespace content { |
+ |
+ |
+class CompositedScrollingBrowserTest : public ContentBrowserTest { |
+ public: |
+ CompositedScrollingBrowserTest() {} |
+ ~CompositedScrollingBrowserTest() override {} |
+ |
+ void SetUpCommandLine(base::CommandLine* cmd) override { |
+ cmd->AppendSwitch(switches::kEnablePreferCompositingToLCDText); |
+ } |
+ |
+ RenderWidgetHostImpl* GetWidgetHost() { |
+ return RenderWidgetHostImpl::From( |
+ shell()->web_contents()->GetRenderViewHost()->GetWidget()); |
+ } |
+ |
+ void OnSyntheticGestureCompleted(SyntheticGesture::Result result) { |
+ EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result); |
+ runner_->Quit(); |
+ } |
+ |
+ protected: |
+ void LoadURL() { |
+ const GURL data_url(kCompositedScrollingDataURL); |
+ NavigateToURL(shell(), data_url); |
+ |
+ RenderWidgetHostImpl* host = GetWidgetHost(); |
+ scoped_refptr<FrameWatcher> frame_watcher(new FrameWatcher()); |
+ host->GetProcess()->AddFilter(frame_watcher.get()); |
+ 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()); |
+ |
+ // We need to wait until at least one frame has been composited |
+ // otherwise the injection of the synthetic gestures may get |
+ // dropped because of MainThread/Impl thread sync of touch event |
+ // regions. |
+ frame_watcher->WaitFrames(1); |
+ } |
+ |
+ // ContentBrowserTest: |
+ 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.getElementById(\"scroller\").scrollTop"); |
+ } |
+ |
+ // Generate touch events for a synthetic scroll from |point| for |distance|. |
+ // Returns the distance scrolled. |
+ int DoTouchScroll(const gfx::Point& point, const gfx::Vector2d& distance) { |
+ EXPECT_EQ(0, GetScrollTop()); |
+ |
+ int scrollHeight = ExecuteScriptAndExtractInt( |
+ "document.getElementById('scroller').scrollHeight"); |
+ EXPECT_EQ(1000, scrollHeight); |
+ |
+ SyntheticSmoothScrollGestureParams params; |
+ params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; |
+ params.anchor = gfx::PointF(point); |
+ params.distances.push_back(-distance); |
+ |
+ runner_ = new MessageLoopRunner(); |
+ |
+ scoped_ptr<SyntheticSmoothScrollGesture> gesture( |
+ new SyntheticSmoothScrollGesture(params)); |
+ GetWidgetHost()->QueueSyntheticGesture( |
+ gesture.Pass(), |
+ base::Bind(&CompositedScrollingBrowserTest::OnSyntheticGestureCompleted, |
+ base::Unretained(this))); |
+ |
+ // Runs until we get the OnSyntheticGestureCompleted callback |
+ runner_->Run(); |
+ runner_ = NULL; |
+ |
+ return GetScrollTop(); |
+ } |
+ |
+ private: |
+ scoped_refptr<MessageLoopRunner> runner_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(CompositedScrollingBrowserTest); |
+}; |
+ |
+// Verify transforming a scroller doesn't prevent it from scrolling. See |
+// crbug.com/543655 for a case where this was broken. |
+// Disabled on MacOS because it doesn't support touch input. |
+// Disabled on Android due to flakiness, see https://crbug.com/376668. |
+#if defined(OS_MACOSX) || defined(OS_ANDROID) |
+#define MAYBE_Scroll3DTransformedScroller DISABLED_Scroll3DTransformedScroller |
+#else |
+#define MAYBE_Scroll3DTransformedScroller Scroll3DTransformedScroller |
+#endif |
+IN_PROC_BROWSER_TEST_F(CompositedScrollingBrowserTest, |
+ MAYBE_Scroll3DTransformedScroller) { |
+ LoadURL(); |
+ int scrollDistance = |
+ DoTouchScroll(gfx::Point(50, 150), gfx::Vector2d(0, 100)); |
+ // The scroll distance is increased due to the rotation of the scroller. |
+ EXPECT_EQ(std::floor(100 / std::cos(cc::MathUtil::Deg2Rad(30.f))) - 1, |
+ scrollDistance); |
+} |
+ |
+} // namespace content |