| // Copyright 2013 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. |
| |
| package org.chromium.android_webview.test; |
| |
| import android.support.test.InstrumentationRegistry; |
| import android.support.test.filters.MediumTest; |
| |
| import org.junit.Assert; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| import org.chromium.android_webview.AwContents; |
| import org.chromium.android_webview.AwContentsClient; |
| import org.chromium.android_webview.AwSettings; |
| import org.chromium.base.ThreadUtils; |
| import org.chromium.base.test.util.CallbackHelper; |
| import org.chromium.base.test.util.DisabledTest; |
| import org.chromium.base.test.util.Feature; |
| import org.chromium.base.test.util.RetryOnFailure; |
| import org.chromium.content_public.common.ContentUrlConstants; |
| import org.chromium.ui.display.DisplayAndroid; |
| |
| import java.util.Locale; |
| |
| /** |
| * Tests for legacy quirks (compatibility with WebView Classic). |
| */ |
| @RunWith(AwJUnit4ClassRunner.class) |
| public class AwLegacyQuirksTest { |
| @Rule |
| public AwActivityTestRule mActivityTestRule = new AwActivityTestRule(); |
| |
| // WebView layout width tests are flaky: http://crbug.com/746264 |
| @Test |
| @RetryOnFailure |
| @MediumTest |
| @Feature({"AndroidWebView"}) |
| @DisabledTest(message = "crbug.com/746264") |
| public void testTargetDensityDpi() throws Throwable { |
| final TestAwContentsClient contentClient = new TestAwContentsClient(); |
| final AwTestContainerView testContainerView = |
| createAwTestContainerViewOnMainSyncInQuirksMode(contentClient); |
| final AwContents awContents = testContainerView.getAwContents(); |
| AwSettings settings = mActivityTestRule.getAwSettingsOnUiThread(awContents); |
| CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); |
| |
| final String pageTemplate = "<html><head>" |
| + "<meta name='viewport' content='width=device-width, target-densityDpi=%s' />" |
| + "</head><body onload='document.title=document.body.clientWidth'></body></html>"; |
| final String pageDeviceDpi = String.format((Locale) null, pageTemplate, "device-dpi"); |
| final String pageHighDpi = String.format((Locale) null, pageTemplate, "high-dpi"); |
| final String pageDpi100 = String.format((Locale) null, pageTemplate, "100"); |
| |
| settings.setJavaScriptEnabled(true); |
| |
| DisplayAndroid displayAndroid = ThreadUtils.runOnUiThreadBlockingNoException(() -> { |
| return DisplayAndroid.getNonMultiDisplay( |
| InstrumentationRegistry.getInstrumentation().getTargetContext()); |
| }); |
| mActivityTestRule.loadDataSync( |
| awContents, onPageFinishedHelper, pageDeviceDpi, "text/html", false); |
| int actualWidth = Integer.parseInt(mActivityTestRule.getTitleOnUiThread(awContents)); |
| Assert.assertEquals(displayAndroid.getDisplayWidth(), actualWidth, 10f); |
| |
| float displayWidth = (displayAndroid.getDisplayWidth()); |
| float deviceDpi = 160f * displayAndroid.getDipScale(); |
| |
| mActivityTestRule.loadDataSync( |
| awContents, onPageFinishedHelper, pageHighDpi, "text/html", false); |
| actualWidth = Integer.parseInt(mActivityTestRule.getTitleOnUiThread(awContents)); |
| Assert.assertEquals(displayWidth * (240f / deviceDpi), actualWidth, 10f); |
| |
| mActivityTestRule.loadDataSync( |
| awContents, onPageFinishedHelper, pageDpi100, "text/html", false); |
| actualWidth = Integer.parseInt(mActivityTestRule.getTitleOnUiThread(awContents)); |
| Assert.assertEquals(displayWidth * (100f / deviceDpi), actualWidth, 10f); |
| } |
| |
| // WebView layout width tests are flaky: http://crbug.com/746264 |
| @Test |
| @RetryOnFailure |
| @MediumTest |
| @Feature({"AndroidWebView"}) |
| @DisabledTest(message = "crbug.com/746264") |
| public void testWideViewportInitialScaleDoesNotExpandFixedLayoutWidth() throws Throwable { |
| final TestAwContentsClient contentClient = new TestAwContentsClient(); |
| final AwTestContainerView testContainerView = |
| createAwTestContainerViewOnMainSyncInQuirksMode(contentClient); |
| final AwContents awContents = testContainerView.getAwContents(); |
| AwSettings settings = mActivityTestRule.getAwSettingsOnUiThread(awContents); |
| CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); |
| |
| final String page = "<html><head>" |
| + "<meta name='viewport' content='width=device-width, initial-scale=0.5' />" |
| + "</head><body onload='document.title=document.body.clientWidth'></body></html>"; |
| |
| settings.setJavaScriptEnabled(true); |
| settings.setUseWideViewPort(true); |
| |
| DisplayAndroid displayAndroid = ThreadUtils.runOnUiThreadBlockingNoException(() -> { |
| return DisplayAndroid.getNonMultiDisplay( |
| InstrumentationRegistry.getInstrumentation().getTargetContext()); |
| }); |
| mActivityTestRule.loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); |
| float displayWidth = |
| displayAndroid.getDisplayWidth() / displayAndroid.getDipScale(); |
| int actualWidth = Integer.parseInt(mActivityTestRule.getTitleOnUiThread(awContents)); |
| Assert.assertEquals(displayWidth, actualWidth, 10f); |
| Assert.assertEquals(1.0f, mActivityTestRule.getScaleOnUiThread(awContents), 0); |
| } |
| |
| // WebView layout width tests are flaky: http://crbug.com/746264 |
| @Test |
| @RetryOnFailure |
| @MediumTest |
| @Feature({"AndroidWebView"}) |
| @DisabledTest(message = "crbug.com/746264") |
| public void testZeroValuesQuirk() throws Throwable { |
| final TestAwContentsClient contentClient = new TestAwContentsClient(); |
| final AwTestContainerView testContainerView = |
| createAwTestContainerViewOnMainSyncInQuirksMode(contentClient); |
| final AwContents awContents = testContainerView.getAwContents(); |
| AwSettings settings = mActivityTestRule.getAwSettingsOnUiThread(awContents); |
| CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); |
| |
| final String page = "<html><head>" |
| + "<meta name='viewport' content='width=0, height=0, initial-scale=0.0, " |
| + " minimum-scale=0.0, maximum-scale=0.0' />" |
| + "</head><body onload='document.title=document.body.clientWidth'></body></html>"; |
| |
| settings.setJavaScriptEnabled(true); |
| |
| DisplayAndroid displayAndroid = ThreadUtils.runOnUiThreadBlockingNoException(() -> { |
| return DisplayAndroid.getNonMultiDisplay( |
| InstrumentationRegistry.getInstrumentation().getTargetContext()); |
| }); |
| mActivityTestRule.loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); |
| float displayWidth = |
| displayAndroid.getDisplayWidth() / displayAndroid.getDipScale(); |
| int actualWidth = Integer.parseInt(mActivityTestRule.getTitleOnUiThread(awContents)); |
| Assert.assertEquals(displayWidth, actualWidth, 10f); |
| Assert.assertEquals(1.0f, mActivityTestRule.getScaleOnUiThread(awContents), 0); |
| |
| settings.setUseWideViewPort(true); |
| mActivityTestRule.loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); |
| actualWidth = Integer.parseInt(mActivityTestRule.getTitleOnUiThread(awContents)); |
| Assert.assertEquals(displayWidth, actualWidth, 10f); |
| Assert.assertEquals(1.0f, mActivityTestRule.getScaleOnUiThread(awContents), 0); |
| } |
| |
| @Test |
| @MediumTest |
| @Feature({"AndroidWebView"}) |
| public void testScreenSizeInPhysicalPixelsQuirk() throws Throwable { |
| final TestAwContentsClient contentClient = new TestAwContentsClient(); |
| final AwTestContainerView testContainerView = |
| createAwTestContainerViewOnMainSyncInQuirksMode(contentClient); |
| final AwContents awContents = testContainerView.getAwContents(); |
| AwSettings settings = mActivityTestRule.getAwSettingsOnUiThread(awContents); |
| CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); |
| |
| settings.setJavaScriptEnabled(true); |
| |
| mActivityTestRule.loadUrlSync( |
| awContents, onPageFinishedHelper, ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); |
| |
| DisplayAndroid displayAndroid = ThreadUtils.runOnUiThreadBlockingNoException(() -> { |
| return DisplayAndroid.getNonMultiDisplay( |
| InstrumentationRegistry.getInstrumentation().getTargetContext()); |
| }); |
| float dipScale = displayAndroid.getDipScale(); |
| float physicalDisplayWidth = displayAndroid.getDisplayWidth(); |
| float physicalDisplayHeight = displayAndroid.getDisplayHeight(); |
| |
| float screenWidth = Integer.parseInt(mActivityTestRule.executeJavaScriptAndWaitForResult( |
| awContents, contentClient, "screen.width")); |
| Assert.assertEquals(physicalDisplayWidth, screenWidth, 10f); |
| float screenAvailWidth = |
| Integer.parseInt(mActivityTestRule.executeJavaScriptAndWaitForResult( |
| awContents, contentClient, "screen.availWidth")); |
| Assert.assertEquals(physicalDisplayWidth, screenAvailWidth, 10f); |
| float outerWidth = Integer.parseInt(mActivityTestRule.executeJavaScriptAndWaitForResult( |
| awContents, contentClient, "outerWidth")); |
| float innerWidth = Integer.parseInt(mActivityTestRule.executeJavaScriptAndWaitForResult( |
| awContents, contentClient, "innerWidth")); |
| Assert.assertEquals(innerWidth * dipScale, outerWidth, 10f); |
| String deviceWidthEqualsScreenWidth = mActivityTestRule.executeJavaScriptAndWaitForResult( |
| awContents, contentClient, |
| "matchMedia(\"screen and (device-width:" + (int) screenWidth + "px)\").matches"); |
| Assert.assertEquals("true", deviceWidthEqualsScreenWidth); |
| |
| float screenHeight = Integer.parseInt(mActivityTestRule.executeJavaScriptAndWaitForResult( |
| awContents, contentClient, "screen.height")); |
| Assert.assertEquals(physicalDisplayHeight, screenHeight, 10f); |
| float screenAvailHeight = |
| Integer.parseInt(mActivityTestRule.executeJavaScriptAndWaitForResult( |
| awContents, contentClient, "screen.availHeight")); |
| Assert.assertEquals(physicalDisplayHeight, screenAvailHeight, 10f); |
| float outerHeight = Integer.parseInt(mActivityTestRule.executeJavaScriptAndWaitForResult( |
| awContents, contentClient, "outerHeight")); |
| float innerHeight = Integer.parseInt(mActivityTestRule.executeJavaScriptAndWaitForResult( |
| awContents, contentClient, "innerHeight")); |
| Assert.assertEquals(innerHeight * dipScale, outerHeight, 10f); |
| String deviceHeightEqualsScreenHeight = mActivityTestRule.executeJavaScriptAndWaitForResult( |
| awContents, contentClient, |
| "matchMedia(\"screen and (device-height:" + (int) screenHeight + "px)\").matches"); |
| Assert.assertEquals("true", deviceHeightEqualsScreenHeight); |
| } |
| |
| @Test |
| @MediumTest |
| @Feature({"AndroidWebView"}) |
| public void testMetaMergeContentQuirk() throws Throwable { |
| final TestAwContentsClient contentClient = new TestAwContentsClient(); |
| final AwTestContainerView testContainerView = |
| createAwTestContainerViewOnMainSyncInQuirksMode(contentClient); |
| final AwContents awContents = testContainerView.getAwContents(); |
| AwSettings settings = mActivityTestRule.getAwSettingsOnUiThread(awContents); |
| CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); |
| |
| final int pageWidth = 3000; |
| final float pageScale = 1.0f; |
| final String page = String.format((Locale) null, "<html><head>" |
| + "<meta name='viewport' content='width=%d' />" |
| + "<meta name='viewport' content='initial-scale=%.1f' />" |
| + "<meta name='viewport' content='user-scalable=0' />" |
| + "</head><body onload='document.title=document.body.clientWidth'></body></html>", |
| pageWidth, pageScale); |
| |
| settings.setJavaScriptEnabled(true); |
| settings.setUseWideViewPort(true); |
| settings.setBuiltInZoomControls(true); |
| settings.setSupportZoom(true); |
| |
| mActivityTestRule.loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); |
| // ContentView must update itself according to the viewport setup. |
| // As we specify 'user-scalable=0', the page must become non-zoomable. |
| AwActivityTestRule.pollInstrumentationThread( |
| () -> !mActivityTestRule.canZoomInOnUiThread(awContents) |
| && !mActivityTestRule.canZoomOutOnUiThread(awContents)); |
| int width = Integer.parseInt(mActivityTestRule.getTitleOnUiThread(awContents)); |
| Assert.assertEquals(pageWidth, width); |
| Assert.assertEquals(pageScale, mActivityTestRule.getScaleOnUiThread(awContents), 0); |
| } |
| |
| @Test |
| @MediumTest |
| @Feature({"AndroidWebView"}) |
| public void testMetaMergeContentQuirkOverrides() throws Throwable { |
| final TestAwContentsClient contentClient = new TestAwContentsClient(); |
| final AwTestContainerView testContainerView = |
| createAwTestContainerViewOnMainSyncInQuirksMode(contentClient); |
| final AwContents awContents = testContainerView.getAwContents(); |
| AwSettings settings = mActivityTestRule.getAwSettingsOnUiThread(awContents); |
| CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); |
| |
| final int pageWidth = 3000; |
| final String page = String.format((Locale) null, "<html><head>" |
| + "<meta name='viewport' content='width=device-width' />" |
| + "<meta name='viewport' content='width=%d' />" |
| + "</head><body onload='document.title=document.body.clientWidth'></body></html>", |
| pageWidth); |
| |
| settings.setJavaScriptEnabled(true); |
| settings.setUseWideViewPort(true); |
| |
| mActivityTestRule.loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); |
| int width = Integer.parseInt(mActivityTestRule.getTitleOnUiThread(awContents)); |
| Assert.assertEquals(pageWidth, width); |
| } |
| |
| @Test |
| @MediumTest |
| @Feature({"AndroidWebView"}) |
| public void testInitialScaleClobberQuirk() throws Throwable { |
| final TestAwContentsClient contentClient = new TestAwContentsClient(); |
| final AwTestContainerView testContainerView = |
| createAwTestContainerViewOnMainSyncInQuirksMode(contentClient); |
| final AwContents awContents = testContainerView.getAwContents(); |
| AwSettings settings = mActivityTestRule.getAwSettingsOnUiThread(awContents); |
| CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); |
| |
| final String pageTemplate = "<html><head>" |
| + "<meta name='viewport' content='initial-scale=%d' />" |
| + "</head><body>" |
| + "<div style='width:10000px;height:200px'>A big div</div>" |
| + "</body></html>"; |
| final String pageScale4 = String.format((Locale) null, pageTemplate, 4); |
| final String page = String.format((Locale) null, pageTemplate, 1); |
| |
| // Page scale updates are asynchronous. There is an issue that we can't |
| // reliably check, whether the scale as NOT changed (i.e. remains to be 1.0). |
| // So we first change the scale to some non-default value, and then wait |
| // until it gets back to 1.0. |
| int onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount(); |
| mActivityTestRule.loadDataSync( |
| awContents, onPageFinishedHelper, pageScale4, "text/html", false); |
| contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount); |
| Assert.assertEquals(4.0f, mActivityTestRule.getScaleOnUiThread(awContents), 0); |
| // The following call to set initial scale will be ignored. However, a temporary |
| // page scale change may occur, and this makes the usual onScaleChanged-based workflow |
| // flaky. So instead, we are just polling the scale until it becomes 1.0. |
| settings.setInitialPageScale(50); |
| mActivityTestRule.loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); |
| ensureScaleBecomes(1.0f, awContents); |
| } |
| |
| @Test |
| @MediumTest |
| @Feature({"AndroidWebView"}) |
| public void testNoUserScalableQuirk() throws Throwable { |
| final TestAwContentsClient contentClient = new TestAwContentsClient(); |
| final AwTestContainerView testContainerView = |
| createAwTestContainerViewOnMainSyncInQuirksMode(contentClient); |
| final AwContents awContents = testContainerView.getAwContents(); |
| CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); |
| |
| final String pageScale4 = "<html><head>" |
| + "<meta name='viewport' content='initial-scale=4' />" |
| + "</head><body>" |
| + "<div style='width:10000px;height:200px'>A big div</div>" |
| + "</body></html>"; |
| final String page = "<html><head>" |
| + "<meta name='viewport' " |
| + "content='width=device-width,initial-scale=2,user-scalable=no' />" |
| + "</head><body>" |
| + "<div style='width:10000px;height:200px'>A big div</div>" |
| + "</body></html>"; |
| |
| // Page scale updates are asynchronous. There is an issue that we can't |
| // reliably check, whether the scale as NOT changed (i.e. remains to be 1.0). |
| // So we first change the scale to some non-default value, and then wait |
| // until it gets back to 1.0. |
| int onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount(); |
| mActivityTestRule.loadDataSync( |
| awContents, onPageFinishedHelper, pageScale4, "text/html", false); |
| contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount); |
| Assert.assertEquals(4.0f, mActivityTestRule.getScaleOnUiThread(awContents), 0); |
| onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount(); |
| mActivityTestRule.loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); |
| contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount); |
| Assert.assertEquals(1.0f, mActivityTestRule.getScaleOnUiThread(awContents), 0); |
| } |
| |
| // background shorthand property must not override background-size when |
| // it's already set. |
| @Test |
| @MediumTest |
| @Feature({"AndroidWebView", "Preferences"}) |
| public void testUseLegacyBackgroundSizeShorthandBehavior() throws Throwable { |
| final TestAwContentsClient contentClient = new TestAwContentsClient(); |
| final AwTestContainerView testContainerView = |
| createAwTestContainerViewOnMainSyncInQuirksMode(contentClient); |
| final AwContents awContents = testContainerView.getAwContents(); |
| AwSettings settings = mActivityTestRule.getAwSettingsOnUiThread(awContents); |
| CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); |
| final String expectedBackgroundSize = "cover"; |
| final String page = "<html><head>" |
| + "<script>" |
| + "function getBackgroundSize() {" |
| + " var e = document.getElementById('test'); " |
| + " e.style.backgroundSize = '" + expectedBackgroundSize + "';" |
| + " e.style.background = 'center red url(dummy://test.png) no-repeat border-box'; " |
| + " return e.style.backgroundSize; " |
| + "}" |
| + "</script></head>" |
| + "<body onload='document.title=getBackgroundSize()'>" |
| + " <div id='test'> </div>" |
| + "</body></html>"; |
| settings.setJavaScriptEnabled(true); |
| mActivityTestRule.loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); |
| String actualBackgroundSize = mActivityTestRule.getTitleOnUiThread(awContents); |
| Assert.assertEquals(expectedBackgroundSize, actualBackgroundSize); |
| } |
| |
| private AwTestContainerView createAwTestContainerViewOnMainSyncInQuirksMode( |
| final AwContentsClient client) throws Exception { |
| return mActivityTestRule.createAwTestContainerViewOnMainSync(client, true); |
| } |
| |
| private void ensureScaleBecomes(final float targetScale, final AwContents awContents) |
| throws Throwable { |
| AwActivityTestRule.pollInstrumentationThread( |
| () -> targetScale == mActivityTestRule.getScaleOnUiThread(awContents)); |
| } |
| } |