Home | History | Annotate | Download | only in test
      1 // Copyright 2013 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.android_webview.test;
      6 
      7 import android.test.suitebuilder.annotation.MediumTest;
      8 
      9 import org.chromium.android_webview.AwContents;
     10 import org.chromium.android_webview.AwContentsClient;
     11 import org.chromium.android_webview.AwSettings;
     12 import org.chromium.base.test.util.Feature;
     13 import org.chromium.content.browser.test.util.CallbackHelper;
     14 import org.chromium.ui.gfx.DeviceDisplayInfo;
     15 
     16 import java.util.Locale;
     17 import java.util.concurrent.Callable;
     18 
     19 /**
     20  * Tests for legacy quirks (compatibility with WebView Classic).
     21  */
     22 public class AwLegacyQuirksTest extends AwTestBase {
     23 
     24     @MediumTest
     25     @Feature({"AndroidWebView"})
     26     public void testTargetDensityDpi() throws Throwable {
     27         final TestAwContentsClient contentClient = new TestAwContentsClient();
     28         final AwTestContainerView testContainerView =
     29                 createAwTestContainerViewOnMainSyncInQuirksMode(contentClient);
     30         final AwContents awContents = testContainerView.getAwContents();
     31         AwSettings settings = getAwSettingsOnUiThread(awContents);
     32         CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper();
     33 
     34         final String pageTemplate = "<html><head>" +
     35                 "<meta name='viewport' content='width=device-width, target-densityDpi=%s' />" +
     36                 "</head><body onload='document.title=document.body.clientWidth'></body></html>";
     37         final String pageDeviceDpi = String.format((Locale) null, pageTemplate, "device-dpi");
     38         final String pageHighDpi = String.format((Locale) null, pageTemplate, "high-dpi");
     39         final String pageDpi100 = String.format((Locale) null, pageTemplate, "100");
     40 
     41         settings.setJavaScriptEnabled(true);
     42 
     43         DeviceDisplayInfo deviceInfo =
     44                 DeviceDisplayInfo.create(getInstrumentation().getTargetContext());
     45         loadDataSync(awContents, onPageFinishedHelper, pageDeviceDpi, "text/html", false);
     46         int actualWidth = Integer.parseInt(getTitleOnUiThread(awContents));
     47         assertEquals(deviceInfo.getDisplayWidth(), actualWidth, 10f);
     48 
     49         float displayWidth = (deviceInfo.getDisplayWidth());
     50         float deviceDpi = (float) (160f * deviceInfo.getDIPScale());
     51 
     52         loadDataSync(awContents, onPageFinishedHelper, pageHighDpi, "text/html", false);
     53         actualWidth = Integer.parseInt(getTitleOnUiThread(awContents));
     54         assertEquals(displayWidth * (240f / deviceDpi), actualWidth, 10f);
     55 
     56         loadDataSync(awContents, onPageFinishedHelper, pageDpi100, "text/html", false);
     57         actualWidth = Integer.parseInt(getTitleOnUiThread(awContents));
     58         assertEquals(displayWidth * (100f / deviceDpi), actualWidth, 10f);
     59     }
     60 
     61     @MediumTest
     62     @Feature({"AndroidWebView"})
     63     public void testWideViewportInitialScaleDoesNotExpandFixedLayoutWidth() throws Throwable {
     64         final TestAwContentsClient contentClient = new TestAwContentsClient();
     65         final AwTestContainerView testContainerView =
     66                 createAwTestContainerViewOnMainSyncInQuirksMode(contentClient);
     67         final AwContents awContents = testContainerView.getAwContents();
     68         AwSettings settings = getAwSettingsOnUiThread(awContents);
     69         CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper();
     70 
     71         final String page = "<html><head>" +
     72                 "<meta name='viewport' content='width=device-width, initial-scale=0.5' />" +
     73                 "</head><body onload='document.title=document.body.clientWidth'></body></html>";
     74 
     75         settings.setJavaScriptEnabled(true);
     76         settings.setUseWideViewPort(true);
     77 
     78         DeviceDisplayInfo deviceInfo =
     79                 DeviceDisplayInfo.create(getInstrumentation().getTargetContext());
     80         loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false);
     81         float displayWidth = (float) (deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale());
     82         int actualWidth = Integer.parseInt(getTitleOnUiThread(awContents));
     83         assertEquals(displayWidth, actualWidth, 10f);
     84         assertEquals(1.0f, getScaleOnUiThread(awContents));
     85     }
     86 
     87     @MediumTest
     88     @Feature({"AndroidWebView"})
     89     public void testZeroValuesQuirk() throws Throwable {
     90         final TestAwContentsClient contentClient = new TestAwContentsClient();
     91         final AwTestContainerView testContainerView =
     92                 createAwTestContainerViewOnMainSyncInQuirksMode(contentClient);
     93         final AwContents awContents = testContainerView.getAwContents();
     94         AwSettings settings = getAwSettingsOnUiThread(awContents);
     95         CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper();
     96 
     97         final String page = "<html><head>" +
     98                 "<meta name='viewport' content='width=0, height=0, initial-scale=0.0, " +
     99                 "    minimum-scale=0.0, maximum-scale=0.0' />" +
    100                 "</head><body onload='document.title=document.body.clientWidth'></body></html>";
    101 
    102         settings.setJavaScriptEnabled(true);
    103 
    104         DeviceDisplayInfo deviceInfo =
    105                 DeviceDisplayInfo.create(getInstrumentation().getTargetContext());
    106         loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false);
    107         float displayWidth = (float) (deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale());
    108         int actualWidth = Integer.parseInt(getTitleOnUiThread(awContents));
    109         assertEquals(displayWidth, actualWidth, 10f);
    110         assertEquals(1.0f, getScaleOnUiThread(awContents));
    111 
    112         settings.setUseWideViewPort(true);
    113         loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false);
    114         actualWidth = Integer.parseInt(getTitleOnUiThread(awContents));
    115         assertEquals(displayWidth, actualWidth, 10f);
    116         assertEquals(1.0f, getScaleOnUiThread(awContents));
    117     }
    118 
    119     @MediumTest
    120     @Feature({"AndroidWebView"})
    121     public void testScreenSizeInPhysicalPixelsQuirk() throws Throwable {
    122         final TestAwContentsClient contentClient = new TestAwContentsClient();
    123         final AwTestContainerView testContainerView =
    124                 createAwTestContainerViewOnMainSyncInQuirksMode(contentClient);
    125         final AwContents awContents = testContainerView.getAwContents();
    126         AwSettings settings = getAwSettingsOnUiThread(awContents);
    127         CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper();
    128 
    129         settings.setJavaScriptEnabled(true);
    130 
    131         loadUrlSync(awContents, onPageFinishedHelper, "about:blank");
    132 
    133         DeviceDisplayInfo deviceInfo =
    134                 DeviceDisplayInfo.create(getInstrumentation().getTargetContext());
    135         float dipScale = (float) deviceInfo.getDIPScale();
    136         float physicalDisplayWidth = deviceInfo.getPhysicalDisplayWidth() != 0 ?
    137                                      deviceInfo.getPhysicalDisplayWidth() :
    138                                      deviceInfo.getDisplayWidth();
    139         float cssDisplayWidth = physicalDisplayWidth / dipScale;
    140         float physicalDisplayHeight = deviceInfo.getPhysicalDisplayHeight() != 0 ?
    141                                       deviceInfo.getPhysicalDisplayHeight() :
    142                                       deviceInfo.getDisplayHeight();
    143         float cssDisplayHeight = physicalDisplayHeight / dipScale;
    144 
    145         float screenWidth = Integer.parseInt(
    146                 executeJavaScriptAndWaitForResult(awContents, contentClient, "screen.width"));
    147         assertEquals(physicalDisplayWidth, screenWidth, 10f);
    148         float screenAvailWidth = Integer.parseInt(
    149                 executeJavaScriptAndWaitForResult(awContents, contentClient, "screen.availWidth"));
    150         assertEquals(physicalDisplayWidth, screenAvailWidth, 10f);
    151         float outerWidth = Integer.parseInt(
    152                 executeJavaScriptAndWaitForResult(awContents, contentClient, "outerWidth"));
    153         float innerWidth = Integer.parseInt(
    154                 executeJavaScriptAndWaitForResult(awContents, contentClient, "innerWidth"));
    155         assertEquals(innerWidth * dipScale, outerWidth, 10f);
    156         String deviceWidthEqualsScreenWidth = executeJavaScriptAndWaitForResult(awContents,
    157                 contentClient,
    158                 "matchMedia(\"screen and (device-width:" + (int) screenWidth + "px)\").matches");
    159         assertEquals("true", deviceWidthEqualsScreenWidth);
    160 
    161         float screenHeight = Integer.parseInt(
    162                 executeJavaScriptAndWaitForResult(awContents, contentClient, "screen.height"));
    163         assertEquals(physicalDisplayHeight, screenHeight, 10f);
    164         float screenAvailHeight = Integer.parseInt(
    165                 executeJavaScriptAndWaitForResult(awContents, contentClient, "screen.availHeight"));
    166         assertEquals(physicalDisplayHeight, screenAvailHeight, 10f);
    167         float outerHeight = Integer.parseInt(
    168                 executeJavaScriptAndWaitForResult(awContents, contentClient, "outerHeight"));
    169         float innerHeight = Integer.parseInt(
    170                 executeJavaScriptAndWaitForResult(awContents, contentClient, "innerHeight"));
    171         assertEquals(innerHeight * dipScale, outerHeight, 10f);
    172         String deviceHeightEqualsScreenHeight = executeJavaScriptAndWaitForResult(awContents,
    173                 contentClient,
    174                 "matchMedia(\"screen and (device-height:" + (int) screenHeight + "px)\").matches");
    175         assertEquals("true", deviceHeightEqualsScreenHeight);
    176     }
    177 
    178     @MediumTest
    179     @Feature({"AndroidWebView"})
    180     public void testMetaMergeContentQuirk() throws Throwable {
    181         final TestAwContentsClient contentClient = new TestAwContentsClient();
    182         final AwTestContainerView testContainerView =
    183                 createAwTestContainerViewOnMainSyncInQuirksMode(contentClient);
    184         final AwContents awContents = testContainerView.getAwContents();
    185         AwSettings settings = getAwSettingsOnUiThread(awContents);
    186         CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper();
    187 
    188         final int pageWidth = 3000;
    189         final float pageScale = 1.0f;
    190         final String page = String.format((Locale) null, "<html><head>" +
    191                 "<meta name='viewport' content='width=%d' />" +
    192                 "<meta name='viewport' content='initial-scale=%.1f' />" +
    193                 "<meta name='viewport' content='user-scalable=0' />" +
    194                 "</head><body onload='document.title=document.body.clientWidth'></body></html>",
    195                 pageWidth, pageScale);
    196 
    197         settings.setJavaScriptEnabled(true);
    198         settings.setUseWideViewPort(true);
    199         settings.setBuiltInZoomControls(true);
    200         settings.setSupportZoom(true);
    201 
    202         loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false);
    203         // ContentView must update itself according to the viewport setup.
    204         // As we specify 'user-scalable=0', the page must become non-zoomable.
    205         poll(new Callable<Boolean>() {
    206             @Override
    207             public Boolean call() throws Exception {
    208                 return !canZoomInOnUiThread(awContents) && !canZoomOutOnUiThread(awContents);
    209             }
    210         });
    211         int width = Integer.parseInt(getTitleOnUiThread(awContents));
    212         assertEquals(pageWidth, width);
    213         assertEquals(pageScale, getScaleOnUiThread(awContents));
    214     }
    215 
    216     @MediumTest
    217     @Feature({"AndroidWebView"})
    218     public void testMetaMergeContentQuirkOverrides() throws Throwable {
    219         final TestAwContentsClient contentClient = new TestAwContentsClient();
    220         final AwTestContainerView testContainerView =
    221                 createAwTestContainerViewOnMainSyncInQuirksMode(contentClient);
    222         final AwContents awContents = testContainerView.getAwContents();
    223         AwSettings settings = getAwSettingsOnUiThread(awContents);
    224         CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper();
    225 
    226         final int pageWidth = 3000;
    227         final String page = String.format((Locale) null, "<html><head>" +
    228                 "<meta name='viewport' content='width=device-width' />" +
    229                 "<meta name='viewport' content='width=%d' />" +
    230                 "</head><body onload='document.title=document.body.clientWidth'></body></html>",
    231                 pageWidth);
    232 
    233         settings.setJavaScriptEnabled(true);
    234         settings.setUseWideViewPort(true);
    235 
    236         loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false);
    237         int width = Integer.parseInt(getTitleOnUiThread(awContents));
    238         assertEquals(pageWidth, width);
    239     }
    240 
    241     @MediumTest
    242     @Feature({"AndroidWebView"})
    243     public void testInitialScaleClobberQuirk() throws Throwable {
    244         final TestAwContentsClient contentClient = new TestAwContentsClient();
    245         final AwTestContainerView testContainerView =
    246                 createAwTestContainerViewOnMainSyncInQuirksMode(contentClient);
    247         final AwContents awContents = testContainerView.getAwContents();
    248         AwSettings settings = getAwSettingsOnUiThread(awContents);
    249         CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper();
    250 
    251         final String pageTemplate = "<html><head>" +
    252                 "<meta name='viewport' content='initial-scale=%d' />" +
    253                 "</head><body>" +
    254                 "<div style='width:10000px;height:200px'>A big div</div>" +
    255                 "</body></html>";
    256         final String pageScale4 = String.format((Locale) null, pageTemplate, 4);
    257         final String page = String.format((Locale) null, pageTemplate, 1);
    258 
    259         // Page scale updates are asynchronous. There is an issue that we can't
    260         // reliably check, whether the scale as NOT changed (i.e. remains to be 1.0).
    261         // So we first change the scale to some non-default value, and then wait
    262         // until it gets back to 1.0.
    263         int onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount();
    264         loadDataSync(awContents, onPageFinishedHelper, pageScale4, "text/html", false);
    265         contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount);
    266         assertEquals(4.0f, getScaleOnUiThread(awContents));
    267         // The following call to set initial scale will be ignored. However, a temporary
    268         // page scale change may occur, and this makes the usual onScaleChanged-based workflow
    269         // flaky. So instead, we are just polling the scale until it becomes 1.0.
    270         settings.setInitialPageScale(50);
    271         loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false);
    272         ensureScaleBecomes(1.0f, awContents);
    273     }
    274 
    275     @MediumTest
    276     @Feature({"AndroidWebView"})
    277     public void testNoUserScalableQuirk() throws Throwable {
    278         final TestAwContentsClient contentClient = new TestAwContentsClient();
    279         final AwTestContainerView testContainerView =
    280                 createAwTestContainerViewOnMainSyncInQuirksMode(contentClient);
    281         final AwContents awContents = testContainerView.getAwContents();
    282         CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper();
    283 
    284         final String pageScale4 = "<html><head>" +
    285                 "<meta name='viewport' content='initial-scale=4' />" +
    286                 "</head><body>" +
    287                 "<div style='width:10000px;height:200px'>A big div</div>" +
    288                 "</body></html>";
    289         final String page = "<html><head>" +
    290                 "<meta name='viewport' " +
    291                 "content='width=device-width,initial-scale=2,user-scalable=no' />" +
    292                 "</head><body>" +
    293                 "<div style='width:10000px;height:200px'>A big div</div>" +
    294                 "</body></html>";
    295 
    296         // Page scale updates are asynchronous. There is an issue that we can't
    297         // reliably check, whether the scale as NOT changed (i.e. remains to be 1.0).
    298         // So we first change the scale to some non-default value, and then wait
    299         // until it gets back to 1.0.
    300         int onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount();
    301         loadDataSync(awContents, onPageFinishedHelper, pageScale4, "text/html", false);
    302         contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount);
    303         assertEquals(4.0f, getScaleOnUiThread(awContents));
    304         onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount();
    305         loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false);
    306         contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount);
    307         assertEquals(1.0f, getScaleOnUiThread(awContents));
    308     }
    309 
    310     // background shorthand property must not override background-size when
    311     // it's already set.
    312     @MediumTest
    313     @Feature({"AndroidWebView", "Preferences"})
    314     public void testUseLegacyBackgroundSizeShorthandBehavior() throws Throwable {
    315         final TestAwContentsClient contentClient = new TestAwContentsClient();
    316         final AwTestContainerView testContainerView =
    317                 createAwTestContainerViewOnMainSyncInQuirksMode(contentClient);
    318         final AwContents awContents = testContainerView.getAwContents();
    319         AwSettings settings = getAwSettingsOnUiThread(awContents);
    320         CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper();
    321         final String expectedBackgroundSize = "cover";
    322         final String page = "<html><head>" +
    323                 "<script>" +
    324                 "function getBackgroundSize() {" +
    325                 "  var e = document.getElementById('test'); " +
    326                 "  e.style.backgroundSize = '" + expectedBackgroundSize + "';" +
    327                 "  e.style.background = 'center red url(dummy://test.png) no-repeat border-box'; " +
    328                 "  return e.style.backgroundSize; " +
    329                 "}" +
    330                 "</script></head>" +
    331                 "<body onload='document.title=getBackgroundSize()'>" +
    332                 "  <div id='test'> </div>" +
    333                 "</body></html>";
    334         settings.setJavaScriptEnabled(true);
    335         loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false);
    336         String actualBackgroundSize = getTitleOnUiThread(awContents);
    337         assertEquals(expectedBackgroundSize, actualBackgroundSize);
    338     }
    339 
    340     private AwTestContainerView createAwTestContainerViewOnMainSyncInQuirksMode(
    341             final AwContentsClient client) throws Exception {
    342         return createAwTestContainerViewOnMainSync(client, true);
    343     }
    344 
    345     private void ensureScaleBecomes(final float targetScale, final AwContents awContents)
    346             throws Throwable {
    347         poll(new Callable<Boolean>() {
    348             @Override
    349             public Boolean call() throws Exception {
    350                 return targetScale == getScaleOnUiThread(awContents);
    351             }
    352         });
    353     }
    354 }
    355