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.AwContentsClient.ShouldInterceptRequestParams;
12 import org.chromium.android_webview.AwWebResourceResponse;
13 import org.chromium.android_webview.test.util.CommonResources;
14 import org.chromium.android_webview.test.util.JSUtils;
15 import org.chromium.base.test.util.Feature;
16 import org.chromium.base.test.util.TestFileUtil;
17 import org.chromium.content.browser.test.util.CallbackHelper;
18 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnReceivedErrorHelper;
19 import org.chromium.net.test.util.TestWebServer;
21 import java.io.ByteArrayInputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
28 import java.util.concurrent.Callable;
29 import java.util.concurrent.ConcurrentHashMap;
30 import java.util.concurrent.CountDownLatch;
33 * Tests for the WebViewClient.shouldInterceptRequest() method.
35 public class AwContentsClientShouldInterceptRequestTest extends AwTestBase {
37 private static class TestAwContentsClient
38 extends org.chromium.android_webview.test.TestAwContentsClient {
40 public static class ShouldInterceptRequestHelper extends CallbackHelper {
41 private List<String> mShouldInterceptRequestUrls = new ArrayList<String>();
42 private ConcurrentHashMap<String, AwWebResourceResponse> mReturnValuesByUrls
43 = new ConcurrentHashMap<String, AwWebResourceResponse>();
44 private ConcurrentHashMap<String, ShouldInterceptRequestParams> mParamsByUrls
45 = new ConcurrentHashMap<String, ShouldInterceptRequestParams>();
46 // This is read from the IO thread, so needs to be marked volatile.
47 private volatile AwWebResourceResponse mShouldInterceptRequestReturnValue = null;
48 void setReturnValue(AwWebResourceResponse value) {
49 mShouldInterceptRequestReturnValue = value;
51 void setReturnValueForUrl(String url, AwWebResourceResponse value) {
52 mReturnValuesByUrls.put(url, value);
54 public List<String> getUrls() {
55 assert getCallCount() > 0;
56 return mShouldInterceptRequestUrls;
58 public AwWebResourceResponse getReturnValue(String url) {
59 AwWebResourceResponse value = mReturnValuesByUrls.get(url);
60 if (value != null) return value;
61 return mShouldInterceptRequestReturnValue;
63 public ShouldInterceptRequestParams getParamsForUrl(String url) {
64 assert getCallCount() > 0;
65 assert mParamsByUrls.containsKey(url);
66 return mParamsByUrls.get(url);
68 public void notifyCalled(ShouldInterceptRequestParams params) {
69 mShouldInterceptRequestUrls.add(params.url);
70 mParamsByUrls.put(params.url, params);
75 public static class OnLoadResourceHelper extends CallbackHelper {
78 public String getUrl() {
79 assert getCallCount() > 0;
83 public void notifyCalled(String url) {
90 public AwWebResourceResponse shouldInterceptRequest(ShouldInterceptRequestParams params) {
91 AwWebResourceResponse returnValue =
92 mShouldInterceptRequestHelper.getReturnValue(params.url);
93 mShouldInterceptRequestHelper.notifyCalled(params);
98 public void onLoadResource(String url) {
99 super.onLoadResource(url);
100 mOnLoadResourceHelper.notifyCalled(url);
103 private ShouldInterceptRequestHelper mShouldInterceptRequestHelper;
104 private OnLoadResourceHelper mOnLoadResourceHelper;
106 public TestAwContentsClient() {
107 mShouldInterceptRequestHelper = new ShouldInterceptRequestHelper();
108 mOnLoadResourceHelper = new OnLoadResourceHelper();
111 public ShouldInterceptRequestHelper getShouldInterceptRequestHelper() {
112 return mShouldInterceptRequestHelper;
115 public OnLoadResourceHelper getOnLoadResourceHelper() {
116 return mOnLoadResourceHelper;
120 final int teapotStatusCode = 418;
121 final String teapotResponsePhrase = "I'm a teapot";
123 private String addPageToTestServer(TestWebServer webServer, String httpPath, String html) {
124 List<Pair<String, String>> headers = new ArrayList<Pair<String, String>>();
125 headers.add(Pair.create("Content-Type", "text/html"));
126 headers.add(Pair.create("Cache-Control", "no-store"));
127 return webServer.setResponse(httpPath, html, headers);
130 private String addAboutPageToTestServer(TestWebServer webServer) {
131 return addPageToTestServer(webServer, "/" + CommonResources.ABOUT_FILENAME,
132 CommonResources.ABOUT_HTML);
135 private AwWebResourceResponse stringToAwWebResourceResponse(String input) throws Throwable {
136 final String mimeType = "text/html";
137 final String encoding = "UTF-8";
139 return new AwWebResourceResponse(
140 mimeType, encoding, new ByteArrayInputStream(input.getBytes(encoding)));
143 private TestWebServer mWebServer;
144 private TestAwContentsClient mContentsClient;
145 private AwTestContainerView mTestContainerView;
146 private AwContents mAwContents;
147 private TestAwContentsClient.ShouldInterceptRequestHelper mShouldInterceptRequestHelper;
150 protected void setUp() throws Exception {
153 mContentsClient = new TestAwContentsClient();
154 mTestContainerView = createAwTestContainerViewOnMainSync(mContentsClient);
155 mAwContents = mTestContainerView.getAwContents();
156 mShouldInterceptRequestHelper = mContentsClient.getShouldInterceptRequestHelper();
158 mWebServer = new TestWebServer(false);
162 protected void tearDown() throws Exception {
163 mWebServer.shutdown();
168 @Feature({"AndroidWebView"})
169 public void testCalledWithCorrectUrlParam() throws Throwable {
170 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
172 int onPageFinishedCallCount = mContentsClient.getOnPageFinishedHelper().getCallCount();
174 int callCount = mShouldInterceptRequestHelper.getCallCount();
175 loadUrlAsync(mAwContents, aboutPageUrl);
176 mShouldInterceptRequestHelper.waitForCallback(callCount);
177 assertEquals(1, mShouldInterceptRequestHelper.getUrls().size());
178 assertEquals(aboutPageUrl,
179 mShouldInterceptRequestHelper.getUrls().get(0));
181 mContentsClient.getOnPageFinishedHelper().waitForCallback(onPageFinishedCallCount);
182 assertEquals(CommonResources.ABOUT_TITLE, getTitleOnUiThread(mAwContents));
186 @Feature({"AndroidWebView"})
187 public void testCalledWithCorrectIsMainFrameParam() throws Throwable {
188 final String subframeUrl = addAboutPageToTestServer(mWebServer);
189 final String pageWithIframeUrl = addPageToTestServer(mWebServer, "/page_with_iframe.html",
190 CommonResources.makeHtmlPageFrom("",
191 "<iframe src=\"" + subframeUrl + "\"/>"));
193 int callCount = mShouldInterceptRequestHelper.getCallCount();
194 loadUrlAsync(mAwContents, pageWithIframeUrl);
195 mShouldInterceptRequestHelper.waitForCallback(callCount, 2);
196 assertEquals(2, mShouldInterceptRequestHelper.getUrls().size());
198 mShouldInterceptRequestHelper.getParamsForUrl(subframeUrl).isMainFrame);
200 mShouldInterceptRequestHelper.getParamsForUrl(pageWithIframeUrl).isMainFrame);
204 @Feature({"AndroidWebView"})
205 public void testCalledWithCorrectMethodParam() throws Throwable {
206 final String pageToPostToUrl = addAboutPageToTestServer(mWebServer);
207 final String pageWithFormUrl = addPageToTestServer(mWebServer, "/page_with_form.html",
208 CommonResources.makeHtmlPageWithSimplePostFormTo(pageToPostToUrl));
209 enableJavaScriptOnUiThread(mAwContents);
211 int callCount = mShouldInterceptRequestHelper.getCallCount();
212 loadUrlAsync(mAwContents, pageWithFormUrl);
213 mShouldInterceptRequestHelper.waitForCallback(callCount);
215 mShouldInterceptRequestHelper.getParamsForUrl(pageWithFormUrl).method);
217 callCount = mShouldInterceptRequestHelper.getCallCount();
218 JSUtils.clickOnLinkUsingJs(this, mAwContents,
219 mContentsClient.getOnEvaluateJavaScriptResultHelper(), "link");
220 mShouldInterceptRequestHelper.waitForCallback(callCount);
222 mShouldInterceptRequestHelper.getParamsForUrl(pageToPostToUrl).method);
226 @Feature({"AndroidWebView"})
227 public void testCalledWithCorrectHasUserGestureParam() throws Throwable {
228 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
229 final String pageWithLinkUrl = addPageToTestServer(mWebServer, "/page_with_link.html",
230 CommonResources.makeHtmlPageWithSimpleLinkTo(aboutPageUrl));
231 enableJavaScriptOnUiThread(mAwContents);
233 int callCount = mShouldInterceptRequestHelper.getCallCount();
234 loadUrlAsync(mAwContents, pageWithLinkUrl);
235 mShouldInterceptRequestHelper.waitForCallback(callCount);
237 mShouldInterceptRequestHelper.getParamsForUrl(pageWithLinkUrl).hasUserGesture);
239 callCount = mShouldInterceptRequestHelper.getCallCount();
240 JSUtils.clickOnLinkUsingJs(this, mAwContents,
241 mContentsClient.getOnEvaluateJavaScriptResultHelper(), "link");
242 mShouldInterceptRequestHelper.waitForCallback(callCount);
244 mShouldInterceptRequestHelper.getParamsForUrl(aboutPageUrl).hasUserGesture);
248 @Feature({"AndroidWebView"})
249 public void testCalledWithCorrectHeadersParam() throws Throwable {
250 final String headerName = "X-Test-Header-Name";
251 final String headerValue = "TestHeaderValue";
252 final String syncGetUrl = addPageToTestServer(mWebServer, "/intercept_me",
253 CommonResources.ABOUT_HTML);
254 final String mainPageUrl = addPageToTestServer(mWebServer, "/main",
255 CommonResources.makeHtmlPageFrom("",
257 " var xhr = new XMLHttpRequest();" +
258 " xhr.open('GET', '" + syncGetUrl + "', false);" +
259 " xhr.setRequestHeader('" + headerName + "', '" + headerValue + "'); " +
262 enableJavaScriptOnUiThread(mAwContents);
264 int callCount = mShouldInterceptRequestHelper.getCallCount();
265 loadUrlAsync(mAwContents, mainPageUrl);
266 mShouldInterceptRequestHelper.waitForCallback(callCount, 2);
268 Map<String, String> headers =
269 mShouldInterceptRequestHelper.getParamsForUrl(syncGetUrl).requestHeaders;
270 assertTrue(headers.containsKey(headerName));
271 assertEquals(headerValue, headers.get(headerName));
275 @Feature({"AndroidWebView"})
276 public void testOnLoadResourceCalledWithCorrectUrl() throws Throwable {
277 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
278 final TestAwContentsClient.OnLoadResourceHelper onLoadResourceHelper =
279 mContentsClient.getOnLoadResourceHelper();
281 int callCount = onLoadResourceHelper.getCallCount();
283 loadUrlAsync(mAwContents, aboutPageUrl);
285 onLoadResourceHelper.waitForCallback(callCount);
286 assertEquals(aboutPageUrl, onLoadResourceHelper.getUrl());
290 @Feature({"AndroidWebView"})
291 public void testDoesNotCrashOnInvalidData() throws Throwable {
292 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
294 mShouldInterceptRequestHelper.setReturnValue(
295 new AwWebResourceResponse("text/html", "UTF-8", null));
296 int callCount = mShouldInterceptRequestHelper.getCallCount();
297 loadUrlAsync(mAwContents, aboutPageUrl);
298 mShouldInterceptRequestHelper.waitForCallback(callCount);
300 mShouldInterceptRequestHelper.setReturnValue(
301 new AwWebResourceResponse(null, null, new ByteArrayInputStream(new byte[0])));
302 callCount = mShouldInterceptRequestHelper.getCallCount();
303 loadUrlAsync(mAwContents, aboutPageUrl);
304 mShouldInterceptRequestHelper.waitForCallback(callCount);
306 mShouldInterceptRequestHelper.setReturnValue(
307 new AwWebResourceResponse(null, null, null));
308 callCount = mShouldInterceptRequestHelper.getCallCount();
309 loadUrlAsync(mAwContents, aboutPageUrl);
310 mShouldInterceptRequestHelper.waitForCallback(callCount);
313 private static class EmptyInputStream extends InputStream {
315 public int available() {
320 public int read() throws IOException {
325 public int read(byte b[]) throws IOException {
330 public int read(byte b[], int off, int len) throws IOException {
335 public long skip(long n) throws IOException {
337 throw new IOException("skipping negative number of bytes");
343 @Feature({"AndroidWebView"})
344 public void testDoesNotCrashOnEmptyStream() throws Throwable {
345 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
347 mShouldInterceptRequestHelper.setReturnValue(
348 new AwWebResourceResponse("text/html", "UTF-8", new EmptyInputStream()));
349 int shouldInterceptRequestCallCount = mShouldInterceptRequestHelper.getCallCount();
350 int onPageFinishedCallCount = mContentsClient.getOnPageFinishedHelper().getCallCount();
352 loadUrlAsync(mAwContents, aboutPageUrl);
354 mShouldInterceptRequestHelper.waitForCallback(shouldInterceptRequestCallCount);
355 mContentsClient.getOnPageFinishedHelper().waitForCallback(onPageFinishedCallCount);
358 private static class SlowAwWebResourceResponse extends AwWebResourceResponse {
359 private CallbackHelper mReadStartedCallbackHelper = new CallbackHelper();
360 private CountDownLatch mLatch = new CountDownLatch(1);
362 public SlowAwWebResourceResponse(String mimeType, String encoding, InputStream data) {
363 super(mimeType, encoding, data);
367 public InputStream getData() {
368 mReadStartedCallbackHelper.notifyCalled();
371 } catch (InterruptedException e) {
374 return super.getData();
377 public void unblockReads() {
381 public CallbackHelper getReadStartedCallbackHelper() {
382 return mReadStartedCallbackHelper;
387 @Feature({"AndroidWebView"})
388 public void testDoesNotCrashOnSlowStream() throws Throwable {
389 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
390 final String aboutPageData = makePageWithTitle("some title");
391 final String encoding = "UTF-8";
392 final SlowAwWebResourceResponse slowAwWebResourceResponse =
393 new SlowAwWebResourceResponse("text/html", encoding,
394 new ByteArrayInputStream(aboutPageData.getBytes(encoding)));
396 mShouldInterceptRequestHelper.setReturnValue(slowAwWebResourceResponse);
397 int callCount = slowAwWebResourceResponse.getReadStartedCallbackHelper().getCallCount();
398 loadUrlAsync(mAwContents, aboutPageUrl);
399 slowAwWebResourceResponse.getReadStartedCallbackHelper().waitForCallback(callCount);
401 // Now the AwContents is "stuck" waiting for the SlowInputStream to finish reading so we
402 // delete it to make sure that the dangling 'read' task doesn't cause a crash. Unfortunately
403 // this will not always lead to a crash but it should happen often enough for us to notice.
405 runTestOnUiThread(new Runnable() {
408 getActivity().removeAllViews();
411 destroyAwContentsOnMainSync(mAwContents);
412 pollOnUiThread(new Callable<Boolean>() {
414 public Boolean call() {
415 return AwContents.getNativeInstanceCount() == 0;
419 slowAwWebResourceResponse.unblockReads();
423 @Feature({"AndroidWebView"})
424 public void testHttpStatusCodeAndText() throws Throwable {
425 final String syncGetUrl = mWebServer.getResponseUrl("/intercept_me");
426 final String syncGetJs =
428 " var xhr = new XMLHttpRequest();" +
429 " xhr.open('GET', '" + syncGetUrl + "', false);" +
431 " console.info('xhr.status = ' + xhr.status);" +
432 " console.info('xhr.statusText = ' + xhr.statusText);" +
433 " return '[' + xhr.status + '][' + xhr.statusText + ']';" +
435 enableJavaScriptOnUiThread(mAwContents);
437 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
438 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), aboutPageUrl);
440 mShouldInterceptRequestHelper.setReturnValue(
441 new AwWebResourceResponse("text/html", "UTF-8", null));
442 assertEquals("\"[404][Not Found]\"",
443 executeJavaScriptAndWaitForResult(mAwContents, mContentsClient, syncGetJs));
445 mShouldInterceptRequestHelper.setReturnValue(
446 new AwWebResourceResponse("text/html", "UTF-8", new EmptyInputStream()));
447 assertEquals("\"[200][OK]\"",
448 executeJavaScriptAndWaitForResult(mAwContents, mContentsClient, syncGetJs));
450 mShouldInterceptRequestHelper.setReturnValue(
451 new AwWebResourceResponse("text/html", "UTF-8", new EmptyInputStream(),
452 teapotStatusCode, teapotResponsePhrase, new HashMap<String, String>()));
453 assertEquals("\"[" + teapotStatusCode + "][" + teapotResponsePhrase + "]\"",
454 executeJavaScriptAndWaitForResult(mAwContents, mContentsClient, syncGetJs));
457 private String getHeaderValue(AwContents awContents, TestAwContentsClient contentsClient,
458 String url, String headerName) throws Exception {
459 final String syncGetJs =
461 " var xhr = new XMLHttpRequest();" +
462 " xhr.open('GET', '" + url + "', false);" +
464 " console.info(xhr.getAllResponseHeaders());" +
465 " return xhr.getResponseHeader('" + headerName + "');" +
467 String header = executeJavaScriptAndWaitForResult(awContents, contentsClient, syncGetJs);
468 // JSON stringification applied by executeJavaScriptAndWaitForResult adds quotes
469 // around returned strings.
470 assertTrue(header.length() > 2);
471 assertEquals('"', header.charAt(0));
472 assertEquals('"', header.charAt(header.length() - 1));
473 return header.substring(1, header.length() - 1);
477 @Feature({"AndroidWebView"})
478 public void testHttpResponseClientViaHeader() throws Throwable {
479 final String clientResponseHeaderName = "Client-Via";
480 final String clientResponseHeaderValue = "shouldInterceptRequest";
481 final String syncGetUrl = mWebServer.getResponseUrl("/intercept_me");
482 enableJavaScriptOnUiThread(mAwContents);
484 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
485 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), aboutPageUrl);
487 // The response header is set regardless of whether the embedder has provided a
488 // valid resource stream.
489 mShouldInterceptRequestHelper.setReturnValue(
490 new AwWebResourceResponse("text/html", "UTF-8", null));
491 assertEquals(clientResponseHeaderValue,
492 getHeaderValue(mAwContents, mContentsClient, syncGetUrl, clientResponseHeaderName));
493 mShouldInterceptRequestHelper.setReturnValue(
494 new AwWebResourceResponse("text/html", "UTF-8", new EmptyInputStream()));
495 assertEquals(clientResponseHeaderValue,
496 getHeaderValue(mAwContents, mContentsClient, syncGetUrl, clientResponseHeaderName));
501 @Feature({"AndroidWebView"})
502 public void testHttpResponseHeader() throws Throwable {
503 final String clientResponseHeaderName = "X-Test-Header-Name";
504 final String clientResponseHeaderValue = "TestHeaderValue";
505 final String syncGetUrl = mWebServer.getResponseUrl("/intercept_me");
506 final Map<String, String> headers = new HashMap<String, String>();
507 headers.put(clientResponseHeaderName, clientResponseHeaderValue);
508 enableJavaScriptOnUiThread(mAwContents);
510 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
511 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), aboutPageUrl);
513 mShouldInterceptRequestHelper.setReturnValue(
514 new AwWebResourceResponse("text/html", "UTF-8", null, 0, null, headers));
515 assertEquals(clientResponseHeaderValue,
516 getHeaderValue(mAwContents, mContentsClient, syncGetUrl, clientResponseHeaderName));
519 private String makePageWithTitle(String title) {
520 return CommonResources.makeHtmlPageFrom("<title>" + title + "</title>",
521 "<div> The title is: " + title + " </div>");
525 @Feature({"AndroidWebView"})
526 public void testCanInterceptMainFrame() throws Throwable {
527 final String expectedTitle = "testShouldInterceptRequestCanInterceptMainFrame";
528 final String expectedPage = makePageWithTitle(expectedTitle);
530 mShouldInterceptRequestHelper.setReturnValue(
531 stringToAwWebResourceResponse(expectedPage));
533 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
535 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), aboutPageUrl);
537 assertEquals(expectedTitle, getTitleOnUiThread(mAwContents));
538 assertEquals(0, mWebServer.getRequestCount("/" + CommonResources.ABOUT_FILENAME));
542 @Feature({"AndroidWebView"})
543 public void testDoesNotChangeReportedUrl() throws Throwable {
544 mShouldInterceptRequestHelper.setReturnValue(
545 stringToAwWebResourceResponse(makePageWithTitle("some title")));
547 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
549 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), aboutPageUrl);
551 assertEquals(aboutPageUrl, mContentsClient.getOnPageFinishedHelper().getUrl());
552 assertEquals(aboutPageUrl, mContentsClient.getOnPageStartedHelper().getUrl());
556 @Feature({"AndroidWebView"})
557 public void testNullInputStreamCausesErrorForMainFrame() throws Throwable {
558 final OnReceivedErrorHelper onReceivedErrorHelper =
559 mContentsClient.getOnReceivedErrorHelper();
561 mShouldInterceptRequestHelper.setReturnValue(
562 new AwWebResourceResponse("text/html", "UTF-8", null));
564 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
565 final int callCount = onReceivedErrorHelper.getCallCount();
566 loadUrlAsync(mAwContents, aboutPageUrl);
567 onReceivedErrorHelper.waitForCallback(callCount);
568 assertEquals(0, mWebServer.getRequestCount("/" + CommonResources.ABOUT_FILENAME));
572 @Feature({"AndroidWebView"})
573 public void testCalledForImage() throws Throwable {
574 final String imagePath = "/" + CommonResources.FAVICON_FILENAME;
575 mWebServer.setResponseBase64(imagePath,
576 CommonResources.FAVICON_DATA_BASE64, CommonResources.getImagePngHeaders(true));
577 final String pageWithImage =
578 addPageToTestServer(mWebServer, "/page_with_image.html",
579 CommonResources.getOnImageLoadedHtml(CommonResources.FAVICON_FILENAME));
581 int callCount = mShouldInterceptRequestHelper.getCallCount();
582 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), pageWithImage);
583 mShouldInterceptRequestHelper.waitForCallback(callCount, 2);
585 assertEquals(2, mShouldInterceptRequestHelper.getUrls().size());
586 assertTrue(mShouldInterceptRequestHelper.getUrls().get(1).endsWith(
587 CommonResources.FAVICON_FILENAME));
591 @Feature({"AndroidWebView"})
592 public void testOnReceivedErrorCallback() throws Throwable {
593 mShouldInterceptRequestHelper.setReturnValue(new AwWebResourceResponse(null, null, null));
594 OnReceivedErrorHelper onReceivedErrorHelper = mContentsClient.getOnReceivedErrorHelper();
595 int onReceivedErrorHelperCallCount = onReceivedErrorHelper.getCallCount();
596 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), "foo://bar");
597 onReceivedErrorHelper.waitForCallback(onReceivedErrorHelperCallCount, 1);
601 @Feature({"AndroidWebView"})
602 public void testNoOnReceivedErrorCallback() throws Throwable {
603 final String imagePath = "/" + CommonResources.FAVICON_FILENAME;
604 final String imageUrl = mWebServer.setResponseBase64(imagePath,
605 CommonResources.FAVICON_DATA_BASE64, CommonResources.getImagePngHeaders(true));
606 final String pageWithImage =
607 addPageToTestServer(mWebServer, "/page_with_image.html",
608 CommonResources.getOnImageLoadedHtml(CommonResources.FAVICON_FILENAME));
609 mShouldInterceptRequestHelper.setReturnValueForUrl(
610 imageUrl, new AwWebResourceResponse(null, null, null));
611 OnReceivedErrorHelper onReceivedErrorHelper = mContentsClient.getOnReceivedErrorHelper();
612 int onReceivedErrorHelperCallCount = onReceivedErrorHelper.getCallCount();
613 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), pageWithImage);
614 assertEquals(onReceivedErrorHelperCallCount, onReceivedErrorHelper.getCallCount());
618 @Feature({"AndroidWebView"})
619 public void testCalledForIframe() throws Throwable {
620 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
621 final String pageWithIframeUrl = addPageToTestServer(mWebServer, "/page_with_iframe.html",
622 CommonResources.makeHtmlPageFrom("",
623 "<iframe src=\"" + aboutPageUrl + "\"/>"));
625 int callCount = mShouldInterceptRequestHelper.getCallCount();
626 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), pageWithIframeUrl);
627 mShouldInterceptRequestHelper.waitForCallback(callCount, 2);
628 assertEquals(2, mShouldInterceptRequestHelper.getUrls().size());
629 assertEquals(aboutPageUrl, mShouldInterceptRequestHelper.getUrls().get(1));
632 private void calledForUrlTemplate(final String url) throws Exception {
633 int callCount = mShouldInterceptRequestHelper.getCallCount();
634 int onPageStartedCallCount = mContentsClient.getOnPageStartedHelper().getCallCount();
635 loadUrlAsync(mAwContents, url);
636 mShouldInterceptRequestHelper.waitForCallback(callCount);
637 assertEquals(url, mShouldInterceptRequestHelper.getUrls().get(0));
639 mContentsClient.getOnPageStartedHelper().waitForCallback(onPageStartedCallCount);
640 assertEquals(onPageStartedCallCount + 1,
641 mContentsClient.getOnPageStartedHelper().getCallCount());
644 private void notCalledForUrlTemplate(final String url) throws Exception {
645 int callCount = mShouldInterceptRequestHelper.getCallCount();
646 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), url);
647 // The intercepting must happen before onPageFinished. Since the IPC messages from the
648 // renderer should be delivered in order waiting for onPageFinished is sufficient to
649 // 'flush' any pending interception messages.
650 assertEquals(callCount, mShouldInterceptRequestHelper.getCallCount());
654 @Feature({"AndroidWebView"})
655 public void testCalledForUnsupportedSchemes() throws Throwable {
656 calledForUrlTemplate("foobar://resource/1");
660 @Feature({"AndroidWebView"})
661 public void testCalledForNonexistentFiles() throws Throwable {
662 calledForUrlTemplate("file:///somewhere/something");
666 @Feature({"AndroidWebView"})
667 public void testCalledForExistingFiles() throws Throwable {
668 final String tmpDir = getInstrumentation().getTargetContext().getCacheDir().getPath();
669 final String fileName = tmpDir + "/testfile.html";
670 final String title = "existing file title";
671 TestFileUtil.deleteFile(fileName); // Remove leftover file if any.
672 TestFileUtil.createNewHtmlFile(fileName, title, "");
673 final String existingFileUrl = "file://" + fileName;
675 int callCount = mShouldInterceptRequestHelper.getCallCount();
676 int onPageFinishedCallCount = mContentsClient.getOnPageFinishedHelper().getCallCount();
677 loadUrlAsync(mAwContents, existingFileUrl);
678 mShouldInterceptRequestHelper.waitForCallback(callCount);
679 assertEquals(existingFileUrl, mShouldInterceptRequestHelper.getUrls().get(0));
681 mContentsClient.getOnPageFinishedHelper().waitForCallback(onPageFinishedCallCount);
682 assertEquals(title, getTitleOnUiThread(mAwContents));
683 assertEquals(onPageFinishedCallCount + 1,
684 mContentsClient.getOnPageFinishedHelper().getCallCount());
688 @Feature({"AndroidWebView"})
689 public void testNotCalledForExistingResource() throws Throwable {
690 notCalledForUrlTemplate("file:///android_res/raw/resource_file.html");
694 @Feature({"AndroidWebView"})
695 public void testCalledForNonexistentResource() throws Throwable {
696 calledForUrlTemplate("file:///android_res/raw/no_file.html");
700 @Feature({"AndroidWebView"})
701 public void testNotCalledForExistingAsset() throws Throwable {
702 notCalledForUrlTemplate("file:///android_asset/asset_file.html");
706 @Feature({"AndroidWebView"})
707 public void testCalledForNonexistentAsset() throws Throwable {
708 calledForUrlTemplate("file:///android_res/raw/no_file.html");
712 @Feature({"AndroidWebView"})
713 public void testNotCalledForExistingContentUrl() throws Throwable {
714 final String contentResourceName = "target";
715 final String existingContentUrl = TestContentProvider.createContentUrl(contentResourceName);
717 notCalledForUrlTemplate(existingContentUrl);
719 int contentRequestCount = TestContentProvider.getResourceRequestCount(
720 getInstrumentation().getTargetContext(), contentResourceName);
721 assertEquals(1, contentRequestCount);
725 @Feature({"AndroidWebView"})
726 public void testCalledForNonexistentContentUrl() throws Throwable {
727 calledForUrlTemplate("content://org.chromium.webview.NoSuchProvider/foo");