Home | History | Annotate | Download | only in browser
      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 
      5 package org.chromium.content.browser;
      6 
      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;
     14 
     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;
     21 
     22 /*
     23  * Tests that we can scroll and fling a ContentView running inside ContentShell.
     24  */
     25 public 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     @RerunWithUpdatedContainerView
    178     @Feature({"Main"})
    179     public void testScroll() throws Throwable {
    180         // Vertical scroll to lower-left.
    181         scrollTo(0, 2500);
    182         assertWaitForScroll(true, false);
    183 
    184         // Horizontal scroll to lower-right.
    185         scrollTo(2500, 2500);
    186         assertWaitForScroll(false, false);
    187 
    188         // Vertical scroll to upper-right.
    189         scrollTo(2500, 0);
    190         assertWaitForScroll(false, true);
    191 
    192         // Horizontal scroll to top-left.
    193         scrollTo(0, 0);
    194         assertWaitForScroll(true, true);
    195 
    196         // Diagonal scroll to bottom-right.
    197         scrollTo(2500, 2500);
    198         assertWaitForScroll(false, false);
    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     @RerunWithUpdatedContainerView
    207     @Feature({"Main"})
    208     public void testOverScroll() throws Throwable {
    209         // Overscroll lower-left.
    210         scrollTo(-10000, 10000);
    211         assertWaitForScroll(true, false);
    212 
    213         // Overscroll lower-right.
    214         scrollTo(10000, 10000);
    215         assertWaitForScroll(false, false);
    216 
    217         // Overscroll upper-right.
    218         scrollTo(10000, -10000);
    219         assertWaitForScroll(false, true);
    220 
    221         // Overscroll top-left.
    222         scrollTo(-10000, -10000);
    223         assertWaitForScroll(true, true);
    224 
    225         // Diagonal overscroll lower-right.
    226         scrollTo(10000, 10000);
    227         assertWaitForScroll(false, false);
    228     }
    229 
    230     /**
    231      * To ensure the AccessibilityEvent notifications (Eg:TYPE_VIEW_SCROLLED) are being sent
    232      * properly on scrolling a page.
    233      */
    234     @SmallTest
    235     @RerunWithUpdatedContainerView
    236     @Feature({"Main"})
    237     public void testOnScrollChanged() throws Throwable {
    238         final int scrollToX = getContentViewCore().getNativeScrollXForTest() + 2500;
    239         final int scrollToY = getContentViewCore().getNativeScrollYForTest() + 2500;
    240         final TestInternalAccessDelegate containerViewInternals = new TestInternalAccessDelegate();
    241         runTestOnUiThread(new Runnable() {
    242             @Override
    243             public void run() {
    244                 getContentViewCore().setContainerViewInternals(containerViewInternals);
    245             }
    246         });
    247         scrollTo(scrollToX, scrollToY);
    248         assertWaitForScroll(false, false);
    249         assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
    250             @Override
    251             public boolean isSatisfied() {
    252                 return containerViewInternals.isScrollChanged();
    253             }
    254         }));
    255     }
    256 }
    257