// Copyright (c) 2012 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.content.Context; import android.graphics.Point; import android.os.Build; import android.os.SystemClock; import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.SmallTest; import android.util.Pair; import android.view.MotionEvent; import android.view.WindowManager; import android.webkit.WebSettings; import org.apache.http.Header; import org.apache.http.HttpRequest; import org.chromium.android_webview.AndroidProtocolHandler; import org.chromium.android_webview.AwContents; import org.chromium.android_webview.AwSettings.LayoutAlgorithm; import org.chromium.android_webview.AwSettings; import org.chromium.android_webview.InterceptedRequestData; import org.chromium.android_webview.test.util.CommonResources; import org.chromium.android_webview.test.util.ImagePageGenerator; import org.chromium.android_webview.test.util.JavascriptEventObserver; import org.chromium.android_webview.test.util.VideoTestWebServer; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.TestFileUtil; import org.chromium.base.test.util.UrlUtils; import org.chromium.content.browser.ContentViewCore; import org.chromium.content.browser.test.util.CallbackHelper; import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; import org.chromium.content.browser.test.util.HistoryUtils; import org.chromium.net.test.util.TestWebServer; import org.chromium.ui.gfx.DeviceDisplayInfo; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.ArrayList; import java.util.List; /** * A test suite for AwSettings class. The key objective is to verify that each * settings applies either to each individual view or to all views of the * application */ public class AwSettingsTest extends AwTestBase { private static final long TEST_TIMEOUT = 20000L; private static final int CHECK_INTERVAL = 100; private static final boolean ENABLED = true; private static final boolean DISABLED = false; /** * A helper class for testing a particular preference from AwSettings. * The generic type T is the type of the setting. Usually, to test an * effect of the preference, JS code is executed that sets document's title. * In this case, requiresJsEnabled constructor argument must be set to true. */ abstract class AwSettingsTestHelper { protected final AwContents mAwContents; protected final TestAwContentsClient mContentViewClient; protected final AwSettings mAwSettings; AwSettingsTestHelper(AwContents awContents, TestAwContentsClient contentViewClient, boolean requiresJsEnabled) throws Throwable { mAwContents = awContents; mContentViewClient = contentViewClient; mAwSettings = AwSettingsTest.this.getAwSettingsOnUiThread(awContents); if (requiresJsEnabled) { mAwSettings.setJavaScriptEnabled(true); } } void ensureSettingHasAlteredValue() throws Throwable { ensureSettingHasValue(getAlteredValue()); } void ensureSettingHasInitialValue() throws Throwable { ensureSettingHasValue(getInitialValue()); } void setAlteredSettingValue() throws Throwable { setCurrentValue(getAlteredValue()); } void setInitialSettingValue() throws Throwable { setCurrentValue(getInitialValue()); } protected abstract T getAlteredValue(); protected abstract T getInitialValue(); protected abstract T getCurrentValue(); protected abstract void setCurrentValue(T value) throws Throwable; protected abstract void doEnsureSettingHasValue(T value) throws Throwable; protected String getTitleOnUiThread() throws Throwable { return AwSettingsTest.this.getTitleOnUiThread(mAwContents); } protected void loadDataSync(String data) throws Throwable { AwSettingsTest.this.loadDataSync( mAwContents, mContentViewClient.getOnPageFinishedHelper(), data, "text/html", false); } protected void loadUrlSync(String url) throws Throwable { AwSettingsTest.this.loadUrlSync( mAwContents, mContentViewClient.getOnPageFinishedHelper(), url); } protected void loadUrlSyncAndExpectError(String url) throws Throwable { AwSettingsTest.this.loadUrlSyncAndExpectError( mAwContents, mContentViewClient.getOnPageFinishedHelper(), mContentViewClient.getOnReceivedErrorHelper(), url); } protected String executeJavaScriptAndWaitForResult(String script) throws Throwable { return AwSettingsTest.this.executeJavaScriptAndWaitForResult( mAwContents, mContentViewClient, script); } private void ensureSettingHasValue(T value) throws Throwable { assertEquals(value, getCurrentValue()); doEnsureSettingHasValue(value); } } class AwSettingsJavaScriptTestHelper extends AwSettingsTestHelper { private static final String JS_ENABLED_STRING = "JS Enabled"; private static final String JS_DISABLED_STRING = "JS Disabled"; AwSettingsJavaScriptTestHelper(AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient, false); } @Override protected Boolean getAlteredValue() { return ENABLED; } @Override protected Boolean getInitialValue() { return DISABLED; } @Override protected Boolean getCurrentValue() { return mAwSettings.getJavaScriptEnabled(); } @Override protected void setCurrentValue(Boolean value) { mAwSettings.setJavaScriptEnabled(value); } @Override protected void doEnsureSettingHasValue(Boolean value) throws Throwable { loadDataSync(getData()); assertEquals( value == ENABLED ? JS_ENABLED_STRING : JS_DISABLED_STRING, getTitleOnUiThread()); } private String getData() { return "" + JS_DISABLED_STRING + "" + ""; } } // In contrast to AwSettingsJavaScriptTestHelper, doesn't reload the page when testing // JavaScript state. class AwSettingsJavaScriptDynamicTestHelper extends AwSettingsJavaScriptTestHelper { AwSettingsJavaScriptDynamicTestHelper( AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient); // Load the page. super.doEnsureSettingHasValue(getInitialValue()); } @Override protected void doEnsureSettingHasValue(Boolean value) throws Throwable { String oldTitle = getTitleOnUiThread(); String newTitle = oldTitle + "_modified"; executeJavaScriptAndWaitForResult(getScript(newTitle)); assertEquals(value == ENABLED ? newTitle : oldTitle, getTitleOnUiThread()); } private String getScript(String title) { return "document.title='" + title + "';"; } } class AwSettingsPluginsTestHelper extends AwSettingsTestHelper { private static final String PLUGINS_ENABLED_STRING = "Embed"; private static final String PLUGINS_DISABLED_STRING = "NoEmbed"; AwSettingsPluginsTestHelper(AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient, true); } @Override protected Boolean getAlteredValue() { return ENABLED; } @Override protected Boolean getInitialValue() { return DISABLED; } @Override protected Boolean getCurrentValue() { return mAwSettings.getPluginsEnabled(); } @Override protected void setCurrentValue(Boolean value) { mAwSettings.setPluginsEnabled(value); } @Override protected void doEnsureSettingHasValue(Boolean value) throws Throwable { loadDataSync(getData()); assertEquals( value == ENABLED ? PLUGINS_ENABLED_STRING : PLUGINS_DISABLED_STRING, getTitleOnUiThread()); } private String getData() { return "" + "NoEmbed"; } } class AwSettingsStandardFontFamilyTestHelper extends AwSettingsTestHelper { AwSettingsStandardFontFamilyTestHelper( AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient, true); } @Override protected String getAlteredValue() { return "cursive"; } @Override protected String getInitialValue() { return "sans-serif"; } @Override protected String getCurrentValue() { return mAwSettings.getStandardFontFamily(); } @Override protected void setCurrentValue(String value) { mAwSettings.setStandardFontFamily(value); } @Override protected void doEnsureSettingHasValue(String value) throws Throwable { loadDataSync(getData()); assertEquals(value, getTitleOnUiThread()); } private String getData() { return "" + ""; } } class AwSettingsDefaultFontSizeTestHelper extends AwSettingsTestHelper { AwSettingsDefaultFontSizeTestHelper( AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient, true); } @Override protected Integer getAlteredValue() { return 42; } @Override protected Integer getInitialValue() { return 16; } @Override protected Integer getCurrentValue() { return mAwSettings.getDefaultFontSize(); } @Override protected void setCurrentValue(Integer value) { mAwSettings.setDefaultFontSize(value); } @Override protected void doEnsureSettingHasValue(Integer value) throws Throwable { loadDataSync(getData()); assertEquals(value.toString() + "px", getTitleOnUiThread()); } private String getData() { return "" + ""; } } class AwSettingsLoadImagesAutomaticallyTestHelper extends AwSettingsTestHelper { private ImagePageGenerator mGenerator; AwSettingsLoadImagesAutomaticallyTestHelper( AwContents awContents, TestAwContentsClient contentViewClient, ImagePageGenerator generator) throws Throwable { super(awContents, contentViewClient, true); mGenerator = generator; } @Override protected Boolean getAlteredValue() { return DISABLED; } @Override protected Boolean getInitialValue() { return ENABLED; } @Override protected Boolean getCurrentValue() { return mAwSettings.getLoadsImagesAutomatically(); } @Override protected void setCurrentValue(Boolean value) { mAwSettings.setLoadsImagesAutomatically(value); } @Override protected void doEnsureSettingHasValue(Boolean value) throws Throwable { loadDataSync(mGenerator.getPageSource()); assertEquals(value == ENABLED ? ImagePageGenerator.IMAGE_LOADED_STRING : ImagePageGenerator.IMAGE_NOT_LOADED_STRING, getTitleOnUiThread()); } } class AwSettingsDefaultTextEncodingTestHelper extends AwSettingsTestHelper { AwSettingsDefaultTextEncodingTestHelper( AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient, true); } @Override protected String getAlteredValue() { return "utf-8"; } @Override protected String getInitialValue() { return "Latin-1"; } @Override protected String getCurrentValue() { return mAwSettings.getDefaultTextEncodingName(); } @Override protected void setCurrentValue(String value) { mAwSettings.setDefaultTextEncodingName(value); } @Override protected void doEnsureSettingHasValue(String value) throws Throwable { loadDataSync(getData()); assertEquals(value, getTitleOnUiThread()); } private String getData() { return ""; } } class AwSettingsUserAgentStringTestHelper extends AwSettingsTestHelper { private final String mDefaultUa; private static final String DEFAULT_UA = ""; private static final String CUSTOM_UA = "ChromeViewTest"; AwSettingsUserAgentStringTestHelper( AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient, true); mDefaultUa = mAwSettings.getUserAgentString(); } @Override protected String getAlteredValue() { return CUSTOM_UA; } @Override protected String getInitialValue() { return DEFAULT_UA; } @Override protected String getCurrentValue() { // The test framework expects that getXXX() == Z after setXXX(Z). // But setUserAgentString("" / null) resets the UA string to default, // and getUserAgentString returns the default UA string afterwards. // To align with the framework, we return an empty string instead of // the default UA. String currentUa = mAwSettings.getUserAgentString(); return mDefaultUa.equals(currentUa) ? DEFAULT_UA : currentUa; } @Override protected void setCurrentValue(String value) { mAwSettings.setUserAgentString(value); } @Override protected void doEnsureSettingHasValue(String value) throws Throwable { loadDataSync(getData()); assertEquals( DEFAULT_UA.equals(value) ? mDefaultUa : value, getTitleOnUiThread()); } private String getData() { return ""; } } class AwSettingsDomStorageEnabledTestHelper extends AwSettingsTestHelper { private static final String NO_LOCAL_STORAGE = "No localStorage"; private static final String HAS_LOCAL_STORAGE = "Has localStorage"; AwSettingsDomStorageEnabledTestHelper( AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient, true); } @Override protected Boolean getAlteredValue() { return ENABLED; } @Override protected Boolean getInitialValue() { return DISABLED; } @Override protected Boolean getCurrentValue() { return mAwSettings.getDomStorageEnabled(); } @Override protected void setCurrentValue(Boolean value) { mAwSettings.setDomStorageEnabled(value); } @Override protected void doEnsureSettingHasValue(Boolean value) throws Throwable { // It is not permitted to access localStorage from data URLs in WebKit, // that is why a standalone page must be used. loadUrlSync(UrlUtils.getTestFileUrl("webview/localStorage.html")); assertEquals( value == ENABLED ? HAS_LOCAL_STORAGE : NO_LOCAL_STORAGE, getTitleOnUiThread()); } } class AwSettingsDatabaseTestHelper extends AwSettingsTestHelper { private static final String NO_DATABASE = "No database"; private static final String HAS_DATABASE = "Has database"; AwSettingsDatabaseTestHelper( AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient, true); } @Override protected Boolean getAlteredValue() { return ENABLED; } @Override protected Boolean getInitialValue() { return DISABLED; } @Override protected Boolean getCurrentValue() { return mAwSettings.getDatabaseEnabled(); } @Override protected void setCurrentValue(Boolean value) { mAwSettings.setDatabaseEnabled(value); } @Override protected void doEnsureSettingHasValue(Boolean value) throws Throwable { // It seems accessing the database through a data scheme is not // supported, and fails with a DOM exception (likely a cross-domain // violation). loadUrlSync(UrlUtils.getTestFileUrl("webview/database_access.html")); assertEquals( value == ENABLED ? HAS_DATABASE : NO_DATABASE, getTitleOnUiThread()); } } class AwSettingsUniversalAccessFromFilesTestHelper extends AwSettingsTestHelper { private static final String ACCESS_DENIED_TITLE = "Exception"; AwSettingsUniversalAccessFromFilesTestHelper( AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient, true); mIframeContainerUrl = UrlUtils.getTestFileUrl("webview/iframe_access.html"); mIframeUrl = UrlUtils.getTestFileUrl("webview/hello_world.html"); // The value of the setting depends on the SDK version. mAwSettings.setAllowUniversalAccessFromFileURLs(false); // If universal access is true, the value of file access doesn't // matter. While if universal access is false, having file access // enabled will allow file loading. mAwSettings.setAllowFileAccessFromFileURLs(false); } @Override protected Boolean getAlteredValue() { return ENABLED; } @Override protected Boolean getInitialValue() { return DISABLED; } @Override protected Boolean getCurrentValue() { return mAwSettings.getAllowUniversalAccessFromFileURLs(); } @Override protected void setCurrentValue(Boolean value) { mAwSettings.setAllowUniversalAccessFromFileURLs(value); } @Override protected void doEnsureSettingHasValue(Boolean value) throws Throwable { loadUrlSync(mIframeContainerUrl); assertEquals( value == ENABLED ? mIframeUrl : ACCESS_DENIED_TITLE, getTitleOnUiThread()); } private final String mIframeContainerUrl; private final String mIframeUrl; } class AwSettingsFileAccessFromFilesIframeTestHelper extends AwSettingsTestHelper { private static final String ACCESS_DENIED_TITLE = "Exception"; AwSettingsFileAccessFromFilesIframeTestHelper( AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient, true); mIframeContainerUrl = UrlUtils.getTestFileUrl("webview/iframe_access.html"); mIframeUrl = UrlUtils.getTestFileUrl("webview/hello_world.html"); mAwSettings.setAllowUniversalAccessFromFileURLs(false); // The value of the setting depends on the SDK version. mAwSettings.setAllowFileAccessFromFileURLs(false); } @Override protected Boolean getAlteredValue() { return ENABLED; } @Override protected Boolean getInitialValue() { return DISABLED; } @Override protected Boolean getCurrentValue() { return mAwSettings.getAllowFileAccessFromFileURLs(); } @Override protected void setCurrentValue(Boolean value) { mAwSettings.setAllowFileAccessFromFileURLs(value); } @Override protected void doEnsureSettingHasValue(Boolean value) throws Throwable { loadUrlSync(mIframeContainerUrl); assertEquals( value == ENABLED ? mIframeUrl : ACCESS_DENIED_TITLE, getTitleOnUiThread()); } private final String mIframeContainerUrl; private final String mIframeUrl; } class AwSettingsFileAccessFromFilesXhrTestHelper extends AwSettingsTestHelper { private static final String ACCESS_GRANTED_TITLE = "Hello, World!"; private static final String ACCESS_DENIED_TITLE = "Exception"; AwSettingsFileAccessFromFilesXhrTestHelper( AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient, true); mXhrContainerUrl = UrlUtils.getTestFileUrl("webview/xhr_access.html"); mAwSettings.setAllowUniversalAccessFromFileURLs(false); // The value of the setting depends on the SDK version. mAwSettings.setAllowFileAccessFromFileURLs(false); } @Override protected Boolean getAlteredValue() { return ENABLED; } @Override protected Boolean getInitialValue() { return DISABLED; } @Override protected Boolean getCurrentValue() { return mAwSettings.getAllowFileAccessFromFileURLs(); } @Override protected void setCurrentValue(Boolean value) { mAwSettings.setAllowFileAccessFromFileURLs(value); } @Override protected void doEnsureSettingHasValue(Boolean value) throws Throwable { loadUrlSync(mXhrContainerUrl); assertEquals( value == ENABLED ? ACCESS_GRANTED_TITLE : ACCESS_DENIED_TITLE, getTitleOnUiThread()); } private final String mXhrContainerUrl; } class AwSettingsFileUrlAccessTestHelper extends AwSettingsTestHelper { private static final String ACCESS_GRANTED_TITLE = "Hello, World!"; AwSettingsFileUrlAccessTestHelper( AwContents awContents, TestAwContentsClient contentViewClient, int startIndex) throws Throwable { super(awContents, contentViewClient, true); mIndex = startIndex; } @Override protected Boolean getAlteredValue() { return DISABLED; } @Override protected Boolean getInitialValue() { return ENABLED; } @Override protected Boolean getCurrentValue() { return mAwSettings.getAllowFileAccess(); } @Override protected void setCurrentValue(Boolean value) { mAwSettings.setAllowFileAccess(value); } @Override protected void doEnsureSettingHasValue(Boolean value) throws Throwable { // Use query parameters to avoid hitting a cached page. String fileUrl = UrlUtils.getTestFileUrl("webview/hello_world.html?id=" + mIndex); mIndex += 2; if (value == ENABLED) { loadUrlSync(fileUrl); assertEquals(ACCESS_GRANTED_TITLE, getTitleOnUiThread()); } else { loadUrlSyncAndExpectError(fileUrl); } } private int mIndex; } class AwSettingsContentUrlAccessTestHelper extends AwSettingsTestHelper { AwSettingsContentUrlAccessTestHelper( AwContents awContents, TestAwContentsClient contentViewClient, int index) throws Throwable { super(awContents, contentViewClient, true); mTarget = "content_access_" + index; } @Override protected Boolean getAlteredValue() { return DISABLED; } @Override protected Boolean getInitialValue() { return ENABLED; } @Override protected Boolean getCurrentValue() { return mAwSettings.getAllowContentAccess(); } @Override protected void setCurrentValue(Boolean value) { mAwSettings.setAllowContentAccess(value); } @Override protected void doEnsureSettingHasValue(Boolean value) throws Throwable { AwSettingsTest.this.resetResourceRequestCountInContentProvider(mTarget); loadUrlSync(AwSettingsTest.this.createContentUrl(mTarget)); if (value == ENABLED) { AwSettingsTest.this.ensureResourceRequestCountInContentProvider(mTarget, 1); } else { AwSettingsTest.this.ensureResourceRequestCountInContentProvider(mTarget, 0); } } private final String mTarget; } class AwSettingsContentUrlAccessFromFileTestHelper extends AwSettingsTestHelper { private static final String TARGET = "content_from_file"; AwSettingsContentUrlAccessFromFileTestHelper( AwContents awContents, TestAwContentsClient contentViewClient, int index) throws Throwable { super(awContents, contentViewClient, true); mIndex = index; mTempDir = getInstrumentation().getTargetContext().getCacheDir().getPath(); } @Override protected Boolean getAlteredValue() { return DISABLED; } @Override protected Boolean getInitialValue() { return ENABLED; } @Override protected Boolean getCurrentValue() { return mAwSettings.getAllowContentAccess(); } @Override protected void setCurrentValue(Boolean value) { mAwSettings.setAllowContentAccess(value); } @Override protected void doEnsureSettingHasValue(Boolean value) throws Throwable { AwSettingsTest.this.resetResourceRequestCountInContentProvider(TARGET); final String fileName = mTempDir + "/" + TARGET + ".html"; try { TestFileUtil.createNewHtmlFile(fileName, TARGET, ""); mIndex += 2; loadUrlSync("file://" + fileName); if (value == ENABLED) { AwSettingsTest.this.ensureResourceRequestCountInContentProvider(TARGET, 1); } else { AwSettingsTest.this.ensureResourceRequestCountInContentProvider(TARGET, 0); } } finally { TestFileUtil.deleteFile(fileName); } } private int mIndex; private String mTempDir; } // This class provides helper methods for testing of settings related to // the text autosizing feature. abstract class AwSettingsTextAutosizingTestHelper extends AwSettingsTestHelper { protected static final float PARAGRAPH_FONT_SIZE = 14.0f; AwSettingsTextAutosizingTestHelper( AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient, true); mNeedToWaitForFontSizeChange = false; loadDataSync(getData()); } @Override protected void setCurrentValue(T value) throws Throwable { mNeedToWaitForFontSizeChange = false; if (value != getCurrentValue()) { mOldFontSize = getActualFontSize(); mNeedToWaitForFontSizeChange = true; } } protected float getActualFontSize() throws Throwable { if (!mNeedToWaitForFontSizeChange) { executeJavaScriptAndWaitForResult("setTitleToActualFontSize()"); } else { final float oldFontSize = mOldFontSize; assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { @Override public boolean isSatisfied() { try { executeJavaScriptAndWaitForResult("setTitleToActualFontSize()"); float newFontSize = Float.parseFloat(getTitleOnUiThread()); return newFontSize != oldFontSize; } catch (Throwable t) { t.printStackTrace(); fail("Failed to getTitleOnUiThread: " + t.toString()); return false; } } }, TEST_TIMEOUT, CHECK_INTERVAL)); mNeedToWaitForFontSizeChange = false; } return Float.parseFloat(getTitleOnUiThread()); } protected String getData() { StringBuilder sb = new StringBuilder(); sb.append("" + "" + "" + "

"); // Make the paragraph wide enough for being processed by the font autosizer. for (int i = 0; i < 100; i++) { sb.append("Hello, World! "); } sb.append("

"); return sb.toString(); } private boolean mNeedToWaitForFontSizeChange; private float mOldFontSize; } class AwSettingsLayoutAlgorithmTestHelper extends AwSettingsTextAutosizingTestHelper { AwSettingsLayoutAlgorithmTestHelper( AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient); // Font autosizing doesn't step in for narrow layout widths. mAwSettings.setUseWideViewPort(true); } @Override protected LayoutAlgorithm getAlteredValue() { return LayoutAlgorithm.TEXT_AUTOSIZING; } @Override protected LayoutAlgorithm getInitialValue() { return LayoutAlgorithm.NARROW_COLUMNS; } @Override protected LayoutAlgorithm getCurrentValue() { return mAwSettings.getLayoutAlgorithm(); } @Override protected void setCurrentValue(LayoutAlgorithm value) throws Throwable { super.setCurrentValue(value); mAwSettings.setLayoutAlgorithm(value); } @Override protected void doEnsureSettingHasValue(LayoutAlgorithm value) throws Throwable { final float actualFontSize = getActualFontSize(); if (value == LayoutAlgorithm.TEXT_AUTOSIZING) { assertFalse("Actual font size: " + actualFontSize, actualFontSize == PARAGRAPH_FONT_SIZE); } else { assertTrue("Actual font size: " + actualFontSize, actualFontSize == PARAGRAPH_FONT_SIZE); } } } class AwSettingsTextZoomTestHelper extends AwSettingsTextAutosizingTestHelper { private static final int INITIAL_TEXT_ZOOM = 100; private final float mInitialActualFontSize; AwSettingsTextZoomTestHelper( AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient); mInitialActualFontSize = getActualFontSize(); } @Override protected Integer getAlteredValue() { return INITIAL_TEXT_ZOOM * 2; } @Override protected Integer getInitialValue() { return INITIAL_TEXT_ZOOM; } @Override protected Integer getCurrentValue() { return mAwSettings.getTextZoom(); } @Override protected void setCurrentValue(Integer value) throws Throwable { super.setCurrentValue(value); mAwSettings.setTextZoom(value); } @Override protected void doEnsureSettingHasValue(Integer value) throws Throwable { final float actualFontSize = getActualFontSize(); // Ensure that actual vs. initial font size ratio is similar to actual vs. initial // text zoom values ratio. final float ratiosDelta = Math.abs( (actualFontSize / mInitialActualFontSize) - (value / (float)INITIAL_TEXT_ZOOM)); assertTrue( "|(" + actualFontSize + " / " + mInitialActualFontSize + ") - (" + value + " / " + INITIAL_TEXT_ZOOM + ")| = " + ratiosDelta, ratiosDelta <= 0.2f); } } class AwSettingsTextZoomAutosizingTestHelper extends AwSettingsTextAutosizingTestHelper { private static final int INITIAL_TEXT_ZOOM = 100; private final float mInitialActualFontSize; AwSettingsTextZoomAutosizingTestHelper( AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient); mAwSettings.setLayoutAlgorithm(LayoutAlgorithm.TEXT_AUTOSIZING); // The initial font size can be adjusted by font autosizer depending on the page's // viewport width. mInitialActualFontSize = getActualFontSize(); } @Override protected Integer getAlteredValue() { return INITIAL_TEXT_ZOOM * 2; } @Override protected Integer getInitialValue() { return INITIAL_TEXT_ZOOM; } @Override protected Integer getCurrentValue() { return mAwSettings.getTextZoom(); } @Override protected void setCurrentValue(Integer value) throws Throwable { super.setCurrentValue(value); mAwSettings.setTextZoom(value); } @Override protected void doEnsureSettingHasValue(Integer value) throws Throwable { final float actualFontSize = getActualFontSize(); // Ensure that actual vs. initial font size ratio is similar to actual vs. initial // text zoom values ratio. final float ratiosDelta = Math.abs( (actualFontSize / mInitialActualFontSize) - (value / (float)INITIAL_TEXT_ZOOM)); assertTrue( "|(" + actualFontSize + " / " + mInitialActualFontSize + ") - (" + value + " / " + INITIAL_TEXT_ZOOM + ")| = " + ratiosDelta, ratiosDelta <= 0.2f); } } class AwSettingsJavaScriptPopupsTestHelper extends AwSettingsTestHelper { static private final String POPUP_ENABLED = "Popup enabled"; static private final String POPUP_BLOCKED = "Popup blocked"; AwSettingsJavaScriptPopupsTestHelper( AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient, true); } @Override protected Boolean getAlteredValue() { return ENABLED; } @Override protected Boolean getInitialValue() { return DISABLED; } @Override protected Boolean getCurrentValue() { return mAwSettings.getJavaScriptCanOpenWindowsAutomatically(); } @Override protected void setCurrentValue(Boolean value) { mAwSettings.setJavaScriptCanOpenWindowsAutomatically(value); } @Override protected void doEnsureSettingHasValue(Boolean value) throws Throwable { loadDataSync(getData()); final boolean expectPopupEnabled = value; assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { @Override public boolean isSatisfied() { try { String title = getTitleOnUiThread(); return expectPopupEnabled ? POPUP_ENABLED.equals(title) : POPUP_BLOCKED.equals(title); } catch (Throwable t) { t.printStackTrace(); fail("Failed to getTitleOnUiThread: " + t.toString()); return false; } } }, TEST_TIMEOUT, CHECK_INTERVAL)); assertEquals(value ? POPUP_ENABLED : POPUP_BLOCKED, getTitleOnUiThread()); } private String getData() { return "" + "" + ""; } } class AwSettingsCacheModeTestHelper extends AwSettingsTestHelper { AwSettingsCacheModeTestHelper( AwContents awContents, TestAwContentsClient contentViewClient, int index, TestWebServer webServer) throws Throwable { super(awContents, contentViewClient, true); mIndex = index; mWebServer = webServer; } @Override protected Integer getAlteredValue() { // We use the value that results in a behaviour completely opposite to default. return WebSettings.LOAD_CACHE_ONLY; } @Override protected Integer getInitialValue() { return WebSettings.LOAD_DEFAULT; } @Override protected Integer getCurrentValue() { return mAwSettings.getCacheMode(); } @Override protected void setCurrentValue(Integer value) { mAwSettings.setCacheMode(value); } @Override protected void doEnsureSettingHasValue(Integer value) throws Throwable { final String htmlPath = "/cache_mode_" + mIndex + ".html"; mIndex += 2; final String url = mWebServer.setResponse(htmlPath, "response", null); assertEquals(0, mWebServer.getRequestCount(htmlPath)); if (value == WebSettings.LOAD_DEFAULT) { loadUrlSync(url); assertEquals(1, mWebServer.getRequestCount(htmlPath)); } else { loadUrlSyncAndExpectError(url); assertEquals(0, mWebServer.getRequestCount(htmlPath)); } } private int mIndex; private TestWebServer mWebServer; } // To verify whether UseWideViewport works, we check, if the page width specified // in the "meta viewport" tag is applied. When UseWideViewport is turned off, the // "viewport" tag is ignored, and the layout width is set to device width in DIP pixels. // We specify a very high width value to make sure that it doesn't intersect with // device screen widths (in DIP pixels). class AwSettingsUseWideViewportTestHelper extends AwSettingsTestHelper { static private final String VIEWPORT_TAG_LAYOUT_WIDTH = "3000"; AwSettingsUseWideViewportTestHelper( AwContents awContents, TestAwContentsClient contentViewClient) throws Throwable { super(awContents, contentViewClient, true); } @Override protected Boolean getAlteredValue() { return ENABLED; } @Override protected Boolean getInitialValue() { return DISABLED; } @Override protected Boolean getCurrentValue() { return mAwSettings.getUseWideViewPort(); } @Override protected void setCurrentValue(Boolean value) { mAwSettings.setUseWideViewPort(value); } @Override protected void doEnsureSettingHasValue(Boolean value) throws Throwable { loadDataSync(getData()); final String bodyWidth = getTitleOnUiThread(); if (value) { assertTrue(bodyWidth, VIEWPORT_TAG_LAYOUT_WIDTH.equals(bodyWidth)); } else { assertFalse(bodyWidth, VIEWPORT_TAG_LAYOUT_WIDTH.equals(bodyWidth)); } } private String getData() { return "" + "" + "" + ""; } } class AwSettingsLoadWithOverviewModeTestHelper extends AwSettingsTestHelper { private static final float DEFAULT_PAGE_SCALE = 1.0f; AwSettingsLoadWithOverviewModeTestHelper( AwContents awContents, TestAwContentsClient contentViewClient, boolean withViewPortTag) throws Throwable { super(awContents, contentViewClient, true); mWithViewPortTag = withViewPortTag; mAwSettings.setUseWideViewPort(true); } @Override protected Boolean getAlteredValue() { return ENABLED; } @Override protected Boolean getInitialValue() { return DISABLED; } @Override protected Boolean getCurrentValue() { return mAwSettings.getLoadWithOverviewMode(); } @Override protected void setCurrentValue(Boolean value) { mExpectScaleChange = mAwSettings.getLoadWithOverviewMode() != value; if (mExpectScaleChange) { mOnScaleChangedCallCount = mContentViewClient.getOnScaleChangedHelper().getCallCount(); } mAwSettings.setLoadWithOverviewMode(value); } @Override protected void doEnsureSettingHasValue(Boolean value) throws Throwable { loadDataSync(getData()); if (mExpectScaleChange) { mContentViewClient.getOnScaleChangedHelper(). waitForCallback(mOnScaleChangedCallCount); mExpectScaleChange = false; } float currentScale = AwSettingsTest.this.getScaleOnUiThread(mAwContents); if (value) { assertTrue("Expected: " + currentScale + " < " + DEFAULT_PAGE_SCALE, currentScale < DEFAULT_PAGE_SCALE); } else { assertEquals(DEFAULT_PAGE_SCALE, currentScale); } } private String getData() { return "" + (mWithViewPortTag ? "" : "") + "" + ""; } private final boolean mWithViewPortTag; private boolean mExpectScaleChange; private int mOnScaleChangedCallCount; } // The test verifies that JavaScript is disabled upon WebView // creation without accessing AwSettings. If the test passes, // it means that WebView-specific web preferences configuration // is applied on WebView creation. JS state is used, because it is // enabled by default in Chrome, but must be disabled by default // in WebView. @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testJavaScriptDisabledByDefault() throws Throwable { final String JS_ENABLED_STRING = "JS has run"; final String JS_DISABLED_STRING = "JS has not run"; final String TEST_PAGE_HTML = "" + JS_DISABLED_STRING + "" + ""; final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainerView.getAwContents(); loadDataSync( awContents, contentClient.getOnPageFinishedHelper(), TEST_PAGE_HTML, "text/html", false); assertEquals(JS_DISABLED_STRING, getTitleOnUiThread(awContents)); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testJavaScriptEnabledWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsJavaScriptTestHelper(views.getContents0(), views.getClient0()), new AwSettingsJavaScriptTestHelper(views.getContents1(), views.getClient1())); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testJavaScriptEnabledDynamicWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsJavaScriptDynamicTestHelper(views.getContents0(), views.getClient0()), new AwSettingsJavaScriptDynamicTestHelper(views.getContents1(), views.getClient1())); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testPluginsEnabledWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsPluginsTestHelper(views.getContents0(), views.getClient0()), new AwSettingsPluginsTestHelper(views.getContents1(), views.getClient1())); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testStandardFontFamilyWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsStandardFontFamilyTestHelper(views.getContents0(), views.getClient0()), new AwSettingsStandardFontFamilyTestHelper(views.getContents1(), views.getClient1())); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testDefaultFontSizeWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsDefaultFontSizeTestHelper(views.getContents0(), views.getClient0()), new AwSettingsDefaultFontSizeTestHelper(views.getContents1(), views.getClient1())); } // The test verifies that after changing the LoadsImagesAutomatically // setting value from false to true previously skipped images are // automatically loaded. @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testLoadsImagesAutomaticallyNoPageReload() throws Throwable { final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainerView.getAwContents(); AwSettings settings = getAwSettingsOnUiThread(awContents); settings.setJavaScriptEnabled(true); ImagePageGenerator generator = new ImagePageGenerator(0, false); settings.setLoadsImagesAutomatically(false); loadDataSync(awContents, contentClient.getOnPageFinishedHelper(), generator.getPageSource(), "text/html", false); assertEquals(ImagePageGenerator.IMAGE_NOT_LOADED_STRING, getTitleOnUiThread(awContents)); settings.setLoadsImagesAutomatically(true); assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { @Override public boolean isSatisfied() { try { return !ImagePageGenerator.IMAGE_NOT_LOADED_STRING.equals( getTitleOnUiThread(awContents)); } catch (Throwable t) { t.printStackTrace(); fail("Failed to getTitleOnUiThread: " + t.toString()); return false; } } }, TEST_TIMEOUT, CHECK_INTERVAL)); assertEquals(ImagePageGenerator.IMAGE_LOADED_STRING, getTitleOnUiThread(awContents)); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testLoadsImagesAutomaticallyWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsLoadImagesAutomaticallyTestHelper( views.getContents0(), views.getClient0(), new ImagePageGenerator(0, true)), new AwSettingsLoadImagesAutomaticallyTestHelper( views.getContents1(), views.getClient1(), new ImagePageGenerator(1, true))); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testDefaultTextEncodingWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsDefaultTextEncodingTestHelper(views.getContents0(), views.getClient0()), new AwSettingsDefaultTextEncodingTestHelper(views.getContents1(), views.getClient1())); } // The test verifies that the default user agent string follows the format // defined in Android CTS tests: // // Mozilla/5.0 (Linux;[ U;] Android ;[ -;] // [;] Build/) AppleWebKit/. (KHTML, like Gecko) // Version/.[ Mobile] Safari/. @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testUserAgentStringDefault() throws Throwable { final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainerView.getAwContents(); AwSettings settings = getAwSettingsOnUiThread(awContents); final String actualUserAgentString = settings.getUserAgentString(); final String patternString = "Mozilla/5\\.0 \\(Linux;( U;)? Android ([^;]+);( (\\w+)-(\\w+);)?" + "\\s?(.*)\\sBuild/(.+)\\) AppleWebKit/(\\d+)\\.(\\d+) \\(KHTML, like Gecko\\) " + "Version/\\d+\\.\\d+( Mobile)? Safari/(\\d+)\\.(\\d+)"; final Pattern userAgentExpr = Pattern.compile(patternString); Matcher patternMatcher = userAgentExpr.matcher(actualUserAgentString); assertTrue(String.format("User agent string did not match expected pattern. %nExpected " + "pattern:%n%s%nActual:%n%s", patternString, actualUserAgentString), patternMatcher.find()); // No country-language code token. assertEquals(null, patternMatcher.group(3)); if ("REL".equals(Build.VERSION.CODENAME)) { // Model is only added in release builds assertEquals(Build.MODEL, patternMatcher.group(6)); // Release version is valid only in release builds assertEquals(Build.VERSION.RELEASE, patternMatcher.group(2)); } assertEquals(Build.ID, patternMatcher.group(7)); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testUserAgentStringOverride() throws Throwable { final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainerView.getAwContents(); AwSettings settings = getAwSettingsOnUiThread(awContents); final String defaultUserAgentString = settings.getUserAgentString(); // Check that an attempt to reset the default UA string has no effect. settings.setUserAgentString(null); assertEquals(defaultUserAgentString, settings.getUserAgentString()); settings.setUserAgentString(""); assertEquals(defaultUserAgentString, settings.getUserAgentString()); // Check that we can also set the default value. settings.setUserAgentString(defaultUserAgentString); assertEquals(defaultUserAgentString, settings.getUserAgentString()); // Set a custom UA string, verify that it can be reset back to default. final String customUserAgentString = "AwSettingsTest"; settings.setUserAgentString(customUserAgentString); assertEquals(customUserAgentString, settings.getUserAgentString()); settings.setUserAgentString(null); assertEquals(defaultUserAgentString, settings.getUserAgentString()); } // Verify that the current UA override setting has a priority over UA // overrides in navigation history entries. @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testUserAgentStringOverrideForHistory() throws Throwable { final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainerView.getAwContents(); final ContentViewCore contentView = testContainerView.getContentViewCore(); CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); AwSettings settings = getAwSettingsOnUiThread(awContents); settings.setJavaScriptEnabled(true); final String defaultUserAgentString = settings.getUserAgentString(); final String customUserAgentString = "AwSettingsTest"; // We are using different page titles to make sure that we are really // going back and forward between them. final String pageTemplate = "%s" + "" + ""; final String page1Title = "Page1"; final String page2Title = "Page2"; final String page1 = String.format(pageTemplate, page1Title); final String page2 = String.format(pageTemplate, page2Title); settings.setUserAgentString(customUserAgentString); loadDataSync( awContents, onPageFinishedHelper, page1, "text/html", false); assertEquals(page1Title + customUserAgentString, getTitleOnUiThread(awContents)); loadDataSync( awContents, onPageFinishedHelper, page2, "text/html", false); assertEquals(page2Title + customUserAgentString, getTitleOnUiThread(awContents)); settings.setUserAgentString(null); // Must not cause any changes until the next page loading. assertEquals(page2Title + customUserAgentString, getTitleOnUiThread(awContents)); HistoryUtils.goBackSync(getInstrumentation(), contentView, onPageFinishedHelper); assertEquals(page1Title + defaultUserAgentString, getTitleOnUiThread(awContents)); HistoryUtils.goForwardSync(getInstrumentation(), contentView, onPageFinishedHelper); assertEquals(page2Title + defaultUserAgentString, getTitleOnUiThread(awContents)); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testUserAgentStringWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsUserAgentStringTestHelper(views.getContents0(), views.getClient0()), new AwSettingsUserAgentStringTestHelper(views.getContents1(), views.getClient1())); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testUserAgentWithTestServer() throws Throwable { final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient); AwContents awContents = testContainerView.getAwContents(); AwSettings settings = getAwSettingsOnUiThread(awContents); final String customUserAgentString = "testUserAgentWithTestServerUserAgent"; TestWebServer webServer = null; String fileName = null; try { webServer = new TestWebServer(false); final String httpPath = "/testUserAgentWithTestServer.html"; final String url = webServer.setResponse(httpPath, "foo", null); settings.setUserAgentString(customUserAgentString); loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); assertEquals(1, webServer.getRequestCount(httpPath)); HttpRequest request = webServer.getLastRequest(httpPath); Header[] matchingHeaders = request.getHeaders("User-Agent"); assertEquals(1, matchingHeaders.length); Header header = matchingHeaders[0]; assertEquals(customUserAgentString, header.getValue()); } finally { if (webServer != null) webServer.shutdown(); } } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testDomStorageEnabledWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsDomStorageEnabledTestHelper(views.getContents0(), views.getClient0()), new AwSettingsDomStorageEnabledTestHelper(views.getContents1(), views.getClient1())); } // Ideally, these three tests below should be combined into one, or tested using // runPerViewSettingsTest. However, it seems the database setting cannot be toggled // once set. Filed b/8186497. @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testDatabaseInitialValue() throws Throwable { TestAwContentsClient client = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(client); final AwContents awContents = testContainerView.getAwContents(); AwSettingsDatabaseTestHelper helper = new AwSettingsDatabaseTestHelper(awContents, client); helper.ensureSettingHasInitialValue(); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testDatabaseEnabled() throws Throwable { TestAwContentsClient client = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(client); final AwContents awContents = testContainerView.getAwContents(); AwSettingsDatabaseTestHelper helper = new AwSettingsDatabaseTestHelper(awContents, client); helper.setAlteredSettingValue(); helper.ensureSettingHasAlteredValue(); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testDatabaseDisabled() throws Throwable { TestAwContentsClient client = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(client); final AwContents awContents = testContainerView.getAwContents(); AwSettingsDatabaseTestHelper helper = new AwSettingsDatabaseTestHelper(awContents, client); helper.setInitialSettingValue(); helper.ensureSettingHasInitialValue(); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testUniversalAccessFromFilesWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsUniversalAccessFromFilesTestHelper(views.getContents0(), views.getClient0()), new AwSettingsUniversalAccessFromFilesTestHelper(views.getContents1(), views.getClient1())); } // This test verifies that local image resources can be loaded from file: // URLs regardless of file access state. @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testFileAccessFromFilesImage() throws Throwable { final String imageContainerUrl = UrlUtils.getTestFileUrl("webview/image_access.html"); final String imageHeight = "16"; final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainerView.getAwContents(); AwSettings settings = getAwSettingsOnUiThread(awContents); settings.setJavaScriptEnabled(true); settings.setAllowUniversalAccessFromFileURLs(false); settings.setAllowFileAccessFromFileURLs(false); loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), imageContainerUrl); assertEquals(imageHeight, getTitleOnUiThread(awContents)); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testFileAccessFromFilesIframeWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsFileAccessFromFilesIframeTestHelper( views.getContents0(), views.getClient0()), new AwSettingsFileAccessFromFilesIframeTestHelper( views.getContents1(), views.getClient1())); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testFileAccessFromFilesXhrWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsFileAccessFromFilesXhrTestHelper(views.getContents0(), views.getClient0()), new AwSettingsFileAccessFromFilesXhrTestHelper(views.getContents1(), views.getClient1())); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testFileUrlAccessWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsFileUrlAccessTestHelper(views.getContents0(), views.getClient0(), 0), new AwSettingsFileUrlAccessTestHelper(views.getContents1(), views.getClient1(), 1)); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testContentUrlAccessWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsContentUrlAccessTestHelper(views.getContents0(), views.getClient0(), 0), new AwSettingsContentUrlAccessTestHelper(views.getContents1(), views.getClient1(), 1)); } @SmallTest @Feature({"AndroidWebView", "Preferences", "Navigation"}) public void testBlockingContentUrlsFromDataUrls() throws Throwable { final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainerView.getAwContents(); final String target = "content_from_data"; final String page = "" + "" + ""; resetResourceRequestCountInContentProvider(target); loadDataSync( awContents, contentClient.getOnPageFinishedHelper(), page, "text/html", false); ensureResourceRequestCountInContentProvider(target, 0); } @SmallTest @Feature({"AndroidWebView", "Preferences", "Navigation"}) public void testContentUrlFromFileWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsContentUrlAccessFromFileTestHelper( views.getContents0(), views.getClient0(), 0), new AwSettingsContentUrlAccessFromFileTestHelper( views.getContents1(), views.getClient1(), 1)); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testBlockNetworkImagesDoesNotBlockDataUrlImage() throws Throwable { final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainerView.getAwContents(); final AwSettings settings = getAwSettingsOnUiThread(awContents); ImagePageGenerator generator = new ImagePageGenerator(0, false); settings.setJavaScriptEnabled(true); settings.setImagesEnabled(false); loadDataSync(awContents, contentClient.getOnPageFinishedHelper(), generator.getPageSource(), "text/html", false); assertEquals(ImagePageGenerator.IMAGE_LOADED_STRING, getTitleOnUiThread(awContents)); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testBlockNetworkImagesBlocksNetworkImageAndReloadInPlace() throws Throwable { final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainerView.getAwContents(); final AwSettings settings = getAwSettingsOnUiThread(awContents); settings.setJavaScriptEnabled(true); ImagePageGenerator generator = new ImagePageGenerator(0, false); TestWebServer webServer = null; try { webServer = new TestWebServer(false); final String imagePath = "/image.png"; webServer.setResponseBase64(imagePath, generator.getImageSourceNoAdvance(), CommonResources.getImagePngHeaders(false)); final String pagePath = "/html_image.html"; final String httpUrlImageHtml = generator.getPageTemplateSource(imagePath); final String httpImageUrl = webServer.setResponse(pagePath, httpUrlImageHtml, null); settings.setImagesEnabled(false); loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), httpImageUrl); assertEquals(ImagePageGenerator.IMAGE_NOT_LOADED_STRING, getTitleOnUiThread(awContents)); settings.setImagesEnabled(true); assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { @Override public boolean isSatisfied() { try { return ImagePageGenerator.IMAGE_LOADED_STRING.equals( getTitleOnUiThread(awContents)); } catch (Throwable t) { t.printStackTrace(); fail("Failed to getTitleOnUIThread: " + t.toString()); return false; } } }, TEST_TIMEOUT, CHECK_INTERVAL)); } finally { if (webServer != null) webServer.shutdown(); } } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testBlockNetworkLoadsWithHttpResources() throws Throwable { final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainer = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainer.getAwContents(); final AwSettings awSettings = getAwSettingsOnUiThread(awContents); awSettings.setJavaScriptEnabled(true); ImagePageGenerator generator = new ImagePageGenerator(0, false); TestWebServer webServer = null; String fileName = null; try { // Set up http image. webServer = new TestWebServer(false); final String httpPath = "/image.png"; final String imageUrl = webServer.setResponseBase64( httpPath, generator.getImageSourceNoAdvance(), CommonResources.getImagePngHeaders(true)); // Set up file html that loads http iframe. String pageHtml =""; Context context = getInstrumentation().getTargetContext(); fileName = context.getCacheDir() + "/block_network_loads_test.html"; TestFileUtil.deleteFile(fileName); // Remove leftover file if any. TestFileUtil.createNewHtmlFile(fileName, "unset", pageHtml); // Actual test. Blocking should trigger onerror handler. awSettings.setBlockNetworkLoads(true); loadUrlSync( awContents, contentClient.getOnPageFinishedHelper(), "file:///" + fileName); assertEquals(0, webServer.getRequestCount(httpPath)); assertEquals("img_onerror_fired", getTitleOnUiThread(awContents)); // Unblock should load normally. awSettings.setBlockNetworkLoads(false); loadUrlSync( awContents, contentClient.getOnPageFinishedHelper(), "file:///" + fileName); assertEquals(1, webServer.getRequestCount(httpPath)); assertEquals("img_onload_fired", getTitleOnUiThread(awContents)); } finally { if (fileName != null) TestFileUtil.deleteFile(fileName); if (webServer != null) webServer.shutdown(); } } // Test an assert URL (file:///android_asset/) @SmallTest @Feature({"AndroidWebView", "Navigation"}) public void testAssetUrl() throws Throwable { // Note: this text needs to be kept in sync with the contents of the html file referenced // below. final String expectedTitle = "Asset File"; final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainerView.getAwContents(); loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), "file:///android_asset/asset_file.html"); assertEquals(expectedTitle, getTitleOnUiThread(awContents)); } // Test a resource URL (file:///android_res/). @SmallTest @Feature({"AndroidWebView", "Navigation"}) public void testResourceUrl() throws Throwable { // Note: this text needs to be kept in sync with the contents of the html file referenced // below. final String expectedTitle = "Resource File"; final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainerView.getAwContents(); loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), "file:///android_res/raw/resource_file.html"); assertEquals(expectedTitle, getTitleOnUiThread(awContents)); } // Test that the file URL access toggle does not affect asset URLs. @SmallTest @Feature({"AndroidWebView", "Navigation"}) public void testFileUrlAccessToggleDoesNotBlockAssetUrls() throws Throwable { // Note: this text needs to be kept in sync with the contents of the html file referenced // below. final String expectedTitle = "Asset File"; final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainerView.getAwContents(); final AwSettings settings = getAwSettingsOnUiThread(awContents); settings.setAllowFileAccess(false); loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), "file:///android_asset/asset_file.html"); assertEquals(expectedTitle, getTitleOnUiThread(awContents)); } // Test that the file URL access toggle does not affect resource URLs. @SmallTest @Feature({"AndroidWebView", "Navigation"}) public void testFileUrlAccessToggleDoesNotBlockResourceUrls() throws Throwable { // Note: this text needs to be kept in sync with the contents of the html file referenced // below. final String expectedTitle = "Resource File"; final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainerView.getAwContents(); final AwSettings settings = getAwSettingsOnUiThread(awContents); settings.setAllowFileAccess(false); loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), "file:///android_res/raw/resource_file.html"); assertEquals(expectedTitle, getTitleOnUiThread(awContents)); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testLayoutAlgorithmWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsLayoutAlgorithmTestHelper(views.getContents0(), views.getClient0()), new AwSettingsLayoutAlgorithmTestHelper(views.getContents1(), views.getClient1())); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testTextZoomWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsTextZoomTestHelper(views.getContents0(), views.getClient0()), new AwSettingsTextZoomTestHelper(views.getContents1(), views.getClient1())); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testTextZoomAutosizingWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsTextZoomAutosizingTestHelper(views.getContents0(), views.getClient0()), new AwSettingsTextZoomAutosizingTestHelper(views.getContents1(), views.getClient1())); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testJavaScriptPopupsWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsJavaScriptPopupsTestHelper(views.getContents0(), views.getClient0()), new AwSettingsJavaScriptPopupsTestHelper(views.getContents1(), views.getClient1())); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testCacheMode() throws Throwable { final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainer = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainer.getAwContents(); final AwSettings awSettings = getAwSettingsOnUiThread(testContainer.getAwContents()); clearCacheOnUiThread(awContents, true); assertEquals(WebSettings.LOAD_DEFAULT, awSettings.getCacheMode()); TestWebServer webServer = null; try { webServer = new TestWebServer(false); final String htmlPath = "/testCacheMode.html"; final String url = webServer.setResponse(htmlPath, "response", null); awSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); assertEquals(1, webServer.getRequestCount(htmlPath)); loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); assertEquals(1, webServer.getRequestCount(htmlPath)); awSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); assertEquals(2, webServer.getRequestCount(htmlPath)); loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); assertEquals(3, webServer.getRequestCount(htmlPath)); awSettings.setCacheMode(WebSettings.LOAD_CACHE_ONLY); loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); assertEquals(3, webServer.getRequestCount(htmlPath)); loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); assertEquals(3, webServer.getRequestCount(htmlPath)); final String htmlNotInCachePath = "/testCacheMode-not-in-cache.html"; final String urlNotInCache = webServer.setResponse(htmlNotInCachePath, "", null); loadUrlSyncAndExpectError(awContents, contentClient.getOnPageFinishedHelper(), contentClient.getOnReceivedErrorHelper(), urlNotInCache); assertEquals(0, webServer.getRequestCount(htmlNotInCachePath)); } finally { if (webServer != null) webServer.shutdown(); } } @SmallTest @Feature({"AndroidWebView", "Preferences"}) // As our implementation of network loads blocking uses the same net::URLRequest settings, make // sure that setting cache mode doesn't accidentally enable network loads. The reference // behaviour is that when network loads are blocked, setting cache mode has no effect. public void testCacheModeWithBlockedNetworkLoads() throws Throwable { final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainer = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainer.getAwContents(); final AwSettings awSettings = getAwSettingsOnUiThread(testContainer.getAwContents()); clearCacheOnUiThread(awContents, true); assertEquals(WebSettings.LOAD_DEFAULT, awSettings.getCacheMode()); awSettings.setBlockNetworkLoads(true); TestWebServer webServer = null; try { webServer = new TestWebServer(false); final String htmlPath = "/testCacheModeWithBlockedNetworkLoads.html"; final String url = webServer.setResponse(htmlPath, "response", null); loadUrlSyncAndExpectError(awContents, contentClient.getOnPageFinishedHelper(), contentClient.getOnReceivedErrorHelper(), url); assertEquals(0, webServer.getRequestCount(htmlPath)); awSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); loadUrlSyncAndExpectError(awContents, contentClient.getOnPageFinishedHelper(), contentClient.getOnReceivedErrorHelper(), url); assertEquals(0, webServer.getRequestCount(htmlPath)); awSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); loadUrlSyncAndExpectError(awContents, contentClient.getOnPageFinishedHelper(), contentClient.getOnReceivedErrorHelper(), url); assertEquals(0, webServer.getRequestCount(htmlPath)); awSettings.setCacheMode(WebSettings.LOAD_CACHE_ONLY); loadUrlSyncAndExpectError(awContents, contentClient.getOnPageFinishedHelper(), contentClient.getOnReceivedErrorHelper(), url); assertEquals(0, webServer.getRequestCount(htmlPath)); } finally { if (webServer != null) webServer.shutdown(); } } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testCacheModeWithTwoViews() throws Throwable { ViewPair views = createViews(); TestWebServer webServer = null; try { webServer = new TestWebServer(false); runPerViewSettingsTest( new AwSettingsCacheModeTestHelper( views.getContents0(), views.getClient0(), 0, webServer), new AwSettingsCacheModeTestHelper( views.getContents1(), views.getClient1(), 1, webServer)); } finally { if (webServer != null) webServer.shutdown(); } } static class ManifestTestHelper { private final TestWebServer mWebServer; private final String mHtmlPath; private final String mHtmlUrl; private final String mManifestPath; ManifestTestHelper( TestWebServer webServer, String htmlPageName, String manifestName) { mWebServer = webServer; mHtmlPath = "/" + htmlPageName; mHtmlUrl = webServer.setResponse( mHtmlPath, "", null); mManifestPath = "/" + manifestName; webServer.setResponse( mManifestPath, "CACHE MANIFEST", CommonResources.getContentTypeAndCacheHeaders("text/cache-manifest", false)); } String getHtmlPath() { return mHtmlPath; } String getHtmlUrl() { return mHtmlUrl; } String getManifestPath() { return mManifestPath; } int waitUntilHtmlIsRequested(final int initialRequestCount) throws InterruptedException { return waitUntilResourceIsRequested(mHtmlPath, initialRequestCount); } int waitUntilManifestIsRequested(final int initialRequestCount) throws InterruptedException { return waitUntilResourceIsRequested(mManifestPath, initialRequestCount); } private int waitUntilResourceIsRequested( final String path, final int initialRequestCount) throws InterruptedException { assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { @Override public boolean isSatisfied() { return mWebServer.getRequestCount(path) > initialRequestCount; } }, TEST_TIMEOUT, CHECK_INTERVAL)); return mWebServer.getRequestCount(path); } } @SmallTest @Feature({"AndroidWebView", "Preferences", "AppCache"}) public void testAppCache() throws Throwable { final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainer = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainer.getAwContents(); final AwSettings settings = getAwSettingsOnUiThread(awContents); settings.setJavaScriptEnabled(true); // Note that the cache isn't actually enabled until the call to setAppCachePath. settings.setAppCacheEnabled(true); TestWebServer webServer = null; try { webServer = new TestWebServer(false); ManifestTestHelper helper = new ManifestTestHelper( webServer, "testAppCache.html", "appcache.manifest"); loadUrlSync( awContents, contentClient.getOnPageFinishedHelper(), helper.getHtmlUrl()); helper.waitUntilHtmlIsRequested(0); // Unfortunately, there is no other good way of verifying that AppCache is // disabled, other than checking that it didn't try to fetch the manifest. Thread.sleep(1000); assertEquals(0, webServer.getRequestCount(helper.getManifestPath())); settings.setAppCachePath("whatever"); // Enables AppCache. loadUrlSync( awContents, contentClient.getOnPageFinishedHelper(), helper.getHtmlUrl()); helper.waitUntilManifestIsRequested(0); } finally { if (webServer != null) webServer.shutdown(); } } /* * @SmallTest * @Feature({"AndroidWebView", "Preferences", "AppCache"}) * This test is flaky but the root cause is not found yet. See crbug.com/171765. */ @DisabledTest public void testAppCacheWithTwoViews() throws Throwable { // We don't use the test helper here, because making sure that AppCache // is disabled takes a lot of time, so running through the usual drill // will take about 20 seconds. ViewPair views = createViews(); AwSettings settings0 = getAwSettingsOnUiThread(views.getContents0()); settings0.setJavaScriptEnabled(true); settings0.setAppCachePath("whatever"); settings0.setAppCacheEnabled(true); AwSettings settings1 = getAwSettingsOnUiThread(views.getContents1()); settings1.setJavaScriptEnabled(true); // AppCachePath setting is global, no need to set it for the second view. settings1.setAppCacheEnabled(true); TestWebServer webServer = null; try { webServer = new TestWebServer(false); ManifestTestHelper helper0 = new ManifestTestHelper( webServer, "testAppCache_0.html", "appcache.manifest_0"); loadUrlSync( views.getContents0(), views.getClient0().getOnPageFinishedHelper(), helper0.getHtmlUrl()); int manifestRequests0 = helper0.waitUntilManifestIsRequested(0); ManifestTestHelper helper1 = new ManifestTestHelper( webServer, "testAppCache_1.html", "appcache.manifest_1"); loadUrlSync( views.getContents1(), views.getClient1().getOnPageFinishedHelper(), helper1.getHtmlUrl()); helper1.waitUntilManifestIsRequested(0); settings1.setAppCacheEnabled(false); loadUrlSync( views.getContents0(), views.getClient0().getOnPageFinishedHelper(), helper0.getHtmlUrl()); helper0.waitUntilManifestIsRequested(manifestRequests0); final int prevManifestRequestCount = webServer.getRequestCount(helper1.getManifestPath()); int htmlRequests1 = webServer.getRequestCount(helper1.getHtmlPath()); loadUrlSync( views.getContents1(), views.getClient1().getOnPageFinishedHelper(), helper1.getHtmlUrl()); helper1.waitUntilHtmlIsRequested(htmlRequests1); // Unfortunately, there is no other good way of verifying that AppCache is // disabled, other than checking that it didn't try to fetch the manifest. Thread.sleep(1000); assertEquals( prevManifestRequestCount, webServer.getRequestCount(helper1.getManifestPath())); } finally { if (webServer != null) webServer.shutdown(); } } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testUseWideViewportWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsUseWideViewportTestHelper(views.getContents0(), views.getClient0()), new AwSettingsUseWideViewportTestHelper(views.getContents1(), views.getClient1())); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testUseWideViewportWithTwoViewsNoQuirks() throws Throwable { ViewPair views = createViews(false); runPerViewSettingsTest( new AwSettingsUseWideViewportTestHelper(views.getContents0(), views.getClient0()), new AwSettingsUseWideViewportTestHelper(views.getContents1(), views.getClient1())); } private void useWideViewportLayoutWidthTest( final AwContents awContents, CallbackHelper onPageFinishedHelper) throws Throwable { AwSettings settings = getAwSettingsOnUiThread(awContents); final String pageTemplate = "%s" + ""; final String pageNoViewport = String.format(pageTemplate, ""); final String pageViewportDeviceWidth = String.format( pageTemplate, ""); final String viewportTagSpecifiedWidth = "3000"; final String pageViewportSpecifiedWidth = String.format( pageTemplate, ""); DeviceDisplayInfo deviceInfo = DeviceDisplayInfo.create(getInstrumentation().getTargetContext()); int displayWidth = (int) (deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale()); settings.setJavaScriptEnabled(true); assertFalse(settings.getUseWideViewPort()); // When UseWideViewPort is off, "width" setting of "meta viewport" // tags is ignored, and the layout width is set to device width in CSS pixels. // Thus, all 3 pages will have the same body width. loadDataSync(awContents, onPageFinishedHelper, pageNoViewport, "text/html", false); int actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); // Avoid rounding errors. assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth, Math.abs(displayWidth - actualWidth) <= 1); loadDataSync(awContents, onPageFinishedHelper, pageViewportDeviceWidth, "text/html", false); actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth, Math.abs(displayWidth - actualWidth) <= 1); loadDataSync( awContents, onPageFinishedHelper, pageViewportSpecifiedWidth, "text/html", false); actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth, Math.abs(displayWidth - actualWidth) <= 1); settings.setUseWideViewPort(true); // When UseWideViewPort is on, "meta viewport" tag is used. // If there is no viewport tag, or width isn't specified, // then layout width is set to max(980, ) loadDataSync(awContents, onPageFinishedHelper, pageNoViewport, "text/html", false); actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); assertTrue("Expected: >= 980 , Actual: " + actualWidth, actualWidth >= 980); loadDataSync(awContents, onPageFinishedHelper, pageViewportDeviceWidth, "text/html", false); actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth, Math.abs(displayWidth - actualWidth) <= 1); loadDataSync( awContents, onPageFinishedHelper, pageViewportSpecifiedWidth, "text/html", false); assertEquals(viewportTagSpecifiedWidth, getTitleOnUiThread(awContents)); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testUseWideViewportLayoutWidth() throws Throwable { TestAwContentsClient contentClient = new TestAwContentsClient(); AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient); useWideViewportLayoutWidthTest(testContainerView.getAwContents(), contentClient.getOnPageFinishedHelper()); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testUseWideViewportLayoutWidthNoQuirks() throws Throwable { TestAwContentsClient contentClient = new TestAwContentsClient(); AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient, false); useWideViewportLayoutWidthTest(testContainerView.getAwContents(), contentClient.getOnPageFinishedHelper()); } /* @MediumTest @Feature({"AndroidWebView", "Preferences"}) http://crbug.com/239144 */ @DisabledTest public void testUseWideViewportControlsDoubleTabToZoom() throws Throwable { final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainerView.getAwContents(); AwSettings settings = getAwSettingsOnUiThread(awContents); CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); final String page = "Page Text"; assertFalse(settings.getUseWideViewPort()); loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); final float initialScale = getScaleOnUiThread(awContents); simulateDoubleTapCenterOfWebViewOnUiThread(testContainerView); Thread.sleep(1000); assertEquals(initialScale, getScaleOnUiThread(awContents)); settings.setUseWideViewPort(true); loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); int onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount(); simulateDoubleTapCenterOfWebViewOnUiThread(testContainerView); contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount); final float zoomedOutScale = getScaleOnUiThread(awContents); assertTrue("zoomedOut: " + zoomedOutScale + ", initial: " + initialScale, zoomedOutScale < initialScale); } /* @SmallTest @Feature({"AndroidWebView", "Preferences"}) http://crbug.com/239144 */ @DisabledTest public void testLoadWithOverviewModeWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsLoadWithOverviewModeTestHelper( views.getContents0(), views.getClient0(), false), new AwSettingsLoadWithOverviewModeTestHelper( views.getContents1(), views.getClient1(), false)); } /* @SmallTest @Feature({"AndroidWebView", "Preferences"}) http://crbug.com/239144 */ @DisabledTest public void testLoadWithOverviewModeViewportTagWithTwoViews() throws Throwable { ViewPair views = createViews(); runPerViewSettingsTest( new AwSettingsLoadWithOverviewModeTestHelper( views.getContents0(), views.getClient0(), true), new AwSettingsLoadWithOverviewModeTestHelper( views.getContents1(), views.getClient1(), true)); } @SmallTest @Feature({"AndroidWebView", "Preferences"}) public void testSetInitialScale() throws Throwable { final TestAwContentsClient contentClient = new TestAwContentsClient(); final AwTestContainerView testContainerView = createAwTestContainerViewOnMainSync(contentClient); final AwContents awContents = testContainerView.getAwContents(); final AwSettings awSettings = getAwSettingsOnUiThread(awContents); CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); WindowManager wm = (WindowManager) getInstrumentation().getTargetContext() .getSystemService(Context.WINDOW_SERVICE); Point screenSize = new Point(); wm.getDefaultDisplay().getSize(screenSize); // Make sure after 50% scale, page width still larger than screen. int height = screenSize.y * 2 + 1; int width = screenSize.x * 2 + 1; final String page = "" + "

" + "testSetInitialScale

"; final float defaultScale = getInstrumentation().getTargetContext().getResources().getDisplayMetrics().density; assertEquals(defaultScale, getPixelScaleOnUiThread(awContents), .01f); loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); assertEquals(defaultScale, getPixelScaleOnUiThread(awContents), .01f); int onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount(); awSettings.setInitialPageScale(50); loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount); assertEquals(0.5f, getPixelScaleOnUiThread(awContents), .01f); onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount(); awSettings.setInitialPageScale(500); loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount); assertEquals(5.0f, getPixelScaleOnUiThread(awContents), .01f); onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount(); awSettings.setInitialPageScale(0); loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount); assertEquals(defaultScale, getPixelScaleOnUiThread(awContents), .01f); } /** * Run video test. * @param requiredUserGesture the settings of MediaPlaybackRequiresUserGesture. * @param waitTime time for waiting event happen, -1 means forever. * @return true if the event happened, * @throws Throwable throw exception if timeout. */ private boolean runVideoTest(final boolean requiredUserGesture, long waitTime) throws Throwable { final JavascriptEventObserver observer = new JavascriptEventObserver(); TestAwContentsClient client = new TestAwContentsClient(); final AwContents awContents = createAwTestContainerViewOnMainSync(client).getAwContents(); getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { AwSettings awSettings = awContents.getSettings(); awSettings.setJavaScriptEnabled(true); awSettings.setMediaPlaybackRequiresUserGesture(requiredUserGesture); observer.register(awContents.getContentViewCore(), "javaObserver"); } }); VideoTestWebServer webServer = new VideoTestWebServer(getActivity()); try { String data = "" + "