1 /* 2 * Copyright 2018 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 androidx.webkit; 18 19 import android.graphics.Bitmap; 20 import android.net.Uri; 21 import android.webkit.WebResourceRequest; 22 import android.webkit.WebResourceResponse; 23 import android.webkit.WebView; 24 import android.webkit.WebViewClient; 25 26 import androidx.concurrent.futures.ResolvableFuture; 27 import androidx.test.ext.junit.runners.AndroidJUnit4; 28 import androidx.test.filters.LargeTest; 29 import androidx.webkit.test.common.WebViewOnUiThread; 30 import androidx.webkit.test.common.WebkitUtils; 31 32 import org.jspecify.annotations.NonNull; 33 import org.junit.After; 34 import org.junit.Assert; 35 import org.junit.Assume; 36 import org.junit.Before; 37 import org.junit.Test; 38 import org.junit.runner.RunWith; 39 40 import java.io.IOException; 41 import java.util.HashMap; 42 import java.util.Map; 43 import java.util.concurrent.ExecutionException; 44 import java.util.concurrent.TimeUnit; 45 import java.util.concurrent.TimeoutException; 46 47 import okhttp3.mockwebserver.MockResponse; 48 import okhttp3.mockwebserver.MockWebServer; 49 import okhttp3.mockwebserver.RecordedRequest; 50 51 @LargeTest 52 @RunWith(AndroidJUnit4.class) 53 public class WebViewClientCompatTest { 54 private WebViewOnUiThread mWebViewOnUiThread; 55 private MockWebServer mWebServer; 56 57 private static final String TEST_URL = "http://www.example.com/"; 58 59 private static final String TEST_SAFE_BROWSING_URL_PREFIX = 60 "chrome://safe-browsing/match?type="; 61 private static final String TEST_SAFE_BROWSING_MALWARE_URL = 62 TEST_SAFE_BROWSING_URL_PREFIX + "malware"; 63 private static final String TEST_SAFE_BROWSING_PHISHING_URL = 64 TEST_SAFE_BROWSING_URL_PREFIX + "phishing"; 65 private static final String TEST_SAFE_BROWSING_UNWANTED_SOFTWARE_URL = 66 TEST_SAFE_BROWSING_URL_PREFIX + "unwanted"; 67 private static final String TEST_SAFE_BROWSING_BILLING_URL = 68 TEST_SAFE_BROWSING_URL_PREFIX + "billing"; 69 70 @Before setUp()71 public void setUp() { 72 mWebViewOnUiThread = new WebViewOnUiThread(); 73 } 74 75 @After tearDown()76 public void tearDown() throws IOException { 77 if (mWebViewOnUiThread != null) { 78 mWebViewOnUiThread.cleanUp(); 79 } 80 if (mWebServer != null) { 81 mWebServer.shutdown(); 82 } 83 } 84 85 /** 86 * This should remain functionally equivalent to 87 * android.webkit.cts.WebViewClientTest#testShouldOverrideUrlLoadingDefault. Modifications to 88 * this test should be reflected in that test as necessary. See http://go/modifying-webview-cts. 89 */ 90 @Test testShouldOverrideUrlLoadingDefault()91 public void testShouldOverrideUrlLoadingDefault() { 92 // This never calls into chromium, so we don't need to do any feature checks. 93 94 final MockWebViewClient webViewClient = new MockWebViewClient(); 95 96 // Create any valid WebResourceRequest, the return values don't matter much. 97 final WebResourceRequest resourceRequest = new WebResourceRequest() { 98 @Override 99 public Uri getUrl() { 100 return Uri.parse(TEST_URL); 101 } 102 103 @Override 104 public boolean isForMainFrame() { 105 return false; 106 } 107 108 @Override 109 public boolean isRedirect() { 110 return false; 111 } 112 113 @Override 114 public boolean hasGesture() { 115 return false; 116 } 117 118 @Override 119 public String getMethod() { 120 return "GET"; 121 } 122 123 @Override 124 public Map<String, String> getRequestHeaders() { 125 return new HashMap<>(); 126 } 127 }; 128 129 Assert.assertFalse(webViewClient.shouldOverrideUrlLoading( 130 mWebViewOnUiThread.getWebViewOnCurrentThread(), resourceRequest)); 131 } 132 133 /** 134 * This should remain functionally equivalent to 135 * android.webkit.cts.WebViewClientTest#testShouldOverrideUrlLoading. Modifications to this 136 * test should be reflected in that test as necessary. See http://go/modifying-webview-cts. 137 */ 138 @Test testShouldOverrideUrlLoading()139 public void testShouldOverrideUrlLoading() throws Throwable { 140 WebkitUtils.checkFeature(WebViewFeature.SHOULD_OVERRIDE_WITH_REDIRECTS); 141 WebkitUtils.checkFeature(WebViewFeature.WEB_RESOURCE_REQUEST_IS_REDIRECT); 142 143 // We need to pull up a web server (rather than pick a URL and let the navigation fail) 144 // because the network may attempt to rewrite URLs to send us to a captive portal 145 // (http://b/172937423). 146 mWebServer = new MockWebServer(); 147 mWebServer.start(); 148 String testUrl = mWebServer.url("/some_test_url").toString(); 149 String body = "<html>This is a test page</html>"; 150 mWebServer.enqueue(new MockResponse().setBody(body)); 151 152 String data = "<html><body>" 153 + "<a href=\"" + testUrl + "\" id=\"link\">new page</a>" 154 + "</body></html>"; 155 mWebViewOnUiThread.loadDataAndWaitForCompletion(data, "text/html", null); 156 final ResolvableFuture<Void> pageFinishedFuture = ResolvableFuture.create(); 157 final MockWebViewClient webViewClient = new MockWebViewClient() { 158 @Override 159 public void onPageFinished(WebView view, String url) { 160 pageFinishedFuture.set(null); 161 } 162 }; 163 mWebViewOnUiThread.setWebViewClient(webViewClient); 164 mWebViewOnUiThread.getSettings().setJavaScriptEnabled(true); 165 clickOnLinkUsingJs("link", mWebViewOnUiThread); 166 WebkitUtils.waitForFuture(pageFinishedFuture); 167 Assert.assertEquals(testUrl, 168 webViewClient.getLastShouldOverrideResourceRequest().getUrl().toString()); 169 170 WebResourceRequest request = webViewClient.getLastShouldOverrideResourceRequest(); 171 Assert.assertNotNull(request); 172 Assert.assertTrue(request.isForMainFrame()); 173 Assert.assertFalse(WebResourceRequestCompat.isRedirect(request)); 174 Assert.assertFalse(request.hasGesture()); 175 } 176 clickOnLinkUsingJs(final String linkId, WebViewOnUiThread webViewOnUiThread)177 private void clickOnLinkUsingJs(final String linkId, WebViewOnUiThread webViewOnUiThread) 178 throws InterruptedException, ExecutionException, TimeoutException { 179 webViewOnUiThread.evaluateJavascriptSync( 180 "document.getElementById('" + linkId + "').click();" 181 + "console.log('element with id [" + linkId + "] clicked');"); 182 } 183 184 /** 185 * This should remain functionally equivalent to 186 * android.webkit.cts.WebViewClientTest#testOnReceivedError. Modifications to this test should 187 * be reflected in that test as necessary. See http://go/modifying-webview-cts. 188 */ 189 @Test testOnReceivedError()190 public void testOnReceivedError() throws Exception { 191 WebkitUtils.checkFeature(WebViewFeature.RECEIVE_WEB_RESOURCE_ERROR); 192 WebkitUtils.checkFeature(WebViewFeature.WEB_RESOURCE_ERROR_GET_CODE); 193 194 final MockWebViewClient webViewClient = new MockWebViewClient(); 195 mWebViewOnUiThread.setWebViewClient(webViewClient); 196 197 String wrongUri = "invalidscheme://some/resource"; 198 Assert.assertNull(webViewClient.getOnReceivedResourceError()); 199 mWebViewOnUiThread.loadUrlAndWaitForCompletion(wrongUri); 200 Assert.assertNotNull(webViewClient.getOnReceivedResourceError()); 201 Assert.assertEquals(WebViewClient.ERROR_UNSUPPORTED_SCHEME, 202 webViewClient.getOnReceivedResourceError().getErrorCode()); 203 } 204 205 /** 206 * This should remain functionally equivalent to 207 * android.webkit.cts.WebViewClientTest#testOnReceivedErrorForSubresource. Modifications to 208 * this test should be reflected in that test as necessary. See http://go/modifying-webview-cts. 209 */ 210 @Test testOnReceivedErrorForSubresource()211 public void testOnReceivedErrorForSubresource() throws Exception { 212 WebkitUtils.checkFeature(WebViewFeature.RECEIVE_WEB_RESOURCE_ERROR); 213 214 final MockWebViewClient webViewClient = new MockWebViewClient(); 215 mWebViewOnUiThread.setWebViewClient(webViewClient); 216 217 Assert.assertNull(webViewClient.getOnReceivedResourceError()); 218 String data = "<html>" 219 + " <body>" 220 + " <img src=\"invalidscheme://some/resource\" />" 221 + " </body>" 222 + "</html>"; 223 224 mWebViewOnUiThread.loadDataAndWaitForCompletion(data, "text/html", null); 225 Assert.assertNotNull(webViewClient.getOnReceivedResourceError()); 226 Assert.assertEquals(WebViewClient.ERROR_UNSUPPORTED_SCHEME, 227 webViewClient.getOnReceivedResourceError().getErrorCode()); 228 } 229 230 /** 231 * This should remain functionally equivalent to 232 * android.webkit.cts.WebViewClientTest#testOnReceivedHttpError. Modifications to 233 * this test should be reflected in that test as necessary. See http://go/modifying-webview-cts. 234 */ 235 @Test testOnReceivedHttpError()236 public void testOnReceivedHttpError() throws Exception { 237 WebkitUtils.checkFeature(WebViewFeature.RECEIVE_HTTP_ERROR); 238 239 final MockWebViewClient webViewClient = new MockWebViewClient(); 240 mWebViewOnUiThread.setWebViewClient(webViewClient); 241 mWebServer = new MockWebServer(); 242 mWebServer.start(); 243 244 Assert.assertNull(webViewClient.getOnReceivedHttpError()); 245 String url = mWebServer.url("/non_existent_page").toString(); 246 mWebServer.enqueue(new MockResponse().setResponseCode(404)); 247 248 mWebViewOnUiThread.loadUrlAndWaitForCompletion(url); 249 250 RecordedRequest request = mWebServer.takeRequest(WebkitUtils.TEST_TIMEOUT_MS, 251 TimeUnit.MILLISECONDS); 252 Assert.assertNotNull("The server should receive an HTTP request", request); 253 Assert.assertEquals("/non_existent_page", request.getPath()); 254 255 Assert.assertNotNull(webViewClient.getOnReceivedHttpError()); 256 Assert.assertEquals(404, 257 webViewClient.getOnReceivedHttpError().getStatusCode()); 258 } 259 260 /** 261 * This should remain functionally equivalent to 262 * android.webkit.cts.WebViewClientTest#testOnSafeBrowsingHitBackToSafety. Modifications to 263 * this test should be reflected in that test as necessary. See http://go/modifying-webview-cts. 264 */ 265 @Test testOnSafeBrowsingHitBackToSafety()266 public void testOnSafeBrowsingHitBackToSafety() throws Throwable { 267 WebkitUtils.checkFeature(WebViewFeature.SAFE_BROWSING_HIT); 268 WebkitUtils.checkFeature(WebViewFeature.SAFE_BROWSING_ENABLE); 269 WebkitUtils.checkFeature(WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY); 270 WebkitUtils.checkFeature(WebViewFeature.WEB_RESOURCE_ERROR_GET_CODE); 271 272 final SafeBrowsingBackToSafetyClient backToSafetyWebViewClient = 273 new SafeBrowsingBackToSafetyClient(); 274 mWebViewOnUiThread.setWebViewClient(backToSafetyWebViewClient); 275 WebSettingsCompat.setSafeBrowsingEnabled(mWebViewOnUiThread.getSettings(), true); 276 277 // Load any page 278 String data = "<html><body>some safe page</body></html>"; 279 mWebViewOnUiThread.loadDataAndWaitForCompletion(data, "text/html", null); 280 final String originalUrl = mWebViewOnUiThread.getUrl(); 281 282 enableSafeBrowsingAndLoadUnsafePage(backToSafetyWebViewClient); 283 284 // Back to safety should produce a network error 285 Assert.assertNotNull(backToSafetyWebViewClient.getOnReceivedResourceError()); 286 Assert.assertEquals(WebViewClient.ERROR_UNSAFE_RESOURCE, 287 backToSafetyWebViewClient.getOnReceivedResourceError().getErrorCode()); 288 289 // Check that we actually navigated backward 290 Assert.assertEquals(originalUrl, mWebViewOnUiThread.getUrl()); 291 } 292 293 /** 294 * This should remain functionally equivalent to 295 * android.webkit.cts.WebViewClientTest#testOnSafeBrowsingHitProceed. Modifications to this 296 * test should be reflected in that test as necessary. See http://go/modifying-webview-cts. 297 */ 298 @Test testOnSafeBrowsingHitProceed()299 public void testOnSafeBrowsingHitProceed() throws Throwable { 300 WebkitUtils.checkFeature(WebViewFeature.SAFE_BROWSING_HIT); 301 WebkitUtils.checkFeature(WebViewFeature.SAFE_BROWSING_ENABLE); 302 WebkitUtils.checkFeature(WebViewFeature.SAFE_BROWSING_RESPONSE_PROCEED); 303 304 final SafeBrowsingProceedClient proceedWebViewClient = new SafeBrowsingProceedClient(); 305 mWebViewOnUiThread.setWebViewClient(proceedWebViewClient); 306 WebSettingsCompat.setSafeBrowsingEnabled(mWebViewOnUiThread.getSettings(), true); 307 308 // Load any page 309 String data = "<html><body>some safe page</body></html>"; 310 mWebViewOnUiThread.loadDataAndWaitForCompletion(data, "text/html", null); 311 312 enableSafeBrowsingAndLoadUnsafePage(proceedWebViewClient); 313 314 // Check that we actually proceeded 315 Assert.assertEquals(TEST_SAFE_BROWSING_MALWARE_URL, mWebViewOnUiThread.getUrl()); 316 } 317 testOnSafeBrowsingCode(String expectedUrl, int expectedThreatType)318 private void testOnSafeBrowsingCode(String expectedUrl, int expectedThreatType) 319 throws Throwable { 320 WebkitUtils.checkFeature(WebViewFeature.SAFE_BROWSING_HIT); 321 WebkitUtils.checkFeature(WebViewFeature.SAFE_BROWSING_ENABLE); 322 WebkitUtils.checkFeature(WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY); 323 324 // Load any page 325 String data = "<html><body>some safe page</body></html>"; 326 mWebViewOnUiThread.loadDataAndWaitForCompletion(data, "text/html", null); 327 328 final SafeBrowsingBackToSafetyClient backToSafetyWebViewClient = 329 new SafeBrowsingBackToSafetyClient(); 330 mWebViewOnUiThread.setWebViewClient(backToSafetyWebViewClient); 331 WebSettingsCompat.setSafeBrowsingEnabled(mWebViewOnUiThread.getSettings(), true); 332 333 // Note: Safe Browsing depends on user opt-in as well, so we can't assume it's actually 334 // enabled. #getSafeBrowsingEnabled will tell us the true state of whether Safe Browsing is 335 // enabled. 336 if (WebSettingsCompat.getSafeBrowsingEnabled(mWebViewOnUiThread.getSettings())) { 337 mWebViewOnUiThread.loadUrlAndWaitForCompletion(expectedUrl); 338 339 Assert.assertEquals("Safe Browsing hit is for unexpected URL", 340 expectedUrl, 341 backToSafetyWebViewClient.getOnSafeBrowsingHitRequest().getUrl().toString()); 342 343 Assert.assertEquals("Safe Browsing hit has unexpected threat type", 344 expectedThreatType, 345 backToSafetyWebViewClient.getOnSafeBrowsingHitThreatType()); 346 } 347 } 348 349 /** 350 * This should remain functionally equivalent to 351 * android.webkit.cts.WebViewClientTest#testOnSafeBrowsingMalwareCode. Modifications to this 352 * test should be reflected in that test as necessary. See http://go/modifying-webview-cts. 353 */ 354 @Test testOnSafeBrowsingMalwareCode()355 public void testOnSafeBrowsingMalwareCode() throws Throwable { 356 testOnSafeBrowsingCode(TEST_SAFE_BROWSING_MALWARE_URL, 357 WebViewClient.SAFE_BROWSING_THREAT_MALWARE); 358 } 359 360 /** 361 * This should remain functionally equivalent to 362 * android.webkit.cts.WebViewClientTest#testOnSafeBrowsingPhishingCode. Modifications to this 363 * test should be reflected in that test as necessary. See http://go/modifying-webview-cts. 364 */ 365 @Test testOnSafeBrowsingPhishingCode()366 public void testOnSafeBrowsingPhishingCode() throws Throwable { 367 testOnSafeBrowsingCode(TEST_SAFE_BROWSING_PHISHING_URL, 368 WebViewClient.SAFE_BROWSING_THREAT_PHISHING); 369 } 370 371 /** 372 * This should remain functionally equivalent to 373 * android.webkit.cts.WebViewClientTest#testOnSafeBrowsingUnwantedSoftwareCode. Modifications to 374 * this test should be reflected in that test as necessary. See http://go/modifying-webview-cts. 375 */ 376 @Test testOnSafeBrowsingUnwantedSoftwareCode()377 public void testOnSafeBrowsingUnwantedSoftwareCode() throws Throwable { 378 testOnSafeBrowsingCode(TEST_SAFE_BROWSING_UNWANTED_SOFTWARE_URL, 379 WebViewClient.SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE); 380 } 381 382 /** 383 * This should remain functionally equivalent to 384 * android.webkit.cts.WebViewClientTest#testOnSafeBrowsingBillingCode. Modifications to this 385 * test should be reflected in that test as necessary. See http://go/modifying-webview-cts. 386 */ 387 @Test testOnSafeBrowsingBillingCode()388 public void testOnSafeBrowsingBillingCode() throws Throwable { 389 testOnSafeBrowsingCode(TEST_SAFE_BROWSING_BILLING_URL, 390 WebViewClient.SAFE_BROWSING_THREAT_BILLING); 391 } 392 enableSafeBrowsingAndLoadUnsafePage(SafeBrowsingClient client)393 private void enableSafeBrowsingAndLoadUnsafePage(SafeBrowsingClient client) throws Throwable { 394 // Note: Safe Browsing depends on user opt-in as well, so we can't assume it's actually 395 // enabled. #getSafeBrowsingEnabled will tell us the true state of whether Safe Browsing is 396 // enabled. 397 boolean deviceSupportsSafeBrowsing = 398 WebSettingsCompat.getSafeBrowsingEnabled(mWebViewOnUiThread.getSettings()); 399 final String msg = "The device should support Safe Browsing"; 400 Assume.assumeTrue(msg, deviceSupportsSafeBrowsing); 401 402 Assert.assertNull(client.getOnReceivedResourceError()); 403 mWebViewOnUiThread.loadUrlAndWaitForCompletion(TEST_SAFE_BROWSING_MALWARE_URL); 404 405 Assert.assertEquals(TEST_SAFE_BROWSING_MALWARE_URL, 406 client.getOnSafeBrowsingHitRequest().getUrl().toString()); 407 Assert.assertTrue( 408 client.getOnSafeBrowsingHitRequest().isForMainFrame()); 409 } 410 411 /** 412 * This should remain functionally equivalent to 413 * android.webkit.cts.WebViewClientTest#testOnPageCommitVisibleCalled. Modifications to this 414 * test should be reflected in that test as necessary. See http://go/modifying-webview-cts. 415 */ 416 @Test testOnPageCommitVisibleCalled()417 public void testOnPageCommitVisibleCalled() throws Exception { 418 WebkitUtils.checkFeature(WebViewFeature.VISUAL_STATE_CALLBACK); 419 420 final ResolvableFuture<String> pageCommitVisibleFuture = ResolvableFuture.create(); 421 mWebViewOnUiThread.setWebViewClient(new WebViewClientCompat() { 422 @Override 423 public void onPageCommitVisible(@NonNull WebView view, @NonNull String url) { 424 pageCommitVisibleFuture.set(url); 425 } 426 }); 427 428 mWebViewOnUiThread.loadUrl("about:blank"); 429 Assert.assertEquals("about:blank", WebkitUtils.waitForFuture(pageCommitVisibleFuture)); 430 } 431 432 @Test testResetClientToCompat()433 public void testResetClientToCompat() throws Exception { 434 WebkitUtils.checkFeature(WebViewFeature.VISUAL_STATE_CALLBACK); 435 436 final ResolvableFuture<String> pageCommitVisibleFuture = ResolvableFuture.create(); 437 WebViewClient nonCompatClient = new WebViewClient() { 438 @Override 439 public void onPageStarted(WebView view, String url, Bitmap bitmap) { 440 pageCommitVisibleFuture.setException(new IllegalStateException( 441 "This client should not have callbacks invoked")); 442 } 443 }; 444 mWebViewOnUiThread.setWebViewClient(nonCompatClient); 445 446 WebViewClientCompat compatClient = new WebViewClientCompat() { 447 @Override 448 public void onPageCommitVisible(@NonNull WebView view, @NonNull String url) { 449 pageCommitVisibleFuture.set(url); 450 } 451 }; 452 mWebViewOnUiThread.setWebViewClient(compatClient); // reset to the new client 453 mWebViewOnUiThread.loadUrl("about:blank"); 454 Assert.assertEquals("about:blank", WebkitUtils.waitForFuture(pageCommitVisibleFuture)); 455 } 456 457 @Test testResetClientToRegular()458 public void testResetClientToRegular() throws Exception { 459 WebViewClientCompat compatClient = new WebViewClientCompat() { 460 @Override 461 public void onPageStarted(WebView view, String url, Bitmap bitmap) { 462 Assert.fail("This client should not have callbacks invoked"); 463 } 464 }; 465 mWebViewOnUiThread.setWebViewClient(compatClient); 466 467 final ResolvableFuture<String> pageFinishedFuture = ResolvableFuture.create(); 468 WebViewClient nonCompatClient = new WebViewClient() { 469 @Override 470 public void onPageFinished(WebView view, String url) { 471 pageFinishedFuture.set(url); 472 } 473 }; 474 mWebViewOnUiThread.setWebViewClient(nonCompatClient); // reset to the new client 475 mWebViewOnUiThread.loadUrl("about:blank"); 476 Assert.assertEquals("about:blank", WebkitUtils.waitForFuture(pageFinishedFuture)); 477 } 478 479 private class MockWebViewClient extends WebViewOnUiThread.WaitForLoadedClient { 480 private boolean mOnPageStartedCalled; 481 private boolean mOnPageFinishedCalled; 482 private boolean mOnLoadResourceCalled; 483 private WebResourceErrorCompat mOnReceivedResourceError; 484 private WebResourceResponse mOnReceivedHttpError; 485 private WebResourceRequest mLastShouldOverrideResourceRequest; 486 MockWebViewClient()487 MockWebViewClient() { 488 super(mWebViewOnUiThread); 489 } 490 getOnReceivedResourceError()491 public WebResourceErrorCompat getOnReceivedResourceError() { 492 return mOnReceivedResourceError; 493 } 494 getOnReceivedHttpError()495 public WebResourceResponse getOnReceivedHttpError() { 496 return mOnReceivedHttpError; 497 } 498 getLastShouldOverrideResourceRequest()499 public WebResourceRequest getLastShouldOverrideResourceRequest() { 500 return mLastShouldOverrideResourceRequest; 501 } 502 503 @Override onPageStarted(WebView view, String url, Bitmap favicon)504 public void onPageStarted(WebView view, String url, Bitmap favicon) { 505 super.onPageStarted(view, url, favicon); 506 mOnPageStartedCalled = true; 507 } 508 509 @Override onPageFinished(WebView view, String url)510 public void onPageFinished(WebView view, String url) { 511 super.onPageFinished(view, url); 512 Assert.assertTrue("Expected onPageStarted to be called before onPageFinished", 513 mOnPageStartedCalled); 514 Assert.assertTrue( 515 "Expected onLoadResource or onReceivedError to be called before onPageFinished", 516 mOnLoadResourceCalled || mOnReceivedResourceError != null); 517 mOnPageFinishedCalled = true; 518 } 519 520 @Override onLoadResource(WebView view, String url)521 public void onLoadResource(WebView view, String url) { 522 super.onLoadResource(view, url); 523 mOnLoadResourceCalled = true; 524 } 525 526 @Override 527 @SuppressWarnings("deprecation") onReceivedError(WebView view, int errorCode, String description, String failingUrl)528 public void onReceivedError(WebView view, int errorCode, 529 String description, String failingUrl) { 530 // This can be called if a test runs for a WebView which does not support the {@link 531 // WebViewFeature#RECEIVE_WEB_RESOURCE_ERROR} feature. 532 } 533 534 @Override onReceivedError(@onNull WebView view, @NonNull WebResourceRequest request, @NonNull WebResourceErrorCompat error)535 public void onReceivedError(@NonNull WebView view, @NonNull WebResourceRequest request, 536 @NonNull WebResourceErrorCompat error) { 537 mOnReceivedResourceError = error; 538 } 539 540 @Override onReceivedHttpError(@onNull WebView view, @NonNull WebResourceRequest request, @NonNull WebResourceResponse errorResponse)541 public void onReceivedHttpError(@NonNull WebView view, @NonNull WebResourceRequest request, 542 @NonNull WebResourceResponse errorResponse) { 543 super.onReceivedHttpError(view, request, errorResponse); 544 mOnReceivedHttpError = errorResponse; 545 } 546 547 @Override 548 @SuppressWarnings("deprecation") shouldOverrideUrlLoading(WebView view, String url)549 public boolean shouldOverrideUrlLoading(WebView view, String url) { 550 // This can be called if a test runs for a WebView which does not support the {@link 551 // WebViewFeature#SHOULD_OVERRIDE_WITH_REDIRECTS} feature. 552 return false; 553 } 554 555 @Override shouldOverrideUrlLoading(@onNull WebView view, @NonNull WebResourceRequest request)556 public boolean shouldOverrideUrlLoading(@NonNull WebView view, 557 @NonNull WebResourceRequest request) { 558 mLastShouldOverrideResourceRequest = request; 559 return false; 560 } 561 } 562 563 private class SafeBrowsingClient extends MockWebViewClient { 564 private WebResourceRequest mOnSafeBrowsingHitRequest; 565 private int mOnSafeBrowsingHitThreatType; 566 getOnSafeBrowsingHitRequest()567 public WebResourceRequest getOnSafeBrowsingHitRequest() { 568 return mOnSafeBrowsingHitRequest; 569 } 570 setOnSafeBrowsingHitRequest(WebResourceRequest request)571 public void setOnSafeBrowsingHitRequest(WebResourceRequest request) { 572 mOnSafeBrowsingHitRequest = request; 573 } 574 getOnSafeBrowsingHitThreatType()575 public int getOnSafeBrowsingHitThreatType() { 576 return mOnSafeBrowsingHitThreatType; 577 } 578 setOnSafeBrowsingHitThreatType(int type)579 public void setOnSafeBrowsingHitThreatType(int type) { 580 mOnSafeBrowsingHitThreatType = type; 581 } 582 } 583 584 private class SafeBrowsingBackToSafetyClient extends SafeBrowsingClient { 585 @Override onSafeBrowsingHit(@onNull WebView view, @NonNull WebResourceRequest request, int threatType, @NonNull SafeBrowsingResponseCompat response)586 public void onSafeBrowsingHit(@NonNull WebView view, @NonNull WebResourceRequest request, 587 int threatType, @NonNull SafeBrowsingResponseCompat response) { 588 // Immediately go back to safety to return the network error code 589 setOnSafeBrowsingHitRequest(request); 590 setOnSafeBrowsingHitThreatType(threatType); 591 response.backToSafety(/* report */ true); 592 } 593 } 594 595 private class SafeBrowsingProceedClient extends SafeBrowsingClient { 596 @Override onSafeBrowsingHit(@onNull WebView view, @NonNull WebResourceRequest request, int threatType, @NonNull SafeBrowsingResponseCompat response)597 public void onSafeBrowsingHit(@NonNull WebView view, @NonNull WebResourceRequest request, 598 int threatType, @NonNull SafeBrowsingResponseCompat response) { 599 // Proceed through Safe Browsing warnings 600 setOnSafeBrowsingHitRequest(request); 601 setOnSafeBrowsingHitThreatType(threatType); 602 response.proceed(/* report */ true); 603 } 604 } 605 } 606