// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.android_webview.test;

import android.annotation.SuppressLint;
import android.support.test.filters.SmallTest;
import android.util.Pair;

import org.chromium.android_webview.AwContents;
import org.chromium.android_webview.AwContentsClient;
import org.chromium.android_webview.test.util.CommonResources;
import org.chromium.android_webview.test.util.JSUtils;
import org.chromium.base.annotations.SuppressFBWarnings;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.DisabledTest;
import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.RetryOnFailure;
import org.chromium.content.browser.test.util.DOMUtils;
import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnEvaluateJavaScriptResultHelper;
import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageStartedHelper;
import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnReceivedErrorHelper;
import org.chromium.content.common.ContentSwitches;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.common.ContentUrlConstants;
import org.chromium.net.test.util.TestWebServer;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

/**
 * Tests for the WebViewClient.shouldOverrideUrlLoading() method.
 */
public class AwContentsClientShouldOverrideUrlLoadingTest extends AwTestBase {
    private static final String DATA_URL = "data:text/html,<div/>";
    private static final String REDIRECT_TARGET_PATH = "/redirect_target.html";
    private static final String TITLE = "TITLE";
    private static final String TAG = "AwContentsClientShouldOverrideUrlLoadingTest";
    private static final String TEST_EMAIL = "nobody@example.org";
    private static final String TEST_EMAIL_URI = "mailto:" + TEST_EMAIL.replace("@", "%40");
    private static final String TEST_PHONE = "+16503336000";
    private static final String TEST_PHONE_URI = "tel:" + TEST_PHONE.replace("+", "%2B");
    // Use the shortest possible address to ensure it fits into one line.
    // Otherwise, click on the center of the HTML element may get into empty space.
    private static final String TEST_ADDRESS = "1 st. long enough, CA 90000";
    private static final String TEST_ADDRESS_URI = "geo:0,0?q="
            + TEST_ADDRESS.replace(" ", "+").replace(",", "%2C");

    private TestWebServer mWebServer;
    private TestAwContentsClient mContentsClient;
    private AwTestContainerView mTestContainerView;
    private AwContents mAwContents;
    private TestAwContentsClient.ShouldOverrideUrlLoadingHelper mShouldOverrideUrlLoadingHelper;

    private static class TestDefaultContentsClient extends TestAwContentsClient {
        @Override
        public boolean hasWebViewClient() {
            return false;
        }
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mWebServer = TestWebServer.start();
    }

    @Override
    protected void tearDown() throws Exception {
        mWebServer.shutdown();
        super.tearDown();
    }

    private void standardSetup() throws Throwable {
        mContentsClient = new TestAwContentsClient();
        setupWithProvidedContentsClient(mContentsClient);
        mShouldOverrideUrlLoadingHelper = mContentsClient.getShouldOverrideUrlLoadingHelper();
    }

    private void setupWithProvidedContentsClient(AwContentsClient contentsClient) throws Throwable {
        mTestContainerView = createAwTestContainerViewOnMainSync(contentsClient);
        mAwContents = mTestContainerView.getAwContents();
    }

    private void clickOnLinkUsingJs() throws Throwable {
        enableJavaScriptOnUiThread(mAwContents);
        JSUtils.clickOnLinkUsingJs(this, mAwContents,
                mContentsClient.getOnEvaluateJavaScriptResultHelper(), "link");
    }

    // Since this value is read on the UI thread, it's simpler to set it there too.
    void setShouldOverrideUrlLoadingReturnValueOnUiThread(final boolean value) throws Throwable {
        runTestOnUiThread(new Runnable() {
            @Override
            public void run() {
                mShouldOverrideUrlLoadingHelper.setShouldOverrideUrlLoadingReturnValue(value);
            }
        });
    }

    private String getTestPageCommonHeaders() {
        return "<title>" + TITLE + "</title> ";
    }

    private String makeHtmlPageFrom(String headers, String body) {
        return CommonResources.makeHtmlPageFrom(getTestPageCommonHeaders() + headers, body);
    }

    private String getHtmlForPageWithJsAssignLinkTo(String url) {
        return makeHtmlPageFrom("",
                "<img onclick=\"location.href='" + url + "'\" class=\"big\" id=\"link\" />");
    }

    private String getHtmlForPageWithJsReplaceLinkTo(String url) {
        return makeHtmlPageFrom("",
                "<img onclick=\"location.replace('" + url + "');\" class=\"big\" id=\"link\" />");
    }

    private String getHtmlForPageWithMetaRefreshRedirectTo(String url) {
        return makeHtmlPageFrom("<meta http-equiv=\"refresh\" content=\"0;url=" + url + "\" />",
                "<div>Meta refresh redirect</div>");
    }

    @SuppressLint("DefaultLocale")
    private String getHtmlForPageWithJsRedirectTo(String url, String method, int timeout) {
        return makeHtmlPageFrom(""
                + "<script>"
                +   "function doRedirectAssign() {"
                +     "location.href = '" + url + "';"
                +   "} "
                +   "function doRedirectReplace() {"
                +     "location.replace('" + url + "');"
                +   "} "
                + "</script>",
                String.format("<iframe onLoad=\"setTimeout('doRedirect%s()', %d);\" />",
                    method, timeout));
    }

    private String addPageToTestServer(String httpPath, String html) {
        List<Pair<String, String>> headers = new ArrayList<Pair<String, String>>();
        headers.add(Pair.create("Content-Type", "text/html"));
        headers.add(Pair.create("Cache-Control", "no-store"));
        return mWebServer.setResponse(httpPath, html, headers);
    }

    private String createRedirectTargetPage() {
        return addPageToTestServer(REDIRECT_TARGET_PATH,
                makeHtmlPageFrom("", "<div>This is the end of the redirect chain</div>"));
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testNotCalledOnLoadUrl() throws Throwable {
        standardSetup();
        loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                CommonResources.makeHtmlPageWithSimpleLinkTo(DATA_URL), "text/html", false);

        assertEquals(0, mShouldOverrideUrlLoadingHelper.getCallCount());
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testNotCalledOnReload() throws Throwable {
        standardSetup();
        loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                CommonResources.makeHtmlPageWithSimpleLinkTo(DATA_URL), "text/html", false);

        int callCountBeforeReload = mShouldOverrideUrlLoadingHelper.getCallCount();
        reloadSync(mAwContents, mContentsClient.getOnPageFinishedHelper());
        assertEquals(callCountBeforeReload, mShouldOverrideUrlLoadingHelper.getCallCount());
    }

    private void waitForNavigationRunnableAndAssertTitleChanged(
            Runnable navigationRunnable) throws Exception {
        CallbackHelper onPageFinishedHelper = mContentsClient.getOnPageFinishedHelper();
        final int callCount = onPageFinishedHelper.getCallCount();
        final String oldTitle = getTitleOnUiThread(mAwContents);
        getInstrumentation().runOnMainSync(navigationRunnable);
        onPageFinishedHelper.waitForCallback(callCount);
        assertFalse(oldTitle.equals(getTitleOnUiThread(mAwContents)));
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testNotCalledOnBackForwardNavigation() throws Throwable {
        standardSetup();
        final String[] pageTitles = new String[] { "page1", "page2", "page3" };

        for (String title : pageTitles) {
            loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                    CommonResources.makeHtmlPageFrom("<title>" + title + "</title>", ""),
                    "text/html", false);
        }
        assertEquals(0, mShouldOverrideUrlLoadingHelper.getCallCount());

        waitForNavigationRunnableAndAssertTitleChanged(new Runnable() {
                    @Override
                    public void run() {
                        mAwContents.goBack();
                    }
                });
        assertEquals(0, mShouldOverrideUrlLoadingHelper.getCallCount());

        waitForNavigationRunnableAndAssertTitleChanged(new Runnable() {
                    @Override
                    public void run() {
                        mAwContents.goForward();
                    }
                });
        assertEquals(0, mShouldOverrideUrlLoadingHelper.getCallCount());

        waitForNavigationRunnableAndAssertTitleChanged(new Runnable() {
                    @Override
                    public void run() {
                        mAwContents.goBackOrForward(-2);
                    }
                });
        assertEquals(0, mShouldOverrideUrlLoadingHelper.getCallCount());

        waitForNavigationRunnableAndAssertTitleChanged(new Runnable() {
                    @Override
                    public void run() {
                        mAwContents.goBackOrForward(1);
                    }
                });
        assertEquals(0, mShouldOverrideUrlLoadingHelper.getCallCount());
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testCantBlockLoads() throws Throwable {
        standardSetup();
        setShouldOverrideUrlLoadingReturnValueOnUiThread(true);

        loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                CommonResources.makeHtmlPageWithSimpleLinkTo(getTestPageCommonHeaders(),
                    DATA_URL), "text/html", false);

        assertEquals(TITLE, getTitleOnUiThread(mAwContents));
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testCalledBeforeOnPageStarted() throws Throwable {
        standardSetup();
        OnPageStartedHelper onPageStartedHelper = mContentsClient.getOnPageStartedHelper();

        loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                CommonResources.makeHtmlPageWithSimpleLinkTo(
                        ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL),
                "text/html", false);

        final int shouldOverrideUrlLoadingCallCount =
                mShouldOverrideUrlLoadingHelper.getCallCount();
        final int onPageStartedCallCount = onPageStartedHelper.getCallCount();
        setShouldOverrideUrlLoadingReturnValueOnUiThread(true);
        clickOnLinkUsingJs();

        mShouldOverrideUrlLoadingHelper.waitForCallback(shouldOverrideUrlLoadingCallCount);
        assertEquals(onPageStartedCallCount, onPageStartedHelper.getCallCount());
    }


    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testDoesNotCauseOnReceivedError() throws Throwable {
        standardSetup();
        OnReceivedErrorHelper onReceivedErrorHelper = mContentsClient.getOnReceivedErrorHelper();
        final int onReceivedErrorCallCount = onReceivedErrorHelper.getCallCount();

        loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                CommonResources.makeHtmlPageWithSimpleLinkTo(
                        ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL),
                "text/html", false);

        final int shouldOverrideUrlLoadingCallCount =
                mShouldOverrideUrlLoadingHelper.getCallCount();
        setShouldOverrideUrlLoadingReturnValueOnUiThread(true);
        clickOnLinkUsingJs();
        mShouldOverrideUrlLoadingHelper.waitForCallback(shouldOverrideUrlLoadingCallCount);
        setShouldOverrideUrlLoadingReturnValueOnUiThread(false);

        // After we load this URL we're certain that any in-flight callbacks for the previous
        // navigation have been delivered.
        loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), DATA_URL);

        assertEquals(onReceivedErrorCallCount, onReceivedErrorHelper.getCallCount());
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testNotCalledForAnchorNavigations() throws Throwable {
        doTestNotCalledForAnchorNavigations(false);
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testNotCalledForAnchorNavigationsWithNonHierarchicalScheme() throws Throwable {
        doTestNotCalledForAnchorNavigations(true);
    }

    private void doTestNotCalledForAnchorNavigations(boolean useLoadData) throws Throwable {
        standardSetup();

        final String anchorLinkPath = "/anchor_link.html";
        final String anchorLinkUrl = mWebServer.getResponseUrl(anchorLinkPath);
        addPageToTestServer(anchorLinkPath,
                CommonResources.makeHtmlPageWithSimpleLinkTo(anchorLinkUrl + "#anchor"));

        if (useLoadData) {
            loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                    CommonResources.makeHtmlPageWithSimpleLinkTo("#anchor"), "text/html", false);
        } else {
            loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), anchorLinkUrl);
        }

        final int shouldOverrideUrlLoadingCallCount =
                mShouldOverrideUrlLoadingHelper.getCallCount();

        clickOnLinkUsingJs();

        // After we load this URL we're certain that any in-flight callbacks for the previous
        // navigation have been delivered.
        loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL);

        assertEquals(shouldOverrideUrlLoadingCallCount,
                mShouldOverrideUrlLoadingHelper.getCallCount());
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testCalledWhenLinkClicked() throws Throwable {
        standardSetup();

        loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                CommonResources.makeHtmlPageWithSimpleLinkTo(
                        ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL),
                "text/html", false);

        int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();

        clickOnLinkUsingJs();

        mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
        assertEquals(ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL,
                mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
        assertFalse(mShouldOverrideUrlLoadingHelper.isRedirect());
        assertFalse(mShouldOverrideUrlLoadingHelper.hasUserGesture());
        assertTrue(mShouldOverrideUrlLoadingHelper.isMainFrame());
    }

    /*
    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    */
    @DisabledTest(message = "crbug.com/462306")
    public void testCalledWhenTopLevelAboutBlankNavigation() throws Throwable {
        standardSetup();

        final String httpPath = "/page_with_about_blank_navigation";
        final String httpPathOnServer = mWebServer.getResponseUrl(httpPath);
        addPageToTestServer(httpPath,
                CommonResources.makeHtmlPageWithSimpleLinkTo(
                        ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL));

        loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                httpPathOnServer);

        int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();

        clickOnLinkUsingJs();

        mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
        assertEquals(ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL,
                mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testCalledWhenSelfLinkClicked() throws Throwable {
        standardSetup();

        final String httpPath = "/page_with_link_to_self.html";
        final String httpPathOnServer = mWebServer.getResponseUrl(httpPath);
        addPageToTestServer(httpPath,
                CommonResources.makeHtmlPageWithSimpleLinkTo(httpPathOnServer));

        loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                httpPathOnServer);

        int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();

        clickOnLinkUsingJs();

        mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
        assertEquals(httpPathOnServer,
                mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
        assertFalse(mShouldOverrideUrlLoadingHelper.isRedirect());
        assertFalse(mShouldOverrideUrlLoadingHelper.hasUserGesture());
        assertTrue(mShouldOverrideUrlLoadingHelper.isMainFrame());
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testCalledWhenNavigatingFromJavaScriptUsingAssign()
            throws Throwable {
        standardSetup();
        enableJavaScriptOnUiThread(mAwContents);

        final String redirectTargetUrl = createRedirectTargetPage();
        loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                getHtmlForPageWithJsAssignLinkTo(redirectTargetUrl), "text/html", false);

        int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();
        clickOnLinkUsingJs();
        mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testCalledWhenNavigatingFromJavaScriptUsingReplace()
            throws Throwable {
        standardSetup();
        enableJavaScriptOnUiThread(mAwContents);

        final String redirectTargetUrl = createRedirectTargetPage();
        loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                getHtmlForPageWithJsReplaceLinkTo(redirectTargetUrl), "text/html", false);

        int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();
        clickOnLinkUsingJs();
        mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
        // It's not a server-side redirect.
        assertFalse(mShouldOverrideUrlLoadingHelper.isRedirect());
        assertFalse(mShouldOverrideUrlLoadingHelper.hasUserGesture());
        assertTrue(mShouldOverrideUrlLoadingHelper.isMainFrame());
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testPassesCorrectUrl() throws Throwable {
        standardSetup();

        final String redirectTargetUrl = createRedirectTargetPage();
        loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                CommonResources.makeHtmlPageWithSimpleLinkTo(redirectTargetUrl), "text/html",
                false);

        int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();
        clickOnLinkUsingJs();
        mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
        assertEquals(redirectTargetUrl,
                mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
        // It's not a server-side redirect.
        assertFalse(mShouldOverrideUrlLoadingHelper.isRedirect());
        assertFalse(mShouldOverrideUrlLoadingHelper.hasUserGesture());
        assertTrue(mShouldOverrideUrlLoadingHelper.isMainFrame());
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testCanIgnoreLoading() throws Throwable {
        standardSetup();

        final String redirectTargetUrl = createRedirectTargetPage();
        final String pageWithLinkToIgnorePath = "/page_with_link_to_ignore.html";
        final String pageWithLinkToIgnoreUrl = addPageToTestServer(pageWithLinkToIgnorePath,
                CommonResources.makeHtmlPageWithSimpleLinkTo(redirectTargetUrl));
        final String synchronizationPath = "/sync.html";
        final String synchronizationUrl = addPageToTestServer(synchronizationPath,
                CommonResources.makeHtmlPageWithSimpleLinkTo(redirectTargetUrl));

        loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                pageWithLinkToIgnoreUrl);

        setShouldOverrideUrlLoadingReturnValueOnUiThread(true);

        int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();
        clickOnLinkUsingJs();
        // Some time around here true should be returned from the shouldOverrideUrlLoading
        // callback causing the navigation caused by calling clickOnLinkUsingJs to be ignored.
        // We validate this by checking which pages were loaded on the server.
        mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);

        setShouldOverrideUrlLoadingReturnValueOnUiThread(false);

        loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), synchronizationUrl);

        assertEquals(1, mWebServer.getRequestCount(pageWithLinkToIgnorePath));
        assertEquals(1, mWebServer.getRequestCount(synchronizationPath));
        assertEquals(0, mWebServer.getRequestCount(REDIRECT_TARGET_PATH));
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testCalledForUnsupportedSchemes() throws Throwable {
        standardSetup();
        final String unsupportedSchemeUrl = "foobar://resource/1";
        loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                CommonResources.makeHtmlPageWithSimpleLinkTo(unsupportedSchemeUrl), "text/html",
                false);

        int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();
        clickOnLinkUsingJs();

        mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
        assertEquals(unsupportedSchemeUrl,
                mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
        assertFalse(mShouldOverrideUrlLoadingHelper.isRedirect());
        assertFalse(mShouldOverrideUrlLoadingHelper.hasUserGesture());
        assertTrue(mShouldOverrideUrlLoadingHelper.isMainFrame());
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testNotCalledForPostNavigations() throws Throwable {
        // The reason POST requests are excluded is BUG 155250.
        standardSetup();

        final String redirectTargetUrl = createRedirectTargetPage();
        final String postLinkUrl = addPageToTestServer("/page_with_post_link.html",
                CommonResources.makeHtmlPageWithSimplePostFormTo(redirectTargetUrl));

        loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), postLinkUrl);

        final int shouldOverrideUrlLoadingCallCount =
                mShouldOverrideUrlLoadingHelper.getCallCount();

        assertEquals(0, mWebServer.getRequestCount(REDIRECT_TARGET_PATH));
        clickOnLinkUsingJs();

        // Wait for the target URL to be fetched from the server.
        pollInstrumentationThread(new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                return mWebServer.getRequestCount(REDIRECT_TARGET_PATH) == 1;
            }
        });

        // Since the targetURL was loaded from the test server it means all processing related
        // to dispatching a shouldOverrideUrlLoading callback had finished and checking the call
        // is stable.
        assertEquals(shouldOverrideUrlLoadingCallCount,
                mShouldOverrideUrlLoadingHelper.getCallCount());
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testCalledFor302AfterPostNavigations() throws Throwable {
        // The reason POST requests are excluded is BUG 155250.
        standardSetup();

        final String redirectTargetUrl = createRedirectTargetPage();
        final String postToGetRedirectUrl = mWebServer.setRedirect("/302.html", redirectTargetUrl);
        final String postLinkUrl = addPageToTestServer("/page_with_post_link.html",
                CommonResources.makeHtmlPageWithSimplePostFormTo(postToGetRedirectUrl));

        loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), postLinkUrl);

        final int shouldOverrideUrlLoadingCallCount =
                mShouldOverrideUrlLoadingHelper.getCallCount();
        clickOnLinkUsingJs();
        mShouldOverrideUrlLoadingHelper.waitForCallback(shouldOverrideUrlLoadingCallCount);

        // Wait for the target URL to be fetched from the server.
        pollInstrumentationThread(new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                return mWebServer.getRequestCount(REDIRECT_TARGET_PATH) == 1;
            }
        });

        assertEquals(redirectTargetUrl,
                mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
        assertTrue(mShouldOverrideUrlLoadingHelper.isRedirect());
        assertFalse(mShouldOverrideUrlLoadingHelper.hasUserGesture());
        assertTrue(mShouldOverrideUrlLoadingHelper.isMainFrame());
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testNotCalledForIframeHttpNavigations() throws Throwable {
        standardSetup();

        final String iframeRedirectTargetUrl = createRedirectTargetPage();
        final String iframeRedirectUrl =
                mWebServer.setRedirect("/302.html", iframeRedirectTargetUrl);
        final String pageWithIframeUrl =
                addPageToTestServer("/iframe_intercept.html",
                        makeHtmlPageFrom("", "<iframe src=\"" + iframeRedirectUrl + "\" />"));

        final int shouldOverrideUrlLoadingCallCount =
                mShouldOverrideUrlLoadingHelper.getCallCount();

        assertEquals(0, mWebServer.getRequestCount(REDIRECT_TARGET_PATH));
        loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), pageWithIframeUrl);

        // Wait for the redirect target URL to be fetched from the server.
        pollInstrumentationThread(new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                return mWebServer.getRequestCount(REDIRECT_TARGET_PATH) == 1;
            }
        });

        assertEquals(shouldOverrideUrlLoadingCallCount,
                mShouldOverrideUrlLoadingHelper.getCallCount());
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testCalledForIframeUnsupportedSchemeNavigations() throws Throwable {
        standardSetup();

        final String unsupportedSchemeUrl = "foobar://resource/1";
        final String pageWithIframeUrl =
                addPageToTestServer("/iframe_intercept.html",
                        makeHtmlPageFrom("", "<iframe src=\"" + unsupportedSchemeUrl + "\" />"));

        final int shouldOverrideUrlLoadingCallCount =
                mShouldOverrideUrlLoadingHelper.getCallCount();

        loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), pageWithIframeUrl);

        mShouldOverrideUrlLoadingHelper.waitForCallback(shouldOverrideUrlLoadingCallCount);
        assertEquals(unsupportedSchemeUrl,
                mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
        assertFalse(mShouldOverrideUrlLoadingHelper.isRedirect());
        assertFalse(mShouldOverrideUrlLoadingHelper.hasUserGesture());
        assertFalse(mShouldOverrideUrlLoadingHelper.isMainFrame());
    }

    /**
     * Worker method for the various redirect tests.
     *
     * Calling this will first load the redirect URL built from redirectFilePath, query and
     * locationFilePath and assert that we get a override callback for the destination.
     * The second part of the test loads a page that contains a link which points at the redirect
     * URL. We expect two callbacks - one for the redirect link and another for the destination.
     */
    private void doTestCalledOnRedirect(String redirectUrl, String redirectTarget,
            boolean serverSideRedirect) throws Throwable {
        standardSetup();
        final String pageTitle = "doTestCalledOnRedirect page";
        final String pageWithLinkToRedirectUrl = addPageToTestServer(
                "/page_with_link_to_redirect.html", CommonResources.makeHtmlPageWithSimpleLinkTo(
                        "<title>" + pageTitle + "</title>", redirectUrl));
        enableJavaScriptOnUiThread(mAwContents);

        // There is a slight difference between navigations caused by calling load and navigations
        // caused by clicking on a link:
        //
        //  * when using load the navigation is treated as if it came from the URL bar (has the
        //    navigation type TYPED, doesn't have the has_user_gesture flag); thus the navigation
        //    itself is not reported via shouldOverrideUrlLoading, but then if it has caused a
        //    redirect, the redirect itself is reported;
        //
        //  * when clicking on a link the navigation has the LINK type and has_user_gesture depends
        //    on whether it was a real click done by the user, or has it been done by JS; on click,
        //    both the initial navigation and the redirect are reported via
        //    shouldOverrideUrlLoading.
        int directLoadCallCount = mShouldOverrideUrlLoadingHelper.getCallCount();
        loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), redirectUrl);

        mShouldOverrideUrlLoadingHelper.waitForCallback(directLoadCallCount, 1);
        assertEquals(redirectTarget,
                mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
        assertEquals(serverSideRedirect, mShouldOverrideUrlLoadingHelper.isRedirect());
        assertFalse(mShouldOverrideUrlLoadingHelper.hasUserGesture());
        assertTrue(mShouldOverrideUrlLoadingHelper.isMainFrame());

        // Test clicking with JS, hasUserGesture must be false.
        int indirectLoadCallCount = mShouldOverrideUrlLoadingHelper.getCallCount();
        loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                pageWithLinkToRedirectUrl);
        assertEquals(indirectLoadCallCount, mShouldOverrideUrlLoadingHelper.getCallCount());

        clickOnLinkUsingJs();

        mShouldOverrideUrlLoadingHelper.waitForCallback(indirectLoadCallCount, 1);
        assertEquals(redirectUrl,
                mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
        assertFalse(mShouldOverrideUrlLoadingHelper.isRedirect());
        assertFalse(mShouldOverrideUrlLoadingHelper.hasUserGesture());
        assertTrue(mShouldOverrideUrlLoadingHelper.isMainFrame());
        mShouldOverrideUrlLoadingHelper.waitForCallback(indirectLoadCallCount + 1, 1);
        assertEquals(redirectTarget,
                mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
        assertEquals(serverSideRedirect, mShouldOverrideUrlLoadingHelper.isRedirect());
        assertFalse(mShouldOverrideUrlLoadingHelper.hasUserGesture());
        assertTrue(mShouldOverrideUrlLoadingHelper.isMainFrame());

        // Make sure the redirect target page has finished loading.
        pollUiThread(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return !mAwContents.getTitle().equals(pageTitle);
            }
        });
        indirectLoadCallCount = mShouldOverrideUrlLoadingHelper.getCallCount();
        loadUrlAsync(mAwContents, pageWithLinkToRedirectUrl);
        pollUiThread(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return mAwContents.getTitle().equals(pageTitle);
            }
        });
        assertEquals(indirectLoadCallCount, mShouldOverrideUrlLoadingHelper.getCallCount());

        // Simulate touch, hasUserGesture must be true only on the first call.
        DOMUtils.clickNode(mAwContents.getContentViewCore(), "link");

        mShouldOverrideUrlLoadingHelper.waitForCallback(indirectLoadCallCount, 1);
        assertEquals(redirectUrl,
                mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
        assertFalse(mShouldOverrideUrlLoadingHelper.isRedirect());
        assertTrue(mShouldOverrideUrlLoadingHelper.hasUserGesture());
        assertTrue(mShouldOverrideUrlLoadingHelper.isMainFrame());
        mShouldOverrideUrlLoadingHelper.waitForCallback(indirectLoadCallCount + 1, 1);
        assertEquals(redirectTarget,
                mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
        assertEquals(serverSideRedirect, mShouldOverrideUrlLoadingHelper.isRedirect());
        assertFalse(mShouldOverrideUrlLoadingHelper.hasUserGesture());
        assertTrue(mShouldOverrideUrlLoadingHelper.isMainFrame());
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testCalledOn302Redirect() throws Throwable {
        final String redirectTargetUrl = createRedirectTargetPage();
        final String redirectUrl = mWebServer.setRedirect("/302.html", redirectTargetUrl);
        doTestCalledOnRedirect(redirectUrl, redirectTargetUrl, true);
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testCalledOnMetaRefreshRedirect() throws Throwable {
        final String redirectTargetUrl = createRedirectTargetPage();
        final String redirectUrl = addPageToTestServer("/meta_refresh.html",
                getHtmlForPageWithMetaRefreshRedirectTo(redirectTargetUrl));
        doTestCalledOnRedirect(redirectUrl, redirectTargetUrl, false);
    }


    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testCalledOnJavaScriptLocationImmediateAssignRedirect()
            throws Throwable {
        final String redirectTargetUrl = createRedirectTargetPage();
        final String redirectUrl = addPageToTestServer("/js_immediate_assign.html",
                getHtmlForPageWithJsRedirectTo(redirectTargetUrl, "Assign", 0));
        doTestCalledOnRedirect(redirectUrl, redirectTargetUrl, false);
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testCalledOnJavaScriptLocationImmediateReplaceRedirect()
            throws Throwable {
        final String redirectTargetUrl = createRedirectTargetPage();
        final String redirectUrl = addPageToTestServer("/js_immediate_replace.html",
                getHtmlForPageWithJsRedirectTo(redirectTargetUrl, "Replace", 0));
        doTestCalledOnRedirect(redirectUrl, redirectTargetUrl, false);
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    @RetryOnFailure
    public void testCalledOnJavaScriptLocationDelayedAssignRedirect()
            throws Throwable {
        final String redirectTargetUrl = createRedirectTargetPage();
        final String redirectUrl = addPageToTestServer("/js_delayed_assign.html",
                getHtmlForPageWithJsRedirectTo(redirectTargetUrl, "Assign", 100));
        doTestCalledOnRedirect(redirectUrl, redirectTargetUrl, false);
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    @RetryOnFailure
    public void testCalledOnJavaScriptLocationDelayedReplaceRedirect()
            throws Throwable {
        final String redirectTargetUrl = createRedirectTargetPage();
        final String redirectUrl = addPageToTestServer("/js_delayed_replace.html",
                getHtmlForPageWithJsRedirectTo(redirectTargetUrl, "Replace", 100));
        doTestCalledOnRedirect(redirectUrl, redirectTargetUrl, false);
    }

    @SmallTest
    @Feature({"AndroidWebView", "Navigation"})
    public void testDoubleNavigateDoesNotSuppressInitialNavigate() throws Throwable {
        final String jsUrl = "javascript:try{console.log('processed js loadUrl');}catch(e){};";
        standardSetup();

        // Do a double navigagtion, the second being an effective no-op, in quick succession (i.e.
        // without yielding the main thread inbetween).
        int currentCallCount = mContentsClient.getOnPageFinishedHelper().getCallCount();
        getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                mAwContents.loadUrl(LoadUrlParams.createLoadDataParams(
                        CommonResources.makeHtmlPageWithSimpleLinkTo(DATA_URL), "text/html",
                        false));
                mAwContents.loadUrl(new LoadUrlParams(jsUrl));
            }
        });
        mContentsClient.getOnPageFinishedHelper().waitForCallback(currentCallCount, 1,
                WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);

        assertEquals(0, mShouldOverrideUrlLoadingHelper.getCallCount());
    }

    @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
    @SmallTest
    @Feature({"AndroidWebView"})
    public void testCallDestroyInCallback() throws Throwable {
        class DestroyInCallbackClient extends TestAwContentsClient {
            @Override
            public boolean shouldOverrideUrlLoading(AwContentsClient.AwWebResourceRequest request) {
                mAwContents.destroy();
                return super.shouldOverrideUrlLoading(request);
            }
        }

        mContentsClient = new DestroyInCallbackClient();
        setupWithProvidedContentsClient(mContentsClient);
        mShouldOverrideUrlLoadingHelper = mContentsClient.getShouldOverrideUrlLoadingHelper();

        OnReceivedErrorHelper onReceivedErrorHelper = mContentsClient.getOnReceivedErrorHelper();
        int onReceivedErrorCallCount = onReceivedErrorHelper.getCallCount();

        loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                CommonResources.makeHtmlPageWithSimpleLinkTo(
                        ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL),
                "text/html", false);

        int shouldOverrideUrlLoadingCallCount = mShouldOverrideUrlLoadingHelper.getCallCount();
        setShouldOverrideUrlLoadingReturnValueOnUiThread(true);
        clickOnLinkUsingJs();
        mShouldOverrideUrlLoadingHelper.waitForCallback(shouldOverrideUrlLoadingCallCount);

        pollUiThread(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return AwContents.getNativeInstanceCount() == 0;
            }
        });
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    public void testNullContentsClientWithServerRedirect() throws Throwable {
        try {
            // The test will fire real intents through the test activity.
            // Need to temporarily suppress startActivity otherwise there will be a
            // handler selection window and the test can't dismiss that.
            getActivity().setIgnoreStartActivity(true);
            final String testUrl = mWebServer.setResponse("/" + CommonResources.ABOUT_FILENAME,
                    CommonResources.ABOUT_HTML, CommonResources.getTextHtmlHeaders(true));
            setupWithProvidedContentsClient(new NullContentsClient() {
                @Override
                public boolean hasWebViewClient() {
                    return false;
                }
            });
            loadUrlAsync(mAwContents, testUrl);
            pollUiThread(new Callable<Boolean>() {
                @Override
                public Boolean call() {
                    return mAwContents.getTitle().equals(CommonResources.ABOUT_TITLE);
                }
            });

            assertNull(getActivity().getLastSentIntent());

            // Now the server will redirect path1 to path2. Path2 will load ABOUT_HTML.
            // AwContents should create an intent for the server initiated redirection.
            final String path1 = "/from.html";
            final String path2 = "/to.html";
            final String fromUrl = mWebServer.setRedirect(path1, path2);
            final String toUrl = mWebServer.setResponse(
                    path2, CommonResources.ABOUT_HTML, CommonResources.getTextHtmlHeaders(true));
            loadUrlAsync(mAwContents, fromUrl);

            pollUiThread(new Callable<Boolean>() {
                @Override
                public Boolean call() {
                    return getActivity().getLastSentIntent() != null;
                }
            });
            assertEquals(toUrl, getActivity().getLastSentIntent().getData().toString());
        } finally {
            getActivity().setIgnoreStartActivity(false);
        }
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    public void testNullContentsClientOpenAboutUrlInWebView() throws Throwable {
        try {
            // If there's a bug in WebView, this may fire real intents through the test activity.
            // Need to temporarily suppress startActivity otherwise there will be a
            // handler selection window and the test can't dismiss that.
            getActivity().setIgnoreStartActivity(true);
            TestDefaultContentsClient nullClient = new TestDefaultContentsClient();
            setupWithProvidedContentsClient(nullClient);
            enableJavaScriptOnUiThread(mAwContents);
            final String pageTitle = "Click Title";
            final String htmlWithLink = "<html><title>" + pageTitle + "</title>"
                    + "<body><a id='link' href='" + ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL
                    + "'>Click this!</a></body></html>";
            final String urlWithLink = mWebServer.setResponse(
                    "/html_with_link.html", htmlWithLink, CommonResources.getTextHtmlHeaders(true));

            loadUrlSync(mAwContents, nullClient.getOnPageFinishedHelper(), urlWithLink);

            // Clicking on an about:blank link should always navigate to the page directly
            int currentCallCount = nullClient.getOnPageFinishedHelper().getCallCount();
            DOMUtils.clickNode(mAwContents.getContentViewCore(), "link");
            nullClient.getOnPageFinishedHelper().waitForCallback(
                    currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);

            assertEquals(ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL, mAwContents.getUrl());
        } finally {
            getActivity().setIgnoreStartActivity(false);
        }
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    public void testNullContentsClientOpenLink() throws Throwable {
        try {
            // The test will fire real intents through the test activity.
            // Need to temporarily suppress startActivity otherwise there will be a
            // handler selection window and the test can't dismiss that.
            getActivity().setIgnoreStartActivity(true);
            final String testUrl = mWebServer.setResponse("/" + CommonResources.ABOUT_FILENAME,
                    CommonResources.ABOUT_HTML, CommonResources.getTextHtmlHeaders(true));
            TestDefaultContentsClient nullClient = new TestDefaultContentsClient();
            setupWithProvidedContentsClient(nullClient);
            enableJavaScriptOnUiThread(mAwContents);
            final String pageTitle = "Click Title";
            final String htmlWithLink = "<html><title>" + pageTitle + "</title>"
                    + "<body><a id='link' href='" + testUrl + "'>Click this!</a></body></html>";
            final String urlWithLink = mWebServer.setResponse(
                    "/html_with_link.html", htmlWithLink, CommonResources.getTextHtmlHeaders(true));

            loadUrlSync(mAwContents, nullClient.getOnPageFinishedHelper(), urlWithLink);
            // Executing JS code that tries to navigate somewhere should not create an intent.
            assertEquals("\"" + testUrl + "\"", JSUtils.executeJavaScriptAndWaitForResult(
                            this, mAwContents, new OnEvaluateJavaScriptResultHelper(),
                            "document.location.href='" + testUrl + "'"));
            assertNull(getActivity().getLastSentIntent());

            // Clicking on a link should create an intent.
            DOMUtils.clickNode(mAwContents.getContentViewCore(), "link");
            pollUiThread(new Callable<Boolean>() {
                @Override
                public Boolean call() {
                    return getActivity().getLastSentIntent() != null;
                }
            });
            assertEquals(testUrl, getActivity().getLastSentIntent().getData().toString());
        } finally {
            getActivity().setIgnoreStartActivity(false);
        }
    }

    private String setupForContentClickTest(final String content, boolean inMainFrame)
            throws Exception {
        final String contentId = "content";
        final String findContentJs = inMainFrame
                ? "document.getElementById(\"" + contentId + "\")"
                : "window.frames[0].document.getElementById(\"" + contentId + "\")";
        final String pageHtml = inMainFrame
                ? "<html><body onload='document.title=" + findContentJs + ".innerText'>"
                + "<span id='" + contentId + "'>" + content + "</span></body></html>"
                : "<html>"
                + "<body style='margin:0;' onload='document.title=" + findContentJs + ".innerText'>"
                + " <iframe style='border:none;width:100%;' srcdoc=\""
                + "   <body style='margin:0;'><span id='" + contentId + "'>"
                + content + "</span></body>"
                + "\" src='iframe.html'></iframe>"
                + "</body></html>";
        final String testUrl = mWebServer.setResponse("/content_test.html", pageHtml, null);

        enableJavaScriptOnUiThread(mAwContents);
        loadUrlAsync(mAwContents, testUrl);
        pollUiThread(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return mAwContents.getTitle().equals(content);
            }
        });
        return findContentJs;
    }

    private void doTestNullContentsClientClickableContent(String pageContent,
            String intentContent) throws Throwable {
        try {
            // The test will fire real intents through the test activity.
            // Need to temporarily suppress startActivity otherwise there will be a
            // handler selection window and the test can't dismiss that.
            getActivity().setIgnoreStartActivity(true);
            setupWithProvidedContentsClient(new NullContentsClient() {
                @Override
                public boolean hasWebViewClient() {
                    return false;
                }
            });

            final String findContentJs = setupForContentClickTest(pageContent, true);
            // Clicking on the content should create an intent.
            DOMUtils.clickNodeByJs(mAwContents.getContentViewCore(), findContentJs);
            pollUiThread(new Callable<Boolean>() {
                @Override
                public Boolean call() {
                    return getActivity().getLastSentIntent() != null;
                }
            });
            assertEquals(intentContent,
                    getActivity().getLastSentIntent().getData().toString());
        } finally {
            getActivity().setIgnoreStartActivity(false);
        }
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    @CommandLineFlags.Add({ContentSwitches.ENABLE_CONTENT_INTENT_DETECTION})
    public void testNullContentsClientClickableEmail() throws Throwable {
        doTestNullContentsClientClickableContent(TEST_EMAIL, TEST_EMAIL_URI);
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    @CommandLineFlags.Add({ContentSwitches.NETWORK_COUNTRY_ISO + "=us",
            ContentSwitches.ENABLE_CONTENT_INTENT_DETECTION})
    public void testNullContentsClientClickablePhone() throws Throwable {
        doTestNullContentsClientClickableContent(TEST_PHONE, TEST_PHONE_URI);
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    @CommandLineFlags.Add({ContentSwitches.ENABLE_CONTENT_INTENT_DETECTION})
    public void testNullContentsClientClickableAddress() throws Throwable {
        doTestNullContentsClientClickableContent(TEST_ADDRESS, TEST_ADDRESS_URI);
    }

    private void doTestClickableContent(String pageContent, String intentContent,
            boolean inMainFrame) throws Throwable {
        standardSetup();

        final String findContentJs = setupForContentClickTest(pageContent, inMainFrame);
        int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();
        DOMUtils.clickNodeByJs(mAwContents.getContentViewCore(), findContentJs);
        mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
        assertEquals(intentContent,
                mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
        assertFalse(mShouldOverrideUrlLoadingHelper.isRedirect());
        assertTrue(mShouldOverrideUrlLoadingHelper.hasUserGesture());
        assertEquals(inMainFrame, mShouldOverrideUrlLoadingHelper.isMainFrame());
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    @CommandLineFlags.Add({ContentSwitches.ENABLE_CONTENT_INTENT_DETECTION})
    public void testClickableEmail() throws Throwable {
        doTestClickableContent(TEST_EMAIL, TEST_EMAIL_URI, true);
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    @CommandLineFlags.Add({ContentSwitches.NETWORK_COUNTRY_ISO + "=us",
            ContentSwitches.ENABLE_CONTENT_INTENT_DETECTION})
    public void testClickablePhone() throws Throwable {
        doTestClickableContent(TEST_PHONE, TEST_PHONE_URI, true);
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    @CommandLineFlags.Add({ContentSwitches.ENABLE_CONTENT_INTENT_DETECTION})
    public void testClickableAddress() throws Throwable {
        doTestClickableContent(TEST_ADDRESS, TEST_ADDRESS_URI, true);
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    @CommandLineFlags.Add({ContentSwitches.ENABLE_CONTENT_INTENT_DETECTION})
    public void testClickableEmailInIframe() throws Throwable {
        doTestClickableContent(TEST_EMAIL, TEST_EMAIL_URI, false);
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    @CommandLineFlags.Add({ContentSwitches.NETWORK_COUNTRY_ISO + "=us",
            ContentSwitches.ENABLE_CONTENT_INTENT_DETECTION})
    public void testClickablePhoneInIframe() throws Throwable {
        doTestClickableContent(TEST_PHONE, TEST_PHONE_URI, false);
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    @CommandLineFlags.Add({ContentSwitches.ENABLE_CONTENT_INTENT_DETECTION})
    public void testClickableAddressInIframe() throws Throwable {
        doTestClickableContent(TEST_ADDRESS, TEST_ADDRESS_URI, false);
    }
}
