1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.chromium.android_webview.test;
7 import android.test.suitebuilder.annotation.SmallTest;
8 import android.util.Pair;
10 import org.apache.http.Header;
11 import org.apache.http.HttpRequest;
12 import org.chromium.android_webview.AwContents;
13 import org.chromium.android_webview.AwSettings;
14 import org.chromium.android_webview.test.util.CommonResources;
15 import org.chromium.android_webview.test.util.JSUtils;
16 import org.chromium.base.test.util.Feature;
17 import org.chromium.content.browser.test.util.CallbackHelper;
18 import org.chromium.content.browser.test.util.HistoryUtils;
19 import org.chromium.content_public.browser.LoadUrlParams;
20 import org.chromium.net.test.util.TestWebServer;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Locale;
27 import java.util.concurrent.TimeUnit;
30 * Test suite for loadUrl().
32 public class LoadUrlTest extends AwTestBase {
34 @Feature({"AndroidWebView"})
35 public void testDataUrl() throws Throwable {
36 final String expectedTitle = "dataUrlTest";
38 "<html><head><title>" + expectedTitle + "</title></head><body>foo</body></html>";
40 final TestAwContentsClient contentsClient = new TestAwContentsClient();
41 final AwTestContainerView testContainerView =
42 createAwTestContainerViewOnMainSync(contentsClient);
43 final AwContents awContents = testContainerView.getAwContents();
44 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(), data,
46 assertEquals(expectedTitle, getTitleOnUiThread(awContents));
50 @Feature({"AndroidWebView"})
51 public void testDataUrlBase64() throws Throwable {
52 final String expectedTitle = "dataUrlTestBase64";
53 final String data = "PGh0bWw+PGhlYWQ+PHRpdGxlPmRhdGFVcmxUZXN0QmFzZTY0PC90aXRsZT48" +
54 "L2hlYWQ+PC9odG1sPg==";
56 final TestAwContentsClient contentsClient = new TestAwContentsClient();
57 final AwTestContainerView testContainerView =
58 createAwTestContainerViewOnMainSync(contentsClient);
59 final AwContents awContents = testContainerView.getAwContents();
60 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(), data,
62 assertEquals(expectedTitle, getTitleOnUiThread(awContents));
66 @Feature({"AndroidWebView"})
67 public void testDataUrlCharset() throws Throwable {
68 // Note that the \u00a3 (pound sterling) is the important character in the following
69 // string as it's not in the US_ASCII character set.
70 final String expectedTitle = "You win \u00a3100!";
72 "<html><head><title>" + expectedTitle + "</title></head><body>foo</body></html>";
73 final TestAwContentsClient contentsClient = new TestAwContentsClient();
74 final AwTestContainerView testContainerView =
75 createAwTestContainerViewOnMainSync(contentsClient);
76 final AwContents awContents = testContainerView.getAwContents();
77 loadDataSyncWithCharset(awContents, contentsClient.getOnPageFinishedHelper(), data,
78 "text/html", false, "UTF-8");
79 assertEquals(expectedTitle, getTitleOnUiThread(awContents));
83 * Loads url on the UI thread and blocks until onPageFinished is called.
85 protected void loadUrlWithExtraHeadersSync(
86 final AwContents awContents,
87 CallbackHelper onPageFinishedHelper,
89 final Map<String, String> extraHeaders) throws Throwable {
90 int currentCallCount = onPageFinishedHelper.getCallCount();
91 runTestOnUiThread(new Runnable() {
94 LoadUrlParams params = new LoadUrlParams(url);
95 params.setExtraHeaders(extraHeaders);
96 awContents.loadUrl(params);
99 onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS,
100 TimeUnit.MILLISECONDS);
103 private static List<Pair<String, String>> createHeadersList(String[] namesAndValues) {
104 List<Pair<String, String>> result = new ArrayList<Pair<String, String>>();
105 for (int i = 0; i < namesAndValues.length; i += 2)
106 result.add(Pair.create(namesAndValues[i], namesAndValues[i + 1]));
110 private static Map<String, String> createHeadersMap(String[] namesAndValues) {
111 Map<String, String> result = new HashMap<String, String>();
112 for (int i = 0; i < namesAndValues.length; i += 2) {
113 result.put(namesAndValues[i], namesAndValues[i + 1]);
118 private void validateRequestHeaders(String[] refNamesAndValues, HttpRequest request) {
119 for (int i = 0; i < refNamesAndValues.length; i += 2) {
120 Header[] matchingHeaders = request.getHeaders(refNamesAndValues[i]);
121 assertEquals(1, matchingHeaders.length);
123 Header header = matchingHeaders[0];
124 assertEquals(refNamesAndValues[i].toLowerCase(Locale.ENGLISH), header.getName());
125 assertEquals(refNamesAndValues[i + 1], header.getValue());
129 private void validateNoRequestHeaders(String[] refNamesAndValues, HttpRequest request) {
130 for (int i = 0; i < refNamesAndValues.length; i += 2) {
131 Header[] matchingHeaders = request.getHeaders(refNamesAndValues[i]);
132 assertEquals(0, matchingHeaders.length);
137 @Feature({"AndroidWebView"})
138 public void testLoadUrlWithExtraHeaders() throws Throwable {
139 final TestAwContentsClient contentsClient = new TestAwContentsClient();
140 final AwTestContainerView testContainerView =
141 createAwTestContainerViewOnMainSync(contentsClient);
142 final AwContents awContents = testContainerView.getAwContents();
144 TestWebServer webServer = TestWebServer.start();
146 final String imagePath = "/" + CommonResources.FAVICON_FILENAME;
147 webServer.setResponseBase64(imagePath,
148 CommonResources.FAVICON_DATA_BASE64, CommonResources.getImagePngHeaders(true));
149 final String path = "/load_url_with_extra_headers_test.html";
150 final String url = webServer.setResponse(
152 CommonResources.getOnImageLoadedHtml(CommonResources.FAVICON_FILENAME),
154 String[] extraHeaders = {
155 "X-ExtraHeaders1", "extra-header-data1",
156 "x-extraHeaders2", "EXTRA-HEADER-DATA2"
159 loadUrlWithExtraHeadersSync(awContents,
160 contentsClient.getOnPageFinishedHelper(),
162 createHeadersMap(extraHeaders));
163 validateRequestHeaders(extraHeaders, webServer.getLastRequest(path));
164 // Verify that extra headers are only passed for the main resource.
165 validateNoRequestHeaders(extraHeaders, webServer.getLastRequest(imagePath));
167 webServer.shutdown();
172 @Feature({"AndroidWebView"})
173 public void testNoOverridingOfExistingHeaders() throws Throwable {
174 final TestAwContentsClient contentsClient = new TestAwContentsClient();
175 final AwTestContainerView testContainerView =
176 createAwTestContainerViewOnMainSync(contentsClient);
177 final AwContents awContents = testContainerView.getAwContents();
179 TestWebServer webServer = TestWebServer.start();
181 final String path = "/no_overriding_of_existing_headers_test.html";
182 final String url = webServer.setResponse(
184 "<html><body>foo</body></html>",
186 String[] extraHeaders = {
190 loadUrlWithExtraHeadersSync(awContents,
191 contentsClient.getOnPageFinishedHelper(),
193 createHeadersMap(extraHeaders));
194 Header[] matchingHeaders = webServer.getLastRequest(path).getHeaders(extraHeaders[0]);
195 assertEquals(1, matchingHeaders.length);
196 Header header = matchingHeaders[0];
197 assertEquals(extraHeaders[0].toLowerCase(Locale.ENGLISH),
198 header.getName().toLowerCase(Locale.ENGLISH));
199 // Just check that the value is there, and it's not the one we provided.
200 assertTrue(header.getValue().length() > 0);
201 assertFalse(extraHeaders[1].equals(header.getValue()));
203 webServer.shutdown();
208 @Feature({"AndroidWebView"})
209 public void testReloadWithExtraHeaders() throws Throwable {
210 final TestAwContentsClient contentsClient = new TestAwContentsClient();
211 final AwTestContainerView testContainerView =
212 createAwTestContainerViewOnMainSync(contentsClient);
213 final AwContents awContents = testContainerView.getAwContents();
215 TestWebServer webServer = TestWebServer.start();
217 final String path = "/reload_with_extra_headers_test.html";
218 final String url = webServer.setResponse(path,
219 "<html><body>foo</body></html>",
220 createHeadersList(new String[] { "cache-control", "no-cache, no-store" }));
221 String[] extraHeaders = {
222 "X-ExtraHeaders1", "extra-header-data1",
223 "x-extraHeaders2", "EXTRA-HEADER-DATA2"
226 loadUrlWithExtraHeadersSync(awContents,
227 contentsClient.getOnPageFinishedHelper(),
229 createHeadersMap(extraHeaders));
230 validateRequestHeaders(extraHeaders, webServer.getLastRequest(path));
232 reloadSync(awContents, contentsClient.getOnPageFinishedHelper());
233 assertEquals(2, webServer.getRequestCount(path));
234 validateRequestHeaders(extraHeaders, webServer.getLastRequest(path));
236 webServer.shutdown();
241 @Feature({"AndroidWebView"})
242 public void testRedirectAndReloadWithExtraHeaders() throws Throwable {
243 final TestAwContentsClient contentsClient = new TestAwContentsClient();
244 final AwTestContainerView testContainerView =
245 createAwTestContainerViewOnMainSync(contentsClient);
246 final AwContents awContents = testContainerView.getAwContents();
248 TestWebServer webServer = TestWebServer.start();
250 final String path = "/redirect_and_reload_with_extra_headers_test.html";
251 final String url = webServer.setResponse(path,
252 "<html><body>foo</body></html>",
253 createHeadersList(new String[] { "cache-control", "no-cache, no-store" }));
254 final String redirectedPath = "/redirected.html";
255 final String redirectedUrl = webServer.setRedirect(redirectedPath, path);
256 String[] extraHeaders = {
257 "X-ExtraHeaders1", "extra-header-data1",
258 "x-extraHeaders2", "EXTRA-HEADER-DATA2"
261 loadUrlWithExtraHeadersSync(awContents,
262 contentsClient.getOnPageFinishedHelper(),
264 createHeadersMap(extraHeaders));
265 validateRequestHeaders(extraHeaders, webServer.getLastRequest(path));
266 validateRequestHeaders(extraHeaders, webServer.getLastRequest(redirectedPath));
268 // WebView will only reload the main page.
269 reloadSync(awContents, contentsClient.getOnPageFinishedHelper());
270 assertEquals(2, webServer.getRequestCount(path));
271 // No extra headers. This is consistent with legacy behavior.
272 validateNoRequestHeaders(extraHeaders, webServer.getLastRequest(path));
274 webServer.shutdown();
279 @Feature({"AndroidWebView"})
280 public void testRendererNavigationAndGoBackWithExtraHeaders() throws Throwable {
281 final TestAwContentsClient contentsClient = new TestAwContentsClient();
282 final AwTestContainerView testContainerView =
283 createAwTestContainerViewOnMainSync(contentsClient);
284 final AwContents awContents = testContainerView.getAwContents();
285 final AwSettings settings = getAwSettingsOnUiThread(awContents);
286 settings.setJavaScriptEnabled(true);
288 TestWebServer webServer = TestWebServer.start();
290 final String nextPath = "/next.html";
291 final String nextUrl = webServer.setResponse(nextPath,
292 "<html><body>Next!</body></html>",
294 final String path = "/renderer_nav_and_go_back_with_extra_headers_test.html";
295 final String url = webServer.setResponse(path,
296 "<html><body><a id=\"next\" href=\"next.html\">Next!</a></body></html>",
297 createHeadersList(new String[] { "cache-control", "no-cache, no-store" }));
298 String[] extraHeaders = {
299 "X-ExtraHeaders1", "extra-header-data1",
300 "x-extraHeaders2", "EXTRA-HEADER-DATA2"
303 loadUrlWithExtraHeadersSync(awContents,
304 contentsClient.getOnPageFinishedHelper(),
306 createHeadersMap(extraHeaders));
307 validateRequestHeaders(extraHeaders, webServer.getLastRequest(path));
309 int currentCallCount = contentsClient.getOnPageFinishedHelper().getCallCount();
310 JSUtils.clickOnLinkUsingJs(this,
312 contentsClient.getOnEvaluateJavaScriptResultHelper(),
314 contentsClient.getOnPageFinishedHelper().waitForCallback(
315 currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
316 // No extra headers for the page navigated via clicking.
317 validateNoRequestHeaders(extraHeaders, webServer.getLastRequest(nextPath));
319 HistoryUtils.goBackSync(getInstrumentation(),
320 awContents.getWebContents(),
321 contentsClient.getOnPageFinishedHelper());
322 assertEquals(2, webServer.getRequestCount(path));
323 validateRequestHeaders(extraHeaders, webServer.getLastRequest(path));
325 webServer.shutdown();