This source file includes following definitions.
- ensureSettingHasAlteredValue
 
- ensureSettingHasInitialValue
 
- setAlteredSettingValue
 
- setInitialSettingValue
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getTitleOnUiThread
 
- loadDataSync
 
- loadUrlSync
 
- loadUrlSyncAndExpectError
 
- executeJavaScriptAndWaitForResult
 
- ensureSettingHasValue
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getData
 
- doEnsureSettingHasValue
 
- getScript
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getData
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getData
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getData
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getData
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getData
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- setCurrentValue
 
- getActualFontSize
 
- getData
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getData
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getData
 
- getAlteredValue
 
- getInitialValue
 
- getCurrentValue
 
- setCurrentValue
 
- doEnsureSettingHasValue
 
- getData
 
- Feature
 
- testJavaScriptDisabledByDefault
 
- Feature
 
- testJavaScriptEnabledWithTwoViews
 
- Feature
 
- testJavaScriptEnabledDynamicWithTwoViews
 
- Feature
 
- testPluginsEnabledWithTwoViews
 
- Feature
 
- testStandardFontFamilyWithTwoViews
 
- Feature
 
- testDefaultFontSizeWithTwoViews
 
- Feature
 
- testLoadsImagesAutomaticallyNoPageReload
 
- Feature
 
- testLoadsImagesAutomaticallyWithTwoViews
 
- Feature
 
- testDefaultTextEncodingWithTwoViews
 
- Feature
 
- testUserAgentStringDefault
 
- Feature
 
- testUserAgentStringOverride
 
- Feature
 
- testUserAgentStringOverrideForHistory
 
- Feature
 
- testUserAgentStringWithTwoViews
 
- Feature
 
- testUserAgentWithTestServer
 
- Feature
 
- testDomStorageEnabledWithTwoViews
 
- Feature
 
- testDatabaseInitialValue
 
- Feature
 
- testDatabaseEnabled
 
- Feature
 
- testDatabaseDisabled
 
- Feature
 
- testUniversalAccessFromFilesWithTwoViews
 
- Feature
 
- testFileAccessFromFilesImage
 
- Feature
 
- testFileAccessFromFilesIframeWithTwoViews
 
- Feature
 
- testFileAccessFromFilesXhrWithTwoViews
 
- Feature
 
- testFileUrlAccessWithTwoViews
 
- Feature
 
- testContentUrlAccessWithTwoViews
 
- Feature
 
- testBlockingContentUrlsFromDataUrls
 
- Feature
 
- testContentUrlFromFileWithTwoViews
 
- Feature
 
- testBlockNetworkImagesDoesNotBlockDataUrlImage
 
- Feature
 
- testBlockNetworkImagesBlocksNetworkImageAndReloadInPlace
 
- Feature
 
- testBlockNetworkImagesWithTwoViews
 
- Feature
 
- testBlockNetworkLoadsWithHttpResources
 
- onCanPlay
 
- onError
 
- Feature
 
- testBlockNetworkLoadsWithAudio
 
- Feature
 
- testAssetUrl
 
- Feature
 
- testResourceUrl
 
- Feature
 
- testFileUrlAccessToggleDoesNotBlockAssetUrls
 
- Feature
 
- testFileUrlAccessToggleDoesNotBlockResourceUrls
 
- Feature
 
- testLayoutAlgorithmWithTwoViews
 
- Feature
 
- testTextZoomWithTwoViews
 
- Feature
 
- testTextZoomAutosizingWithTwoViews
 
- Feature
 
- testJavaScriptPopupsWithTwoViews
 
- Feature
 
- testCacheMode
 
- Feature
 
- testCacheModeWithBlockedNetworkLoads
 
- Feature
 
- testCacheModeWithTwoViews
 
- getHtmlPath
 
- getHtmlUrl
 
- getManifestPath
 
- waitUntilHtmlIsRequested
 
- waitUntilManifestIsRequested
 
- waitUntilResourceIsRequested
 
- Feature
 
- testAppCache
 
- Feature
 
- testAppCacheWithTwoViews
 
- Feature
 
- testUseWideViewportWithTwoViews
 
- Feature
 
- testUseWideViewportWithTwoViewsNoQuirks
 
- useWideViewportLayoutWidthTest
 
- Feature
 
- testUseWideViewportLayoutWidth
 
- Feature
 
- testUseWideViewportLayoutWidthNoQuirks
 
- Feature
 
- testUseWideViewportControlsDoubleTabToZoom
 
- Feature
 
- testLoadWithOverviewModeWithTwoViews
 
- Feature
 
- testLoadWithOverviewModeViewportTagWithTwoViews
 
- Feature
 
- testSetInitialScale
 
- runVideoTest
 
- testMediaPlaybackWithoutUserGesture
 
- Feature
 
- testMediaPlaybackWithUserGesture
 
- Feature
 
- testDefaultVideoPosterURL
 
- getContainer0
 
- getContents0
 
- getClient0
 
- getContainer1
 
- getContents1
 
- getClient1
 
- runPerViewSettingsTest
 
- createViews
 
- createViews
 
- assertFileIsReadable
 
- ensureResourceRequestCountInContentProvider
 
- resetResourceRequestCountInContentProvider
 
- createContentUrl
 
- simulateDoubleTapCenterOfWebViewOnUiThread
 
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.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.WindowManager;
import android.webkit.JavascriptInterface;
import android.webkit.WebSettings;
import org.apache.http.Header;
import org.apache.http.HttpRequest;
import org.chromium.android_webview.AwContents;
import org.chromium.android_webview.AwSettings;
import org.chromium.android_webview.AwSettings.LayoutAlgorithm;
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.HistoryUtils;
import org.chromium.net.test.util.TestWebServer;
import org.chromium.ui.gfx.DeviceDisplayInfo;
import java.io.File;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class AwSettingsTest extends AwTestBase {
    private static final boolean ENABLED = true;
    private static final boolean DISABLED = false;
    
    abstract class AwSettingsTestHelper<T> {
        protected final AwContents mAwContents;
        protected final Context mContext;
        protected final TestAwContentsClient mContentViewClient;
        protected final AwSettings mAwSettings;
        AwSettingsTestHelper(AwTestContainerView containerView,
                             TestAwContentsClient contentViewClient,
                             boolean requiresJsEnabled) throws Throwable {
            mAwContents = containerView.getAwContents();
            mContext = containerView.getContext();
            mContentViewClient = contentViewClient;
            mAwSettings = AwSettingsTest.this.getAwSettingsOnUiThread(mAwContents);
            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 Exception {
            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 Exception {
            return AwSettingsTest.this.executeJavaScriptAndWaitForResult(
                    mAwContents, mContentViewClient, script);
        }
        private void ensureSettingHasValue(T value) throws Throwable {
            assertEquals(value, getCurrentValue());
            doEnsureSettingHasValue(value);
        }
    }
    class AwSettingsJavaScriptTestHelper extends AwSettingsTestHelper<Boolean> {
        private static final String JS_ENABLED_STRING = "JS Enabled";
        private static final String JS_DISABLED_STRING = "JS Disabled";
        AwSettingsJavaScriptTestHelper(AwTestContainerView containerView,
                                       TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, 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 "<html><head><title>" + JS_DISABLED_STRING + "</title>"
                    + "</head><body onload=\"document.title='" + JS_ENABLED_STRING
                    + "';\"></body></html>";
        }
    }
    
    
    class AwSettingsJavaScriptDynamicTestHelper extends AwSettingsJavaScriptTestHelper {
        AwSettingsJavaScriptDynamicTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, contentViewClient);
            
            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<Boolean> {
        private static final String PLUGINS_ENABLED_STRING = "Embed";
        private static final String PLUGINS_DISABLED_STRING = "NoEmbed";
        AwSettingsPluginsTestHelper(AwTestContainerView containerView,
                                    TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, 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 "<html><body onload=\"document.title = document.body.innerText;\">"
                    + "<noembed>No</noembed><span>Embed</span></body></html>";
        }
    }
    class AwSettingsStandardFontFamilyTestHelper extends AwSettingsTestHelper<String> {
        AwSettingsStandardFontFamilyTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, 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 "<html><body onload=\"document.title = " +
                    "getComputedStyle(document.body).getPropertyValue('font-family');\">"
                    + "</body></html>";
        }
    }
    class AwSettingsDefaultFontSizeTestHelper extends AwSettingsTestHelper<Integer> {
        AwSettingsDefaultFontSizeTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, 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 "<html><body onload=\"document.title = " +
                    "getComputedStyle(document.body).getPropertyValue('font-size');\">"
                    + "</body></html>";
        }
    }
    class AwSettingsLoadImagesAutomaticallyTestHelper extends AwSettingsTestHelper<Boolean> {
        private ImagePageGenerator mGenerator;
        AwSettingsLoadImagesAutomaticallyTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient,
                ImagePageGenerator generator) throws Throwable {
            super(containerView, 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 AwSettingsImagesEnabledHelper extends AwSettingsTestHelper<Boolean> {
        AwSettingsImagesEnabledHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient,
                TestWebServer webServer,
                ImagePageGenerator generator) throws Throwable {
            super(containerView, contentViewClient, true);
            mWebServer = webServer;
            mGenerator = generator;
        }
        @Override
        protected Boolean getAlteredValue() {
            return DISABLED;
        }
        @Override
        protected Boolean getInitialValue() {
            return ENABLED;
        }
        @Override
        protected Boolean getCurrentValue() {
            return mAwSettings.getImagesEnabled();
        }
        @Override
        protected void setCurrentValue(Boolean value) {
            mAwSettings.setImagesEnabled(value);
        }
        @Override
        protected void doEnsureSettingHasValue(Boolean value) throws Throwable {
            final String httpImageUrl = mGenerator.getPageUrl(mWebServer);
            AwSettingsTest.this.loadUrlSync(
                    mAwContents,
                    mContentViewClient.getOnPageFinishedHelper(),
                    httpImageUrl);
            assertEquals(value == ENABLED ?
                         ImagePageGenerator.IMAGE_LOADED_STRING :
                         ImagePageGenerator.IMAGE_NOT_LOADED_STRING,
                         getTitleOnUiThread());
        }
        private TestWebServer mWebServer;
        private ImagePageGenerator mGenerator;
    }
    class AwSettingsDefaultTextEncodingTestHelper extends AwSettingsTestHelper<String> {
        AwSettingsDefaultTextEncodingTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, 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 "<html><body onload='document.title=document.defaultCharset'></body></html>";
        }
    }
    class AwSettingsUserAgentStringTestHelper extends AwSettingsTestHelper<String> {
        private final String mDefaultUa;
        private static final String DEFAULT_UA = "";
        private static final String CUSTOM_UA = "ChromeViewTest";
        AwSettingsUserAgentStringTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, contentViewClient, true);
            mDefaultUa = mAwSettings.getUserAgentString();
        }
        @Override
        protected String getAlteredValue() {
            return CUSTOM_UA;
        }
        @Override
        protected String getInitialValue() {
            return DEFAULT_UA;
        }
        @Override
        protected String getCurrentValue() {
            
            
            
            
            
            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 "<html><body onload='document.title=navigator.userAgent'></body></html>";
        }
    }
    class AwSettingsDomStorageEnabledTestHelper extends AwSettingsTestHelper<Boolean> {
        private static final String TEST_FILE = "webview/localStorage.html";
        private static final String NO_LOCAL_STORAGE = "No localStorage";
        private static final String HAS_LOCAL_STORAGE = "Has localStorage";
        AwSettingsDomStorageEnabledTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, contentViewClient, true);
            AwSettingsTest.assertFileIsReadable(UrlUtils.getTestFilePath(TEST_FILE));
        }
        @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 {
            
            
            loadUrlSync(UrlUtils.getTestFileUrl(TEST_FILE));
            assertEquals(
                value == ENABLED ? HAS_LOCAL_STORAGE : NO_LOCAL_STORAGE,
                getTitleOnUiThread());
        }
    }
    class AwSettingsDatabaseTestHelper extends AwSettingsTestHelper<Boolean> {
        private static final String TEST_FILE = "webview/database_access.html";
        private static final String NO_DATABASE = "No database";
        private static final String HAS_DATABASE = "Has database";
        AwSettingsDatabaseTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, contentViewClient, true);
            AwSettingsTest.assertFileIsReadable(UrlUtils.getTestFilePath(TEST_FILE));
        }
        @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 {
            
            
            
            loadUrlSync(UrlUtils.getTestFileUrl(TEST_FILE));
            assertEquals(
                value == ENABLED ? HAS_DATABASE : NO_DATABASE,
                getTitleOnUiThread());
        }
    }
    class AwSettingsUniversalAccessFromFilesTestHelper extends AwSettingsTestHelper<Boolean> {
        private static final String TEST_CONTAINER_FILE = "webview/iframe_access.html";
        private static final String TEST_FILE = "webview/hello_world.html";
        private static final String ACCESS_DENIED_TITLE = "Exception";
        AwSettingsUniversalAccessFromFilesTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, contentViewClient, true);
            AwSettingsTest.assertFileIsReadable(UrlUtils.getTestFilePath(TEST_CONTAINER_FILE));
            AwSettingsTest.assertFileIsReadable(UrlUtils.getTestFilePath(TEST_FILE));
            mIframeContainerUrl = UrlUtils.getTestFileUrl(TEST_CONTAINER_FILE);
            mIframeUrl = UrlUtils.getTestFileUrl(TEST_FILE);
            
            mAwSettings.setAllowUniversalAccessFromFileURLs(false);
            
            
            
            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<Boolean> {
        private static final String TEST_CONTAINER_FILE = "webview/iframe_access.html";
        private static final String TEST_FILE = "webview/hello_world.html";
        private static final String ACCESS_DENIED_TITLE = "Exception";
        AwSettingsFileAccessFromFilesIframeTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, contentViewClient, true);
            AwSettingsTest.assertFileIsReadable(UrlUtils.getTestFilePath(TEST_CONTAINER_FILE));
            AwSettingsTest.assertFileIsReadable(UrlUtils.getTestFilePath(TEST_FILE));
            mIframeContainerUrl = UrlUtils.getTestFileUrl(TEST_CONTAINER_FILE);
            mIframeUrl = UrlUtils.getTestFileUrl(TEST_FILE);
            mAwSettings.setAllowUniversalAccessFromFileURLs(false);
            
            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<Boolean> {
        private static final String TEST_FILE = "webview/xhr_access.html";
        private static final String ACCESS_GRANTED_TITLE = "Hello, World!";
        private static final String ACCESS_DENIED_TITLE = "Exception";
        AwSettingsFileAccessFromFilesXhrTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, contentViewClient, true);
            assertFileIsReadable(UrlUtils.getTestFilePath(TEST_FILE));
            mXhrContainerUrl = UrlUtils.getTestFileUrl(TEST_FILE);
            mAwSettings.setAllowUniversalAccessFromFileURLs(false);
            
            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<Boolean> {
        private static final String TEST_FILE = "webview/hello_world.html";
        private static final String ACCESS_GRANTED_TITLE = "Hello, World!";
        AwSettingsFileUrlAccessTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient,
                int startIndex) throws Throwable {
            super(containerView, contentViewClient, true);
            mIndex = startIndex;
            AwSettingsTest.assertFileIsReadable(UrlUtils.getTestFilePath(TEST_FILE));
        }
        @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 {
            
            String fileUrl = UrlUtils.getTestFileUrl(TEST_FILE + "?id=" + mIndex);
            mIndex += 2;
            if (value == ENABLED) {
                loadUrlSync(fileUrl);
                assertEquals(ACCESS_GRANTED_TITLE, getTitleOnUiThread());
            } else {
                loadUrlSyncAndExpectError(fileUrl);
            }
        }
        private int mIndex;
    }
    class AwSettingsContentUrlAccessTestHelper extends AwSettingsTestHelper<Boolean> {
        AwSettingsContentUrlAccessTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient,
                int index) throws Throwable {
            super(containerView, 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<Boolean> {
        private static final String TARGET = "content_from_file";
        AwSettingsContentUrlAccessFromFileTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient,
                int index) throws Throwable {
            super(containerView, 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,
                        "<img src=\"" +
                        
                        
                        
                        AwSettingsTest.this.createContentUrl(TARGET + "?id=" + mIndex) + "\">");
                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;
    }
    
    
    abstract class AwSettingsTextAutosizingTestHelper<T> extends AwSettingsTestHelper<T> {
        protected static final float PARAGRAPH_FONT_SIZE = 14.0f;
        AwSettingsTextAutosizingTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, 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;
                poll(new Callable<Boolean>() {
                    @Override
                    public Boolean call() throws Exception {
                        executeJavaScriptAndWaitForResult("setTitleToActualFontSize()");
                        float newFontSize = Float.parseFloat(getTitleOnUiThread());
                        return newFontSize != oldFontSize;
                    }
                });
                mNeedToWaitForFontSizeChange = false;
            }
            return Float.parseFloat(getTitleOnUiThread());
        }
        protected String getData() {
            DeviceDisplayInfo deviceInfo = DeviceDisplayInfo.create(mContext);
            int displayWidth = (int) (deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale());
            int layoutWidth = (int) (displayWidth * 2.5f); 
            StringBuilder sb = new StringBuilder();
            sb.append("<html>" +
                    "<head>" +
                    "<meta name=\"viewport\" content=\"width=" + layoutWidth + "\">" +
                    "<style>" +
                    "body { width: " + layoutWidth + "px; margin: 0; overflow-y: hidden; }" +
                    "</style>" +
                    "<script>" +
                    "function setTitleToActualFontSize() {" +
                    
                    "  document.title = parseFloat(getComputedStyle(" +
                    "    document.getElementById('par')).getPropertyValue('font-size'));" +
                    "}</script></head>" +
                    "<body>" +
                    "<p id=\"par\" style=\"font-size:");
            sb.append(PARAGRAPH_FONT_SIZE);
            sb.append("px;\">");
            
            for (int i = 0; i < 500; i++) {
                sb.append("Hello, World! ");
            }
            sb.append("</p></body></html>");
            return sb.toString();
        }
        private boolean mNeedToWaitForFontSizeChange;
        private float mOldFontSize;
    }
    class AwSettingsLayoutAlgorithmTestHelper extends
                                              AwSettingsTextAutosizingTestHelper<LayoutAlgorithm> {
        AwSettingsLayoutAlgorithmTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, contentViewClient);
            
            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<Integer> {
        private static final int INITIAL_TEXT_ZOOM = 100;
        private final float mInitialActualFontSize;
        AwSettingsTextZoomTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, 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();
            
            
            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<Integer> {
        private static final int INITIAL_TEXT_ZOOM = 100;
        private final float mInitialActualFontSize;
        AwSettingsTextZoomAutosizingTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, contentViewClient);
            mAwSettings.setLayoutAlgorithm(LayoutAlgorithm.TEXT_AUTOSIZING);
            
            
            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();
            
            
            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<Boolean> {
        private static final String POPUP_ENABLED = "Popup enabled";
        private static final String POPUP_BLOCKED = "Popup blocked";
        AwSettingsJavaScriptPopupsTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, 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;
            poll(new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    String title = getTitleOnUiThread();
                    return expectPopupEnabled ? POPUP_ENABLED.equals(title) :
                            POPUP_BLOCKED.equals(title);
                }
            });
            assertEquals(value ? POPUP_ENABLED : POPUP_BLOCKED, getTitleOnUiThread());
        }
        private String getData() {
            return "<html><head>" +
                    "<script>" +
                    "    function tryOpenWindow() {" +
                    "        var newWindow = window.open(" +
                    "           'data:text/html;charset=utf-8," +
                    "           <html><head><title>" + POPUP_ENABLED + "</title></head></html>');" +
                    "        if (!newWindow) document.title = '" + POPUP_BLOCKED + "';" +
                    "    }" +
                    "</script></head>" +
                    "<body onload='tryOpenWindow()'></body></html>";
        }
    }
    class AwSettingsCacheModeTestHelper extends AwSettingsTestHelper<Integer> {
        AwSettingsCacheModeTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient,
                int index,
                TestWebServer webServer) throws Throwable {
            super(containerView, contentViewClient, true);
            mIndex = index;
            mWebServer = webServer;
        }
        @Override
        protected Integer getAlteredValue() {
            
            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;
    }
    
    
    
    
    
    class AwSettingsUseWideViewportTestHelper extends AwSettingsTestHelper<Boolean> {
        private static final String VIEWPORT_TAG_LAYOUT_WIDTH = "3000";
        AwSettingsUseWideViewportTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient) throws Throwable {
            super(containerView, 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 "<html><head>" +
                    "<meta name='viewport' content='width=" + VIEWPORT_TAG_LAYOUT_WIDTH + "' />" +
                    "</head>" +
                    "<body onload='document.title=document.body.clientWidth'></body></html>";
        }
    }
    class AwSettingsLoadWithOverviewModeTestHelper extends AwSettingsTestHelper<Boolean> {
        private static final float DEFAULT_PAGE_SCALE = 1.0f;
        AwSettingsLoadWithOverviewModeTestHelper(
                AwTestContainerView containerView,
                TestAwContentsClient contentViewClient,
                boolean withViewPortTag) throws Throwable {
            super(containerView, 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 "<html><head>" +
                    (mWithViewPortTag ? "<meta name='viewport' content='width=3000' />" : "") +
                    "</head>" +
                    "<body></body></html>";
        }
        private final boolean mWithViewPortTag;
        private boolean mExpectScaleChange;
        private int mOnScaleChangedCallCount;
    }
    
    
    
    
    
    
    @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 =
                "<html><head><title>" + JS_DISABLED_STRING + "</title>"
                + "</head><body onload=\"document.title='" + JS_ENABLED_STRING
                + "';\"></body></html>";
        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.getContainer0(), views.getClient0()),
            new AwSettingsJavaScriptTestHelper(views.getContainer1(), views.getClient1()));
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testJavaScriptEnabledDynamicWithTwoViews() throws Throwable {
        ViewPair views = createViews();
        runPerViewSettingsTest(
            new AwSettingsJavaScriptDynamicTestHelper(views.getContainer0(), views.getClient0()),
            new AwSettingsJavaScriptDynamicTestHelper(views.getContainer1(), views.getClient1()));
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testPluginsEnabledWithTwoViews() throws Throwable {
        ViewPair views = createViews();
        runPerViewSettingsTest(
            new AwSettingsPluginsTestHelper(views.getContainer0(), views.getClient0()),
            new AwSettingsPluginsTestHelper(views.getContainer1(), views.getClient1()));
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testStandardFontFamilyWithTwoViews() throws Throwable {
        ViewPair views = createViews();
        runPerViewSettingsTest(
            new AwSettingsStandardFontFamilyTestHelper(views.getContainer0(), views.getClient0()),
            new AwSettingsStandardFontFamilyTestHelper(views.getContainer1(), views.getClient1()));
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testDefaultFontSizeWithTwoViews() throws Throwable {
        ViewPair views = createViews();
        runPerViewSettingsTest(
            new AwSettingsDefaultFontSizeTestHelper(views.getContainer0(), views.getClient0()),
            new AwSettingsDefaultFontSizeTestHelper(views.getContainer1(), views.getClient1()));
    }
    
    
    
    @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);
        poll(new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                return !ImagePageGenerator.IMAGE_NOT_LOADED_STRING.equals(
                        getTitleOnUiThread(awContents));
            }
        });
        assertEquals(ImagePageGenerator.IMAGE_LOADED_STRING, getTitleOnUiThread(awContents));
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testLoadsImagesAutomaticallyWithTwoViews() throws Throwable {
        ViewPair views = createViews();
        runPerViewSettingsTest(
            new AwSettingsLoadImagesAutomaticallyTestHelper(
                views.getContainer0(), views.getClient0(), new ImagePageGenerator(0, true)),
            new AwSettingsLoadImagesAutomaticallyTestHelper(
                views.getContainer1(), views.getClient1(), new ImagePageGenerator(1, true)));
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testDefaultTextEncodingWithTwoViews() throws Throwable {
        ViewPair views = createViews();
        runPerViewSettingsTest(
            new AwSettingsDefaultTextEncodingTestHelper(views.getContainer0(), views.getClient0()),
            new AwSettingsDefaultTextEncodingTestHelper(views.getContainer1(), views.getClient1()));
    }
    
    
    
    
    
    
    @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();
        assertEquals(actualUserAgentString, AwSettings.getDefaultUserAgent());
        final String patternString =
                "Mozilla/5\\.0 \\(Linux;( U;)? Android ([^;]+);( (\\w+)-(\\w+);)?" +
                "\\s?(.*)\\sBuild/(.+)\\) AppleWebKit/(\\d+)\\.(\\d+) \\(KHTML, like Gecko\\) " +
                "Version/\\d+\\.\\d Chrome/\\d+\\.\\d+\\.\\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());
        
        assertEquals(null, patternMatcher.group(3));
        if ("REL".equals(Build.VERSION.CODENAME)) {
            
            assertEquals(Build.MODEL, patternMatcher.group(6));
            
            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();
        
        settings.setUserAgentString(null);
        assertEquals(defaultUserAgentString, settings.getUserAgentString());
        settings.setUserAgentString("");
        assertEquals(defaultUserAgentString, settings.getUserAgentString());
        
        settings.setUserAgentString(defaultUserAgentString);
        assertEquals(defaultUserAgentString, settings.getUserAgentString());
        
        final String customUserAgentString = "AwSettingsTest";
        settings.setUserAgentString(customUserAgentString);
        assertEquals(customUserAgentString, settings.getUserAgentString());
        settings.setUserAgentString(null);
        assertEquals(defaultUserAgentString, settings.getUserAgentString());
    }
    
    
    @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";
        
        
        final String pageTemplate =
                "<html><head><title>%s</title></head>" +
                "<body onload='document.title+=navigator.userAgent'></body>" +
                "</html>";
        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);
        
        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.getContainer0(), views.getClient0()),
            new AwSettingsUserAgentStringTestHelper(views.getContainer1(), 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.getContainer0(), views.getClient0()),
            new AwSettingsDomStorageEnabledTestHelper(views.getContainer1(), views.getClient1()));
    }
    
    
    
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testDatabaseInitialValue() throws Throwable {
        TestAwContentsClient client = new TestAwContentsClient();
        final AwTestContainerView testContainerView =
                createAwTestContainerViewOnMainSync(client);
        AwSettingsDatabaseTestHelper helper =
                new AwSettingsDatabaseTestHelper(testContainerView, client);
        helper.ensureSettingHasInitialValue();
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testDatabaseEnabled() throws Throwable {
        TestAwContentsClient client = new TestAwContentsClient();
        final AwTestContainerView testContainerView =
                createAwTestContainerViewOnMainSync(client);
        AwSettingsDatabaseTestHelper helper =
                new AwSettingsDatabaseTestHelper(testContainerView, client);
        helper.setAlteredSettingValue();
        helper.ensureSettingHasAlteredValue();
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testDatabaseDisabled() throws Throwable {
        TestAwContentsClient client = new TestAwContentsClient();
        final AwTestContainerView testContainerView =
                createAwTestContainerViewOnMainSync(client);
        AwSettingsDatabaseTestHelper helper =
                new AwSettingsDatabaseTestHelper(testContainerView, client);
        helper.setInitialSettingValue();
        helper.ensureSettingHasInitialValue();
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testUniversalAccessFromFilesWithTwoViews() throws Throwable {
        ViewPair views = createViews();
        runPerViewSettingsTest(
            new AwSettingsUniversalAccessFromFilesTestHelper(views.getContainer0(),
                views.getClient0()),
            new AwSettingsUniversalAccessFromFilesTestHelper(views.getContainer1(),
                views.getClient1()));
    }
    
    
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testFileAccessFromFilesImage() throws Throwable {
        final String testFile = "webview/image_access.html";
        assertFileIsReadable(UrlUtils.getTestFilePath(testFile));
        final String imageContainerUrl = UrlUtils.getTestFileUrl(testFile);
        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.getContainer0(), views.getClient0()),
            new AwSettingsFileAccessFromFilesIframeTestHelper(
                views.getContainer1(), views.getClient1()));
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testFileAccessFromFilesXhrWithTwoViews() throws Throwable {
        ViewPair views = createViews();
        runPerViewSettingsTest(
            new AwSettingsFileAccessFromFilesXhrTestHelper(views.getContainer0(),
                views.getClient0()),
            new AwSettingsFileAccessFromFilesXhrTestHelper(views.getContainer1(),
                views.getClient1()));
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testFileUrlAccessWithTwoViews() throws Throwable {
        ViewPair views = createViews();
        runPerViewSettingsTest(
            new AwSettingsFileUrlAccessTestHelper(views.getContainer0(), views.getClient0(), 0),
            new AwSettingsFileUrlAccessTestHelper(views.getContainer1(), views.getClient1(), 1));
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testContentUrlAccessWithTwoViews() throws Throwable {
        ViewPair views = createViews();
        runPerViewSettingsTest(
            new AwSettingsContentUrlAccessTestHelper(views.getContainer0(), views.getClient0(), 0),
            new AwSettingsContentUrlAccessTestHelper(views.getContainer1(), 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 = "<html><body>" +
                "<img src=\"" +
                createContentUrl(target) + "\">" +
                "</body></html>";
        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.getContainer0(), views.getClient0(), 0),
            new AwSettingsContentUrlAccessFromFileTestHelper(
                    views.getContainer1(), 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 httpImageUrl = generator.getPageUrl(webServer);
            settings.setImagesEnabled(false);
            loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), httpImageUrl);
            assertEquals(ImagePageGenerator.IMAGE_NOT_LOADED_STRING,
                    getTitleOnUiThread(awContents));
            settings.setImagesEnabled(true);
            poll(new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    return ImagePageGenerator.IMAGE_LOADED_STRING.equals(
                        getTitleOnUiThread(awContents));
                }
            });
        } finally {
            if (webServer != null) webServer.shutdown();
        }
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testBlockNetworkImagesWithTwoViews() throws Throwable {
        ViewPair views = createViews();
        TestWebServer webServer = null;
        try {
            webServer = new TestWebServer(false);
            runPerViewSettingsTest(
                    new AwSettingsImagesEnabledHelper(
                            views.getContainer0(),
                            views.getClient0(),
                            webServer,
                            new ImagePageGenerator(0, true)),
                    new AwSettingsImagesEnabledHelper(
                            views.getContainer1(),
                            views.getClient1(),
                            webServer,
                            new ImagePageGenerator(1, true)));
        } 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 {
            
            webServer = new TestWebServer(false);
            final String httpPath = "/image.png";
            final String imageUrl = webServer.setResponseBase64(
                    httpPath, generator.getImageSourceNoAdvance(),
                    CommonResources.getImagePngHeaders(true));
            
            String pageHtml = "<img src='" + imageUrl + "' " +
                      "onload=\"document.title='img_onload_fired';\" " +
                      "onerror=\"document.title='img_onerror_fired';\" />";
            Context context = getInstrumentation().getTargetContext();
            fileName = context.getCacheDir() + "/block_network_loads_test.html";
            TestFileUtil.deleteFile(fileName);  
            TestFileUtil.createNewHtmlFile(fileName, "unset", pageHtml);
            
            awSettings.setBlockNetworkLoads(true);
            loadUrlSync(
                awContents,
                contentClient.getOnPageFinishedHelper(),
                "file:///" + fileName);
            assertEquals(0, webServer.getRequestCount(httpPath));
            assertEquals("img_onerror_fired", getTitleOnUiThread(awContents));
            
            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();
        }
    }
    private static class AudioEvent {
        private CallbackHelper mCallback;
        public AudioEvent(CallbackHelper callback) {
            mCallback = callback;
        }
        @JavascriptInterface
        public void onCanPlay() {
            mCallback.notifyCalled();
        }
        @JavascriptInterface
        public void onError() {
            mCallback.notifyCalled();
        }
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testBlockNetworkLoadsWithAudio() throws Throwable {
        final TestAwContentsClient contentClient = new TestAwContentsClient();
        final AwTestContainerView testContainer =
                createAwTestContainerViewOnMainSync(contentClient);
        final AwContents awContents = testContainer.getAwContents();
        final AwSettings awSettings = getAwSettingsOnUiThread(awContents);
        CallbackHelper callback = new CallbackHelper();
        awSettings.setJavaScriptEnabled(true);
        TestWebServer webServer = null;
        try {
            webServer = new TestWebServer(false);
            final String httpPath = "/audio.mp3";
            
            
            final String audioUrl = webServer.setResponse(httpPath, "1", null);
            String pageHtml = "<html><body><audio controls src='" + audioUrl + "' " +
                    "oncanplay=\"AudioEvent.onCanPlay();\" " +
                    "onerror=\"AudioEvent.onError();\" /> </body></html>";
            
            awSettings.setBlockNetworkLoads(true);
            awContents.addPossiblyUnsafeJavascriptInterface(
                    new AudioEvent(callback), "AudioEvent", null);
            int count = callback.getCallCount();
            loadDataSync(awContents, contentClient.getOnPageFinishedHelper(), pageHtml,
                    "text/html", false);
            callback.waitForCallback(count, 1);
            assertEquals(0, webServer.getRequestCount(httpPath));
            
            
            
            
        } finally {
            if (webServer != null) webServer.shutdown();
        }
    }
    
    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testAssetUrl() throws Throwable {
        
        
        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));
    }
    
    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testResourceUrl() throws Throwable {
        
        
        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));
    }
    
    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testFileUrlAccessToggleDoesNotBlockAssetUrls() throws Throwable {
        
        
        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));
    }
    
    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testFileUrlAccessToggleDoesNotBlockResourceUrls() throws Throwable {
        
        
        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.getContainer0(), views.getClient0()),
            new AwSettingsLayoutAlgorithmTestHelper(views.getContainer1(), views.getClient1()));
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testTextZoomWithTwoViews() throws Throwable {
        ViewPair views = createViews();
        runPerViewSettingsTest(
            new AwSettingsTextZoomTestHelper(views.getContainer0(), views.getClient0()),
            new AwSettingsTextZoomTestHelper(views.getContainer1(), views.getClient1()));
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testTextZoomAutosizingWithTwoViews() throws Throwable {
        ViewPair views = createViews();
        runPerViewSettingsTest(
            new AwSettingsTextZoomAutosizingTestHelper(views.getContainer0(), views.getClient0()),
            new AwSettingsTextZoomAutosizingTestHelper(views.getContainer1(), views.getClient1()));
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testJavaScriptPopupsWithTwoViews() throws Throwable {
        ViewPair views = createViews();
        runPerViewSettingsTest(
            new AwSettingsJavaScriptPopupsTestHelper(views.getContainer0(), views.getClient0()),
            new AwSettingsJavaScriptPopupsTestHelper(views.getContainer1(), 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"})
    
    
    
    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.getContainer0(), views.getClient0(), 0, webServer),
                    new AwSettingsCacheModeTestHelper(
                            views.getContainer1(), 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, "<html manifest=\"" + manifestName + "\"></html>", 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 Exception {
            return waitUntilResourceIsRequested(mHtmlPath, initialRequestCount);
        }
        int waitUntilManifestIsRequested(final int initialRequestCount) throws Exception {
            return waitUntilResourceIsRequested(mManifestPath, initialRequestCount);
        }
        private int waitUntilResourceIsRequested(
                final String path, final int initialRequestCount) throws Exception {
            poll(new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    return mWebServer.getRequestCount(path) > initialRequestCount;
                }
            });
            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);
        
        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);
            
            
            Thread.sleep(1000);
            assertEquals(0, webServer.getRequestCount(helper.getManifestPath()));
            settings.setAppCachePath("whatever");  
            loadUrlSync(
                    awContents,
                    contentClient.getOnPageFinishedHelper(),
                    helper.getHtmlUrl());
            helper.waitUntilManifestIsRequested(0);
        } finally {
            if (webServer != null) webServer.shutdown();
        }
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences", "AppCache"})
    public void testAppCacheWithTwoViews() throws Throwable {
        
        
        
        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);
        
        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);
            
            
            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(true);
        runPerViewSettingsTest(
            new AwSettingsUseWideViewportTestHelper(views.getContainer0(), views.getClient0()),
            new AwSettingsUseWideViewportTestHelper(views.getContainer1(), views.getClient1()));
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testUseWideViewportWithTwoViewsNoQuirks() throws Throwable {
        ViewPair views = createViews();
        runPerViewSettingsTest(
            new AwSettingsUseWideViewportTestHelper(views.getContainer0(), views.getClient0()),
            new AwSettingsUseWideViewportTestHelper(views.getContainer1(), views.getClient1()));
    }
    private void useWideViewportLayoutWidthTest(
            AwTestContainerView testContainer, CallbackHelper onPageFinishedHelper)
            throws Throwable {
        final AwContents awContents = testContainer.getAwContents();
        AwSettings settings = getAwSettingsOnUiThread(awContents);
        final String pageTemplate = "<html><head>%s</head>" +
                "<body onload='document.title=document.body.clientWidth'></body></html>";
        final String pageNoViewport = String.format(pageTemplate, "");
        final String pageViewportDeviceWidth = String.format(
                pageTemplate,
                "<meta name='viewport' content='width=device-width' />");
        final String viewportTagSpecifiedWidth = "3000";
        final String pageViewportSpecifiedWidth = String.format(
                pageTemplate,
                "<meta name='viewport' content='width=" + viewportTagSpecifiedWidth + "' />");
        DeviceDisplayInfo deviceInfo = DeviceDisplayInfo.create(testContainer.getContext());
        int displayWidth = (int) (deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale());
        settings.setJavaScriptEnabled(true);
        assertFalse(settings.getUseWideViewPort());
        
        
        
        loadDataSync(awContents, onPageFinishedHelper, pageNoViewport, "text/html", false);
        int actualWidth = Integer.parseInt(getTitleOnUiThread(awContents));
        
        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);
        
        
        
        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, contentClient.getOnPageFinishedHelper());
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testUseWideViewportLayoutWidthNoQuirks() throws Throwable {
        TestAwContentsClient contentClient = new TestAwContentsClient();
        AwTestContainerView testContainerView =
                createAwTestContainerViewOnMainSync(contentClient, false);
        useWideViewportLayoutWidthTest(testContainerView, contentClient.getOnPageFinishedHelper());
    }
    @MediumTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testUseWideViewportControlsDoubleTabToZoom() throws Throwable {
        final TestAwContentsClient contentClient = new TestAwContentsClient();
        final AwTestContainerView testContainerView =
                createAwTestContainerViewOnMainSync(contentClient);
        final AwContents awContents = testContainerView.getAwContents();
        CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper();
        AwSettings settings = getAwSettingsOnUiThread(awContents);
        settings.setBuiltInZoomControls(true);
        DeviceDisplayInfo deviceInfo =
                DeviceDisplayInfo.create(testContainerView.getContext());
        int displayWidth = (int) (deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale());
        int layoutWidth = displayWidth * 2;
        final String page = "<html>" +
                "<head><meta name='viewport' content='width=" + layoutWidth + "'>" +
                "<style> body { width: " + layoutWidth + "px; }</style></head>" +
                "<body>Page Text</body></html>";
        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"})
    public void testLoadWithOverviewModeWithTwoViews() throws Throwable {
        ViewPair views = createViews();
        runPerViewSettingsTest(
                new AwSettingsLoadWithOverviewModeTestHelper(
                        views.getContainer0(), views.getClient0(), false),
                new AwSettingsLoadWithOverviewModeTestHelper(
                        views.getContainer1(), views.getClient1(), false));
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testLoadWithOverviewModeViewportTagWithTwoViews() throws Throwable {
        ViewPair views = createViews();
        runPerViewSettingsTest(
                new AwSettingsLoadWithOverviewModeTestHelper(
                        views.getContainer0(), views.getClient0(), true),
                new AwSettingsLoadWithOverviewModeTestHelper(
                        views.getContainer1(), 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);
        
        int height = screenSize.y * 2 + 1;
        int width = screenSize.x * 2 + 1;
        final String page = "<html><body>" +
                "<p style='height:" + height + "px;width:" + width + "px'>" +
                "testSetInitialScale</p></body></html>";
        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);
    }
    
    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 = "<html><head><script>" +
                "addEventListener('DOMContentLoaded', function() { " +
                "  document.getElementById('video').addEventListener('play', function() { " +
                "    javaObserver.notifyJava(); " +
                "  }, false); " +
                "}, false); " +
                "</script></head><body>" +
                "<video id='video' autoplay control src='" +
                webServer.getOnePixelOneFrameWebmURL() + "' /> </body></html>";
            loadDataAsync(awContents, data, "text/html", false);
            if (waitTime == -1) {
                observer.waitForEvent();
                return true;
            } else {
                return observer.waitForEvent(waitTime);
            }
        } finally {
            if (webServer != null && webServer.getTestWebServer() != null)
                webServer.getTestWebServer().shutdown();
        }
    }
    
    @DisabledTest
    public void testMediaPlaybackWithoutUserGesture() throws Throwable {
        assertTrue(runVideoTest(false, -1));
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testMediaPlaybackWithUserGesture() throws Throwable {
        
        assertFalse(runVideoTest(true, 5000));
    }
    @SmallTest
    @Feature({"AndroidWebView", "Preferences"})
    public void testDefaultVideoPosterURL() throws Throwable {
        final CallbackHelper videoPosterAccessedCallbackHelper = new CallbackHelper();
        final String DEFAULT_VIDEO_POSTER_URL = "http://default_video_poster/";
        TestAwContentsClient client = new TestAwContentsClient() {
            @Override
            public InterceptedRequestData shouldInterceptRequest(String url) {
                if (url.equals(DEFAULT_VIDEO_POSTER_URL)) {
                    videoPosterAccessedCallbackHelper.notifyCalled();
                }
                return null;
            }
        };
        final AwContents awContents = createAwTestContainerViewOnMainSync(client).getAwContents();
        getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                AwSettings awSettings = awContents.getSettings();
                awSettings.setDefaultVideoPosterURL(DEFAULT_VIDEO_POSTER_URL);
            }
        });
        VideoTestWebServer webServer = new VideoTestWebServer(
                getInstrumentation().getTargetContext());
        try {
            String data = "<html><head><body>" +
                "<video id='video' control src='" +
                webServer.getOnePixelOneFrameWebmURL() + "' /> </body></html>";
            loadDataAsync(awContents, data, "text/html", false);
            videoPosterAccessedCallbackHelper.waitForCallback(0, 1, 20, TimeUnit.SECONDS);
        } finally {
            if (webServer.getTestWebServer() != null)
                webServer.getTestWebServer().shutdown();
        }
    }
    static class ViewPair {
        private final AwTestContainerView mContainer0;
        private final TestAwContentsClient mClient0;
        private final AwTestContainerView mContainer1;
        private final TestAwContentsClient mClient1;
        ViewPair(AwTestContainerView container0, TestAwContentsClient client0,
                 AwTestContainerView container1, TestAwContentsClient client1) {
            this.mContainer0 = container0;
            this.mClient0 = client0;
            this.mContainer1 = container1;
            this.mClient1 = client1;
        }
        AwTestContainerView getContainer0() {
            return mContainer0;
        }
        AwContents getContents0() {
            return mContainer0.getAwContents();
        }
        TestAwContentsClient getClient0() {
            return mClient0;
        }
        AwTestContainerView getContainer1() {
            return mContainer1;
        }
        AwContents getContents1() {
            return mContainer1.getAwContents();
        }
        TestAwContentsClient getClient1() {
            return mClient1;
        }
    }
    
    private void runPerViewSettingsTest(AwSettingsTestHelper helper0,
                                        AwSettingsTestHelper helper1) throws Throwable {
        helper0.ensureSettingHasInitialValue();
        helper1.ensureSettingHasInitialValue();
        helper1.setAlteredSettingValue();
        helper0.ensureSettingHasInitialValue();
        helper1.ensureSettingHasAlteredValue();
        helper1.setInitialSettingValue();
        helper0.ensureSettingHasInitialValue();
        helper1.ensureSettingHasInitialValue();
        helper0.setAlteredSettingValue();
        helper0.ensureSettingHasAlteredValue();
        helper1.ensureSettingHasInitialValue();
        helper0.setInitialSettingValue();
        helper0.ensureSettingHasInitialValue();
        helper1.ensureSettingHasInitialValue();
        helper0.setAlteredSettingValue();
        helper0.ensureSettingHasAlteredValue();
        helper1.ensureSettingHasInitialValue();
        helper1.setAlteredSettingValue();
        helper0.ensureSettingHasAlteredValue();
        helper1.ensureSettingHasAlteredValue();
        helper0.setInitialSettingValue();
        helper0.ensureSettingHasInitialValue();
        helper1.ensureSettingHasAlteredValue();
        helper1.setInitialSettingValue();
        helper0.ensureSettingHasInitialValue();
        helper1.ensureSettingHasInitialValue();
    }
    private ViewPair createViews() throws Throwable {
        return createViews(false);
    }
    private ViewPair createViews(boolean supportsLegacyQuirks) throws Throwable {
        TestAwContentsClient client0 = new TestAwContentsClient();
        TestAwContentsClient client1 = new TestAwContentsClient();
        return new ViewPair(
            createAwTestContainerViewOnMainSync(client0, supportsLegacyQuirks),
            client0,
            createAwTestContainerViewOnMainSync(client1, supportsLegacyQuirks),
            client1);
    }
    static void assertFileIsReadable(String filePath) {
        File file = new File(filePath);
        try {
            assertTrue("Test file \"" + filePath + "\" is not readable." +
                    "Please make sure that files from android_webview/test/data/device_files/ " +
                    "has been pushed to the device before testing",
                    file.canRead());
        } catch (SecurityException e) {
            fail("Got a SecurityException for \"" + filePath + "\": " + e.toString());
        }
    }
    
    private void ensureResourceRequestCountInContentProvider(String resource, int expectedCount) {
        Context context = getInstrumentation().getTargetContext();
        int actualCount = TestContentProvider.getResourceRequestCount(context, resource);
        assertEquals(expectedCount, actualCount);
    }
    private void resetResourceRequestCountInContentProvider(String resource) {
        Context context = getInstrumentation().getTargetContext();
        TestContentProvider.resetResourceRequestCount(context, resource);
    }
    private String createContentUrl(final String target) {
        return TestContentProvider.createContentUrl(target);
    }
    private void simulateDoubleTapCenterOfWebViewOnUiThread(final AwTestContainerView webView)
            throws Throwable {
        final int x = (webView.getRight() - webView.getLeft()) / 2;
        final int y = (webView.getBottom() - webView.getTop()) / 2;
        final AwContents awContents = webView.getAwContents();
        runTestOnUiThread(new Runnable() {
            @Override
            public void run() {
                awContents.getContentViewCore().sendDoubleTapForTest(
                        SystemClock.uptimeMillis(), x, y);
            }
        });
    }
}