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 private static final int TEAPOT_STATUS_CODE = 418;
121 private static final String TEAPOT_RESPONSE_PHRASE = "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 ThrowingInputStream extends EmptyInputStream {
360 public int available() {
365 public int read() throws IOException {
366 throw new IOException("test exception");
370 public int read(byte b[]) throws IOException {
371 throw new IOException("test exception");
375 public int read(byte b[], int off, int len) throws IOException {
376 throw new IOException("test exception");
380 public long skip(long n) throws IOException {
386 @Feature({"AndroidWebView"})
387 public void testDoesNotCrashOnThrowingStream() throws Throwable {
388 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
390 mShouldInterceptRequestHelper.setReturnValue(
391 new AwWebResourceResponse("text/html", "UTF-8", new ThrowingInputStream()));
392 int shouldInterceptRequestCallCount = mShouldInterceptRequestHelper.getCallCount();
393 int onPageFinishedCallCount = mContentsClient.getOnPageFinishedHelper().getCallCount();
395 loadUrlAsync(mAwContents, aboutPageUrl);
397 mShouldInterceptRequestHelper.waitForCallback(shouldInterceptRequestCallCount);
398 mContentsClient.getOnPageFinishedHelper().waitForCallback(onPageFinishedCallCount);
401 private static class SlowAwWebResourceResponse extends AwWebResourceResponse {
402 private CallbackHelper mReadStartedCallbackHelper = new CallbackHelper();
403 private CountDownLatch mLatch = new CountDownLatch(1);
405 public SlowAwWebResourceResponse(String mimeType, String encoding, InputStream data) {
406 super(mimeType, encoding, data);
410 public InputStream getData() {
411 mReadStartedCallbackHelper.notifyCalled();
414 } catch (InterruptedException e) {
417 return super.getData();
420 public void unblockReads() {
424 public CallbackHelper getReadStartedCallbackHelper() {
425 return mReadStartedCallbackHelper;
430 @Feature({"AndroidWebView"})
431 public void testDoesNotCrashOnSlowStream() throws Throwable {
432 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
433 final String aboutPageData = makePageWithTitle("some title");
434 final String encoding = "UTF-8";
435 final SlowAwWebResourceResponse slowAwWebResourceResponse =
436 new SlowAwWebResourceResponse("text/html", encoding,
437 new ByteArrayInputStream(aboutPageData.getBytes(encoding)));
439 mShouldInterceptRequestHelper.setReturnValue(slowAwWebResourceResponse);
440 int callCount = slowAwWebResourceResponse.getReadStartedCallbackHelper().getCallCount();
441 loadUrlAsync(mAwContents, aboutPageUrl);
442 slowAwWebResourceResponse.getReadStartedCallbackHelper().waitForCallback(callCount);
444 // Now the AwContents is "stuck" waiting for the SlowInputStream to finish reading so we
445 // delete it to make sure that the dangling 'read' task doesn't cause a crash. Unfortunately
446 // this will not always lead to a crash but it should happen often enough for us to notice.
448 runTestOnUiThread(new Runnable() {
451 getActivity().removeAllViews();
454 destroyAwContentsOnMainSync(mAwContents);
455 pollOnUiThread(new Callable<Boolean>() {
457 public Boolean call() {
458 return AwContents.getNativeInstanceCount() == 0;
462 slowAwWebResourceResponse.unblockReads();
466 @Feature({"AndroidWebView"})
467 public void testHttpStatusCodeAndText() throws Throwable {
468 final String syncGetUrl = mWebServer.getResponseUrl("/intercept_me");
469 final String syncGetJs =
471 " var xhr = new XMLHttpRequest();" +
472 " xhr.open('GET', '" + syncGetUrl + "', false);" +
474 " console.info('xhr.status = ' + xhr.status);" +
475 " console.info('xhr.statusText = ' + xhr.statusText);" +
476 " return '[' + xhr.status + '][' + xhr.statusText + ']';" +
478 enableJavaScriptOnUiThread(mAwContents);
480 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
481 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), aboutPageUrl);
483 mShouldInterceptRequestHelper.setReturnValue(
484 new AwWebResourceResponse("text/html", "UTF-8", null));
485 assertEquals("\"[404][Not Found]\"",
486 executeJavaScriptAndWaitForResult(mAwContents, mContentsClient, syncGetJs));
488 mShouldInterceptRequestHelper.setReturnValue(
489 new AwWebResourceResponse("text/html", "UTF-8", new EmptyInputStream()));
490 assertEquals("\"[200][OK]\"",
491 executeJavaScriptAndWaitForResult(mAwContents, mContentsClient, syncGetJs));
493 mShouldInterceptRequestHelper.setReturnValue(
494 new AwWebResourceResponse("text/html", "UTF-8", new EmptyInputStream(),
495 TEAPOT_STATUS_CODE, TEAPOT_RESPONSE_PHRASE, new HashMap<String, String>()));
496 assertEquals("\"[" + TEAPOT_STATUS_CODE + "][" + TEAPOT_RESPONSE_PHRASE + "]\"",
497 executeJavaScriptAndWaitForResult(mAwContents, mContentsClient, syncGetJs));
500 private String getHeaderValue(AwContents awContents, TestAwContentsClient contentsClient,
501 String url, String headerName) throws Exception {
502 final String syncGetJs =
504 " var xhr = new XMLHttpRequest();" +
505 " xhr.open('GET', '" + url + "', false);" +
507 " console.info(xhr.getAllResponseHeaders());" +
508 " return xhr.getResponseHeader('" + headerName + "');" +
510 String header = executeJavaScriptAndWaitForResult(awContents, contentsClient, syncGetJs);
512 if (header.equals("null"))
514 // JSON stringification applied by executeJavaScriptAndWaitForResult adds quotes
515 // around returned strings.
516 assertTrue(header.length() > 2);
517 assertEquals('"', header.charAt(0));
518 assertEquals('"', header.charAt(header.length() - 1));
519 return header.substring(1, header.length() - 1);
523 @Feature({"AndroidWebView"})
524 public void testHttpResponseClientViaHeader() throws Throwable {
525 final String clientResponseHeaderName = "Client-Via";
526 final String clientResponseHeaderValue = "shouldInterceptRequest";
527 final String syncGetUrl = mWebServer.getResponseUrl("/intercept_me");
528 enableJavaScriptOnUiThread(mAwContents);
530 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
531 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), aboutPageUrl);
533 // The response header is set regardless of whether the embedder has provided a
534 // valid resource stream.
535 mShouldInterceptRequestHelper.setReturnValue(
536 new AwWebResourceResponse("text/html", "UTF-8", null));
537 assertEquals(clientResponseHeaderValue,
538 getHeaderValue(mAwContents, mContentsClient, syncGetUrl, clientResponseHeaderName));
539 mShouldInterceptRequestHelper.setReturnValue(
540 new AwWebResourceResponse("text/html", "UTF-8", new EmptyInputStream()));
541 assertEquals(clientResponseHeaderValue,
542 getHeaderValue(mAwContents, mContentsClient, syncGetUrl, clientResponseHeaderName));
547 @Feature({"AndroidWebView"})
548 public void testHttpResponseHeader() throws Throwable {
549 final String clientResponseHeaderName = "X-Test-Header-Name";
550 final String clientResponseHeaderValue = "TestHeaderValue";
551 final String syncGetUrl = mWebServer.getResponseUrl("/intercept_me");
552 final Map<String, String> headers = new HashMap<String, String>();
553 headers.put(clientResponseHeaderName, clientResponseHeaderValue);
554 enableJavaScriptOnUiThread(mAwContents);
556 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
557 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), aboutPageUrl);
559 mShouldInterceptRequestHelper.setReturnValue(
560 new AwWebResourceResponse("text/html", "UTF-8", null, 0, null, headers));
561 assertEquals(clientResponseHeaderValue,
562 getHeaderValue(mAwContents, mContentsClient, syncGetUrl, clientResponseHeaderName));
566 @Feature({"AndroidWebView"})
567 public void testNullHttpResponseHeaders() throws Throwable {
568 final String syncGetUrl = mWebServer.getResponseUrl("/intercept_me");
569 enableJavaScriptOnUiThread(mAwContents);
571 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
572 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), aboutPageUrl);
574 mShouldInterceptRequestHelper.setReturnValue(
575 new AwWebResourceResponse("text/html", "UTF-8", null, 0, null, null));
576 assertEquals(null, getHeaderValue(mAwContents, mContentsClient, syncGetUrl, "Some-Header"));
579 private String makePageWithTitle(String title) {
580 return CommonResources.makeHtmlPageFrom("<title>" + title + "</title>",
581 "<div> The title is: " + title + " </div>");
585 @Feature({"AndroidWebView"})
586 public void testCanInterceptMainFrame() throws Throwable {
587 final String expectedTitle = "testShouldInterceptRequestCanInterceptMainFrame";
588 final String expectedPage = makePageWithTitle(expectedTitle);
590 mShouldInterceptRequestHelper.setReturnValue(
591 stringToAwWebResourceResponse(expectedPage));
593 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
595 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), aboutPageUrl);
597 assertEquals(expectedTitle, getTitleOnUiThread(mAwContents));
598 assertEquals(0, mWebServer.getRequestCount("/" + CommonResources.ABOUT_FILENAME));
602 @Feature({"AndroidWebView"})
603 public void testDoesNotChangeReportedUrl() throws Throwable {
604 mShouldInterceptRequestHelper.setReturnValue(
605 stringToAwWebResourceResponse(makePageWithTitle("some title")));
607 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
609 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), aboutPageUrl);
611 assertEquals(aboutPageUrl, mContentsClient.getOnPageFinishedHelper().getUrl());
612 assertEquals(aboutPageUrl, mContentsClient.getOnPageStartedHelper().getUrl());
616 @Feature({"AndroidWebView"})
617 public void testNullInputStreamCausesErrorForMainFrame() throws Throwable {
618 final OnReceivedErrorHelper onReceivedErrorHelper =
619 mContentsClient.getOnReceivedErrorHelper();
621 mShouldInterceptRequestHelper.setReturnValue(
622 new AwWebResourceResponse("text/html", "UTF-8", null));
624 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
625 final int callCount = onReceivedErrorHelper.getCallCount();
626 loadUrlAsync(mAwContents, aboutPageUrl);
627 onReceivedErrorHelper.waitForCallback(callCount);
628 assertEquals(0, mWebServer.getRequestCount("/" + CommonResources.ABOUT_FILENAME));
632 @Feature({"AndroidWebView"})
633 public void testCalledForImage() throws Throwable {
634 final String imagePath = "/" + CommonResources.FAVICON_FILENAME;
635 mWebServer.setResponseBase64(imagePath,
636 CommonResources.FAVICON_DATA_BASE64, CommonResources.getImagePngHeaders(true));
637 final String pageWithImage =
638 addPageToTestServer(mWebServer, "/page_with_image.html",
639 CommonResources.getOnImageLoadedHtml(CommonResources.FAVICON_FILENAME));
641 int callCount = mShouldInterceptRequestHelper.getCallCount();
642 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), pageWithImage);
643 mShouldInterceptRequestHelper.waitForCallback(callCount, 2);
645 assertEquals(2, mShouldInterceptRequestHelper.getUrls().size());
646 assertTrue(mShouldInterceptRequestHelper.getUrls().get(1).endsWith(
647 CommonResources.FAVICON_FILENAME));
651 @Feature({"AndroidWebView"})
652 public void testOnReceivedErrorCallback() throws Throwable {
653 mShouldInterceptRequestHelper.setReturnValue(new AwWebResourceResponse(null, null, null));
654 OnReceivedErrorHelper onReceivedErrorHelper = mContentsClient.getOnReceivedErrorHelper();
655 int onReceivedErrorHelperCallCount = onReceivedErrorHelper.getCallCount();
656 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), "foo://bar");
657 onReceivedErrorHelper.waitForCallback(onReceivedErrorHelperCallCount, 1);
661 @Feature({"AndroidWebView"})
662 public void testNoOnReceivedErrorCallback() throws Throwable {
663 final String imagePath = "/" + CommonResources.FAVICON_FILENAME;
664 final String imageUrl = mWebServer.setResponseBase64(imagePath,
665 CommonResources.FAVICON_DATA_BASE64, CommonResources.getImagePngHeaders(true));
666 final String pageWithImage =
667 addPageToTestServer(mWebServer, "/page_with_image.html",
668 CommonResources.getOnImageLoadedHtml(CommonResources.FAVICON_FILENAME));
669 mShouldInterceptRequestHelper.setReturnValueForUrl(
670 imageUrl, new AwWebResourceResponse(null, null, null));
671 OnReceivedErrorHelper onReceivedErrorHelper = mContentsClient.getOnReceivedErrorHelper();
672 int onReceivedErrorHelperCallCount = onReceivedErrorHelper.getCallCount();
673 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), pageWithImage);
674 assertEquals(onReceivedErrorHelperCallCount, onReceivedErrorHelper.getCallCount());
678 @Feature({"AndroidWebView"})
679 public void testCalledForIframe() throws Throwable {
680 final String aboutPageUrl = addAboutPageToTestServer(mWebServer);
681 final String pageWithIframeUrl = addPageToTestServer(mWebServer, "/page_with_iframe.html",
682 CommonResources.makeHtmlPageFrom("",
683 "<iframe src=\"" + aboutPageUrl + "\"/>"));
685 int callCount = mShouldInterceptRequestHelper.getCallCount();
686 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), pageWithIframeUrl);
687 mShouldInterceptRequestHelper.waitForCallback(callCount, 2);
688 assertEquals(2, mShouldInterceptRequestHelper.getUrls().size());
689 assertEquals(aboutPageUrl, mShouldInterceptRequestHelper.getUrls().get(1));
692 private void calledForUrlTemplate(final String url) throws Exception {
693 int callCount = mShouldInterceptRequestHelper.getCallCount();
694 int onPageStartedCallCount = mContentsClient.getOnPageStartedHelper().getCallCount();
695 loadUrlAsync(mAwContents, url);
696 mShouldInterceptRequestHelper.waitForCallback(callCount);
697 assertEquals(url, mShouldInterceptRequestHelper.getUrls().get(0));
699 mContentsClient.getOnPageStartedHelper().waitForCallback(onPageStartedCallCount);
700 assertEquals(onPageStartedCallCount + 1,
701 mContentsClient.getOnPageStartedHelper().getCallCount());
704 private void notCalledForUrlTemplate(final String url) throws Exception {
705 int callCount = mShouldInterceptRequestHelper.getCallCount();
706 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), url);
707 // The intercepting must happen before onPageFinished. Since the IPC messages from the
708 // renderer should be delivered in order waiting for onPageFinished is sufficient to
709 // 'flush' any pending interception messages.
710 assertEquals(callCount, mShouldInterceptRequestHelper.getCallCount());
714 @Feature({"AndroidWebView"})
715 public void testCalledForUnsupportedSchemes() throws Throwable {
716 calledForUrlTemplate("foobar://resource/1");
720 @Feature({"AndroidWebView"})
721 public void testCalledForNonexistentFiles() throws Throwable {
722 calledForUrlTemplate("file:///somewhere/something");
726 @Feature({"AndroidWebView"})
727 public void testCalledForExistingFiles() throws Throwable {
728 final String tmpDir = getInstrumentation().getTargetContext().getCacheDir().getPath();
729 final String fileName = tmpDir + "/testfile.html";
730 final String title = "existing file title";
731 TestFileUtil.deleteFile(fileName); // Remove leftover file if any.
732 TestFileUtil.createNewHtmlFile(fileName, title, "");
733 final String existingFileUrl = "file://" + fileName;
735 int callCount = mShouldInterceptRequestHelper.getCallCount();
736 int onPageFinishedCallCount = mContentsClient.getOnPageFinishedHelper().getCallCount();
737 loadUrlAsync(mAwContents, existingFileUrl);
738 mShouldInterceptRequestHelper.waitForCallback(callCount);
739 assertEquals(existingFileUrl, mShouldInterceptRequestHelper.getUrls().get(0));
741 mContentsClient.getOnPageFinishedHelper().waitForCallback(onPageFinishedCallCount);
742 assertEquals(title, getTitleOnUiThread(mAwContents));
743 assertEquals(onPageFinishedCallCount + 1,
744 mContentsClient.getOnPageFinishedHelper().getCallCount());
748 @Feature({"AndroidWebView"})
749 public void testNotCalledForExistingResource() throws Throwable {
750 notCalledForUrlTemplate("file:///android_res/raw/resource_file.html");
754 @Feature({"AndroidWebView"})
755 public void testCalledForNonexistentResource() throws Throwable {
756 calledForUrlTemplate("file:///android_res/raw/no_file.html");
760 @Feature({"AndroidWebView"})
761 public void testNotCalledForExistingAsset() throws Throwable {
762 notCalledForUrlTemplate("file:///android_asset/asset_file.html");
766 @Feature({"AndroidWebView"})
767 public void testCalledForNonexistentAsset() throws Throwable {
768 calledForUrlTemplate("file:///android_res/raw/no_file.html");
772 @Feature({"AndroidWebView"})
773 public void testNotCalledForExistingContentUrl() throws Throwable {
774 final String contentResourceName = "target";
775 final String existingContentUrl = TestContentProvider.createContentUrl(contentResourceName);
777 notCalledForUrlTemplate(existingContentUrl);
779 int contentRequestCount = TestContentProvider.getResourceRequestCount(
780 getInstrumentation().getTargetContext(), contentResourceName);
781 assertEquals(1, contentRequestCount);
785 @Feature({"AndroidWebView"})
786 public void testCalledForNonexistentContentUrl() throws Throwable {
787 calledForUrlTemplate("content://org.chromium.webview.NoSuchProvider/foo");