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.chromium.android_webview.AwContents;
11 import org.chromium.android_webview.test.util.CommonResources;
12 import org.chromium.android_webview.test.util.JSUtils;
13 import org.chromium.base.test.util.Feature;
14 import org.chromium.content.browser.test.util.CallbackHelper;
15 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageStartedHelper;
16 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnReceivedErrorHelper;
17 import org.chromium.content_public.browser.LoadUrlParams;
18 import org.chromium.net.test.util.TestWebServer;
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.concurrent.Callable;
23 import java.util.concurrent.TimeUnit;
26 * Tests for the WebViewClient.shouldOverrideUrlLoading() method.
28 public class AwContentsClientShouldOverrideUrlLoadingTest extends AwTestBase {
29 private static final String ABOUT_BLANK_URL = "about:blank";
30 private static final String DATA_URL = "data:text/html,<div/>";
31 private static final String REDIRECT_TARGET_PATH = "/redirect_target.html";
32 private static final String TITLE = "TITLE";
34 private TestWebServer mWebServer;
37 protected void setUp() throws Exception {
39 mWebServer = new TestWebServer(false);
43 protected void tearDown() throws Exception {
44 mWebServer.shutdown();
48 private void clickOnLinkUsingJs(final AwContents awContents,
49 final TestAwContentsClient contentsClient) throws Throwable {
50 enableJavaScriptOnUiThread(awContents);
51 JSUtils.clickOnLinkUsingJs(this, awContents,
52 contentsClient.getOnEvaluateJavaScriptResultHelper(), "link");
55 // Since this value is read on the UI thread, it's simpler to set it there too.
56 void setShouldOverrideUrlLoadingReturnValueOnUiThread(
57 final TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideHelper,
58 final boolean value) throws Throwable {
59 runTestOnUiThread(new Runnable() {
62 shouldOverrideHelper.setShouldOverrideUrlLoadingReturnValue(value);
67 private String getTestPageCommonHeaders() {
68 return "<title>" + TITLE + "</title> ";
71 private String makeHtmlPageFrom(String headers, String body) {
72 return CommonResources.makeHtmlPageFrom(getTestPageCommonHeaders() + headers, body);
75 private String getHtmlForPageWithJsAssignLinkTo(String url) {
76 return makeHtmlPageFrom("",
77 "<img onclick=\"location.href='" + url + "'\" class=\"big\" id=\"link\" />");
80 private String getHtmlForPageWithJsReplaceLinkTo(String url) {
81 return makeHtmlPageFrom("",
82 "<img onclick=\"location.replace('" + url + "');\" class=\"big\" id=\"link\" />");
85 private String getHtmlForPageWithMetaRefreshRedirectTo(String url) {
86 return makeHtmlPageFrom("<meta http-equiv=\"refresh\" content=\"0;url=" + url + "\" />",
87 "<div>Meta refresh redirect</div>");
90 private String getHtmlForPageWithJsRedirectTo(String url, String method, int timeout) {
91 return makeHtmlPageFrom(
93 "function doRedirectAssign() {" +
94 "location.href = '" + url + "';" +
96 "function doRedirectReplace() {" +
97 "location.replace('" + url + "');" +
100 String.format("<iframe onLoad=\"setTimeout('doRedirect%s()', %d);\" />",
104 private String addPageToTestServer(TestWebServer webServer, String httpPath, String html) {
105 List<Pair<String, String>> headers = new ArrayList<Pair<String, String>>();
106 headers.add(Pair.create("Content-Type", "text/html"));
107 headers.add(Pair.create("Cache-Control", "no-store"));
108 return webServer.setResponse(httpPath, html, headers);
111 private String createRedirectTargetPage(TestWebServer webServer) {
112 return addPageToTestServer(webServer, REDIRECT_TARGET_PATH,
113 makeHtmlPageFrom("", "<div>This is the end of the redirect chain</div>"));
117 @Feature({"AndroidWebView", "Navigation"})
118 public void testNotCalledOnLoadUrl() throws Throwable {
119 final TestAwContentsClient contentsClient = new TestAwContentsClient();
120 final AwTestContainerView testContainerView =
121 createAwTestContainerViewOnMainSync(contentsClient);
122 final AwContents awContents = testContainerView.getAwContents();
123 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
124 contentsClient.getShouldOverrideUrlLoadingHelper();
126 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
127 CommonResources.makeHtmlPageWithSimpleLinkTo(DATA_URL), "text/html", false);
129 assertEquals(0, shouldOverrideUrlLoadingHelper.getCallCount());
132 private void waitForNavigationRunnableAndAssertTitleChanged(AwContents awContents,
133 CallbackHelper onPageFinishedHelper,
134 Runnable navigationRunnable) throws Exception {
135 final int callCount = onPageFinishedHelper.getCallCount();
136 final String oldTitle = getTitleOnUiThread(awContents);
137 getInstrumentation().runOnMainSync(navigationRunnable);
138 onPageFinishedHelper.waitForCallback(callCount);
139 assertFalse(oldTitle.equals(getTitleOnUiThread(awContents)));
143 @Feature({"AndroidWebView", "Navigation"})
144 public void testNotCalledOnBackForwardNavigation() throws Throwable {
145 final TestAwContentsClient contentsClient = new TestAwContentsClient();
146 final AwTestContainerView testContainerView =
147 createAwTestContainerViewOnMainSync(contentsClient);
148 final AwContents awContents = testContainerView.getAwContents();
149 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
150 contentsClient.getShouldOverrideUrlLoadingHelper();
151 final String[] pageTitles = new String[] { "page1", "page2", "page3" };
153 for (String title : pageTitles) {
154 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
155 CommonResources.makeHtmlPageFrom("<title>" + title + "</title>", ""),
158 assertEquals(0, shouldOverrideUrlLoadingHelper.getCallCount());
160 waitForNavigationRunnableAndAssertTitleChanged(awContents,
161 contentsClient.getOnPageFinishedHelper(), new Runnable() {
167 assertEquals(0, shouldOverrideUrlLoadingHelper.getCallCount());
169 waitForNavigationRunnableAndAssertTitleChanged(awContents,
170 contentsClient.getOnPageFinishedHelper(), new Runnable() {
173 awContents.goForward();
176 assertEquals(0, shouldOverrideUrlLoadingHelper.getCallCount());
178 waitForNavigationRunnableAndAssertTitleChanged(awContents,
179 contentsClient.getOnPageFinishedHelper(), new Runnable() {
182 awContents.goBackOrForward(-2);
185 assertEquals(0, shouldOverrideUrlLoadingHelper.getCallCount());
187 waitForNavigationRunnableAndAssertTitleChanged(awContents,
188 contentsClient.getOnPageFinishedHelper(), new Runnable() {
191 awContents.goBackOrForward(1);
194 assertEquals(0, shouldOverrideUrlLoadingHelper.getCallCount());
198 @Feature({"AndroidWebView", "Navigation"})
199 public void testCantBlockLoads() throws Throwable {
200 final TestAwContentsClient contentsClient = new TestAwContentsClient();
201 final AwTestContainerView testContainerView =
202 createAwTestContainerViewOnMainSync(contentsClient);
203 final AwContents awContents = testContainerView.getAwContents();
204 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
205 contentsClient.getShouldOverrideUrlLoadingHelper();
207 setShouldOverrideUrlLoadingReturnValueOnUiThread(shouldOverrideUrlLoadingHelper, true);
209 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
210 CommonResources.makeHtmlPageWithSimpleLinkTo(getTestPageCommonHeaders(),
211 DATA_URL), "text/html", false);
213 assertEquals(TITLE, getTitleOnUiThread(awContents));
217 @Feature({"AndroidWebView", "Navigation"})
218 public void testCalledBeforeOnPageStarted() throws Throwable {
219 final TestAwContentsClient contentsClient = new TestAwContentsClient();
220 final AwTestContainerView testContainerView =
221 createAwTestContainerViewOnMainSync(contentsClient);
222 final AwContents awContents = testContainerView.getAwContents();
223 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
224 contentsClient.getShouldOverrideUrlLoadingHelper();
225 OnPageStartedHelper onPageStartedHelper = contentsClient.getOnPageStartedHelper();
227 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
228 CommonResources.makeHtmlPageWithSimpleLinkTo(DATA_URL), "text/html", false);
230 final int shouldOverrideUrlLoadingCallCount = shouldOverrideUrlLoadingHelper.getCallCount();
231 final int onPageStartedCallCount = onPageStartedHelper.getCallCount();
232 setShouldOverrideUrlLoadingReturnValueOnUiThread(shouldOverrideUrlLoadingHelper, true);
233 clickOnLinkUsingJs(awContents, contentsClient);
235 shouldOverrideUrlLoadingHelper.waitForCallback(shouldOverrideUrlLoadingCallCount);
236 assertEquals(onPageStartedCallCount, onPageStartedHelper.getCallCount());
241 @Feature({"AndroidWebView", "Navigation"})
242 public void testDoesNotCauseOnReceivedError() throws Throwable {
243 final TestAwContentsClient contentsClient = new TestAwContentsClient();
244 final AwTestContainerView testContainerView =
245 createAwTestContainerViewOnMainSync(contentsClient);
246 final AwContents awContents = testContainerView.getAwContents();
247 final TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
248 contentsClient.getShouldOverrideUrlLoadingHelper();
249 OnReceivedErrorHelper onReceivedErrorHelper = contentsClient.getOnReceivedErrorHelper();
250 final int onReceivedErrorCallCount = onReceivedErrorHelper.getCallCount();
252 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
253 CommonResources.makeHtmlPageWithSimpleLinkTo(DATA_URL), "text/html", false);
255 final int shouldOverrideUrlLoadingCallCount = shouldOverrideUrlLoadingHelper.getCallCount();
257 setShouldOverrideUrlLoadingReturnValueOnUiThread(shouldOverrideUrlLoadingHelper, true);
259 clickOnLinkUsingJs(awContents, contentsClient);
261 shouldOverrideUrlLoadingHelper.waitForCallback(shouldOverrideUrlLoadingCallCount);
263 setShouldOverrideUrlLoadingReturnValueOnUiThread(shouldOverrideUrlLoadingHelper, false);
265 // After we load this URL we're certain that any in-flight callbacks for the previous
266 // navigation have been delivered.
267 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), ABOUT_BLANK_URL);
269 assertEquals(onReceivedErrorCallCount, onReceivedErrorHelper.getCallCount());
273 @Feature({"AndroidWebView", "Navigation"})
274 public void testNotCalledForAnchorNavigations() throws Throwable {
275 doTestNotCalledForAnchorNavigations(false);
279 @Feature({"AndroidWebView", "Navigation"})
280 public void testNotCalledForAnchorNavigationsWithNonHierarchicalScheme() throws Throwable {
281 doTestNotCalledForAnchorNavigations(true);
284 private void doTestNotCalledForAnchorNavigations(boolean useLoadData) throws Throwable {
285 final TestAwContentsClient contentsClient = new TestAwContentsClient();
286 final AwTestContainerView testContainerView =
287 createAwTestContainerViewOnMainSync(contentsClient);
288 final AwContents awContents = testContainerView.getAwContents();
289 final TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
290 contentsClient.getShouldOverrideUrlLoadingHelper();
292 final String anchorLinkPath = "/anchor_link.html";
293 final String anchorLinkUrl = mWebServer.getResponseUrl(anchorLinkPath);
294 addPageToTestServer(mWebServer, anchorLinkPath,
295 CommonResources.makeHtmlPageWithSimpleLinkTo(anchorLinkUrl + "#anchor"));
298 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
299 CommonResources.makeHtmlPageWithSimpleLinkTo("#anchor"), "text/html", false);
301 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), anchorLinkUrl);
304 final int shouldOverrideUrlLoadingCallCount =
305 shouldOverrideUrlLoadingHelper.getCallCount();
307 clickOnLinkUsingJs(awContents, contentsClient);
309 // After we load this URL we're certain that any in-flight callbacks for the previous
310 // navigation have been delivered.
311 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), ABOUT_BLANK_URL);
313 assertEquals(shouldOverrideUrlLoadingCallCount,
314 shouldOverrideUrlLoadingHelper.getCallCount());
318 @Feature({"AndroidWebView", "Navigation"})
319 public void testCalledWhenLinkClicked() throws Throwable {
320 final TestAwContentsClient contentsClient = new TestAwContentsClient();
321 final AwTestContainerView testContainerView =
322 createAwTestContainerViewOnMainSync(contentsClient);
323 final AwContents awContents = testContainerView.getAwContents();
324 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
325 contentsClient.getShouldOverrideUrlLoadingHelper();
327 // We can't go to about:blank from here because we'd get a cross-origin error.
328 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
329 CommonResources.makeHtmlPageWithSimpleLinkTo(DATA_URL), "text/html", false);
331 int callCount = shouldOverrideUrlLoadingHelper.getCallCount();
333 clickOnLinkUsingJs(awContents, contentsClient);
335 shouldOverrideUrlLoadingHelper.waitForCallback(callCount);
339 @Feature({"AndroidWebView", "Navigation"})
340 public void testCalledWhenTopLevelAboutBlankNavigation() throws Throwable {
341 final TestAwContentsClient contentsClient = new TestAwContentsClient();
342 final AwTestContainerView testContainerView =
343 createAwTestContainerViewOnMainSync(contentsClient);
344 final AwContents awContents = testContainerView.getAwContents();
345 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
346 contentsClient.getShouldOverrideUrlLoadingHelper();
348 final String httpPath = "/page_with_about_blank_navigation";
349 final String httpPathOnServer = mWebServer.getResponseUrl(httpPath);
350 addPageToTestServer(mWebServer, httpPath,
351 CommonResources.makeHtmlPageWithSimpleLinkTo(ABOUT_BLANK_URL));
353 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(),
356 int callCount = shouldOverrideUrlLoadingHelper.getCallCount();
358 clickOnLinkUsingJs(awContents, contentsClient);
360 shouldOverrideUrlLoadingHelper.waitForCallback(callCount);
361 assertEquals(ABOUT_BLANK_URL,
362 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
366 @Feature({"AndroidWebView", "Navigation"})
367 public void testCalledWhenSelfLinkClicked() throws Throwable {
368 final TestAwContentsClient contentsClient = new TestAwContentsClient();
369 final AwTestContainerView testContainerView =
370 createAwTestContainerViewOnMainSync(contentsClient);
371 final AwContents awContents = testContainerView.getAwContents();
372 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
373 contentsClient.getShouldOverrideUrlLoadingHelper();
375 final String httpPath = "/page_with_link_to_self.html";
376 final String httpPathOnServer = mWebServer.getResponseUrl(httpPath);
377 addPageToTestServer(mWebServer, httpPath,
378 CommonResources.makeHtmlPageWithSimpleLinkTo(httpPathOnServer));
380 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(),
383 int callCount = shouldOverrideUrlLoadingHelper.getCallCount();
385 clickOnLinkUsingJs(awContents, contentsClient);
387 shouldOverrideUrlLoadingHelper.waitForCallback(callCount);
388 assertEquals(httpPathOnServer,
389 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
393 @Feature({"AndroidWebView", "Navigation"})
394 public void testCalledWhenNavigatingFromJavaScriptUsingAssign()
396 final TestAwContentsClient contentsClient = new TestAwContentsClient();
397 final AwTestContainerView testContainerView =
398 createAwTestContainerViewOnMainSync(contentsClient);
399 final AwContents awContents = testContainerView.getAwContents();
400 enableJavaScriptOnUiThread(awContents);
401 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
402 contentsClient.getShouldOverrideUrlLoadingHelper();
404 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
405 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
406 getHtmlForPageWithJsAssignLinkTo(redirectTargetUrl), "text/html", false);
408 int callCount = shouldOverrideUrlLoadingHelper.getCallCount();
410 clickOnLinkUsingJs(awContents, contentsClient);
412 shouldOverrideUrlLoadingHelper.waitForCallback(callCount);
416 @Feature({"AndroidWebView", "Navigation"})
417 public void testCalledWhenNavigatingFromJavaScriptUsingReplace()
419 final TestAwContentsClient contentsClient = new TestAwContentsClient();
420 final AwTestContainerView testContainerView =
421 createAwTestContainerViewOnMainSync(contentsClient);
422 final AwContents awContents = testContainerView.getAwContents();
423 enableJavaScriptOnUiThread(awContents);
424 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
425 contentsClient.getShouldOverrideUrlLoadingHelper();
427 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
428 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
429 getHtmlForPageWithJsReplaceLinkTo(redirectTargetUrl), "text/html", false);
431 int callCount = shouldOverrideUrlLoadingHelper.getCallCount();
432 clickOnLinkUsingJs(awContents, contentsClient);
433 shouldOverrideUrlLoadingHelper.waitForCallback(callCount);
437 @Feature({"AndroidWebView", "Navigation"})
438 public void testPassesCorrectUrl() throws Throwable {
439 final TestAwContentsClient contentsClient = new TestAwContentsClient();
440 final AwTestContainerView testContainerView =
441 createAwTestContainerViewOnMainSync(contentsClient);
442 final AwContents awContents = testContainerView.getAwContents();
443 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
444 contentsClient.getShouldOverrideUrlLoadingHelper();
446 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
447 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
448 CommonResources.makeHtmlPageWithSimpleLinkTo(redirectTargetUrl), "text/html",
451 int callCount = shouldOverrideUrlLoadingHelper.getCallCount();
452 clickOnLinkUsingJs(awContents, contentsClient);
453 shouldOverrideUrlLoadingHelper.waitForCallback(callCount);
454 assertEquals(redirectTargetUrl,
455 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
459 @Feature({"AndroidWebView", "Navigation"})
460 public void testCanIgnoreLoading() throws Throwable {
461 final TestAwContentsClient contentsClient = new TestAwContentsClient();
462 final AwTestContainerView testContainerView =
463 createAwTestContainerViewOnMainSync(contentsClient);
464 final AwContents awContents = testContainerView.getAwContents();
465 final TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
466 contentsClient.getShouldOverrideUrlLoadingHelper();
468 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
469 final String pageWithLinkToIgnorePath = "/page_with_link_to_ignore.html";
470 final String pageWithLinkToIgnoreUrl = addPageToTestServer(mWebServer,
471 pageWithLinkToIgnorePath,
472 CommonResources.makeHtmlPageWithSimpleLinkTo(redirectTargetUrl));
473 final String synchronizationPath = "/sync.html";
474 final String synchronizationUrl = addPageToTestServer(mWebServer,
476 CommonResources.makeHtmlPageWithSimpleLinkTo(redirectTargetUrl));
478 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(),
479 pageWithLinkToIgnoreUrl);
481 setShouldOverrideUrlLoadingReturnValueOnUiThread(shouldOverrideUrlLoadingHelper, true);
483 int callCount = shouldOverrideUrlLoadingHelper.getCallCount();
484 clickOnLinkUsingJs(awContents, contentsClient);
485 // Some time around here true should be returned from the shouldOverrideUrlLoading
486 // callback causing the navigation caused by calling clickOnLinkUsingJs to be ignored.
487 // We validate this by checking which pages were loaded on the server.
488 shouldOverrideUrlLoadingHelper.waitForCallback(callCount);
490 setShouldOverrideUrlLoadingReturnValueOnUiThread(shouldOverrideUrlLoadingHelper, false);
492 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), synchronizationUrl);
494 assertEquals(1, mWebServer.getRequestCount(pageWithLinkToIgnorePath));
495 assertEquals(1, mWebServer.getRequestCount(synchronizationPath));
496 assertEquals(0, mWebServer.getRequestCount(REDIRECT_TARGET_PATH));
500 @Feature({"AndroidWebView", "Navigation"})
501 public void testCalledForDataUrl() throws Throwable {
502 final String dataUrl =
503 "data:text/html;base64," +
504 "PGh0bWw+PGhlYWQ+PHRpdGxlPmRhdGFVcmxUZXN0QmFzZTY0PC90aXRsZT48" +
505 "L2hlYWQ+PC9odG1sPg==";
506 final TestAwContentsClient contentsClient = new TestAwContentsClient();
507 final AwTestContainerView testContainerView =
508 createAwTestContainerViewOnMainSync(contentsClient);
509 final AwContents awContents = testContainerView.getAwContents();
510 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
511 contentsClient.getShouldOverrideUrlLoadingHelper();
512 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
513 CommonResources.makeHtmlPageWithSimpleLinkTo(dataUrl), "text/html", false);
515 int callCount = shouldOverrideUrlLoadingHelper.getCallCount();
516 clickOnLinkUsingJs(awContents, contentsClient);
518 shouldOverrideUrlLoadingHelper.waitForCallback(callCount);
519 assertTrue("Expected URL that starts with 'data:' but got: <" +
520 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl() + "> instead.",
521 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl().startsWith(
526 @Feature({"AndroidWebView", "Navigation"})
527 public void testCalledForUnsupportedSchemes() throws Throwable {
528 final TestAwContentsClient contentsClient = new TestAwContentsClient();
529 final AwTestContainerView testContainerView =
530 createAwTestContainerViewOnMainSync(contentsClient);
531 final AwContents awContents = testContainerView.getAwContents();
532 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
533 contentsClient.getShouldOverrideUrlLoadingHelper();
534 final String unsupportedSchemeUrl = "foobar://resource/1";
535 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
536 CommonResources.makeHtmlPageWithSimpleLinkTo(unsupportedSchemeUrl), "text/html",
539 int callCount = shouldOverrideUrlLoadingHelper.getCallCount();
540 clickOnLinkUsingJs(awContents, contentsClient);
542 shouldOverrideUrlLoadingHelper.waitForCallback(callCount);
543 assertEquals(unsupportedSchemeUrl,
544 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
548 @Feature({"AndroidWebView", "Navigation"})
549 public void testNotCalledForPostNavigations() throws Throwable {
550 // The reason POST requests are excluded is BUG 155250.
551 final TestAwContentsClient contentsClient = new TestAwContentsClient();
552 final AwTestContainerView testContainerView =
553 createAwTestContainerViewOnMainSync(contentsClient);
554 final AwContents awContents = testContainerView.getAwContents();
555 final TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
556 contentsClient.getShouldOverrideUrlLoadingHelper();
558 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
559 final String postLinkUrl = addPageToTestServer(mWebServer, "/page_with_post_link.html",
560 CommonResources.makeHtmlPageWithSimplePostFormTo(redirectTargetUrl));
562 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), postLinkUrl);
564 final int shouldOverrideUrlLoadingCallCount =
565 shouldOverrideUrlLoadingHelper.getCallCount();
567 assertEquals(0, mWebServer.getRequestCount(REDIRECT_TARGET_PATH));
568 clickOnLinkUsingJs(awContents, contentsClient);
570 // Wait for the target URL to be fetched from the server.
571 poll(new Callable<Boolean>() {
573 public Boolean call() throws Exception {
574 return mWebServer.getRequestCount(REDIRECT_TARGET_PATH) == 1;
578 // Since the targetURL was loaded from the test server it means all processing related
579 // to dispatching a shouldOverrideUrlLoading callback had finished and checking the call
581 assertEquals(shouldOverrideUrlLoadingCallCount,
582 shouldOverrideUrlLoadingHelper.getCallCount());
586 @Feature({"AndroidWebView", "Navigation"})
587 public void testCalledFor302AfterPostNavigations() throws Throwable {
588 // The reason POST requests are excluded is BUG 155250.
589 final TestAwContentsClient contentsClient = new TestAwContentsClient();
590 final AwTestContainerView testContainerView =
591 createAwTestContainerViewOnMainSync(contentsClient);
592 final AwContents awContents = testContainerView.getAwContents();
593 final TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
594 contentsClient.getShouldOverrideUrlLoadingHelper();
596 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
597 final String postToGetRedirectUrl = mWebServer.setRedirect("/302.html", redirectTargetUrl);
598 final String postLinkUrl = addPageToTestServer(mWebServer, "/page_with_post_link.html",
599 CommonResources.makeHtmlPageWithSimplePostFormTo(postToGetRedirectUrl));
601 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), postLinkUrl);
603 final int shouldOverrideUrlLoadingCallCount =
604 shouldOverrideUrlLoadingHelper.getCallCount();
606 clickOnLinkUsingJs(awContents, contentsClient);
608 shouldOverrideUrlLoadingHelper.waitForCallback(shouldOverrideUrlLoadingCallCount);
610 // Wait for the target URL to be fetched from the server.
611 poll(new Callable<Boolean>() {
613 public Boolean call() throws Exception {
614 return mWebServer.getRequestCount(REDIRECT_TARGET_PATH) == 1;
618 assertEquals(redirectTargetUrl,
619 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
623 @Feature({"AndroidWebView", "Navigation"})
624 public void testNotCalledForIframeHttpNavigations() throws Throwable {
625 final TestAwContentsClient contentsClient = new TestAwContentsClient();
626 final AwTestContainerView testContainerView =
627 createAwTestContainerViewOnMainSync(contentsClient);
628 final AwContents awContents = testContainerView.getAwContents();
629 final TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
630 contentsClient.getShouldOverrideUrlLoadingHelper();
632 final String iframeRedirectTargetUrl = createRedirectTargetPage(mWebServer);
633 final String iframeRedirectUrl =
634 mWebServer.setRedirect("/302.html", iframeRedirectTargetUrl);
635 final String pageWithIframeUrl =
636 addPageToTestServer(mWebServer, "/iframe_intercept.html",
637 makeHtmlPageFrom("", "<iframe src=\"" + iframeRedirectUrl + "\" />"));
639 final int shouldOverrideUrlLoadingCallCount =
640 shouldOverrideUrlLoadingHelper.getCallCount();
642 assertEquals(0, mWebServer.getRequestCount(REDIRECT_TARGET_PATH));
643 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), pageWithIframeUrl);
645 // Wait for the redirect target URL to be fetched from the server.
646 poll(new Callable<Boolean>() {
648 public Boolean call() throws Exception {
649 return mWebServer.getRequestCount(REDIRECT_TARGET_PATH) == 1;
653 assertEquals(shouldOverrideUrlLoadingCallCount,
654 shouldOverrideUrlLoadingHelper.getCallCount());
658 @Feature({"AndroidWebView", "Navigation"})
659 public void testCalledForIframeUnsupportedSchemeNavigations() throws Throwable {
660 final TestAwContentsClient contentsClient = new TestAwContentsClient();
661 final AwTestContainerView testContainerView =
662 createAwTestContainerViewOnMainSync(contentsClient);
663 final AwContents awContents = testContainerView.getAwContents();
664 final TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
665 contentsClient.getShouldOverrideUrlLoadingHelper();
667 final String unsupportedSchemeUrl = "foobar://resource/1";
668 final String pageWithIframeUrl =
669 addPageToTestServer(mWebServer, "/iframe_intercept.html",
670 makeHtmlPageFrom("", "<iframe src=\"" + unsupportedSchemeUrl + "\" />"));
672 final int shouldOverrideUrlLoadingCallCount =
673 shouldOverrideUrlLoadingHelper.getCallCount();
675 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), pageWithIframeUrl);
677 shouldOverrideUrlLoadingHelper.waitForCallback(shouldOverrideUrlLoadingCallCount);
678 assertEquals(unsupportedSchemeUrl,
679 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
683 * Worker method for the various redirect tests.
685 * Calling this will first load the redirect URL built from redirectFilePath, query and
686 * locationFilePath and assert that we get a override callback for the destination.
687 * The second part of the test loads a page that contains a link which points at the redirect
688 * URL. We expect two callbacks - one for the redirect link and another for the destination.
690 private void doTestCalledOnRedirect(TestWebServer webServer,
691 String redirectUrl, String redirectTarget) throws Throwable {
692 final TestAwContentsClient contentsClient = new TestAwContentsClient();
693 final AwTestContainerView testContainerView =
694 createAwTestContainerViewOnMainSync(contentsClient);
695 final AwContents awContents = testContainerView.getAwContents();
696 final String pageWithLinkToRedirectUrl = addPageToTestServer(webServer,
697 "/page_with_link_to_redirect.html",
698 CommonResources.makeHtmlPageWithSimpleLinkTo(redirectUrl));
699 enableJavaScriptOnUiThread(awContents);
701 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
702 contentsClient.getShouldOverrideUrlLoadingHelper();
703 int directLoadCallCount = shouldOverrideUrlLoadingHelper.getCallCount();
704 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), redirectUrl);
706 shouldOverrideUrlLoadingHelper.waitForCallback(directLoadCallCount, 1);
707 assertEquals(redirectTarget,
708 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
710 // There is a slight difference between navigations caused by calling load and navigations
711 // caused by clicking on a link:
712 // * when using load the navigation is treated as if it came from the URL bar (has the
713 // navigation type TYPED and doesn't have the has_user_gesture flag)
714 // * when clicking on a link the navigation has the LINK type and has_user_gesture is
716 // Both of these should yield the same result which is what we're verifying here.
717 int indirectLoadCallCount = shouldOverrideUrlLoadingHelper.getCallCount();
718 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(),
719 pageWithLinkToRedirectUrl);
721 assertEquals(indirectLoadCallCount, shouldOverrideUrlLoadingHelper.getCallCount());
723 clickOnLinkUsingJs(awContents, contentsClient);
725 shouldOverrideUrlLoadingHelper.waitForCallback(indirectLoadCallCount, 2);
726 assertEquals(redirectTarget,
727 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
728 assertEquals(redirectUrl,
729 shouldOverrideUrlLoadingHelper.getPreviousShouldOverrideUrlLoadingUrl());
733 @Feature({"AndroidWebView", "Navigation"})
734 public void testCalledOn302Redirect() throws Throwable {
735 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
736 final String redirectUrl = mWebServer.setRedirect("/302.html", redirectTargetUrl);
738 doTestCalledOnRedirect(mWebServer, redirectUrl, redirectTargetUrl);
742 @Feature({"AndroidWebView", "Navigation"})
743 public void testCalledOnMetaRefreshRedirect() throws Throwable {
744 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
745 final String redirectUrl = addPageToTestServer(mWebServer, "/meta_refresh.html",
746 getHtmlForPageWithMetaRefreshRedirectTo(redirectTargetUrl));
747 doTestCalledOnRedirect(mWebServer, redirectUrl, redirectTargetUrl);
752 @Feature({"AndroidWebView", "Navigation"})
753 public void testCalledOnJavaScriptLocationImmediateAssignRedirect()
755 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
756 final String redirectUrl = addPageToTestServer(mWebServer, "/js_immediate_assign.html",
757 getHtmlForPageWithJsRedirectTo(redirectTargetUrl, "Assign", 0));
758 doTestCalledOnRedirect(mWebServer, redirectUrl, redirectTargetUrl);
762 @Feature({"AndroidWebView", "Navigation"})
763 public void testCalledOnJavaScriptLocationImmediateReplaceRedirect()
765 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
766 final String redirectUrl = addPageToTestServer(mWebServer, "/js_immediate_replace.html",
767 getHtmlForPageWithJsRedirectTo(redirectTargetUrl, "Replace", 0));
768 doTestCalledOnRedirect(mWebServer, redirectUrl, redirectTargetUrl);
772 @Feature({"AndroidWebView", "Navigation"})
773 public void testCalledOnJavaScriptLocationDelayedAssignRedirect()
775 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
776 final String redirectUrl = addPageToTestServer(mWebServer, "/js_delayed_assign.html",
777 getHtmlForPageWithJsRedirectTo(redirectTargetUrl, "Assign", 100));
778 doTestCalledOnRedirect(mWebServer, redirectUrl, redirectTargetUrl);
782 @Feature({"AndroidWebView", "Navigation"})
783 public void testCalledOnJavaScriptLocationDelayedReplaceRedirect()
785 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
786 final String redirectUrl = addPageToTestServer(mWebServer, "/js_delayed_replace.html",
787 getHtmlForPageWithJsRedirectTo(redirectTargetUrl, "Replace", 100));
788 doTestCalledOnRedirect(mWebServer, redirectUrl, redirectTargetUrl);
792 @Feature({"AndroidWebView", "Navigation"})
793 public void testDoubleNavigateDoesNotSuppressInitialNavigate() throws Throwable {
794 final String jsUrl = "javascript:try{console.log('processed js loadUrl');}catch(e){};";
795 final TestAwContentsClient contentsClient = new TestAwContentsClient();
796 final AwTestContainerView testContainerView =
797 createAwTestContainerViewOnMainSync(contentsClient);
798 final AwContents awContents = testContainerView.getAwContents();
799 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
800 contentsClient.getShouldOverrideUrlLoadingHelper();
802 // Do a double navigagtion, the second being an effective no-op, in quick succession (i.e.
803 // without yielding the main thread inbetween).
804 int currentCallCount = contentsClient.getOnPageFinishedHelper().getCallCount();
805 getInstrumentation().runOnMainSync(new Runnable() {
808 awContents.loadUrl(LoadUrlParams.createLoadDataParams(
809 CommonResources.makeHtmlPageWithSimpleLinkTo(DATA_URL), "text/html",
811 awContents.loadUrl(new LoadUrlParams(jsUrl));
814 contentsClient.getOnPageFinishedHelper().waitForCallback(currentCallCount, 1,
815 WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
817 assertEquals(0, shouldOverrideUrlLoadingHelper.getCallCount());