1 // Copyright (c) 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.os.Bundle;
8 import android.os.SystemClock;
9 import android.test.suitebuilder.annotation.SmallTest;
10 import android.util.Pair;
11 import android.view.MotionEvent;
12 import android.util.Log;
14 import org.chromium.android_webview.AwContents;
15 import org.chromium.android_webview.test.util.CommonResources;
16 import org.chromium.android_webview.test.util.JSUtils;
17 import org.chromium.base.test.util.Feature;
18 import org.chromium.content.browser.NavigationHistory;
19 import org.chromium.content.browser.LoadUrlParams;
20 import org.chromium.content.browser.test.util.CallbackHelper;
21 import org.chromium.content.browser.test.util.Criteria;
22 import org.chromium.content.browser.test.util.CriteriaHelper;
23 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageFinishedHelper;
24 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageStartedHelper;
25 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnReceivedErrorHelper;
26 import org.chromium.net.test.util.TestWebServer;
28 import java.net.URLEncoder;
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.concurrent.Callable;
32 import java.util.concurrent.TimeUnit;
35 * Tests for the WebViewClient.shouldOverrideUrlLoading() method.
37 public class AwContentsClientShouldOverrideUrlLoadingTest extends AwTestBase {
38 private final static String ABOUT_BLANK_URL = "about:blank";
39 private final static String DATA_URL = "data:text/html,<div/>";
40 private final static String REDIRECT_TARGET_PATH = "/redirect_target.html";
41 private final static String TITLE = "TITLE";
43 private static final long TEST_TIMEOUT = 20000L;
44 private static final long CHECK_INTERVAL = 100;
46 private static class TestAwContentsClient
47 extends org.chromium.android_webview.test.TestAwContentsClient {
49 public static class ShouldOverrideUrlLoadingHelper extends CallbackHelper {
50 private String mShouldOverrideUrlLoadingUrl;
51 private String mPreviousShouldOverrideUrlLoadingUrl;
52 private boolean mShouldOverrideUrlLoadingReturnValue = false;
53 void setShouldOverrideUrlLoadingUrl(String url) {
54 mShouldOverrideUrlLoadingUrl = url;
56 void setPreviousShouldOverrideUrlLoadingUrl(String url) {
57 mPreviousShouldOverrideUrlLoadingUrl = url;
59 void setShouldOverrideUrlLoadingReturnValue(boolean value) {
60 mShouldOverrideUrlLoadingReturnValue = value;
62 public String getShouldOverrideUrlLoadingUrl() {
63 assert getCallCount() > 0;
64 return mShouldOverrideUrlLoadingUrl;
66 public String getPreviousShouldOverrideUrlLoadingUrl() {
67 assert getCallCount() > 1;
68 return mPreviousShouldOverrideUrlLoadingUrl;
70 public boolean getShouldOverrideUrlLoadingReturnValue() {
71 return mShouldOverrideUrlLoadingReturnValue;
73 public void notifyCalled(String url) {
74 mPreviousShouldOverrideUrlLoadingUrl = mShouldOverrideUrlLoadingUrl;
75 mShouldOverrideUrlLoadingUrl = url;
81 public boolean shouldOverrideUrlLoading(String url) {
82 super.shouldOverrideUrlLoading(url);
84 mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingReturnValue();
85 mShouldOverrideUrlLoadingHelper.notifyCalled(url);
89 private ShouldOverrideUrlLoadingHelper mShouldOverrideUrlLoadingHelper;
91 public TestAwContentsClient() {
92 mShouldOverrideUrlLoadingHelper = new ShouldOverrideUrlLoadingHelper();
95 public ShouldOverrideUrlLoadingHelper getShouldOverrideUrlLoadingHelper() {
96 return mShouldOverrideUrlLoadingHelper;
100 private TestWebServer mWebServer;
103 protected void setUp() throws Exception {
105 mWebServer = new TestWebServer(false);
109 protected void tearDown() throws Exception {
110 mWebServer.shutdown();
114 private void clickOnLinkUsingJs(final AwContents awContents,
115 final TestAwContentsClient contentsClient) throws Throwable {
116 enableJavaScriptOnUiThread(awContents);
117 JSUtils.clickOnLinkUsingJs(this, awContents,
118 contentsClient.getOnEvaluateJavaScriptResultHelper(), "link");
121 // Since this value is read on the UI thread, it's simpler to set it there too.
122 void setShouldOverrideUrlLoadingReturnValueOnUiThread(
123 final TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideHelper,
124 final boolean value) throws Throwable {
125 runTestOnUiThread(new Runnable() {
128 shouldOverrideHelper.setShouldOverrideUrlLoadingReturnValue(value);
133 private String makeHtmlPageFrom(String headers, String body) {
134 return CommonResources.makeHtmlPageFrom("<title>" + TITLE + "</title> " + headers, body);
137 private String getHtmlForPageWithSimpleLinkTo(String destination) {
138 return makeHtmlPageFrom("",
139 "<a href=\"" + destination + "\" id=\"link\">" +
140 "<img class=\"big\" />" +
144 private String getHtmlForPageWithJsAssignLinkTo(String url) {
145 return makeHtmlPageFrom("",
146 "<img onclick=\"location.href='" + url + "'\" class=\"big\" id=\"link\" />");
149 private String getHtmlForPageWithJsReplaceLinkTo(String url) {
150 return makeHtmlPageFrom("",
151 "<img onclick=\"location.replace('" + url + "');\" class=\"big\" id=\"link\" />");
154 private String getHtmlForPageWithMetaRefreshRedirectTo(String url) {
155 return makeHtmlPageFrom("<meta http-equiv=\"refresh\" content=\"0;url=" + url + "\" />",
156 "<div>Meta refresh redirect</div>");
159 private String getHtmlForPageWithJsRedirectTo(String url, String method, int timeout) {
160 return makeHtmlPageFrom(
162 "function doRedirectAssign() {" +
163 "location.href = '" + url + "';" +
165 "function doRedirectReplace() {" +
166 "location.replace('" + url + "');" +
169 String.format("<iframe onLoad=\"setTimeout('doRedirect%s()', %d);\" />",
173 private String getHtmlForPageWithSimplePostFormTo(String destination) {
174 return makeHtmlPageFrom("",
175 "<form action=\"" + destination + "\" method=\"post\">" +
176 "<input type=\"submit\" value=\"post\" id=\"link\">"+
180 private String addPageToTestServer(TestWebServer webServer, String httpPath, String html) {
181 List<Pair<String, String>> headers = new ArrayList<Pair<String, String>>();
182 headers.add(Pair.create("Content-Type", "text/html"));
183 headers.add(Pair.create("Cache-Control", "no-store"));
184 return webServer.setResponse(httpPath, html, headers);
187 private String createRedirectTargetPage(TestWebServer webServer) {
188 return addPageToTestServer(webServer, REDIRECT_TARGET_PATH,
189 makeHtmlPageFrom("", "<div>This is the end of the redirect chain</div>"));
193 @Feature({"AndroidWebView", "Navigation"})
194 public void testNotCalledOnLoadUrl() throws Throwable {
195 final TestAwContentsClient contentsClient = new TestAwContentsClient();
196 final AwTestContainerView testContainerView =
197 createAwTestContainerViewOnMainSync(contentsClient);
198 final AwContents awContents = testContainerView.getAwContents();
199 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
200 contentsClient.getShouldOverrideUrlLoadingHelper();
202 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
203 getHtmlForPageWithSimpleLinkTo(DATA_URL), "text/html", false);
205 assertEquals(0, shouldOverrideUrlLoadingHelper.getCallCount());
208 private void waitForNavigationRunnableAndAssertTitleChanged(AwContents awContents,
209 CallbackHelper onPageFinishedHelper,
210 Runnable navigationRunnable) throws Exception {
211 final int callCount = onPageFinishedHelper.getCallCount();
212 final String oldTitle = getTitleOnUiThread(awContents);
213 getInstrumentation().runOnMainSync(navigationRunnable);
214 onPageFinishedHelper.waitForCallback(callCount);
215 assertFalse(oldTitle.equals(getTitleOnUiThread(awContents)));
219 @Feature({"AndroidWebView", "Navigation"})
220 public void testNotCalledOnBackForwardNavigation() throws Throwable {
221 final TestAwContentsClient contentsClient = new TestAwContentsClient();
222 final AwTestContainerView testContainerView =
223 createAwTestContainerViewOnMainSync(contentsClient);
224 final AwContents awContents = testContainerView.getAwContents();
225 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
226 contentsClient.getShouldOverrideUrlLoadingHelper();
227 final String[] pageTitles = new String[] { "page1", "page2", "page3" };
229 for (String title: pageTitles) {
230 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
231 CommonResources.makeHtmlPageFrom("<title>" + title + "</title>", ""),
234 assertEquals(0, shouldOverrideUrlLoadingHelper.getCallCount());
236 waitForNavigationRunnableAndAssertTitleChanged(awContents,
237 contentsClient.getOnPageFinishedHelper(), new Runnable() {
243 assertEquals(0, shouldOverrideUrlLoadingHelper.getCallCount());
245 waitForNavigationRunnableAndAssertTitleChanged(awContents,
246 contentsClient.getOnPageFinishedHelper(), new Runnable() {
249 awContents.goForward();
252 assertEquals(0, shouldOverrideUrlLoadingHelper.getCallCount());
254 waitForNavigationRunnableAndAssertTitleChanged(awContents,
255 contentsClient.getOnPageFinishedHelper(), new Runnable() {
258 awContents.goBackOrForward(-2);
261 assertEquals(0, shouldOverrideUrlLoadingHelper.getCallCount());
263 waitForNavigationRunnableAndAssertTitleChanged(awContents,
264 contentsClient.getOnPageFinishedHelper(), new Runnable() {
267 awContents.goBackOrForward(1);
270 assertEquals(0, shouldOverrideUrlLoadingHelper.getCallCount());
274 @Feature({"AndroidWebView", "Navigation"})
275 public void testCantBlockLoads() throws Throwable {
276 final TestAwContentsClient contentsClient = new TestAwContentsClient();
277 final AwTestContainerView testContainerView =
278 createAwTestContainerViewOnMainSync(contentsClient);
279 final AwContents awContents = testContainerView.getAwContents();
280 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
281 contentsClient.getShouldOverrideUrlLoadingHelper();
283 setShouldOverrideUrlLoadingReturnValueOnUiThread(shouldOverrideUrlLoadingHelper, true);
285 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
286 getHtmlForPageWithSimpleLinkTo(DATA_URL), "text/html", false);
288 assertEquals(TITLE, getTitleOnUiThread(awContents));
292 @Feature({"AndroidWebView", "Navigation"})
293 public void testCalledBeforeOnPageStarted() throws Throwable {
294 final TestAwContentsClient contentsClient = new TestAwContentsClient();
295 final AwTestContainerView testContainerView =
296 createAwTestContainerViewOnMainSync(contentsClient);
297 final AwContents awContents = testContainerView.getAwContents();
298 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
299 contentsClient.getShouldOverrideUrlLoadingHelper();
300 OnPageStartedHelper onPageStartedHelper = contentsClient.getOnPageStartedHelper();
302 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
303 getHtmlForPageWithSimpleLinkTo(DATA_URL), "text/html", false);
305 final int shouldOverrideUrlLoadingCallCount = shouldOverrideUrlLoadingHelper.getCallCount();
306 final int onPageStartedCallCount = onPageStartedHelper.getCallCount();
307 setShouldOverrideUrlLoadingReturnValueOnUiThread(shouldOverrideUrlLoadingHelper, true);
308 clickOnLinkUsingJs(awContents, contentsClient);
310 shouldOverrideUrlLoadingHelper.waitForCallback(shouldOverrideUrlLoadingCallCount);
311 assertEquals(onPageStartedCallCount, onPageStartedHelper.getCallCount());
316 @Feature({"AndroidWebView", "Navigation"})
317 public void testDoesNotCauseOnReceivedError() throws Throwable {
318 final TestAwContentsClient contentsClient = new TestAwContentsClient();
319 final AwTestContainerView testContainerView =
320 createAwTestContainerViewOnMainSync(contentsClient);
321 final AwContents awContents = testContainerView.getAwContents();
322 final TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
323 contentsClient.getShouldOverrideUrlLoadingHelper();
324 OnReceivedErrorHelper onReceivedErrorHelper = contentsClient.getOnReceivedErrorHelper();
325 final int onReceivedErrorCallCount = onReceivedErrorHelper.getCallCount();
327 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
328 getHtmlForPageWithSimpleLinkTo(DATA_URL), "text/html", false);
330 final int shouldOverrideUrlLoadingCallCount = shouldOverrideUrlLoadingHelper.getCallCount();
332 setShouldOverrideUrlLoadingReturnValueOnUiThread(shouldOverrideUrlLoadingHelper, true);
334 clickOnLinkUsingJs(awContents, contentsClient);
336 shouldOverrideUrlLoadingHelper.waitForCallback(shouldOverrideUrlLoadingCallCount);
338 setShouldOverrideUrlLoadingReturnValueOnUiThread(shouldOverrideUrlLoadingHelper, false);
340 // After we load this URL we're certain that any in-flight callbacks for the previous
341 // navigation have been delivered.
342 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), ABOUT_BLANK_URL);
344 assertEquals(onReceivedErrorCallCount, onReceivedErrorHelper.getCallCount());
348 @Feature({"AndroidWebView", "Navigation"})
349 public void testNotCalledForAnchorNavigations() throws Throwable {
350 final TestAwContentsClient contentsClient = new TestAwContentsClient();
351 final AwTestContainerView testContainerView =
352 createAwTestContainerViewOnMainSync(contentsClient);
353 final AwContents awContents = testContainerView.getAwContents();
354 final TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
355 contentsClient.getShouldOverrideUrlLoadingHelper();
357 final String anchorLinkPath = "/anchor_link.html";
358 final String anchorLinkUrl = mWebServer.getResponseUrl(anchorLinkPath);
359 addPageToTestServer(mWebServer, anchorLinkPath,
360 getHtmlForPageWithSimpleLinkTo(anchorLinkUrl + "#anchor"));
362 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), anchorLinkUrl);
364 final int shouldOverrideUrlLoadingCallCount =
365 shouldOverrideUrlLoadingHelper.getCallCount();
367 clickOnLinkUsingJs(awContents, contentsClient);
369 // After we load this URL we're certain that any in-flight callbacks for the previous
370 // navigation have been delivered.
371 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), ABOUT_BLANK_URL);
373 assertEquals(shouldOverrideUrlLoadingCallCount,
374 shouldOverrideUrlLoadingHelper.getCallCount());
378 @Feature({"AndroidWebView", "Navigation"})
379 public void testCalledWhenLinkClicked() throws Throwable {
380 final TestAwContentsClient contentsClient = new TestAwContentsClient();
381 final AwTestContainerView testContainerView =
382 createAwTestContainerViewOnMainSync(contentsClient);
383 final AwContents awContents = testContainerView.getAwContents();
384 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
385 contentsClient.getShouldOverrideUrlLoadingHelper();
387 // We can't go to about:blank from here because we'd get a cross-origin error.
388 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
389 getHtmlForPageWithSimpleLinkTo(DATA_URL), "text/html", false);
391 int callCount = shouldOverrideUrlLoadingHelper.getCallCount();
393 clickOnLinkUsingJs(awContents, contentsClient);
395 shouldOverrideUrlLoadingHelper.waitForCallback(callCount);
400 @Feature({"AndroidWebView", "Navigation"})
401 public void testCalledWhenSelfLinkClicked() throws Throwable {
402 final TestAwContentsClient contentsClient = new TestAwContentsClient();
403 final AwTestContainerView testContainerView =
404 createAwTestContainerViewOnMainSync(contentsClient);
405 final AwContents awContents = testContainerView.getAwContents();
406 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
407 contentsClient.getShouldOverrideUrlLoadingHelper();
409 final String httpPath = "/page_with_link_to_self.html";
410 final String httpPathOnServer = mWebServer.getResponseUrl(httpPath);
411 addPageToTestServer(mWebServer, httpPath,
412 getHtmlForPageWithSimpleLinkTo(httpPathOnServer));
414 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(),
417 int callCount = shouldOverrideUrlLoadingHelper.getCallCount();
419 clickOnLinkUsingJs(awContents, contentsClient);
421 shouldOverrideUrlLoadingHelper.waitForCallback(callCount);
422 assertEquals(httpPathOnServer,
423 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
427 @Feature({"AndroidWebView", "Navigation"})
428 public void testCalledWhenNavigatingFromJavaScriptUsingAssign()
430 final TestAwContentsClient contentsClient = new TestAwContentsClient();
431 final AwTestContainerView testContainerView =
432 createAwTestContainerViewOnMainSync(contentsClient);
433 final AwContents awContents = testContainerView.getAwContents();
434 enableJavaScriptOnUiThread(awContents);
435 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
436 contentsClient.getShouldOverrideUrlLoadingHelper();
438 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
439 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
440 getHtmlForPageWithJsAssignLinkTo(redirectTargetUrl), "text/html", false);
442 int callCount = shouldOverrideUrlLoadingHelper.getCallCount();
444 clickOnLinkUsingJs(awContents, contentsClient);
446 shouldOverrideUrlLoadingHelper.waitForCallback(callCount);
450 @Feature({"AndroidWebView", "Navigation"})
451 public void testCalledWhenNavigatingFromJavaScriptUsingReplace()
453 final TestAwContentsClient contentsClient = new TestAwContentsClient();
454 final AwTestContainerView testContainerView =
455 createAwTestContainerViewOnMainSync(contentsClient);
456 final AwContents awContents = testContainerView.getAwContents();
457 enableJavaScriptOnUiThread(awContents);
458 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
459 contentsClient.getShouldOverrideUrlLoadingHelper();
461 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
462 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
463 getHtmlForPageWithJsReplaceLinkTo(redirectTargetUrl), "text/html", false);
465 int callCount = shouldOverrideUrlLoadingHelper.getCallCount();
466 clickOnLinkUsingJs(awContents, contentsClient);
467 shouldOverrideUrlLoadingHelper.waitForCallback(callCount);
471 @Feature({"AndroidWebView", "Navigation"})
472 public void testPassesCorrectUrl() throws Throwable {
473 final TestAwContentsClient contentsClient = new TestAwContentsClient();
474 final AwTestContainerView testContainerView =
475 createAwTestContainerViewOnMainSync(contentsClient);
476 final AwContents awContents = testContainerView.getAwContents();
477 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
478 contentsClient.getShouldOverrideUrlLoadingHelper();
480 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
481 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
482 getHtmlForPageWithSimpleLinkTo(redirectTargetUrl), "text/html", false);
484 int callCount = shouldOverrideUrlLoadingHelper.getCallCount();
485 clickOnLinkUsingJs(awContents, contentsClient);
486 shouldOverrideUrlLoadingHelper.waitForCallback(callCount);
487 assertEquals(redirectTargetUrl,
488 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
492 @Feature({"AndroidWebView", "Navigation"})
493 public void testCanIgnoreLoading() throws Throwable {
494 final TestAwContentsClient contentsClient = new TestAwContentsClient();
495 final AwTestContainerView testContainerView =
496 createAwTestContainerViewOnMainSync(contentsClient);
497 final AwContents awContents = testContainerView.getAwContents();
498 final TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
499 contentsClient.getShouldOverrideUrlLoadingHelper();
501 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
502 final String pageWithLinkToIgnorePath = "/page_with_link_to_ignore.html";
503 final String pageWithLinkToIgnoreUrl = addPageToTestServer(mWebServer,
504 pageWithLinkToIgnorePath,
505 getHtmlForPageWithSimpleLinkTo(redirectTargetUrl));
506 final String synchronizationPath = "/sync.html";
507 final String synchronizationUrl = addPageToTestServer(mWebServer,
509 getHtmlForPageWithSimpleLinkTo(redirectTargetUrl));
511 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(),
512 pageWithLinkToIgnoreUrl);
514 setShouldOverrideUrlLoadingReturnValueOnUiThread(shouldOverrideUrlLoadingHelper, true);
516 int callCount = shouldOverrideUrlLoadingHelper.getCallCount();
517 int onPageFinishedCallCount = contentsClient.getOnPageFinishedHelper().getCallCount();
518 clickOnLinkUsingJs(awContents, contentsClient);
519 // Some time around here true should be returned from the shouldOverrideUrlLoading
520 // callback causing the navigation caused by calling clickOnLinkUsingJs to be ignored.
521 // We validate this by checking which pages were loaded on the server.
522 shouldOverrideUrlLoadingHelper.waitForCallback(callCount);
524 setShouldOverrideUrlLoadingReturnValueOnUiThread(shouldOverrideUrlLoadingHelper, false);
526 // We need to wait for the navigation to complete before we can initiate another load.
527 contentsClient.getOnPageFinishedHelper().waitForCallback(onPageFinishedCallCount);
528 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), synchronizationUrl);
530 assertEquals(1, mWebServer.getRequestCount(pageWithLinkToIgnorePath));
531 assertEquals(1, mWebServer.getRequestCount(synchronizationPath));
532 assertEquals(0, mWebServer.getRequestCount(REDIRECT_TARGET_PATH));
536 @Feature({"AndroidWebView", "Navigation"})
537 public void testCalledForDataUrl() throws Throwable {
538 final String dataUrl =
539 "data:text/html;base64," +
540 "PGh0bWw+PGhlYWQ+PHRpdGxlPmRhdGFVcmxUZXN0QmFzZTY0PC90aXRsZT48" +
541 "L2hlYWQ+PC9odG1sPg==";
542 final TestAwContentsClient contentsClient = new TestAwContentsClient();
543 final AwTestContainerView testContainerView =
544 createAwTestContainerViewOnMainSync(contentsClient);
545 final AwContents awContents = testContainerView.getAwContents();
546 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
547 contentsClient.getShouldOverrideUrlLoadingHelper();
548 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
549 getHtmlForPageWithSimpleLinkTo(dataUrl), "text/html", false);
551 int callCount = shouldOverrideUrlLoadingHelper.getCallCount();
552 clickOnLinkUsingJs(awContents, contentsClient);
554 shouldOverrideUrlLoadingHelper.waitForCallback(callCount);
555 assertTrue("Expected URL that starts with 'data:' but got: <" +
556 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl() + "> instead.",
557 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl().startsWith(
562 @Feature({"AndroidWebView", "Navigation"})
563 public void testCalledForUnsupportedSchemes() throws Throwable {
564 final TestAwContentsClient contentsClient = new TestAwContentsClient();
565 final AwTestContainerView testContainerView =
566 createAwTestContainerViewOnMainSync(contentsClient);
567 final AwContents awContents = testContainerView.getAwContents();
568 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
569 contentsClient.getShouldOverrideUrlLoadingHelper();
570 final String unsupportedSchemeUrl = "foobar://resource/1";
571 loadDataSync(awContents, contentsClient.getOnPageFinishedHelper(),
572 getHtmlForPageWithSimpleLinkTo(unsupportedSchemeUrl), "text/html", false);
574 int callCount = shouldOverrideUrlLoadingHelper.getCallCount();
575 clickOnLinkUsingJs(awContents, contentsClient);
577 shouldOverrideUrlLoadingHelper.waitForCallback(callCount);
578 assertEquals(unsupportedSchemeUrl,
579 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
583 @Feature({"AndroidWebView", "Navigation"})
584 public void testNotCalledForPostNavigations() throws Throwable {
585 // The reason POST requests are excluded is BUG 155250.
586 final TestAwContentsClient contentsClient = new TestAwContentsClient();
587 final AwTestContainerView testContainerView =
588 createAwTestContainerViewOnMainSync(contentsClient);
589 final AwContents awContents = testContainerView.getAwContents();
590 final TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
591 contentsClient.getShouldOverrideUrlLoadingHelper();
593 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
594 final String postLinkUrl = addPageToTestServer(mWebServer, "/page_with_post_link.html",
595 getHtmlForPageWithSimplePostFormTo(redirectTargetUrl));
597 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), postLinkUrl);
599 final int shouldOverrideUrlLoadingCallCount =
600 shouldOverrideUrlLoadingHelper.getCallCount();
602 assertEquals(0, mWebServer.getRequestCount(REDIRECT_TARGET_PATH));
603 clickOnLinkUsingJs(awContents, contentsClient);
605 // Wait for the target URL to be fetched from the server.
606 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
608 public boolean isSatisfied() {
609 return mWebServer.getRequestCount(REDIRECT_TARGET_PATH) == 1;
611 }, WAIT_TIMEOUT_SECONDS * 1000L, CHECK_INTERVAL));
613 // Since the targetURL was loaded from the test server it means all processing related
614 // to dispatching a shouldOverrideUrlLoading callback had finished and checking the call
616 assertEquals(shouldOverrideUrlLoadingCallCount,
617 shouldOverrideUrlLoadingHelper.getCallCount());
621 @Feature({"AndroidWebView", "Navigation"})
622 public void testCalledFor302AfterPostNavigations() throws Throwable {
623 // The reason POST requests are excluded is BUG 155250.
624 final TestAwContentsClient contentsClient = new TestAwContentsClient();
625 final AwTestContainerView testContainerView =
626 createAwTestContainerViewOnMainSync(contentsClient);
627 final AwContents awContents = testContainerView.getAwContents();
628 final TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
629 contentsClient.getShouldOverrideUrlLoadingHelper();
631 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
632 final String postToGetRedirectUrl = mWebServer.setRedirect("/302.html", redirectTargetUrl);
633 final String postLinkUrl = addPageToTestServer(mWebServer, "/page_with_post_link.html",
634 getHtmlForPageWithSimplePostFormTo(postToGetRedirectUrl));
636 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), postLinkUrl);
638 final int shouldOverrideUrlLoadingCallCount =
639 shouldOverrideUrlLoadingHelper.getCallCount();
641 clickOnLinkUsingJs(awContents, contentsClient);
643 shouldOverrideUrlLoadingHelper.waitForCallback(shouldOverrideUrlLoadingCallCount);
645 // Wait for the target URL to be fetched from the server.
646 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
648 public boolean isSatisfied() {
649 return mWebServer.getRequestCount(REDIRECT_TARGET_PATH) == 1;
651 }, WAIT_TIMEOUT_SECONDS * 1000L, CHECK_INTERVAL));
653 assertEquals(redirectTargetUrl,
654 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
658 @Feature({"AndroidWebView", "Navigation"})
659 public void testNotCalledForIframeHttpNavigations() 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 iframeRedirectTargetUrl = createRedirectTargetPage(mWebServer);
668 final String iframeRedirectUrl =
669 mWebServer.setRedirect("/302.html", iframeRedirectTargetUrl);
670 final String pageWithIframeUrl =
671 addPageToTestServer(mWebServer, "/iframe_intercept.html",
672 makeHtmlPageFrom("", "<iframe src=\"" + iframeRedirectUrl + "\" />"));
674 final int shouldOverrideUrlLoadingCallCount =
675 shouldOverrideUrlLoadingHelper.getCallCount();
677 assertEquals(0, mWebServer.getRequestCount(REDIRECT_TARGET_PATH));
678 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), pageWithIframeUrl);
680 // Wait for the redirect target URL to be fetched from the server.
681 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
683 public boolean isSatisfied() {
684 return mWebServer.getRequestCount(REDIRECT_TARGET_PATH) == 1;
686 }, WAIT_TIMEOUT_SECONDS * 1000L, CHECK_INTERVAL));
688 assertEquals(shouldOverrideUrlLoadingCallCount,
689 shouldOverrideUrlLoadingHelper.getCallCount());
693 @Feature({"AndroidWebView", "Navigation"})
694 public void testCalledForIframeUnsupportedSchemeNavigations() throws Throwable {
695 final TestAwContentsClient contentsClient = new TestAwContentsClient();
696 final AwTestContainerView testContainerView =
697 createAwTestContainerViewOnMainSync(contentsClient);
698 final AwContents awContents = testContainerView.getAwContents();
699 final TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
700 contentsClient.getShouldOverrideUrlLoadingHelper();
702 final String unsupportedSchemeUrl = "foobar://resource/1";
703 final String pageWithIframeUrl =
704 addPageToTestServer(mWebServer, "/iframe_intercept.html",
705 makeHtmlPageFrom("", "<iframe src=\"" + unsupportedSchemeUrl + "\" />"));
707 final int shouldOverrideUrlLoadingCallCount =
708 shouldOverrideUrlLoadingHelper.getCallCount();
710 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), pageWithIframeUrl);
712 shouldOverrideUrlLoadingHelper.waitForCallback(shouldOverrideUrlLoadingCallCount);
713 assertEquals(unsupportedSchemeUrl,
714 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
718 * Worker method for the various redirect tests.
720 * Calling this will first load the redirect URL built from redirectFilePath, query and
721 * locationFilePath and assert that we get a override callback for the destination.
722 * The second part of the test loads a page that contains a link which points at the redirect
723 * URL. We expect two callbacks - one for the redirect link and another for the destination.
725 private void doTestCalledOnRedirect(TestWebServer webServer,
726 String redirectUrl, String redirectTarget) throws Throwable {
727 final TestAwContentsClient contentsClient = new TestAwContentsClient();
728 final AwTestContainerView testContainerView =
729 createAwTestContainerViewOnMainSync(contentsClient);
730 final AwContents awContents = testContainerView.getAwContents();
731 final String pageWithLinkToRedirectUrl = addPageToTestServer(webServer,
732 "/page_with_link_to_redirect.html",
733 getHtmlForPageWithSimpleLinkTo(redirectUrl));
734 enableJavaScriptOnUiThread(awContents);
736 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
737 contentsClient.getShouldOverrideUrlLoadingHelper();
738 int directLoadCallCount = shouldOverrideUrlLoadingHelper.getCallCount();
739 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), redirectUrl);
741 shouldOverrideUrlLoadingHelper.waitForCallback(directLoadCallCount, 1);
742 assertEquals(redirectTarget,
743 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
745 // There is a slight difference between navigations caused by calling load and navigations
746 // caused by clicking on a link:
747 // * when using load the navigation is treated as if it came from the URL bar (has the
748 // navigation type TYPED and doesn't have the has_user_gesture flag)
749 // * when clicking on a link the navigation has the LINK type and has_user_gesture is
751 // Both of these should yield the same result which is what we're verifying here.
752 int indirectLoadCallCount = shouldOverrideUrlLoadingHelper.getCallCount();
753 loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(),
754 pageWithLinkToRedirectUrl);
756 assertEquals(indirectLoadCallCount, shouldOverrideUrlLoadingHelper.getCallCount());
758 clickOnLinkUsingJs(awContents, contentsClient);
760 shouldOverrideUrlLoadingHelper.waitForCallback(indirectLoadCallCount, 2);
761 assertEquals(redirectTarget,
762 shouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
763 assertEquals(redirectUrl,
764 shouldOverrideUrlLoadingHelper.getPreviousShouldOverrideUrlLoadingUrl());
768 @Feature({"AndroidWebView", "Navigation"})
769 public void testCalledOn302Redirect() throws Throwable {
770 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
771 final String redirectUrl = mWebServer.setRedirect("/302.html", redirectTargetUrl);
773 doTestCalledOnRedirect(mWebServer, redirectUrl, redirectTargetUrl);
777 @Feature({"AndroidWebView", "Navigation"})
778 public void testCalledOnMetaRefreshRedirect() throws Throwable {
779 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
780 final String redirectUrl = addPageToTestServer(mWebServer, "/meta_refresh.html",
781 getHtmlForPageWithMetaRefreshRedirectTo(redirectTargetUrl));
782 doTestCalledOnRedirect(mWebServer, redirectUrl, redirectTargetUrl);
787 @Feature({"AndroidWebView", "Navigation"})
788 public void testCalledOnJavaScriptLocationImmediateAssignRedirect()
790 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
791 final String redirectUrl = addPageToTestServer(mWebServer, "/js_immediate_assign.html",
792 getHtmlForPageWithJsRedirectTo(redirectTargetUrl, "Assign", 0));
793 doTestCalledOnRedirect(mWebServer, redirectUrl, redirectTargetUrl);
797 @Feature({"AndroidWebView", "Navigation"})
798 public void testCalledOnJavaScriptLocationImmediateReplaceRedirect()
800 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
801 final String redirectUrl = addPageToTestServer(mWebServer, "/js_immediate_replace.html",
802 getHtmlForPageWithJsRedirectTo(redirectTargetUrl, "Replace", 0));
803 doTestCalledOnRedirect(mWebServer, redirectUrl, redirectTargetUrl);
807 @Feature({"AndroidWebView", "Navigation"})
808 public void testCalledOnJavaScriptLocationDelayedAssignRedirect()
810 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
811 final String redirectUrl = addPageToTestServer(mWebServer, "/js_delayed_assign.html",
812 getHtmlForPageWithJsRedirectTo(redirectTargetUrl, "Assign", 100));
813 doTestCalledOnRedirect(mWebServer, redirectUrl, redirectTargetUrl);
817 @Feature({"AndroidWebView", "Navigation"})
818 public void testCalledOnJavaScriptLocationDelayedReplaceRedirect()
820 final String redirectTargetUrl = createRedirectTargetPage(mWebServer);
821 final String redirectUrl = addPageToTestServer(mWebServer, "/js_delayed_replace.html",
822 getHtmlForPageWithJsRedirectTo(redirectTargetUrl, "Replace", 100));
823 doTestCalledOnRedirect(mWebServer, redirectUrl, redirectTargetUrl);
827 @Feature({"AndroidWebView", "Navigation"})
828 public void testDoubleNavigateDoesNotSuppressInitialNavigate() throws Throwable {
829 final String jsUrl = "javascript:try{console.log('processed js loadUrl');}catch(e){};";
830 final TestAwContentsClient contentsClient = new TestAwContentsClient();
831 final AwTestContainerView testContainerView =
832 createAwTestContainerViewOnMainSync(contentsClient);
833 final AwContents awContents = testContainerView.getAwContents();
834 TestAwContentsClient.ShouldOverrideUrlLoadingHelper shouldOverrideUrlLoadingHelper =
835 contentsClient.getShouldOverrideUrlLoadingHelper();
837 // Do a double navigagtion, the second being an effective no-op, in quick succession (i.e.
838 // without yielding the main thread inbetween).
839 int currentCallCount = contentsClient.getOnPageFinishedHelper().getCallCount();
840 getInstrumentation().runOnMainSync(new Runnable() {
843 awContents.loadUrl(LoadUrlParams.createLoadDataParams(
844 getHtmlForPageWithSimpleLinkTo(DATA_URL), "text/html", false));
845 awContents.loadUrl(new LoadUrlParams(jsUrl));
848 contentsClient.getOnPageFinishedHelper().waitForCallback(currentCallCount, 1,
849 WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
851 assertEquals(0, shouldOverrideUrlLoadingHelper.getCallCount());