1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.webkit.cts; 18 19 import android.cts.util.EvaluateJsResultPollingCheck; 20 import android.cts.util.NullWebViewUtils; 21 import android.cts.util.PollingCheck; 22 import android.graphics.Bitmap; 23 import android.os.Message; 24 import android.test.ActivityInstrumentationTestCase2; 25 import android.view.KeyEvent; 26 import android.view.ViewGroup; 27 import android.webkit.HttpAuthHandler; 28 import android.webkit.ValueCallback; 29 import android.webkit.WebChromeClient; 30 import android.webkit.WebResourceError; 31 import android.webkit.WebResourceRequest; 32 import android.webkit.WebResourceResponse; 33 import android.webkit.WebSettings; 34 import android.webkit.WebView; 35 import android.webkit.WebViewClient; 36 import android.webkit.cts.WebViewOnUiThread.WaitForLoadedClient; 37 import android.util.Pair; 38 39 import java.io.ByteArrayInputStream; 40 import java.nio.charset.StandardCharsets; 41 import java.util.HashMap; 42 import java.util.Map; 43 import java.util.List; 44 import java.util.ArrayList; 45 46 public class WebViewClientTest extends ActivityInstrumentationTestCase2<WebViewCtsActivity> { 47 private static final long TEST_TIMEOUT = 5000; 48 private static final String TEST_URL = "http://www.example.com/"; 49 50 private WebViewOnUiThread mOnUiThread; 51 private CtsTestServer mWebServer; 52 WebViewClientTest()53 public WebViewClientTest() { 54 super("android.webkit.cts", WebViewCtsActivity.class); 55 } 56 57 @Override setUp()58 protected void setUp() throws Exception { 59 super.setUp(); 60 final WebViewCtsActivity activity = getActivity(); 61 WebView webview = activity.getWebView(); 62 if (webview != null) { 63 new PollingCheck(TEST_TIMEOUT) { 64 @Override 65 protected boolean check() { 66 return activity.hasWindowFocus(); 67 } 68 }.run(); 69 70 mOnUiThread = new WebViewOnUiThread(this, webview); 71 } 72 } 73 74 @Override tearDown()75 protected void tearDown() throws Exception { 76 if (mOnUiThread != null) { 77 mOnUiThread.cleanUp(); 78 } 79 if (mWebServer != null) { 80 mWebServer.shutdown(); 81 } 82 super.tearDown(); 83 } 84 85 // Verify that the shouldoverrideurlloading is false by default testShouldOverrideUrlLoadingDefault()86 public void testShouldOverrideUrlLoadingDefault() { 87 if (!NullWebViewUtils.isWebViewAvailable()) { 88 return; 89 } 90 final WebViewClient webViewClient = new WebViewClient(); 91 assertFalse(webViewClient.shouldOverrideUrlLoading(mOnUiThread.getWebView(), new String())); 92 } 93 94 // Verify shouldoverrideurlloading called on top level navigation testShouldOverrideUrlLoading()95 public void testShouldOverrideUrlLoading() { 96 if (!NullWebViewUtils.isWebViewAvailable()) { 97 return; 98 } 99 final MockWebViewClient webViewClient = new MockWebViewClient(); 100 mOnUiThread.setWebViewClient(webViewClient); 101 mOnUiThread.getSettings().setJavaScriptEnabled(true); 102 String data = "<html><body>" + 103 "<a href=\"" + TEST_URL + "\" id=\"link\">new page</a>" + 104 "</body></html>"; 105 mOnUiThread.loadDataAndWaitForCompletion(data, "text/html", null); 106 clickOnLinkUsingJs("link", mOnUiThread); 107 assertEquals(TEST_URL, webViewClient.getLastShouldOverrideUrl()); 108 assertNotNull(webViewClient.getLastShouldOverrideResourceRequest()); 109 assertTrue(webViewClient.getLastShouldOverrideResourceRequest().isForMainFrame()); 110 assertFalse(webViewClient.getLastShouldOverrideResourceRequest().isRedirect()); 111 assertFalse(webViewClient.getLastShouldOverrideResourceRequest().hasGesture()); 112 } 113 114 // Verify shouldoverrideurlloading called on webview called via onCreateWindow 115 // TODO(sgurun) upstream this test to Aw. testShouldOverrideUrlLoadingOnCreateWindow()116 public void testShouldOverrideUrlLoadingOnCreateWindow() throws Exception { 117 if (!NullWebViewUtils.isWebViewAvailable()) { 118 return; 119 } 120 mWebServer = new CtsTestServer(getActivity()); 121 // WebViewClient for main window 122 final MockWebViewClient mainWebViewClient = new MockWebViewClient(); 123 // WebViewClient for child window 124 final MockWebViewClient childWebViewClient = new MockWebViewClient(); 125 mOnUiThread.setWebViewClient(mainWebViewClient); 126 mOnUiThread.getSettings().setJavaScriptEnabled(true); 127 mOnUiThread.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); 128 mOnUiThread.getSettings().setSupportMultipleWindows(true); 129 130 final WebView childWebView = mOnUiThread.createWebView(); 131 132 mOnUiThread.setWebChromeClient(new WebChromeClient() { 133 @Override 134 public boolean onCreateWindow( 135 WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) { 136 WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj; 137 childWebView.setWebViewClient(childWebViewClient); 138 childWebView.getSettings().setJavaScriptEnabled(true); 139 transport.setWebView(childWebView); 140 getActivity().addContentView(childWebView, new ViewGroup.LayoutParams( 141 ViewGroup.LayoutParams.FILL_PARENT, 142 ViewGroup.LayoutParams.WRAP_CONTENT)); 143 resultMsg.sendToTarget(); 144 return true; 145 } 146 }); 147 mOnUiThread.loadUrl(mWebServer.getAssetUrl(TestHtmlConstants.BLANK_TAG_URL)); 148 149 new PollingCheck(TEST_TIMEOUT) { 150 @Override 151 protected boolean check() { 152 return childWebViewClient.hasOnPageFinishedCalled(); 153 } 154 }.run(); 155 assertEquals(mWebServer.getAssetUrl(TestHtmlConstants.PAGE_WITH_LINK_URL), 156 childWebViewClient.getLastShouldOverrideUrl()); 157 158 // Now test a navigation within the page 159 //TODO(hush) Enable this portion when b/12804986 is fixed. 160 /* 161 WebViewOnUiThread childWebViewOnUiThread = new WebViewOnUiThread(this, childWebView); 162 final int childCallCount = childWebViewClient.getShouldOverrideUrlLoadingCallCount(); 163 final int mainCallCount = mainWebViewClient.getShouldOverrideUrlLoadingCallCount(); 164 clickOnLinkUsingJs("link", childWebViewOnUiThread); 165 new PollingCheck(TEST_TIMEOUT) { 166 @Override 167 protected boolean check() { 168 return childWebViewClient.getShouldOverrideUrlLoadingCallCount() > childCallCount; 169 } 170 }.run(); 171 assertEquals(mainCallCount, mainWebViewClient.getShouldOverrideUrlLoadingCallCount()); 172 assertEquals(TEST_URL, childWebViewClient.getLastShouldOverrideUrl()); 173 */ 174 } 175 clickOnLinkUsingJs(final String linkId, WebViewOnUiThread webViewOnUiThread)176 private void clickOnLinkUsingJs(final String linkId, WebViewOnUiThread webViewOnUiThread) { 177 EvaluateJsResultPollingCheck jsResult = new EvaluateJsResultPollingCheck("null"); 178 webViewOnUiThread.evaluateJavascript( 179 "document.getElementById('" + linkId + "').click();" + 180 "console.log('element with id [" + linkId + "] clicked');", jsResult); 181 jsResult.run(); 182 } 183 testLoadPage()184 public void testLoadPage() throws Exception { 185 if (!NullWebViewUtils.isWebViewAvailable()) { 186 return; 187 } 188 final MockWebViewClient webViewClient = new MockWebViewClient(); 189 mOnUiThread.setWebViewClient(webViewClient); 190 mWebServer = new CtsTestServer(getActivity()); 191 String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 192 193 assertFalse(webViewClient.hasOnPageStartedCalled()); 194 assertFalse(webViewClient.hasOnLoadResourceCalled()); 195 assertFalse(webViewClient.hasOnPageFinishedCalled()); 196 mOnUiThread.loadUrlAndWaitForCompletion(url); 197 198 new PollingCheck(TEST_TIMEOUT) { 199 @Override 200 protected boolean check() { 201 return webViewClient.hasOnPageStartedCalled(); 202 } 203 }.run(); 204 205 new PollingCheck(TEST_TIMEOUT) { 206 @Override 207 protected boolean check() { 208 return webViewClient.hasOnLoadResourceCalled(); 209 } 210 }.run(); 211 212 new PollingCheck(TEST_TIMEOUT) { 213 @Override 214 protected boolean check() { 215 return webViewClient.hasOnPageFinishedCalled(); 216 } 217 }.run(); 218 } 219 testOnReceivedLoginRequest()220 public void testOnReceivedLoginRequest() throws Exception { 221 if (!NullWebViewUtils.isWebViewAvailable()) { 222 return; 223 } 224 final MockWebViewClient webViewClient = new MockWebViewClient(); 225 mOnUiThread.setWebViewClient(webViewClient); 226 TestWebServer testServer = null; 227 //set the url and html 228 final String path = "/main"; 229 final String page = "<head></head><body>test onReceivedLoginRequest</body>"; 230 final String headerName = "x-auto-login"; 231 final String headerValue = "realm=com.google&account=foo%40bar.com&args=random_string"; 232 List<Pair<String, String>> headers = new ArrayList<Pair<String, String>>(); 233 headers.add(Pair.create(headerName, headerValue)); 234 235 try { 236 testServer = new TestWebServer(false); 237 String url = testServer.setResponse(path, page, headers); 238 assertFalse(webViewClient.hasOnReceivedLoginRequest()); 239 mOnUiThread.loadUrlAndWaitForCompletion(url); 240 assertTrue(webViewClient.hasOnReceivedLoginRequest()); 241 new PollingCheck(TEST_TIMEOUT) { 242 @Override 243 protected boolean check() { 244 return webViewClient.hasOnReceivedLoginRequest(); 245 } 246 }.run(); 247 assertEquals("com.google", webViewClient.getLoginRequestRealm()); 248 assertEquals("foo@bar.com", webViewClient.getLoginRequestAccount()); 249 assertEquals("random_string", webViewClient.getLoginRequestArgs()); 250 } finally { 251 testServer.shutdown(); 252 } 253 } testOnReceivedError()254 public void testOnReceivedError() throws Exception { 255 if (!NullWebViewUtils.isWebViewAvailable()) { 256 return; 257 } 258 final MockWebViewClient webViewClient = new MockWebViewClient(); 259 mOnUiThread.setWebViewClient(webViewClient); 260 261 String wrongUri = "invalidscheme://some/resource"; 262 assertEquals(0, webViewClient.hasOnReceivedErrorCode()); 263 mOnUiThread.loadUrlAndWaitForCompletion(wrongUri); 264 assertEquals(WebViewClient.ERROR_UNSUPPORTED_SCHEME, 265 webViewClient.hasOnReceivedErrorCode()); 266 } 267 testOnReceivedErrorForSubresource()268 public void testOnReceivedErrorForSubresource() throws Exception { 269 if (!NullWebViewUtils.isWebViewAvailable()) { 270 return; 271 } 272 final MockWebViewClient webViewClient = new MockWebViewClient(); 273 mOnUiThread.setWebViewClient(webViewClient); 274 mWebServer = new CtsTestServer(getActivity()); 275 276 assertEquals(null, webViewClient.hasOnReceivedResourceError()); 277 String url = mWebServer.getAssetUrl(TestHtmlConstants.BAD_IMAGE_PAGE_URL); 278 mOnUiThread.loadUrlAndWaitForCompletion(url); 279 assertTrue(webViewClient.hasOnReceivedResourceError() != null); 280 assertEquals(WebViewClient.ERROR_UNSUPPORTED_SCHEME, 281 webViewClient.hasOnReceivedResourceError().getErrorCode()); 282 } 283 testOnReceivedHttpError()284 public void testOnReceivedHttpError() throws Exception { 285 if (!NullWebViewUtils.isWebViewAvailable()) { 286 return; 287 } 288 final MockWebViewClient webViewClient = new MockWebViewClient(); 289 mOnUiThread.setWebViewClient(webViewClient); 290 mWebServer = new CtsTestServer(getActivity()); 291 292 assertEquals(null, webViewClient.hasOnReceivedHttpError()); 293 String url = mWebServer.getAssetUrl(TestHtmlConstants.NON_EXISTENT_PAGE_URL); 294 mOnUiThread.loadUrlAndWaitForCompletion(url); 295 assertTrue(webViewClient.hasOnReceivedHttpError() != null); 296 assertEquals(404, webViewClient.hasOnReceivedHttpError().getStatusCode()); 297 } 298 testOnFormResubmission()299 public void testOnFormResubmission() throws Exception { 300 if (!NullWebViewUtils.isWebViewAvailable()) { 301 return; 302 } 303 final MockWebViewClient webViewClient = new MockWebViewClient(); 304 mOnUiThread.setWebViewClient(webViewClient); 305 final WebSettings settings = mOnUiThread.getSettings(); 306 settings.setJavaScriptEnabled(true); 307 mWebServer = new CtsTestServer(getActivity()); 308 309 assertFalse(webViewClient.hasOnFormResubmissionCalled()); 310 String url = mWebServer.getAssetUrl(TestHtmlConstants.JS_FORM_URL); 311 // this loads a form, which automatically posts itself 312 mOnUiThread.loadUrlAndWaitForCompletion(url); 313 // wait for JavaScript to post the form 314 mOnUiThread.waitForLoadCompletion(); 315 // the URL should have changed when the form was posted 316 assertFalse(url.equals(mOnUiThread.getUrl())); 317 // reloading the current URL should trigger the callback 318 mOnUiThread.reload(); 319 new PollingCheck(TEST_TIMEOUT) { 320 @Override 321 protected boolean check() { 322 return webViewClient.hasOnFormResubmissionCalled(); 323 } 324 }.run(); 325 } 326 testDoUpdateVisitedHistory()327 public void testDoUpdateVisitedHistory() throws Exception { 328 if (!NullWebViewUtils.isWebViewAvailable()) { 329 return; 330 } 331 final MockWebViewClient webViewClient = new MockWebViewClient(); 332 mOnUiThread.setWebViewClient(webViewClient); 333 mWebServer = new CtsTestServer(getActivity()); 334 335 assertFalse(webViewClient.hasDoUpdateVisitedHistoryCalled()); 336 String url1 = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 337 String url2 = mWebServer.getAssetUrl(TestHtmlConstants.BR_TAG_URL); 338 mOnUiThread.loadUrlAndWaitForCompletion(url1); 339 mOnUiThread.loadUrlAndWaitForCompletion(url2); 340 new PollingCheck(TEST_TIMEOUT) { 341 @Override 342 protected boolean check() { 343 return webViewClient.hasDoUpdateVisitedHistoryCalled(); 344 } 345 }.run(); 346 } 347 testOnReceivedHttpAuthRequest()348 public void testOnReceivedHttpAuthRequest() throws Exception { 349 if (!NullWebViewUtils.isWebViewAvailable()) { 350 return; 351 } 352 final MockWebViewClient webViewClient = new MockWebViewClient(); 353 mOnUiThread.setWebViewClient(webViewClient); 354 mWebServer = new CtsTestServer(getActivity()); 355 356 assertFalse(webViewClient.hasOnReceivedHttpAuthRequestCalled()); 357 String url = mWebServer.getAuthAssetUrl(TestHtmlConstants.EMBEDDED_IMG_URL); 358 mOnUiThread.loadUrlAndWaitForCompletion(url); 359 assertTrue(webViewClient.hasOnReceivedHttpAuthRequestCalled()); 360 } 361 testShouldOverrideKeyEvent()362 public void testShouldOverrideKeyEvent() { 363 if (!NullWebViewUtils.isWebViewAvailable()) { 364 return; 365 } 366 final MockWebViewClient webViewClient = new MockWebViewClient(); 367 mOnUiThread.setWebViewClient(webViewClient); 368 369 assertFalse(webViewClient.shouldOverrideKeyEvent(mOnUiThread.getWebView(), null)); 370 } 371 testOnUnhandledKeyEvent()372 public void testOnUnhandledKeyEvent() throws Throwable { 373 if (!NullWebViewUtils.isWebViewAvailable()) { 374 return; 375 } 376 requireLoadedPage(); 377 final MockWebViewClient webViewClient = new MockWebViewClient(); 378 mOnUiThread.setWebViewClient(webViewClient); 379 380 mOnUiThread.requestFocus(); 381 getInstrumentation().waitForIdleSync(); 382 383 assertFalse(webViewClient.hasOnUnhandledKeyEventCalled()); 384 sendKeys(KeyEvent.KEYCODE_1); 385 386 new PollingCheck(TEST_TIMEOUT) { 387 @Override 388 protected boolean check() { 389 return webViewClient.hasOnUnhandledKeyEventCalled(); 390 } 391 }.run(); 392 } 393 testOnScaleChanged()394 public void testOnScaleChanged() throws Throwable { 395 if (!NullWebViewUtils.isWebViewAvailable()) { 396 return; 397 } 398 final MockWebViewClient webViewClient = new MockWebViewClient(); 399 mOnUiThread.setWebViewClient(webViewClient); 400 mWebServer = new CtsTestServer(getActivity()); 401 402 assertFalse(webViewClient.hasOnScaleChangedCalled()); 403 String url1 = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 404 mOnUiThread.loadUrlAndWaitForCompletion(url1); 405 406 new PollingCheck(TEST_TIMEOUT) { 407 @Override 408 protected boolean check() { 409 return mOnUiThread.canZoomIn(); 410 } 411 }.run(); 412 413 assertTrue(mOnUiThread.zoomIn()); 414 new PollingCheck(TEST_TIMEOUT) { 415 @Override 416 protected boolean check() { 417 return webViewClient.hasOnScaleChangedCalled(); 418 } 419 }.run(); 420 } 421 422 // Test that shouldInterceptRequest is called with the correct parameters testShouldInterceptRequestParams()423 public void testShouldInterceptRequestParams() throws Throwable { 424 if (!NullWebViewUtils.isWebViewAvailable()) { 425 return; 426 } 427 428 final String mainPath = "/main"; 429 final String mainPage = "<head></head><body>test page</body>"; 430 final String headerName = "x-test-header-name"; 431 final String headerValue = "testheadervalue"; 432 HashMap<String, String> headers = new HashMap<String, String>(1); 433 headers.put(headerName, headerValue); 434 435 // A client which saves the WebResourceRequest as interceptRequest 436 final class TestClient extends WaitForLoadedClient { 437 public TestClient() { 438 super(mOnUiThread); 439 } 440 441 @Override 442 public WebResourceResponse shouldInterceptRequest(WebView view, 443 WebResourceRequest request) { 444 assertNotNull(view); 445 assertNotNull(request); 446 447 assertEquals(view, mOnUiThread.getWebView()); 448 449 // Save the main page request; discard any other requests (e.g. for favicon.ico) 450 if (request.getUrl().getPath().equals(mainPath)) { 451 assertNull(interceptRequest); 452 interceptRequest = request; 453 } 454 455 return null; 456 } 457 458 public volatile WebResourceRequest interceptRequest; 459 } 460 461 TestClient client = new TestClient(); 462 mOnUiThread.setWebViewClient(client); 463 464 TestWebServer server = new TestWebServer(false); 465 try { 466 String mainUrl = server.setResponse(mainPath, mainPage, null); 467 468 mOnUiThread.loadUrlAndWaitForCompletion(mainUrl, headers); 469 470 // Inspect the fields of the saved WebResourceRequest 471 assertNotNull(client.interceptRequest); 472 assertEquals(mainUrl, client.interceptRequest.getUrl().toString()); 473 assertTrue(client.interceptRequest.isForMainFrame()); 474 assertEquals(server.getLastRequest(mainPath).getRequestLine().getMethod(), 475 client.interceptRequest.getMethod()); 476 477 // Web request headers are case-insensitive. We provided lower-case headerName and 478 // headerValue. This will pass implementations which either do not mangle case, 479 // convert to lowercase, or convert to uppercase but return a case-insensitive map. 480 Map<String, String> interceptHeaders = client.interceptRequest.getRequestHeaders(); 481 assertTrue(interceptHeaders.containsKey(headerName)); 482 assertEquals(headerValue, interceptHeaders.get(headerName)); 483 } finally { 484 server.shutdown(); 485 } 486 } 487 488 // Test that the WebResourceResponse returned by shouldInterceptRequest is handled correctly testShouldInterceptRequestResponse()489 public void testShouldInterceptRequestResponse() throws Throwable { 490 if (!NullWebViewUtils.isWebViewAvailable()) { 491 return; 492 } 493 494 final String mainPath = "/main"; 495 final String mainPage = "<head></head><body>test page</body>"; 496 final String interceptPath = "/intercept_me"; 497 498 // A client which responds to requests for interceptPath with a saved interceptResponse 499 final class TestClient extends WaitForLoadedClient { 500 public TestClient() { 501 super(mOnUiThread); 502 } 503 504 @Override 505 public WebResourceResponse shouldInterceptRequest(WebView view, 506 WebResourceRequest request) { 507 if (request.getUrl().toString().contains(interceptPath)) { 508 assertNotNull(interceptResponse); 509 return interceptResponse; 510 } 511 512 return null; 513 } 514 515 volatile public WebResourceResponse interceptResponse; 516 } 517 518 mOnUiThread.getSettings().setJavaScriptEnabled(true); 519 520 TestClient client = new TestClient(); 521 mOnUiThread.setWebViewClient(client); 522 523 TestWebServer server = new TestWebServer(false); 524 try { 525 String interceptUrl = server.getResponseUrl(interceptPath); 526 527 // JavaScript which makes a synchronous AJAX request and logs and returns the status 528 String js = 529 "(function() {" + 530 " var xhr = new XMLHttpRequest();" + 531 " xhr.open('GET', '" + interceptUrl + "', false);" + 532 " xhr.send(null);" + 533 " console.info('xhr.status = ' + xhr.status);" + 534 " console.info('xhr.statusText = ' + xhr.statusText);" + 535 " return '[' + xhr.status + '][' + xhr.statusText + ']';" + 536 "})();"; 537 538 String mainUrl = server.setResponse(mainPath, mainPage, null); 539 mOnUiThread.loadUrlAndWaitForCompletion(mainUrl, null); 540 541 EvaluateJsResultPollingCheck jsResult; 542 543 // Test a nonexistent page 544 client.interceptResponse = new WebResourceResponse("text/html", "UTF-8", null); 545 jsResult = new EvaluateJsResultPollingCheck("\"[404][Not Found]\""); 546 mOnUiThread.evaluateJavascript(js, jsResult); 547 jsResult.run(); 548 549 // Test an empty page 550 client.interceptResponse = new WebResourceResponse("text/html", "UTF-8", 551 new ByteArrayInputStream(new byte[0])); 552 jsResult = new EvaluateJsResultPollingCheck("\"[200][OK]\""); 553 mOnUiThread.evaluateJavascript(js, jsResult); 554 jsResult.run(); 555 556 // Test a nonempty page with unusual response code/text 557 client.interceptResponse = 558 new WebResourceResponse("text/html", "UTF-8", 123, "unusual", null, 559 new ByteArrayInputStream("nonempty page".getBytes(StandardCharsets.UTF_8))); 560 jsResult = new EvaluateJsResultPollingCheck("\"[123][unusual]\""); 561 mOnUiThread.evaluateJavascript(js, jsResult); 562 jsResult.run(); 563 } finally { 564 server.shutdown(); 565 } 566 } 567 requireLoadedPage()568 private void requireLoadedPage() throws Throwable { 569 if (!NullWebViewUtils.isWebViewAvailable()) { 570 return; 571 } 572 mOnUiThread.loadUrlAndWaitForCompletion("about:blank"); 573 } 574 575 private class MockWebViewClient extends WaitForLoadedClient { 576 private boolean mOnPageStartedCalled; 577 private boolean mOnPageFinishedCalled; 578 private boolean mOnLoadResourceCalled; 579 private int mOnReceivedErrorCode; 580 private WebResourceError mOnReceivedResourceError; 581 private WebResourceResponse mOnReceivedHttpError; 582 private boolean mOnFormResubmissionCalled; 583 private boolean mDoUpdateVisitedHistoryCalled; 584 private boolean mOnReceivedHttpAuthRequestCalled; 585 private boolean mOnReceivedLoginRequest; 586 private String mOnReceivedLoginAccount; 587 private String mOnReceivedLoginArgs; 588 private String mOnReceivedLoginRealm; 589 private boolean mOnUnhandledKeyEventCalled; 590 private boolean mOnScaleChangedCalled; 591 private int mShouldOverrideUrlLoadingCallCount; 592 private String mLastShouldOverrideUrl; 593 private WebResourceRequest mLastShouldOverrideResourceRequest; 594 MockWebViewClient()595 public MockWebViewClient() { 596 super(mOnUiThread); 597 } 598 hasOnPageStartedCalled()599 public boolean hasOnPageStartedCalled() { 600 return mOnPageStartedCalled; 601 } 602 hasOnPageFinishedCalled()603 public boolean hasOnPageFinishedCalled() { 604 return mOnPageFinishedCalled; 605 } 606 hasOnLoadResourceCalled()607 public boolean hasOnLoadResourceCalled() { 608 return mOnLoadResourceCalled; 609 } 610 hasOnReceivedErrorCode()611 public int hasOnReceivedErrorCode() { 612 return mOnReceivedErrorCode; 613 } 614 hasOnReceivedLoginRequest()615 public boolean hasOnReceivedLoginRequest() { 616 return mOnReceivedLoginRequest; 617 } 618 hasOnReceivedResourceError()619 public WebResourceError hasOnReceivedResourceError() { 620 return mOnReceivedResourceError; 621 } 622 hasOnReceivedHttpError()623 public WebResourceResponse hasOnReceivedHttpError() { 624 return mOnReceivedHttpError; 625 } 626 hasOnFormResubmissionCalled()627 public boolean hasOnFormResubmissionCalled() { 628 return mOnFormResubmissionCalled; 629 } 630 hasDoUpdateVisitedHistoryCalled()631 public boolean hasDoUpdateVisitedHistoryCalled() { 632 return mDoUpdateVisitedHistoryCalled; 633 } 634 hasOnReceivedHttpAuthRequestCalled()635 public boolean hasOnReceivedHttpAuthRequestCalled() { 636 return mOnReceivedHttpAuthRequestCalled; 637 } 638 hasOnUnhandledKeyEventCalled()639 public boolean hasOnUnhandledKeyEventCalled() { 640 return mOnUnhandledKeyEventCalled; 641 } 642 hasOnScaleChangedCalled()643 public boolean hasOnScaleChangedCalled() { 644 return mOnScaleChangedCalled; 645 } 646 getShouldOverrideUrlLoadingCallCount()647 public int getShouldOverrideUrlLoadingCallCount() { 648 return mShouldOverrideUrlLoadingCallCount; 649 } 650 getLastShouldOverrideUrl()651 public String getLastShouldOverrideUrl() { 652 return mLastShouldOverrideUrl; 653 } 654 getLastShouldOverrideResourceRequest()655 public WebResourceRequest getLastShouldOverrideResourceRequest() { 656 return mLastShouldOverrideResourceRequest; 657 } 658 getLoginRequestRealm()659 public String getLoginRequestRealm() { 660 return mOnReceivedLoginRealm; 661 } 662 getLoginRequestAccount()663 public String getLoginRequestAccount() { 664 return mOnReceivedLoginAccount; 665 } 666 getLoginRequestArgs()667 public String getLoginRequestArgs() { 668 return mOnReceivedLoginArgs; 669 } 670 671 @Override onPageStarted(WebView view, String url, Bitmap favicon)672 public void onPageStarted(WebView view, String url, Bitmap favicon) { 673 super.onPageStarted(view, url, favicon); 674 mOnPageStartedCalled = true; 675 } 676 677 @Override onPageFinished(WebView view, String url)678 public void onPageFinished(WebView view, String url) { 679 super.onPageFinished(view, url); 680 assertTrue(mOnPageStartedCalled); 681 assertTrue(mOnLoadResourceCalled); 682 mOnPageFinishedCalled = true; 683 } 684 685 @Override onLoadResource(WebView view, String url)686 public void onLoadResource(WebView view, String url) { 687 super.onLoadResource(view, url); 688 assertTrue(mOnPageStartedCalled); 689 mOnLoadResourceCalled = true; 690 } 691 692 @Override onReceivedError(WebView view, int errorCode, String description, String failingUrl)693 public void onReceivedError(WebView view, int errorCode, 694 String description, String failingUrl) { 695 super.onReceivedError(view, errorCode, description, failingUrl); 696 mOnReceivedErrorCode = errorCode; 697 } 698 699 @Override onReceivedError(WebView view, WebResourceRequest request, WebResourceError error)700 public void onReceivedError(WebView view, WebResourceRequest request, 701 WebResourceError error) { 702 super.onReceivedError(view, request, error); 703 mOnReceivedResourceError = error; 704 } 705 706 @Override onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse)707 public void onReceivedHttpError(WebView view, WebResourceRequest request, 708 WebResourceResponse errorResponse) { 709 super.onReceivedHttpError(view, request, errorResponse); 710 mOnReceivedHttpError = errorResponse; 711 } 712 713 @Override onReceivedLoginRequest(WebView view, String realm, String account, String args)714 public void onReceivedLoginRequest(WebView view, String realm, String account, 715 String args) { 716 super.onReceivedLoginRequest(view, realm, account, args); 717 mOnReceivedLoginRequest = true; 718 mOnReceivedLoginRealm = realm; 719 mOnReceivedLoginAccount = account; 720 mOnReceivedLoginArgs = args; 721 } 722 723 @Override onFormResubmission(WebView view, Message dontResend, Message resend)724 public void onFormResubmission(WebView view, Message dontResend, Message resend) { 725 mOnFormResubmissionCalled = true; 726 dontResend.sendToTarget(); 727 } 728 729 @Override doUpdateVisitedHistory(WebView view, String url, boolean isReload)730 public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) { 731 super.doUpdateVisitedHistory(view, url, isReload); 732 mDoUpdateVisitedHistoryCalled = true; 733 } 734 735 @Override onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm)736 public void onReceivedHttpAuthRequest(WebView view, 737 HttpAuthHandler handler, String host, String realm) { 738 super.onReceivedHttpAuthRequest(view, handler, host, realm); 739 mOnReceivedHttpAuthRequestCalled = true; 740 } 741 742 @Override onUnhandledKeyEvent(WebView view, KeyEvent event)743 public void onUnhandledKeyEvent(WebView view, KeyEvent event) { 744 super.onUnhandledKeyEvent(view, event); 745 mOnUnhandledKeyEventCalled = true; 746 } 747 748 @Override onScaleChanged(WebView view, float oldScale, float newScale)749 public void onScaleChanged(WebView view, float oldScale, float newScale) { 750 super.onScaleChanged(view, oldScale, newScale); 751 mOnScaleChangedCalled = true; 752 } 753 754 @Override shouldOverrideUrlLoading(WebView view, String url)755 public boolean shouldOverrideUrlLoading(WebView view, String url) { 756 mLastShouldOverrideUrl = url; 757 mLastShouldOverrideResourceRequest = null; 758 mShouldOverrideUrlLoadingCallCount++; 759 return false; 760 } 761 762 @Override shouldOverrideUrlLoading(WebView view, WebResourceRequest request)763 public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { 764 mLastShouldOverrideUrl = request.getUrl().toString(); 765 mLastShouldOverrideResourceRequest = request; 766 mShouldOverrideUrlLoadingCallCount++; 767 return false; 768 } 769 } 770 } 771