// 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.test.suitebuilder.annotation.SmallTest;
import android.util.Pair;

import org.chromium.android_webview.AwContents;
import org.chromium.android_webview.AwContentsClient;
import org.chromium.android_webview.test.TestAwContentsClient.OnFailedLoadHelper;
import org.chromium.android_webview.test.util.CommonResources;
import org.chromium.android_webview.test.util.JSUtils;
import org.chromium.android_webview.test.util.JavascriptEventObserver;
import org.chromium.base.annotations.SuppressFBWarnings;
import org.chromium.base.test.util.DisabledTest;
import org.chromium.base.test.util.Feature;
import org.chromium.content.browser.test.util.CallbackHelper;
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.OnPageFinishedHelper;
import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageStartedHelper;
import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnReceivedErrorHelper;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.net.test.util.TestWebServer;

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

/**
 * Tests for the WebViewClient.shouldOverrideUrlLoading() method.
 */
public class AwContentsClientShouldOverrideUrlLoadingTest extends AwTestBase {
    private static final String ABOUT_BLANK_URL = "about:blank";
    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 TestWebServer mWebServer;
    private TestAwContentsClient mContentsClient;
    private AwTestContainerView mTestContainerView;
    private AwContents mAwContents;
    private TestAwContentsClient.ShouldOverrideUrlLoadingHelper mShouldOverrideUrlLoadingHelper;

    @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>");
    }

    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(DATA_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(DATA_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(), ABOUT_BLANK_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(), ABOUT_BLANK_URL);

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

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

        // We can't go to about:blank from here because we'd get a cross-origin error.
        loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                CommonResources.makeHtmlPageWithSimpleLinkTo(DATA_URL), "text/html", false);

        int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();

        clickOnLinkUsingJs();

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

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

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

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

        int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();

        clickOnLinkUsingJs();

        mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
        assertEquals(ABOUT_BLANK_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 testCalledForDataUrl() throws Throwable {
        standardSetup();
        final String dataUrl =
                "data:text/html;base64,"
                        + "PGh0bWw+PGhlYWQ+PHRpdGxlPmRhdGFVcmxUZXN0QmFzZTY0PC90aXRsZT48"
                        + "L2hlYWQ+PC9odG1sPg==";
        loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
                CommonResources.makeHtmlPageWithSimpleLinkTo(dataUrl), "text/html", false);

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

        mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
        assertTrue("Expected URL that starts with 'data:' but got: <"
                + mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl() + "> instead.",
                mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl().startsWith(
                        "data:"));
        assertFalse(mShouldOverrideUrlLoadingHelper.isRedirect());
        assertFalse(mShouldOverrideUrlLoadingHelper.hasUserGesture());
        assertTrue(mShouldOverrideUrlLoadingHelper.isMainFrame());
    }

    @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.
        poll(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.
        poll(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.
        poll(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.
        pollOnUiThread(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return !mAwContents.getTitle().equals(pageTitle);
            }
        });
        indirectLoadCallCount = mShouldOverrideUrlLoadingHelper.getCallCount();
        loadUrlAsync(mAwContents, pageWithLinkToRedirectUrl);
        pollOnUiThread(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(this, 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());
        // We keep the user gesture from the initial navigation for serverside redirects but drop
        // the user gesture for browser initiated redirects.
        assertEquals(serverSideRedirect, 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"})
    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"})
    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(DATA_URL), "text/html", false);

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

        pollOnUiThread(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);
            pollOnUiThread(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);

            pollOnUiThread(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 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));
            setupWithProvidedContentsClient(new NullContentsClient() {
                @Override
                public boolean hasWebViewClient() {
                    return false;
                }
            });
            mAwContents.getSettings().setJavaScriptEnabled(true);
            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));

            loadUrlAsync(mAwContents, urlWithLink);
            pollOnUiThread(new Callable<Boolean>() {
                @Override
                public Boolean call() {
                    return mAwContents.getTitle().equals(pageTitle);
                }
            });
            // 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(this, mAwContents.getContentViewCore(), "link");
            pollOnUiThread(new Callable<Boolean>() {
                @Override
                public Boolean call() {
                    return getActivity().getLastSentIntent() != null;
                }
            });
            assertEquals(testUrl, getActivity().getLastSentIntent().getData().toString());
        } finally {
            getActivity().setIgnoreStartActivity(false);
        }
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    public void testNullContentsClientClickableContent() 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 pageTitle = "Click Title";
            final String testEmail = "nobody@example.org";
            final String testUrl = mWebServer.setResponse("/email_test.html",
                    "<html><head><title>" + pageTitle + "</title></head>"
                    + "<body><span id='email'>" + testEmail + "</span></body>", null);

            // JS is required for the click simulator.
            mAwContents.getSettings().setJavaScriptEnabled(true);
            loadUrlAsync(mAwContents, testUrl);
            pollOnUiThread(new Callable<Boolean>() {
                @Override
                public Boolean call() {
                    return mAwContents.getTitle().equals(pageTitle);
                }
            });

            // Clicking on an email should create an intent.
            DOMUtils.clickNode(this, mAwContents.getContentViewCore(), "email");
            pollOnUiThread(new Callable<Boolean>() {
                @Override
                public Boolean call() {
                    return getActivity().getLastSentIntent() != null;
                }
            });
            assertEquals("mailto:" + testEmail.replace("@", "%40"),
                    getActivity().getLastSentIntent().getData().toString());
        } finally {
            getActivity().setIgnoreStartActivity(false);
        }
    }

    private void doTestClickableContent(boolean inMainFrame) throws Throwable {
        standardSetup();

        final String testEmail = "nobody@example.org";
        final String findEmailJs = inMainFrame
                ? "document.getElementById(\"email\")"
                : "window.frames[0].document.getElementById(\"email\")";
        final String pageHtml = inMainFrame
                ? "<html><body onload='document.title=" + findEmailJs + ".innerText'>"
                + "<span id='email'>" + testEmail + "</span></body></html>"
                : "<html>"
                + "<body style='margin:0;' onload='document.title=" + findEmailJs + ".innerText'>"
                + " <iframe style='border:none;' srcdoc=\""
                + "   <body style='margin:0;'><span id='email'>" + testEmail + "</span></body>"
                + "\" src='iframe.html'></iframe>"
                + "</body></html>";
        final String testUrl = mWebServer.setResponse("/email_test.html", pageHtml, null);

        // JS is required for the click simulator.
        mAwContents.getSettings().setJavaScriptEnabled(true);
        loadUrlAsync(mAwContents, testUrl);
        pollOnUiThread(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return mAwContents.getTitle().equals(testEmail);
            }
        });

        int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();
        DOMUtils.clickNodeByJs(this, mAwContents.getContentViewCore(), findEmailJs);
        mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
        assertEquals("mailto:" + testEmail.replace("@", "%40"),
                mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
        assertFalse(mShouldOverrideUrlLoadingHelper.isRedirect());
        assertTrue(mShouldOverrideUrlLoadingHelper.hasUserGesture());
        assertEquals(inMainFrame, mShouldOverrideUrlLoadingHelper.isMainFrame());
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    public void testClickableContent() throws Throwable {
        doTestClickableContent(true);
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    public void testClickableContentInIframe() throws Throwable {
        doTestClickableContent(false);
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    public void testXhrInLink() throws Throwable {
        standardSetup();
        final CountDownLatch shouldOverrideUrlLoadingSignal = new CountDownLatch(1);

        final String xhrPath = "/xhrPath.html";
        final String xhrUrl = mWebServer.setResponseWithRunnableAction(
                xhrPath, CommonResources.makeHtmlPageFrom("", ""), null, new Runnable() {
                    @Override
                    public void run() {
                        try {
                            shouldOverrideUrlLoadingSignal.await();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                });

        final String xhrJs = "function xhrFunction() {"
                + "  var xhr = new XMLHttpRequest();"
                + "  xhr.onload=function() {"
                + "     console.info('xhr loaded');"
                + "     window.jsInterface.setValue(true);"
                + "  };"
                + "  xhr.onerror=function() {"
                + "     console.info('xhr failed, status ' + xhr.status);"
                + "     window.jsInterface.setValue(false);"
                + "  };"
                + "  xhr.open('GET', '" + xhrUrl + "', true);"
                + "  xhr.send();"
                + "};";

        String pageWithXhrLink = makeHtmlPageFrom(
                "<script>" + xhrJs + "</script>", "<img onclick=\"xhrFunction(); location.href='"
                        + "thiswillbe://intercepted/"
                        + "'\" class=\"big\" id=\"link\" />");

        final String startPath = "/startPath.html";
        final String startUrl = addPageToTestServer(startPath, pageWithXhrLink);

        enableJavaScriptOnUiThread(mAwContents);
        final BooleanValueJavascriptObserver jsInterface = new BooleanValueJavascriptObserver();

        // add javascript interface
        getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                jsInterface.register(mAwContents.getContentViewCore(), "jsInterface");
            }
        });

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

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

        assertEquals(0, mWebServer.getRequestCount(xhrPath));

        clickOnLinkUsingJs();

        // Make the server xhr response wait until the navigation request is intercepted.
        mShouldOverrideUrlLoadingHelper.waitForCallback(shouldOverrideUrlLoadingCallCount);
        shouldOverrideUrlLoadingSignal.countDown();

        jsInterface.waitForEvent(WAIT_TIMEOUT_MS);
        assertTrue(jsInterface.getValue());
        assertEquals(1, mWebServer.getRequestCount(xhrPath));
    }

    private static class BooleanValueJavascriptObserver extends JavascriptEventObserver {
        private boolean mValue = false;

        public void setValue(boolean value) {
            mValue = value;
            notifyJava();
        }

        public boolean getValue() {
            return mValue;
        }
    }

    /**
     * This is to test a bug where a JS redirect failing in its provisional state would prevent us
     * from posting onPageFinished for the original page load.
     * The original page contains an iframe so that we can commit the original load but then
     * prevent it from finishing until the JS redirect fails by having the test server defer the
     * response to the iframe.
     */
    @SmallTest
    @Feature({"AndroidWebView"})
    public void testOnPageFinishedOnFailedJSRedirect() throws Throwable {
        final CountDownLatch jsRedirectSignal = new CountDownLatch(1);

        final String redirectTargetPath = "/redirectTargetPath.html";
        final String redirectTargetUrl = mWebServer.setResponse(
                redirectTargetPath, CommonResources.makeHtmlPageFrom("", ""), null);

        class DelayingOverrideClient extends TestAwContentsClient {
            @Override
            public boolean shouldOverrideUrlLoading(AwWebResourceRequest request) {
                if (redirectTargetUrl.equals(request.url)) {
                    try {
                        // Wait here to make sure the load reaches its provisional state before we
                        // cancel it. Waiting for a callback to the WebContentsObserver to make sure
                        // we have reached the provisional state causes a deadlock here.
                        Thread.sleep(Math.min(WAIT_TIMEOUT_MS / 2, 2000));
                    } catch (InterruptedException e) {
                    }
                    return true;
                }
                return false;
            }
        }
        mContentsClient = new DelayingOverrideClient();
        setupWithProvidedContentsClient(mContentsClient);

        final String redirectJs = "window.location.href='" + redirectTargetUrl + "';";

        final String iframePath = "/iframePath.html";
        final String iframeUrl = mWebServer.setResponseWithRunnableAction(
                iframePath, CommonResources.makeHtmlPageFrom("", ""), null, new Runnable() {
                    @Override
                    public void run() {
                        try {
                            mAwContents.evaluateJavaScriptForTests(redirectJs, null);
                            jsRedirectSignal.await();
                        } catch (InterruptedException e) {
                        }
                    }
                });
        final String iframeJs = "<iframe src='" + iframeUrl + "'></iframe>";

        String startPage = makeHtmlPageFrom("", iframeJs);
        final String startPath = "/startPath.html";
        final String startUrl = addPageToTestServer(startPath, startPage);

        enableJavaScriptOnUiThread(mAwContents);

        OnPageFinishedHelper onPageFinishedHelper = mContentsClient.getOnPageFinishedHelper();
        int onPageFinishedCallCount = onPageFinishedHelper.getCallCount();

        OnFailedLoadHelper onFailedLoadHelper = mContentsClient.getOnFailedLoadHelper();
        int onFailedLoadCallCount = onFailedLoadHelper.getCallCount();

        // load start url -> iframe -> JS redirect -> fail JS redirect -> finish start URL
        loadUrlAsync(mAwContents, startUrl);

        onFailedLoadHelper.waitForCallback(onFailedLoadCallCount);
        assertEquals(redirectTargetUrl, onFailedLoadHelper.getUrl());

        // let iframe finish
        jsRedirectSignal.countDown();

        onPageFinishedHelper.waitForCallback(onPageFinishedCallCount);
        assertEquals(startUrl, onPageFinishedHelper.getUrl());
    }
}
