ContentViewScrollingTest.java revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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.
4
5package org.chromium.content.browser;
6
7import android.content.res.Configuration;
8import android.graphics.Canvas;
9import android.os.SystemClock;
10import android.test.suitebuilder.annotation.SmallTest;
11import android.view.KeyEvent;
12import android.view.MotionEvent;
13import android.view.View;
14
15import org.chromium.base.test.util.Feature;
16import org.chromium.base.test.util.UrlUtils;
17import org.chromium.content.browser.ContentViewCore.InternalAccessDelegate;
18import org.chromium.content.browser.test.util.Criteria;
19import org.chromium.content.browser.test.util.CriteriaHelper;
20import org.chromium.content_shell_apk.ContentShellTestBase;
21
22/*
23 * Tests that we can scroll and fling a ContentView running inside ContentShell.
24 */
25public class ContentViewScrollingTest extends ContentShellTestBase {
26
27    private static final String LARGE_PAGE = UrlUtils.encodeHtmlDataUri(
28            "<html><head>" +
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>" +
33            "</html>");
34
35    /**
36     * InternalAccessDelegate to ensure AccessibilityEvent notifications (Eg:TYPE_VIEW_SCROLLED)
37     * are being sent properly on scrolling a page.
38     */
39    static class TestInternalAccessDelegate implements InternalAccessDelegate {
40
41        private boolean mScrollChanged;
42        private final Object mLock = new Object();
43
44
45
46        @Override
47        public boolean drawChild(Canvas canvas, View child, long drawingTime) {
48            return false;
49        }
50
51        @Override
52        public boolean super_onKeyUp(int keyCode, KeyEvent event) {
53            return false;
54        }
55
56        @Override
57        public boolean super_dispatchKeyEventPreIme(KeyEvent event) {
58            return false;
59        }
60
61        @Override
62        public boolean super_dispatchKeyEvent(KeyEvent event) {
63            return false;
64        }
65
66        @Override
67        public boolean super_onGenericMotionEvent(MotionEvent event) {
68            return false;
69        }
70
71        @Override
72        public void super_onConfigurationChanged(Configuration newConfig) {
73        }
74
75        @Override
76        public void onScrollChanged(int lPix, int tPix, int oldlPix, int oldtPix) {
77            synchronized (mLock) {
78                mScrollChanged = true;
79            }
80        }
81
82        @Override
83        public boolean awakenScrollBars() {
84            return false;
85        }
86
87        @Override
88        public boolean super_awakenScrollBars(int startDelay, boolean invalidate) {
89            return false;
90        }
91
92        /**
93         * @return Whether OnScrollChanged() has been called.
94         */
95        public boolean isScrollChanged() {
96            synchronized (mLock) {
97                return mScrollChanged;
98            }
99        }
100    }
101
102    private void assertWaitForScroll(final boolean hugLeft, final boolean hugTop)
103            throws InterruptedException {
104        assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
105            @Override
106            public boolean isSatisfied() {
107                // Scrolling and flinging don't result in exact coordinates.
108                final int MIN_THRESHOLD = 5;
109                final int MAX_THRESHOLD = 100;
110
111                boolean xCorrect = hugLeft ?
112                        getContentViewCore().getNativeScrollXForTest() < MIN_THRESHOLD :
113                        getContentViewCore().getNativeScrollXForTest() > MAX_THRESHOLD;
114                boolean yCorrect = hugTop ?
115                        getContentViewCore().getNativeScrollYForTest() < MIN_THRESHOLD :
116                        getContentViewCore().getNativeScrollYForTest() > MAX_THRESHOLD;
117                return xCorrect && yCorrect;
118            }
119        }));
120    }
121
122    private void fling(final int vx, final int vy) throws Throwable {
123        runTestOnUiThread(new Runnable() {
124            @Override
125            public void run() {
126                getContentViewCore().flingForTest(SystemClock.uptimeMillis(), 0, 0, vx, vy);
127            }
128        });
129    }
130
131    private void scrollTo(final int x, final int y) throws Throwable {
132        runTestOnUiThread(new Runnable() {
133            @Override
134            public void run() {
135                getContentViewCore().getContainerView().scrollTo(x, y);
136            }
137        });
138    }
139
140    @Override
141    protected void setUp() throws Exception {
142        super.setUp();
143
144        launchContentShellWithUrl(LARGE_PAGE);
145        assertTrue("Page failed to load", waitForActiveShellToBeDoneLoading());
146        assertWaitForPageScaleFactorMatch(2.0f);
147
148        assertEquals(0, getContentViewCore().getNativeScrollXForTest());
149        assertEquals(0, getContentViewCore().getNativeScrollYForTest());
150    }
151
152    @SmallTest
153    @Feature({"Main"})
154    public void testFling() throws Throwable {
155        // Vertical fling to lower-left.
156        fling(0, -1000);
157        assertWaitForScroll(true, false);
158
159        // Horizontal fling to lower-right.
160        fling(-1000, 0);
161        assertWaitForScroll(false, false);
162
163        // Vertical fling to upper-right.
164        fling(0, 1000);
165        assertWaitForScroll(false, true);
166
167        // Horizontal fling to top-left.
168        fling(1000, 0);
169        assertWaitForScroll(true, true);
170
171        // Diagonal fling to bottom-right.
172        fling(-1000, -1000);
173        assertWaitForScroll(false, false);
174    }
175
176    @SmallTest
177    @Feature({"Main"})
178    public void testScroll() throws Throwable {
179        // Vertical scroll to lower-left.
180        scrollTo(0, 2500);
181        assertWaitForScroll(true, false);
182
183        // Horizontal scroll to lower-right.
184        scrollTo(2500, 2500);
185        assertWaitForScroll(false, false);
186
187        // Vertical scroll to upper-right.
188        scrollTo(2500, 0);
189        assertWaitForScroll(false, true);
190
191        // Horizontal scroll to top-left.
192        scrollTo(0, 0);
193        assertWaitForScroll(true, true);
194
195        // Diagonal scroll to bottom-right.
196        scrollTo(2500, 2500);
197        assertWaitForScroll(false, false);
198    }
199
200
201    /**
202     * To ensure the device properly responds to bounds-exceeding scrolls, e.g., overscroll
203     * effects are properly initialized.
204     */
205    @SmallTest
206    @Feature({"Main"})
207    public void testOverScroll() throws Throwable {
208        // Overscroll lower-left.
209        scrollTo(-10000, 10000);
210        assertWaitForScroll(true, false);
211
212        // Overscroll lower-right.
213        scrollTo(10000, 10000);
214        assertWaitForScroll(false, false);
215
216        // Overscroll upper-right.
217        scrollTo(10000, -10000);
218        assertWaitForScroll(false, true);
219
220        // Overscroll top-left.
221        scrollTo(-10000, -10000);
222        assertWaitForScroll(true, true);
223
224        // Diagonal overscroll lower-right.
225        scrollTo(10000, 10000);
226        assertWaitForScroll(false, false);
227    }
228
229    /**
230     * To ensure the AccessibilityEvent notifications (Eg:TYPE_VIEW_SCROLLED) are being sent
231     * properly on scrolling a page.
232     */
233    @SmallTest
234    @Feature({"Main"})
235    public void testOnScrollChanged() throws Throwable {
236        final int scrollToX = 2500;
237        final int scrollToY = 2500;
238        final TestInternalAccessDelegate containerViewInternals = new TestInternalAccessDelegate();
239        runTestOnUiThread(new Runnable() {
240            @Override
241            public void run() {
242                getContentViewCore().setContainerViewInternals(containerViewInternals);
243            }
244        });
245        scrollTo(scrollToX, scrollToY);
246        assertWaitForScroll(false, false);
247        assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
248            @Override
249            public boolean isSatisfied() {
250                return containerViewInternals.isScrollChanged();
251            }
252        }));
253    }
254}
255