root/android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. Feature
  2. testDataUrl
  3. Feature
  4. testDataUrlBase64
  5. Feature
  6. testDataUrlCharset
  7. loadUrlWithExtraHeadersSync
  8. createHeadersList
  9. createHeadersMap
  10. validateRequestHeaders
  11. validateNoRequestHeaders
  12. Feature
  13. testLoadUrlWithExtraHeaders
  14. Feature
  15. testNoOverridingOfExistingHeaders
  16. Feature
  17. testReloadWithExtraHeaders
  18. Feature
  19. testRedirectAndReloadWithExtraHeaders
  20. Feature
  21. testRendererNavigationAndGoBackWithExtraHeaders

// 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.apache.http.Header;
import org.apache.http.HttpRequest;
import org.chromium.android_webview.AwContents;
import org.chromium.android_webview.AwSettings;
import org.chromium.android_webview.test.util.CommonResources;
import org.chromium.android_webview.test.util.JSUtils;
import org.chromium.base.test.util.Feature;
import org.chromium.content.browser.LoadUrlParams;
import org.chromium.content.browser.test.util.CallbackHelper;
import org.chromium.content.browser.test.util.HistoryUtils;
import org.chromium.net.test.util.TestWebServer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Test suite for loadUrl().
 */
public class LoadUrlTest extends AwTestBase {
    @SmallTest
    @Feature({"AndroidWebView"})
    public void testDataUrl() throws Throwable {
        final String expectedTitle = "dataUrlTest";
        final String data =
            "<html><head><title>" + expectedTitle + "</title></head><body>foo</body></html>";

        final TestAwContentsClient contentsClient = new TestAwContentsClient();
        final AwTestContainerView testContainerView =
                createAwTestContainerViewOnMainSync(contentsClient);
        final AwContents awContents = testContainerView.getAwContents();
        loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(), data,
                     "text/html", false);
        assertEquals(expectedTitle, getTitleOnUiThread(awContents));
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    public void testDataUrlBase64() throws Throwable {
        final String expectedTitle = "dataUrlTestBase64";
        final String data = "PGh0bWw+PGhlYWQ+PHRpdGxlPmRhdGFVcmxUZXN0QmFzZTY0PC90aXRsZT48" +
                            "L2hlYWQ+PC9odG1sPg==";

        final TestAwContentsClient contentsClient = new TestAwContentsClient();
        final AwTestContainerView testContainerView =
                createAwTestContainerViewOnMainSync(contentsClient);
        final AwContents awContents = testContainerView.getAwContents();
        loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(), data,
                     "text/html", true);
        assertEquals(expectedTitle, getTitleOnUiThread(awContents));
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    public void testDataUrlCharset() throws Throwable {
        // Note that the \u00a3 (pound sterling) is the important character in the following
        // string as it's not in the US_ASCII character set.
        final String expectedTitle = "You win \u00a3100!";
        final String data =
            "<html><head><title>" + expectedTitle + "</title></head><body>foo</body></html>";
        final TestAwContentsClient contentsClient = new TestAwContentsClient();
        final AwTestContainerView testContainerView =
                createAwTestContainerViewOnMainSync(contentsClient);
        final AwContents awContents = testContainerView.getAwContents();
        loadDataSyncWithCharset(awContents, contentsClient.getOnPageFinishedHelper(), data,
                     "text/html", false, "UTF-8");
        assertEquals(expectedTitle, getTitleOnUiThread(awContents));
    }

    /**
     * Loads url on the UI thread and blocks until onPageFinished is called.
     */
    protected void loadUrlWithExtraHeadersSync(
            final AwContents awContents,
            CallbackHelper onPageFinishedHelper,
            final String url,
            final Map<String, String> extraHeaders) throws Throwable {
        int currentCallCount = onPageFinishedHelper.getCallCount();
        runTestOnUiThread(new Runnable() {
            @Override
            public void run() {
                LoadUrlParams params = new LoadUrlParams(url);
                params.setExtraHeaders(extraHeaders);
                awContents.loadUrl(params);
            }
        });
        onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS,
                                             TimeUnit.MILLISECONDS);
    }

    private static List<Pair<String, String>> createHeadersList(String[] namesAndValues) {
        List<Pair<String, String>> result = new ArrayList<Pair<String, String>>();
        for (int i = 0; i < namesAndValues.length; i += 2)
            result.add(Pair.create(namesAndValues[i], namesAndValues[i + 1]));
        return result;
    }

    private static Map<String, String> createHeadersMap(String[] namesAndValues) {
        Map<String, String> result = new HashMap<String, String>();
        for (int i = 0; i < namesAndValues.length; i += 2)
            result.put(namesAndValues[i], namesAndValues[i + 1]);
        return result;
    }

    private void validateRequestHeaders(String[] refNamesAndValues,
                                        HttpRequest request) {
        for (int i = 0; i < refNamesAndValues.length; i += 2) {
            Header[] matchingHeaders = request.getHeaders(refNamesAndValues[i]);
            assertEquals(1, matchingHeaders.length);

            Header header = matchingHeaders[0];
            assertEquals(refNamesAndValues[i].toLowerCase(Locale.ENGLISH), header.getName());
            assertEquals(refNamesAndValues[i + 1], header.getValue());
        }
    }

    private void validateNoRequestHeaders(String[] refNamesAndValues,
                                          HttpRequest request) {
        for (int i = 0; i < refNamesAndValues.length; i += 2) {
            Header[] matchingHeaders = request.getHeaders(refNamesAndValues[i]);
            assertEquals(0, matchingHeaders.length);
        }
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    public void testLoadUrlWithExtraHeaders() throws Throwable {
        final TestAwContentsClient contentsClient = new TestAwContentsClient();
        final AwTestContainerView testContainerView =
                createAwTestContainerViewOnMainSync(contentsClient);
        final AwContents awContents = testContainerView.getAwContents();

        TestWebServer webServer = null;
        try {
            webServer = new TestWebServer(false);
            final String imagePath = "/" + CommonResources.FAVICON_FILENAME;
            webServer.setResponseBase64(imagePath,
                    CommonResources.FAVICON_DATA_BASE64, CommonResources.getImagePngHeaders(true));
            final String path = "/load_url_with_extra_headers_test.html";
            final String url = webServer.setResponse(
                    path,
                    CommonResources.getOnImageLoadedHtml(CommonResources.FAVICON_FILENAME),
                    null);
            String[] extraHeaders = {
                "X-ExtraHeaders1", "extra-header-data1",
                "x-extraHeaders2", "EXTRA-HEADER-DATA2"
            };

            loadUrlWithExtraHeadersSync(awContents,
                                        contentsClient.getOnPageFinishedHelper(),
                                        url,
                                        createHeadersMap(extraHeaders));
            validateRequestHeaders(extraHeaders, webServer.getLastRequest(path));
            // Verify that extra headers are only passed for the main resource.
            validateNoRequestHeaders(extraHeaders, webServer.getLastRequest(imagePath));
        } finally {
            if (webServer != null) webServer.shutdown();
        }
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    public void testNoOverridingOfExistingHeaders() throws Throwable {
        final TestAwContentsClient contentsClient = new TestAwContentsClient();
        final AwTestContainerView testContainerView =
                createAwTestContainerViewOnMainSync(contentsClient);
        final AwContents awContents = testContainerView.getAwContents();

        TestWebServer webServer = null;
        try {
            webServer = new TestWebServer(false);
            final String path = "/no_overriding_of_existing_headers_test.html";
            final String url = webServer.setResponse(
                    path,
                    "<html><body>foo</body></html>",
                    null);
            String[] extraHeaders = {
                "user-agent", "007"
            };

            loadUrlWithExtraHeadersSync(awContents,
                                        contentsClient.getOnPageFinishedHelper(),
                                        url,
                                        createHeadersMap(extraHeaders));
            Header[] matchingHeaders = webServer.getLastRequest(path).getHeaders(extraHeaders[0]);
            assertEquals(1, matchingHeaders.length);
            Header header = matchingHeaders[0];
            assertEquals(extraHeaders[0].toLowerCase(Locale.ENGLISH),
                    header.getName().toLowerCase(Locale.ENGLISH));
            // Just check that the value is there, and it's not the one we provided.
            assertTrue(header.getValue().length() > 0);
            assertFalse(extraHeaders[1].equals(header.getValue()));
        } finally {
            if (webServer != null) webServer.shutdown();
        }
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    public void testReloadWithExtraHeaders() throws Throwable {
        final TestAwContentsClient contentsClient = new TestAwContentsClient();
        final AwTestContainerView testContainerView =
                createAwTestContainerViewOnMainSync(contentsClient);
        final AwContents awContents = testContainerView.getAwContents();

        TestWebServer webServer = null;
        try {
            webServer = new TestWebServer(false);
            final String path = "/reload_with_extra_headers_test.html";
            final String url = webServer.setResponse(path,
                    "<html><body>foo</body></html>",
                    createHeadersList(new String[] { "cache-control", "no-cache, no-store" }));
            String[] extraHeaders = {
                "X-ExtraHeaders1", "extra-header-data1",
                "x-extraHeaders2", "EXTRA-HEADER-DATA2"
            };

            loadUrlWithExtraHeadersSync(awContents,
                                        contentsClient.getOnPageFinishedHelper(),
                                        url,
                                        createHeadersMap(extraHeaders));
            validateRequestHeaders(extraHeaders, webServer.getLastRequest(path));

            reloadSync(awContents, contentsClient.getOnPageFinishedHelper());
            assertEquals(2, webServer.getRequestCount(path));
            validateRequestHeaders(extraHeaders, webServer.getLastRequest(path));
        } finally {
            if (webServer != null) webServer.shutdown();
        }
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    public void testRedirectAndReloadWithExtraHeaders() throws Throwable {
        final TestAwContentsClient contentsClient = new TestAwContentsClient();
        final AwTestContainerView testContainerView =
                createAwTestContainerViewOnMainSync(contentsClient);
        final AwContents awContents = testContainerView.getAwContents();

        TestWebServer webServer = null;
        try {
            webServer = new TestWebServer(false);
            final String path = "/redirect_and_reload_with_extra_headers_test.html";
            final String url = webServer.setResponse(path,
                    "<html><body>foo</body></html>",
                    createHeadersList(new String[] { "cache-control", "no-cache, no-store" }));
            final String redirectedPath = "/redirected.html";
            final String redirectedUrl = webServer.setRedirect(redirectedPath, path);
            String[] extraHeaders = {
                "X-ExtraHeaders1", "extra-header-data1",
                "x-extraHeaders2", "EXTRA-HEADER-DATA2"
            };

            loadUrlWithExtraHeadersSync(awContents,
                                        contentsClient.getOnPageFinishedHelper(),
                                        redirectedUrl,
                                        createHeadersMap(extraHeaders));
            validateRequestHeaders(extraHeaders, webServer.getLastRequest(path));
            validateRequestHeaders(extraHeaders, webServer.getLastRequest(redirectedPath));

            // WebView will only reload the main page.
            reloadSync(awContents, contentsClient.getOnPageFinishedHelper());
            assertEquals(2, webServer.getRequestCount(path));
            // No extra headers. This is consistent with legacy behavior.
            validateNoRequestHeaders(extraHeaders, webServer.getLastRequest(path));
        } finally {
            if (webServer != null) webServer.shutdown();
        }
    }

    @SmallTest
    @Feature({"AndroidWebView"})
    public void testRendererNavigationAndGoBackWithExtraHeaders() throws Throwable {
        final TestAwContentsClient contentsClient = new TestAwContentsClient();
        final AwTestContainerView testContainerView =
                createAwTestContainerViewOnMainSync(contentsClient);
        final AwContents awContents = testContainerView.getAwContents();
        final AwSettings settings = getAwSettingsOnUiThread(awContents);
        settings.setJavaScriptEnabled(true);

        TestWebServer webServer = null;
        try {
            webServer = new TestWebServer(false);
            final String nextPath = "/next.html";
            final String nextUrl = webServer.setResponse(nextPath,
                    "<html><body>Next!</body></html>",
                    null);
            final String path = "/renderer_nav_and_go_back_with_extra_headers_test.html";
            final String url = webServer.setResponse(path,
                    "<html><body><a id=\"next\" href=\"next.html\">Next!</a></body></html>",
                    createHeadersList(new String[] { "cache-control", "no-cache, no-store" }));
            String[] extraHeaders = {
                "X-ExtraHeaders1", "extra-header-data1",
                "x-extraHeaders2", "EXTRA-HEADER-DATA2"
            };

            loadUrlWithExtraHeadersSync(awContents,
                                        contentsClient.getOnPageFinishedHelper(),
                                        url,
                                        createHeadersMap(extraHeaders));
            validateRequestHeaders(extraHeaders, webServer.getLastRequest(path));

            int currentCallCount = contentsClient.getOnPageFinishedHelper().getCallCount();
            JSUtils.clickOnLinkUsingJs(this,
                                       awContents,
                                       contentsClient.getOnEvaluateJavaScriptResultHelper(),
                                       "next");
            contentsClient.getOnPageFinishedHelper().waitForCallback(
                    currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
            // No extra headers for the page navigated via clicking.
            validateNoRequestHeaders(extraHeaders, webServer.getLastRequest(nextPath));

            HistoryUtils.goBackSync(getInstrumentation(),
                                    awContents.getContentViewCore(),
                                    contentsClient.getOnPageFinishedHelper());
            assertEquals(2, webServer.getRequestCount(path));
            validateRequestHeaders(extraHeaders, webServer.getLastRequest(path));
        } finally {
            if (webServer != null) webServer.shutdown();
        }
    }
}

/* [<][>][^][v][top][bottom][index][help] */