/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.webkit.cts;

import android.content.Context;
import android.cts.util.NullWebViewUtils;
import android.cts.util.PollingCheck;
import android.graphics.Bitmap;
import android.net.http.SslError;
import android.os.Build;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
import android.webkit.ConsoleMessage;
import android.webkit.SslErrorHandler;
import android.webkit.WebIconDatabase;
import android.webkit.WebSettings;
import android.webkit.WebSettings.TextSize;
import android.webkit.WebStorage;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.cts.WebViewOnUiThread.WaitForLoadedClient;
import android.webkit.cts.WebViewOnUiThread.WaitForProgressClient;
import java.io.FileOutputStream;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Tests for {@link android.webkit.WebSettings}
 */
public class WebSettingsTest extends ActivityInstrumentationTestCase2<WebViewCtsActivity> {

    private static final int WEBVIEW_TIMEOUT = 5000;
    private static final String LOG_TAG = "WebSettingsTest";

    private final String EMPTY_IMAGE_HEIGHT = "0";
    private final String NETWORK_IMAGE_HEIGHT = "48";  // See getNetworkImageHtml()
    private final String DATA_URL_IMAGE_HTML = "<html>" +
            "<head><script>function updateTitle(){" +
            "document.title=document.getElementById('img').naturalHeight;}</script></head>" +
            "<body onload='updateTitle()'>" +
            "<img id='img' onload='updateTitle()' src='data:image/png;base64,iVBORw0KGgoAAA" +
            "ANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAAAXNSR0IArs4c6QAAAA1JREFUCB0BAgD9/wAAAAIAAc3j" +
            "0SsAAAAASUVORK5CYII=" +
            "'></body></html>";
    private final String DATA_URL_IMAGE_HEIGHT = "1";

    private WebSettings mSettings;
    private CtsTestServer mWebServer;
    private WebViewOnUiThread mOnUiThread;
    private Context mContext;

    public WebSettingsTest() {
        super("com.android.cts.webkit", WebViewCtsActivity.class);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        WebView webview = getActivity().getWebView();
        if (webview != null) {
            mOnUiThread = new WebViewOnUiThread(this, webview);
            mSettings = mOnUiThread.getSettings();
        }
        mContext = getInstrumentation().getTargetContext();
    }

    @Override
    protected void tearDown() throws Exception {
        if (mWebServer != null) {
            mWebServer.shutdown();
        }
        if (mOnUiThread != null) {
            mOnUiThread.cleanUp();
        }
        super.tearDown();
    }

    /**
     * Verifies that the default user agent string follows the format defined in Android
     * compatibility definition (tokens in angle brackets are variables, tokens in square
     * brackets are optional):
     * <p/>
     * Mozilla/5.0 (Linux;[ U;] Android <version>;[ <language>-<country>;]
     * [<devicemodel>;] Build/<buildID>; wv) AppleWebKit/<major>.<minor> (KHTML, like Gecko)
     * Version/<major>.<minor> Chrome/<major>.<minor>.<branch>.<build>[ Mobile]
     * Safari/<major>.<minor>
     */
    public void testUserAgentString_default() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        final String actualUserAgentString = mSettings.getUserAgentString();
        Log.i(LOG_TAG, String.format("Checking user agent string %s", actualUserAgentString));
        final String patternString =
                "Mozilla/5\\.0 \\(Linux;( U;)? Android ([^;]+);( (\\w+)-(\\w+);)?" +
                "\\s?(.*)\\sBuild/(.+); wv\\) AppleWebKit/(\\d+)\\.(\\d+) " +
                "\\(KHTML, like Gecko\\) " +
                "Version/\\d+\\.\\d+ Chrome/\\d+\\.\\d+\\.\\d+\\.\\d+( Mobile)? " +
                "Safari/(\\d+)\\.(\\d+)";
        // Groups used:
        //  1 - SSL encryption strength token " U;" (optional)
        //  2 - Android version
        //  3 - full locale string (optional)
        //  4   - country
        //  5   - language
        //  6 - device model (optional)
        //  7 - build ID
        //  8 - AppleWebKit major version number
        //  9 - AppleWebKit minor version number
        // 10 - " Mobile" string (optional)
        // 11 - Safari major version number
        // 12 - Safari minor version number
        Log.i(LOG_TAG, String.format("Trying to match pattern %s", patternString));
        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());
        if (patternMatcher.group(3) != null) {
            Locale currentLocale = Locale.getDefault();
            assertEquals(currentLocale.getLanguage().toLowerCase(), patternMatcher.group(4));
            assertEquals(currentLocale.getCountry().toLowerCase(), patternMatcher.group(5));
        }
        if ("REL".equals(Build.VERSION.CODENAME)) {
            // Model is only added in release builds
            assertEquals(Build.MODEL, patternMatcher.group(6));
            // Release version is valid only in release builds
            assertEquals(Build.VERSION.RELEASE, patternMatcher.group(2));
        }
        assertEquals(Build.ID, patternMatcher.group(7));
    }

    public void testAccessUserAgentString() throws Exception {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        startWebServer();
        String url = mWebServer.getUserAgentUrl();

        String defaultUserAgent = mSettings.getUserAgentString();
        assertNotNull(defaultUserAgent);
        mOnUiThread.loadUrlAndWaitForCompletion(url);
        assertEquals(defaultUserAgent, mOnUiThread.getTitle());

        // attempting to set a null string has no effect
        mSettings.setUserAgentString(null);
        assertEquals(defaultUserAgent, mSettings.getUserAgentString());
        mOnUiThread.loadUrlAndWaitForCompletion(url);
        assertEquals(defaultUserAgent, mOnUiThread.getTitle());

        // attempting to set an empty string has no effect
        mSettings.setUserAgentString("");
        assertEquals(defaultUserAgent, mSettings.getUserAgentString());
        mOnUiThread.loadUrlAndWaitForCompletion(url);
        assertEquals(defaultUserAgent, mOnUiThread.getTitle());

        String customUserAgent = "Cts/test";
        mSettings.setUserAgentString(customUserAgent);
        assertEquals(customUserAgent, mSettings.getUserAgentString());
        mOnUiThread.loadUrlAndWaitForCompletion(url);
        assertEquals(customUserAgent, mOnUiThread.getTitle());
    }

    public void testAccessAllowFileAccess() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        // This test is not compatible with 4.0.3
        if ("4.0.3".equals(Build.VERSION.RELEASE)) {
            return;
        }

        assertTrue(mSettings.getAllowFileAccess());

        String fileUrl = TestHtmlConstants.getFileUrl(TestHtmlConstants.HELLO_WORLD_URL);
        mOnUiThread.loadUrlAndWaitForCompletion(fileUrl);
        assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle());

        fileUrl = TestHtmlConstants.getFileUrl(TestHtmlConstants.BR_TAG_URL);
        mSettings.setAllowFileAccess(false);
        assertFalse(mSettings.getAllowFileAccess());
        mOnUiThread.loadUrlAndWaitForCompletion(fileUrl);
        // android_asset URLs should still be loaded when even with file access
        // disabled.
        assertEquals(TestHtmlConstants.BR_TAG_TITLE, mOnUiThread.getTitle());

        // Files on the file system should not be loaded.
        mOnUiThread.loadUrlAndWaitForCompletion(TestHtmlConstants.LOCAL_FILESYSTEM_URL);
        assertEquals(TestHtmlConstants.WEBPAGE_NOT_AVAILABLE_TITLE, mOnUiThread.getTitle());
    }

    public void testAccessCacheMode() throws Throwable {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        runTestOnUiThread(new Runnable() {
            @Override
            public void run() {
                // getInstance must run on the UI thread
                WebIconDatabase iconDb = WebIconDatabase.getInstance();
                String dbPath = getActivity().getFilesDir().toString() + "/icons";
                iconDb.open(dbPath);
            }
        });
        getInstrumentation().waitForIdleSync();
        Thread.sleep(100); // Wait for open to be received on the icon db thread.
        assertEquals(WebSettings.LOAD_DEFAULT, mSettings.getCacheMode());

        mSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
        assertEquals(WebSettings.LOAD_CACHE_ELSE_NETWORK, mSettings.getCacheMode());
        final IconListenerClient iconListener = new IconListenerClient();
        mOnUiThread.setWebChromeClient(iconListener);
        loadAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
        new PollingCheck(WEBVIEW_TIMEOUT) {
            @Override
            protected boolean check() {
                return iconListener.mReceivedIcon;
            }
        }.run();
        int firstFetch = mWebServer.getRequestCount();
        iconListener.mReceivedIcon = false;
        loadAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
        new PollingCheck(WEBVIEW_TIMEOUT) {
            @Override
            protected boolean check() {
                return iconListener.mReceivedIcon;
            }
        }.run();
        assertEquals(firstFetch, mWebServer.getRequestCount());

        mSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
        assertEquals(WebSettings.LOAD_NO_CACHE, mSettings.getCacheMode());
        iconListener.mReceivedIcon = false;
        loadAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
        new PollingCheck(WEBVIEW_TIMEOUT) {
            @Override
            protected boolean check() {
                return iconListener.mReceivedIcon;
            }
        }.run();
        int secondFetch = mWebServer.getRequestCount();
        iconListener.mReceivedIcon = false;
        loadAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
        new PollingCheck(WEBVIEW_TIMEOUT) {
            @Override
            protected boolean check() {
                return iconListener.mReceivedIcon;
            }
        }.run();
        int thirdFetch = mWebServer.getRequestCount();
        assertTrue(firstFetch < secondFetch);
        assertTrue(secondFetch < thirdFetch);

        mSettings.setCacheMode(WebSettings.LOAD_CACHE_ONLY);
        assertEquals(WebSettings.LOAD_CACHE_ONLY, mSettings.getCacheMode());
        iconListener.mReceivedIcon = false;
        loadAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
        new PollingCheck(WEBVIEW_TIMEOUT) {
            @Override
            protected boolean check() {
                return iconListener.mReceivedIcon;
            }
        }.run();
        assertEquals(thirdFetch, mWebServer.getRequestCount());
    }

    public void testAccessCursiveFontFamily() throws Exception {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertNotNull(mSettings.getCursiveFontFamily());

        String newCusiveFamily = "Apple Chancery";
        mSettings.setCursiveFontFamily(newCusiveFamily);
        assertEquals(newCusiveFamily, mSettings.getCursiveFontFamily());
    }

    public void testAccessFantasyFontFamily() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertNotNull(mSettings.getFantasyFontFamily());

        String newFantasyFamily = "Papyrus";
        mSettings.setFantasyFontFamily(newFantasyFamily);
        assertEquals(newFantasyFamily, mSettings.getFantasyFontFamily());
    }

    public void testAccessFixedFontFamily() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertNotNull(mSettings.getFixedFontFamily());

        String newFixedFamily = "Courier";
        mSettings.setFixedFontFamily(newFixedFamily);
        assertEquals(newFixedFamily, mSettings.getFixedFontFamily());
    }

    public void testAccessSansSerifFontFamily() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertNotNull(mSettings.getSansSerifFontFamily());

        String newFixedFamily = "Verdana";
        mSettings.setSansSerifFontFamily(newFixedFamily);
        assertEquals(newFixedFamily, mSettings.getSansSerifFontFamily());
    }

    public void testAccessSerifFontFamily() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertNotNull(mSettings.getSerifFontFamily());

        String newSerifFamily = "Times";
        mSettings.setSerifFontFamily(newSerifFamily);
        assertEquals(newSerifFamily, mSettings.getSerifFontFamily());
    }

    public void testAccessStandardFontFamily() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertNotNull(mSettings.getStandardFontFamily());

        String newStandardFamily = "Times";
        mSettings.setStandardFontFamily(newStandardFamily);
        assertEquals(newStandardFamily, mSettings.getStandardFontFamily());
    }

    public void testAccessDefaultFontSize() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        int defaultSize = mSettings.getDefaultFontSize();
        assertTrue(defaultSize > 0);

        mSettings.setDefaultFontSize(1000);
        int maxSize = mSettings.getDefaultFontSize();
        // cannot check exact size set, since the implementation caps it at an arbitrary limit
        assertTrue(maxSize > defaultSize);

        mSettings.setDefaultFontSize(-10);
        int minSize = mSettings.getDefaultFontSize();
        assertTrue(minSize > 0);
        assertTrue(minSize < maxSize);

        mSettings.setDefaultFontSize(10);
        assertEquals(10, mSettings.getDefaultFontSize());
    }

    public void testAccessDefaultFixedFontSize() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        int defaultSize = mSettings.getDefaultFixedFontSize();
        assertTrue(defaultSize > 0);

        mSettings.setDefaultFixedFontSize(1000);
        int maxSize = mSettings.getDefaultFixedFontSize();
        // cannot check exact size, since the implementation caps it at an arbitrary limit
        assertTrue(maxSize > defaultSize);

        mSettings.setDefaultFixedFontSize(-10);
        int minSize = mSettings.getDefaultFixedFontSize();
        assertTrue(minSize > 0);
        assertTrue(minSize < maxSize);

        mSettings.setDefaultFixedFontSize(10);
        assertEquals(10, mSettings.getDefaultFixedFontSize());
    }

    public void testAccessDefaultTextEncodingName() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertNotNull(mSettings.getDefaultTextEncodingName());

        String newEncodingName = "iso-8859-1";
        mSettings.setDefaultTextEncodingName(newEncodingName);
        assertEquals(newEncodingName, mSettings.getDefaultTextEncodingName());
    }

    public void testAccessJavaScriptCanOpenWindowsAutomatically() throws Exception {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        mSettings.setJavaScriptEnabled(true);

        mSettings.setJavaScriptCanOpenWindowsAutomatically(false);
        assertFalse(mSettings.getJavaScriptCanOpenWindowsAutomatically());
        loadAssetUrl(TestHtmlConstants.POPUP_URL);
        new PollingCheck(WEBVIEW_TIMEOUT) {
            @Override
            protected boolean check() {
                return "Popup blocked".equals(mOnUiThread.getTitle());
            }
        }.run();

        mSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        assertTrue(mSettings.getJavaScriptCanOpenWindowsAutomatically());
        loadAssetUrl(TestHtmlConstants.POPUP_URL);
        new PollingCheck(WEBVIEW_TIMEOUT) {
            @Override
            protected boolean check() {
                return "Popup allowed".equals(mOnUiThread.getTitle());
            }
        }.run();
    }

    public void testAccessJavaScriptEnabled() throws Exception {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        mSettings.setJavaScriptEnabled(true);
        assertTrue(mSettings.getJavaScriptEnabled());
        loadAssetUrl(TestHtmlConstants.JAVASCRIPT_URL);
        new PollingCheck(WEBVIEW_TIMEOUT) {
            @Override
            protected boolean check() {
                return "javascript on".equals(mOnUiThread.getTitle());
            }
        }.run();

        mSettings.setJavaScriptEnabled(false);
        assertFalse(mSettings.getJavaScriptEnabled());
        loadAssetUrl(TestHtmlConstants.JAVASCRIPT_URL);
        new PollingCheck(WEBVIEW_TIMEOUT) {
            @Override
            protected boolean check() {
                return "javascript off".equals(mOnUiThread.getTitle());
            }
        }.run();

    }

    public void testAccessLayoutAlgorithm() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertEquals(WebSettings.LayoutAlgorithm.NARROW_COLUMNS, mSettings.getLayoutAlgorithm());

        mSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
        assertEquals(WebSettings.LayoutAlgorithm.NORMAL, mSettings.getLayoutAlgorithm());

        mSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
        assertEquals(WebSettings.LayoutAlgorithm.SINGLE_COLUMN, mSettings.getLayoutAlgorithm());
    }

    public void testAccessMinimumFontSize() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertEquals(8, mSettings.getMinimumFontSize());

        mSettings.setMinimumFontSize(100);
        assertEquals(72, mSettings.getMinimumFontSize());

        mSettings.setMinimumFontSize(-10);
        assertEquals(1, mSettings.getMinimumFontSize());

        mSettings.setMinimumFontSize(10);
        assertEquals(10, mSettings.getMinimumFontSize());
    }

    public void testAccessMinimumLogicalFontSize() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertEquals(8, mSettings.getMinimumLogicalFontSize());

        mSettings.setMinimumLogicalFontSize(100);
        assertEquals(72, mSettings.getMinimumLogicalFontSize());

        mSettings.setMinimumLogicalFontSize(-10);
        assertEquals(1, mSettings.getMinimumLogicalFontSize());

        mSettings.setMinimumLogicalFontSize(10);
        assertEquals(10, mSettings.getMinimumLogicalFontSize());
    }

    public void testAccessPluginsEnabled() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertFalse(mSettings.getPluginsEnabled());

        mSettings.setPluginsEnabled(true);
        assertTrue(mSettings.getPluginsEnabled());
    }

    public void testOffscreenPreRaster() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertFalse(mSettings.getOffscreenPreRaster());

        mSettings.setOffscreenPreRaster(true);
        assertTrue(mSettings.getOffscreenPreRaster());
    }

    public void testAccessPluginsPath() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertNotNull(mSettings.getPluginsPath());

        String pluginPath = "pluginPath";
        mSettings.setPluginsPath(pluginPath);
        // plugin path always empty
        assertEquals("", mSettings.getPluginsPath());
    }

    public void testAccessSaveFormData() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertTrue(mSettings.getSaveFormData());

        mSettings.setSaveFormData(false);
        assertFalse(mSettings.getSaveFormData());
    }

    public void testAccessTextSize() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertEquals(TextSize.NORMAL, mSettings.getTextSize());

        mSettings.setTextSize(TextSize.LARGER);
        assertEquals(TextSize.LARGER, mSettings.getTextSize());

        mSettings.setTextSize(TextSize.LARGEST);
        assertEquals(TextSize.LARGEST, mSettings.getTextSize());

        mSettings.setTextSize(TextSize.SMALLER);
        assertEquals(TextSize.SMALLER, mSettings.getTextSize());

        mSettings.setTextSize(TextSize.SMALLEST);
        assertEquals(TextSize.SMALLEST, mSettings.getTextSize());
    }

    public void testAccessUseDoubleTree() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertFalse(mSettings.getUseDoubleTree());

        mSettings.setUseDoubleTree(true);
        // setUseDoubleTree is a no-op
        assertFalse(mSettings.getUseDoubleTree());
    }

    public void testAccessUseWideViewPort() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertFalse(mSettings.getUseWideViewPort());

        mSettings.setUseWideViewPort(true);
        assertTrue(mSettings.getUseWideViewPort());
    }

    public void testSetNeedInitialFocus() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        mSettings.setNeedInitialFocus(false);

        mSettings.setNeedInitialFocus(true);
    }

    public void testSetRenderPriority() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        mSettings.setRenderPriority(WebSettings.RenderPriority.HIGH);

        mSettings.setRenderPriority(WebSettings.RenderPriority.LOW);

        mSettings.setRenderPriority(WebSettings.RenderPriority.NORMAL);
    }

    public void testAccessSupportMultipleWindows() {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertFalse(mSettings.supportMultipleWindows());

        mSettings.setSupportMultipleWindows(true);
        assertTrue(mSettings.supportMultipleWindows());
    }

    public void testAccessSupportZoom() throws Throwable {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertTrue(mSettings.supportZoom());

        runTestOnUiThread(new Runnable() {
            @Override
            public void run() {
                mSettings.setSupportZoom(false);
            }
        });
        assertFalse(mSettings.supportZoom());
    }

    public void testAccessBuiltInZoomControls() throws Throwable {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertFalse(mSettings.getBuiltInZoomControls());

        runTestOnUiThread(new Runnable() {
            @Override
            public void run() {
                mSettings.setBuiltInZoomControls(true);
            }
        });
        assertTrue(mSettings.getBuiltInZoomControls());
    }

    public void testAppCacheDisabled() throws Throwable {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        // Test that when AppCache is disabled, we don't get any AppCache
        // callbacks.
        startWebServer();
        final String url = mWebServer.getAppCacheUrl();
        mSettings.setJavaScriptEnabled(true);

        mOnUiThread.loadUrlAndWaitForCompletion(url);
        new PollingCheck(WEBVIEW_TIMEOUT) {
            protected boolean check() {
                return "Loaded".equals(mOnUiThread.getTitle());
            }
        }.run();
        // The page is now loaded. Wait for a further 1s to check no AppCache
        // callbacks occur.
        Thread.sleep(1000);
        assertEquals("Loaded", mOnUiThread.getTitle());
    }

    public void testAppCacheEnabled() throws Throwable {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        // Note that the AppCache path can only be set once. This limits the
        // amount of testing we can do, and means that we must test all aspects
        // of setting the AppCache path in a single test to guarantee ordering.

        // Test that when AppCache is enabled but no valid path is provided,
        // we don't get any AppCache callbacks.
        startWebServer();
        final String url = mWebServer.getAppCacheUrl();
        mSettings.setAppCacheEnabled(true);
        mSettings.setJavaScriptEnabled(true);

        mOnUiThread.loadUrlAndWaitForCompletion(url);
        new PollingCheck(WEBVIEW_TIMEOUT) {
            @Override
            protected boolean check() {
                return "Loaded".equals(mOnUiThread.getTitle());
            }
        }.run();
        // The page is now loaded. Wait for a further 1s to check no AppCache
        // callbacks occur.
        Thread.sleep(1000);
        assertEquals("Loaded", mOnUiThread.getTitle());

        // Test that when AppCache is enabled and a valid path is provided, we
        // get an AppCache callback of some kind.
        mSettings.setAppCachePath(getActivity().getDir("appcache", 0).getPath());
        mOnUiThread.loadUrlAndWaitForCompletion(url);
        new PollingCheck(WEBVIEW_TIMEOUT) {
            @Override
            protected boolean check() {
                return mOnUiThread.getTitle() != null
                        && mOnUiThread.getTitle().endsWith("Callback");
            }
        }.run();
    }

    // Ideally, we need a test case for the enabled case. However, it seems that
    // enabling the database should happen prior to navigating the first url due to
    // some internal limitations of webview. For this reason, we only provide a
    // test case for "disabled" behavior.
    // Also loading as data rather than using URL should work, but it causes a
    // security exception in JS, most likely due to cross domain access. So we load
    // using a URL. Finally, it looks like enabling database requires creating a
    // webChromeClient and listening to Quota callbacks, which is not documented.
    public void testDatabaseDisabled() throws Throwable {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        // Verify that websql database does not work when disabled.
        startWebServer();

        mOnUiThread.setWebChromeClient(new ChromeClient(mOnUiThread) {
            @Override
            public void onExceededDatabaseQuota(String url, String databaseId, long quota,
                long estimatedSize, long total, WebStorage.QuotaUpdater updater) {
                updater.updateQuota(estimatedSize);
            }
        });
        mSettings.setJavaScriptEnabled(true);
        mSettings.setDatabaseEnabled(false);
        final String url = mWebServer.getAssetUrl(TestHtmlConstants.DATABASE_ACCESS_URL);
        mOnUiThread.loadUrlAndWaitForCompletion(url);
        assertEquals("No database", mOnUiThread.getTitle());
    }

    public void testLoadsImagesAutomatically() throws Throwable {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertTrue(mSettings.getLoadsImagesAutomatically());

        startWebServer();
        mSettings.setJavaScriptEnabled(true);

        // Check that by default network and data url images are loaded.
        mOnUiThread.loadDataAndWaitForCompletion(getNetworkImageHtml(), "text/html", null);
        assertEquals(NETWORK_IMAGE_HEIGHT, mOnUiThread.getTitle());
        mOnUiThread.loadDataAndWaitForCompletion(DATA_URL_IMAGE_HTML, "text/html", null);
        assertEquals(DATA_URL_IMAGE_HEIGHT, mOnUiThread.getTitle());

        // Check that with auto-loading turned off no images are loaded.
        // Also check that images are loaded automatically once we enable the setting,
        // without reloading the page.
        mSettings.setLoadsImagesAutomatically(false);
        mOnUiThread.clearCache(true);
        mOnUiThread.loadDataAndWaitForCompletion(getNetworkImageHtml(), "text/html", null);
        assertEquals(EMPTY_IMAGE_HEIGHT, mOnUiThread.getTitle());
        mSettings.setLoadsImagesAutomatically(true);
        waitForNonEmptyImage();
        assertEquals(NETWORK_IMAGE_HEIGHT, mOnUiThread.getTitle());

        mSettings.setLoadsImagesAutomatically(false);
        mOnUiThread.clearCache(true);
        mOnUiThread.loadDataAndWaitForCompletion(DATA_URL_IMAGE_HTML, "text/html", null);
        assertEquals(EMPTY_IMAGE_HEIGHT, mOnUiThread.getTitle());
        mSettings.setLoadsImagesAutomatically(true);
        waitForNonEmptyImage();
        assertEquals(DATA_URL_IMAGE_HEIGHT, mOnUiThread.getTitle());
    }

    public void testBlockNetworkImage() throws Throwable {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertFalse(mSettings.getBlockNetworkImage());

        startWebServer();
        mSettings.setJavaScriptEnabled(true);

        // Check that by default network and data url images are loaded.
        mOnUiThread.loadDataAndWaitForCompletion(getNetworkImageHtml(), "text/html", null);
        assertEquals(NETWORK_IMAGE_HEIGHT, mOnUiThread.getTitle());
        mOnUiThread.loadDataAndWaitForCompletion(DATA_URL_IMAGE_HTML, "text/html", null);
        assertEquals(DATA_URL_IMAGE_HEIGHT, mOnUiThread.getTitle());

        // Check that only network images are blocked, data url images are still loaded.
        // Also check that network images are loaded automatically once we disable the setting,
        // without reloading the page.
        mSettings.setBlockNetworkImage(true);
        mOnUiThread.clearCache(true);
        mOnUiThread.loadDataAndWaitForCompletion(getNetworkImageHtml(), "text/html", null);
        assertEquals(EMPTY_IMAGE_HEIGHT, mOnUiThread.getTitle());
        mSettings.setBlockNetworkImage(false);
        waitForNonEmptyImage();
        assertEquals(NETWORK_IMAGE_HEIGHT, mOnUiThread.getTitle());

        mSettings.setBlockNetworkImage(true);
        mOnUiThread.clearCache(true);
        mOnUiThread.loadDataAndWaitForCompletion(DATA_URL_IMAGE_HTML, "text/html", null);
        assertEquals(DATA_URL_IMAGE_HEIGHT, mOnUiThread.getTitle());
    }

    public void testBlockNetworkLoads() throws Throwable {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        assertFalse(mSettings.getBlockNetworkLoads());

        startWebServer();
        mSettings.setJavaScriptEnabled(true);

        // Check that by default network resources and data url images are loaded.
        mOnUiThread.loadUrlAndWaitForCompletion(
            mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL));
        assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle());
        mOnUiThread.loadDataAndWaitForCompletion(getNetworkImageHtml(), "text/html", null);
        assertEquals(NETWORK_IMAGE_HEIGHT, mOnUiThread.getTitle());
        mOnUiThread.loadDataAndWaitForCompletion(DATA_URL_IMAGE_HTML, "text/html", null);
        assertEquals(DATA_URL_IMAGE_HEIGHT, mOnUiThread.getTitle());

        // Check that only network resources are blocked, data url images are still loaded.
        mSettings.setBlockNetworkLoads(true);
        mOnUiThread.clearCache(true);
        mOnUiThread.loadUrlAndWaitForCompletion(
            mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL));
        assertFalse(TestHtmlConstants.HELLO_WORLD_TITLE.equals(mOnUiThread.getTitle()));
        mOnUiThread.loadDataAndWaitForCompletion(getNetworkImageHtml(), "text/html", null);
        assertEquals(EMPTY_IMAGE_HEIGHT, mOnUiThread.getTitle());
        mOnUiThread.loadDataAndWaitForCompletion(DATA_URL_IMAGE_HTML, "text/html", null);
        assertEquals(DATA_URL_IMAGE_HEIGHT, mOnUiThread.getTitle());

        // Check that network resources are loaded once we disable the setting and reload the page.
        mSettings.setBlockNetworkLoads(false);
        mOnUiThread.loadUrlAndWaitForCompletion(
            mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL));
        assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle());
        mOnUiThread.loadDataAndWaitForCompletion(getNetworkImageHtml(), "text/html", null);
        assertEquals(NETWORK_IMAGE_HEIGHT, mOnUiThread.getTitle());
    }

    // Verify that an image in local file system can be loaded by an asset
    public void testLocalImageLoads() throws Throwable {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }

        mSettings.setJavaScriptEnabled(true);
        // Check that local images are loaded without issues regardless of domain checkings
        mSettings.setAllowUniversalAccessFromFileURLs(false);
        mSettings.setAllowFileAccessFromFileURLs(false);
        String url = TestHtmlConstants.getFileUrl(TestHtmlConstants.IMAGE_ACCESS_URL);
        mOnUiThread.loadUrlAndWaitForCompletion(url);
        waitForNonEmptyImage();
        assertEquals(NETWORK_IMAGE_HEIGHT, mOnUiThread.getTitle());
    }

    // Verify that javascript cross-domain request permissions matches file domain settings
    // for iframes
    public void testIframesWhenAccessFromFileURLsEnabled() throws Throwable {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }

        mSettings.setJavaScriptEnabled(true);
        // disable universal access from files
        mSettings.setAllowUniversalAccessFromFileURLs(false);
        mSettings.setAllowFileAccessFromFileURLs(true);

        // when cross file scripting is enabled, make sure cross domain requests succeed
        String url = TestHtmlConstants.getFileUrl(TestHtmlConstants.IFRAME_ACCESS_URL);
        mOnUiThread.loadUrlAndWaitForCompletion(url);
        String iframeUrl = TestHtmlConstants.getFileUrl(TestHtmlConstants.HELLO_WORLD_URL);
        assertEquals(iframeUrl, mOnUiThread.getTitle());
    }

    // Verify that javascript cross-domain request permissions matches file domain settings
    // for iframes
    public void testIframesWhenAccessFromFileURLsDisabled() throws Throwable {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }

        mSettings.setJavaScriptEnabled(true);
        // disable universal access from files
        mSettings.setAllowUniversalAccessFromFileURLs(false);
        mSettings.setAllowFileAccessFromFileURLs(false);

        // when cross file scripting is disabled, make sure cross domain requests fail
        final ChromeClient webChromeClient = new ChromeClient(mOnUiThread);
        mOnUiThread.setWebChromeClient(webChromeClient);
        String url = TestHtmlConstants.getFileUrl(TestHtmlConstants.IFRAME_ACCESS_URL);
        mOnUiThread.loadUrlAndWaitForCompletion(url);
        String iframeUrl = TestHtmlConstants.getFileUrl(TestHtmlConstants.HELLO_WORLD_URL);
        assertFalse(iframeUrl.equals(mOnUiThread.getTitle()));
        assertEquals(ConsoleMessage.MessageLevel.ERROR, webChromeClient.getMessageLevel(10000));
    }

    // Verify that enabling file access from file URLs enable XmlHttpRequest (XHR) across files
    public void testXHRWhenAccessFromFileURLsEnabled() throws Throwable {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        verifyFileXHR(true);
    }

    // Verify that disabling file access from file URLs disable XmlHttpRequest (XHR) accross files
    public void testXHRWhenAccessFromFileURLsDisabled() throws Throwable {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }

        final ChromeClient webChromeClient = new ChromeClient(mOnUiThread);
        mOnUiThread.setWebChromeClient(webChromeClient);
        verifyFileXHR(false);
        assertEquals(ConsoleMessage.MessageLevel.ERROR, webChromeClient.getMessageLevel(10000));
    }

    // verify XHR across files matches the allowFileAccessFromFileURLs setting
    private void verifyFileXHR(boolean enableXHR) throws Throwable {
        // target file content
        String target ="<html><body>target</body><html>";

        String targetPath = mContext.getFileStreamPath("target.html").getAbsolutePath();
        // local file content that use XHR to read the target file
        String local ="" +
            "<html><body><script>" +
            "var client = new XMLHttpRequest();" +
            "client.open('GET', 'file://" + targetPath + "',false);" +
            "client.send();" +
            "document.title = client.responseText;" +
            "</script></body></html>";

        // create files in internal storage
        writeFile("local.html", local);
        writeFile("target.html", target);

        mSettings.setJavaScriptEnabled(true);
        // disable universal access from files
        mSettings.setAllowUniversalAccessFromFileURLs(false);
        mSettings.setAllowFileAccessFromFileURLs(enableXHR);
        String localPath = mContext.getFileStreamPath("local.html").getAbsolutePath();
        // when cross file scripting is enabled, make sure cross domain requests succeed
        mOnUiThread.loadUrlAndWaitForCompletion("file://" + localPath);
        if (enableXHR) assertEquals(target, mOnUiThread.getTitle());
        else assertFalse(target.equals(mOnUiThread.getTitle()));
    }

    // Create a private file on internal storage from the given string
    private void writeFile(String filename, String content) throws Exception {

        FileOutputStream fos = mContext.openFileOutput(filename, Context.MODE_PRIVATE);
        fos.write(content.getBytes());
        fos.close();
    }

    public void testAllowMixedMode() throws Throwable {
        if (!NullWebViewUtils.isWebViewAvailable()) {
            return;
        }
        final class SslWebViewClient extends WaitForLoadedClient {
            public SslWebViewClient() {
                super(mOnUiThread);
            }
            @Override
            public void onReceivedSslError(WebView view,
                    SslErrorHandler handler, SslError error) {
                handler.proceed();
            }
        }

        mSettings.setJavaScriptEnabled(true);
        TestWebServer httpsServer = null;
        TestWebServer httpServer = null;
        try {
            httpsServer = new TestWebServer(true);
            httpServer = new TestWebServer(false);
            final String JS_URL = "/insecure.js";
            final String IMG_URL = "/insecure.png";
            final String SECURE_URL = "/secure.html";
            final String JS_HTML = "<script src=\"" + httpServer.getResponseUrl(JS_URL) +
                "\"></script>";
            final String IMG_HTML = "<img src=\"" + httpServer.getResponseUrl(IMG_URL) + "\" />";
            final String SECURE_HTML = "<body>" + IMG_HTML + " " + JS_HTML + "</body>";
            httpServer.setResponse(JS_URL, "window.loaded_js = 42;", null);
            httpServer.setResponseBase64(IMG_URL,
                    "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
                    null);
            String secureUrl = httpsServer.setResponse(SECURE_URL, SECURE_HTML, null);

            mOnUiThread.clearSslPreferences();

            mOnUiThread.setWebViewClient(new SslWebViewClient());

            mSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_NEVER_ALLOW);
            mOnUiThread.loadUrlAndWaitForCompletion(secureUrl);
            assertEquals(1, httpsServer.getRequestCount(SECURE_URL));
            assertEquals(0, httpServer.getRequestCount(JS_URL));
            assertEquals(0, httpServer.getRequestCount(IMG_URL));

            mSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
            mOnUiThread.loadUrlAndWaitForCompletion(secureUrl);
            assertEquals(2, httpsServer.getRequestCount(SECURE_URL));
            assertEquals(1, httpServer.getRequestCount(JS_URL));
            assertEquals(1, httpServer.getRequestCount(IMG_URL));

            mSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
            mOnUiThread.loadUrlAndWaitForCompletion(secureUrl);
            assertEquals(3, httpsServer.getRequestCount(SECURE_URL));
            assertEquals(1, httpServer.getRequestCount(JS_URL));
            assertEquals(2, httpServer.getRequestCount(IMG_URL));
        } finally {
            if (httpServer != null) {
                httpServer.shutdown();
            }
            if (httpsServer != null) {
                httpsServer.shutdown();
            }
        }
    }

    /**
     * Starts the internal web server. The server will be shut down automatically
     * during tearDown().
     *
     * @throws Exception
     */
    private void startWebServer() throws Exception {
        assertNull(mWebServer);
        mWebServer = new CtsTestServer(getActivity(), false);
    }

    /**
     * Load the given asset from the internal web server. Starts the server if
     * it is not already running.
     *
     * @param asset The name of the asset to load.
     * @throws Exception
     */
    private void loadAssetUrl(String asset) throws Exception {
        if (mWebServer == null) {
            startWebServer();
        }
        String url = mWebServer.getAssetUrl(asset);
        mOnUiThread.loadUrlAndWaitForCompletion(url);
    }

    private String getNetworkImageHtml() {
        return "<html>" +
                "<head><script>function updateTitle(){" +
                "document.title=document.getElementById('img').naturalHeight;}</script></head>" +
                "<body onload='updateTitle()'>" +
                "<img id='img' onload='updateTitle()' src='" +
                mWebServer.getAssetUrl(TestHtmlConstants.SMALL_IMG_URL) +
                "'></body></html>";
    }

    private void waitForNonEmptyImage() {
        new PollingCheck(WEBVIEW_TIMEOUT) {
            @Override
            protected boolean check() {
                return !EMPTY_IMAGE_HEIGHT.equals(mOnUiThread.getTitle());
            }
        }.run();
    }

    private class IconListenerClient extends WaitForProgressClient {
        public boolean mReceivedIcon;

        public IconListenerClient() {
            super(mOnUiThread);
        }

        @Override
        public void onReceivedIcon(WebView view, Bitmap icon) {
            mReceivedIcon = true;
        }
    }
}
