1 // Copyright 2012 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 package org.chromium.content.browser;
7 import android.content.res.Configuration;
8 import android.graphics.Canvas;
9 import android.os.SystemClock;
10 import android.test.suitebuilder.annotation.SmallTest;
11 import android.view.KeyEvent;
12 import android.view.MotionEvent;
13 import android.view.View;
15 import org.chromium.base.test.util.Feature;
16 import org.chromium.base.test.util.UrlUtils;
17 import org.chromium.content.browser.ContentViewCore.InternalAccessDelegate;
18 import org.chromium.content.browser.test.util.Criteria;
19 import org.chromium.content.browser.test.util.CriteriaHelper;
20 import org.chromium.content_shell_apk.ContentShellTestBase;
23 * Tests that we can scroll and fling a ContentView running inside ContentShell.
25 public class ContentViewScrollingTest extends ContentShellTestBase {
27 private static final String LARGE_PAGE = UrlUtils.encodeHtmlDataUri(
29 "<meta name=\"viewport\" content=\"width=device-width, " +
30 "initial-scale=2.0, maximum-scale=2.0\" />" +
31 "<style>body { width: 5000px; height: 5000px; }</style></head>" +
32 "<body>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</body>" +
36 * InternalAccessDelegate to ensure AccessibilityEvent notifications (Eg:TYPE_VIEW_SCROLLED)
37 * are being sent properly on scrolling a page.
39 static class TestInternalAccessDelegate implements InternalAccessDelegate {
41 private boolean mScrollChanged;
42 private final Object mLock = new Object();
47 public boolean drawChild(Canvas canvas, View child, long drawingTime) {
52 public boolean super_onKeyUp(int keyCode, KeyEvent event) {
57 public boolean super_dispatchKeyEventPreIme(KeyEvent event) {
62 public boolean super_dispatchKeyEvent(KeyEvent event) {
67 public boolean super_onGenericMotionEvent(MotionEvent event) {
72 public void super_onConfigurationChanged(Configuration newConfig) {
76 public void onScrollChanged(int lPix, int tPix, int oldlPix, int oldtPix) {
77 synchronized (mLock) {
78 mScrollChanged = true;
83 public boolean awakenScrollBars() {
88 public boolean super_awakenScrollBars(int startDelay, boolean invalidate) {
93 * @return Whether OnScrollChanged() has been called.
95 public boolean isScrollChanged() {
96 synchronized (mLock) {
97 return mScrollChanged;
102 private void assertWaitForScroll(final boolean hugLeft, final boolean hugTop)
103 throws InterruptedException {
104 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
106 public boolean isSatisfied() {
107 // Scrolling and flinging don't result in exact coordinates.
108 final int minThreshold = 5;
109 final int maxThreshold = 100;
111 boolean xCorrect = hugLeft ?
112 getContentViewCore().getNativeScrollXForTest() < minThreshold :
113 getContentViewCore().getNativeScrollXForTest() > maxThreshold;
114 boolean yCorrect = hugTop ?
115 getContentViewCore().getNativeScrollYForTest() < minThreshold :
116 getContentViewCore().getNativeScrollYForTest() > maxThreshold;
117 return xCorrect && yCorrect;
122 private void fling(final int vx, final int vy) throws Throwable {
123 runTestOnUiThread(new Runnable() {
126 getContentViewCore().flingForTest(SystemClock.uptimeMillis(), 0, 0, vx, vy);
131 private void scrollTo(final int x, final int y) throws Throwable {
132 runTestOnUiThread(new Runnable() {
135 getContentViewCore().getContainerView().scrollTo(x, y);
141 protected void setUp() throws Exception {
144 launchContentShellWithUrl(LARGE_PAGE);
145 assertTrue("Page failed to load", waitForActiveShellToBeDoneLoading());
146 assertWaitForPageScaleFactorMatch(2.0f);
148 assertEquals(0, getContentViewCore().getNativeScrollXForTest());
149 assertEquals(0, getContentViewCore().getNativeScrollYForTest());
154 public void testFling() throws Throwable {
155 // Scaling the initial velocity by the device scale factor ensures that
156 // it's of sufficient magnitude for all displays densities.
157 float deviceScaleFactor =
158 getInstrumentation().getTargetContext().getResources().getDisplayMetrics().density;
159 int velocity = (int) (1000 * deviceScaleFactor);
161 // Vertical fling to lower-left.
163 assertWaitForScroll(true, false);
165 // Horizontal fling to lower-right.
167 assertWaitForScroll(false, false);
169 // Vertical fling to upper-right.
171 assertWaitForScroll(false, true);
173 // Horizontal fling to top-left.
175 assertWaitForScroll(true, true);
177 // Diagonal fling to bottom-right.
178 fling(-velocity, -velocity);
179 assertWaitForScroll(false, false);
183 @RerunWithUpdatedContainerView
185 public void testScroll() throws Throwable {
186 // Vertical scroll to lower-left.
188 assertWaitForScroll(true, false);
190 // Horizontal scroll to lower-right.
191 scrollTo(2500, 2500);
192 assertWaitForScroll(false, false);
194 // Vertical scroll to upper-right.
196 assertWaitForScroll(false, true);
198 // Horizontal scroll to top-left.
200 assertWaitForScroll(true, true);
202 // Diagonal scroll to bottom-right.
203 scrollTo(2500, 2500);
204 assertWaitForScroll(false, false);
208 * To ensure the device properly responds to bounds-exceeding scrolls, e.g., overscroll
209 * effects are properly initialized.
212 @RerunWithUpdatedContainerView
214 public void testOverScroll() throws Throwable {
215 // Overscroll lower-left.
216 scrollTo(-10000, 10000);
217 assertWaitForScroll(true, false);
219 // Overscroll lower-right.
220 scrollTo(10000, 10000);
221 assertWaitForScroll(false, false);
223 // Overscroll upper-right.
224 scrollTo(10000, -10000);
225 assertWaitForScroll(false, true);
227 // Overscroll top-left.
228 scrollTo(-10000, -10000);
229 assertWaitForScroll(true, true);
231 // Diagonal overscroll lower-right.
232 scrollTo(10000, 10000);
233 assertWaitForScroll(false, false);
237 * To ensure the AccessibilityEvent notifications (Eg:TYPE_VIEW_SCROLLED) are being sent
238 * properly on scrolling a page.
241 @RerunWithUpdatedContainerView
243 public void testOnScrollChanged() throws Throwable {
244 final int scrollToX = getContentViewCore().getNativeScrollXForTest() + 2500;
245 final int scrollToY = getContentViewCore().getNativeScrollYForTest() + 2500;
246 final TestInternalAccessDelegate containerViewInternals = new TestInternalAccessDelegate();
247 runTestOnUiThread(new Runnable() {
250 getContentViewCore().setContainerViewInternals(containerViewInternals);
253 scrollTo(scrollToX, scrollToY);
254 assertWaitForScroll(false, false);
255 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
257 public boolean isSatisfied() {
258 return containerViewInternals.isScrollChanged();