1/* 2 * Copyright (C) 2008 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 17package android.webkit; 18 19import android.annotation.IntDef; 20import android.annotation.Nullable; 21import android.graphics.Bitmap; 22import android.net.http.SslError; 23import android.os.Message; 24import android.view.InputEvent; 25import android.view.KeyEvent; 26import android.view.ViewRootImpl; 27 28import java.lang.annotation.Retention; 29import java.lang.annotation.RetentionPolicy; 30 31public class WebViewClient { 32 33 /** 34 * Give the host application a chance to take over the control when a new 35 * url is about to be loaded in the current WebView. If WebViewClient is not 36 * provided, by default WebView will ask Activity Manager to choose the 37 * proper handler for the url. If WebViewClient is provided, return {@code true} 38 * means the host application handles the url, while return {@code false} means the 39 * current WebView handles the url. 40 * This method is not called for requests using the POST "method". 41 * 42 * @param view The WebView that is initiating the callback. 43 * @param url The url to be loaded. 44 * @return {@code true} if the host application wants to leave the current WebView 45 * and handle the url itself, otherwise return {@code false}. 46 * @deprecated Use {@link #shouldOverrideUrlLoading(WebView, WebResourceRequest) 47 * shouldOverrideUrlLoading(WebView, WebResourceRequest)} instead. 48 */ 49 @Deprecated 50 public boolean shouldOverrideUrlLoading(WebView view, String url) { 51 return false; 52 } 53 54 /** 55 * Give the host application a chance to take over the control when a new 56 * url is about to be loaded in the current WebView. If WebViewClient is not 57 * provided, by default WebView will ask Activity Manager to choose the 58 * proper handler for the url. If WebViewClient is provided, return {@code true} 59 * means the host application handles the url, while return {@code false} means the 60 * current WebView handles the url. 61 * 62 * <p>Notes: 63 * <ul> 64 * <li>This method is not called for requests using the POST "method".</li> 65 * <li>This method is also called for subframes with non-http schemes, thus it is 66 * strongly disadvised to unconditionally call {@link WebView#loadUrl(String)} 67 * with the request's url from inside the method and then return {@code true}, 68 * as this will make WebView to attempt loading a non-http url, and thus fail.</li> 69 * </ul> 70 * 71 * @param view The WebView that is initiating the callback. 72 * @param request Object containing the details of the request. 73 * @return {@code true} if the host application wants to leave the current WebView 74 * and handle the url itself, otherwise return {@code false}. 75 */ 76 public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { 77 return shouldOverrideUrlLoading(view, request.getUrl().toString()); 78 } 79 80 /** 81 * Notify the host application that a page has started loading. This method 82 * is called once for each main frame load so a page with iframes or 83 * framesets will call onPageStarted one time for the main frame. This also 84 * means that onPageStarted will not be called when the contents of an 85 * embedded frame changes, i.e. clicking a link whose target is an iframe, 86 * it will also not be called for fragment navigations (navigations to 87 * #fragment_id). 88 * 89 * @param view The WebView that is initiating the callback. 90 * @param url The url to be loaded. 91 * @param favicon The favicon for this page if it already exists in the 92 * database. 93 */ 94 public void onPageStarted(WebView view, String url, Bitmap favicon) { 95 } 96 97 /** 98 * Notify the host application that a page has finished loading. This method 99 * is called only for main frame. When onPageFinished() is called, the 100 * rendering picture may not be updated yet. To get the notification for the 101 * new Picture, use {@link WebView.PictureListener#onNewPicture}. 102 * 103 * @param view The WebView that is initiating the callback. 104 * @param url The url of the page. 105 */ 106 public void onPageFinished(WebView view, String url) { 107 } 108 109 /** 110 * Notify the host application that the WebView will load the resource 111 * specified by the given url. 112 * 113 * @param view The WebView that is initiating the callback. 114 * @param url The url of the resource the WebView will load. 115 */ 116 public void onLoadResource(WebView view, String url) { 117 } 118 119 /** 120 * Notify the host application that {@link android.webkit.WebView} content left over from 121 * previous page navigations will no longer be drawn. 122 * 123 * <p>This callback can be used to determine the point at which it is safe to make a recycled 124 * {@link android.webkit.WebView} visible, ensuring that no stale content is shown. It is called 125 * at the earliest point at which it can be guaranteed that {@link WebView#onDraw} will no 126 * longer draw any content from previous navigations. The next draw will display either the 127 * {@link WebView#setBackgroundColor background color} of the {@link WebView}, or some of the 128 * contents of the newly loaded page. 129 * 130 * <p>This method is called when the body of the HTTP response has started loading, is reflected 131 * in the DOM, and will be visible in subsequent draws. This callback occurs early in the 132 * document loading process, and as such you should expect that linked resources (for example, 133 * CSS and images) may not be available. 134 * 135 * <p>For more fine-grained notification of visual state updates, see {@link 136 * WebView#postVisualStateCallback}. 137 * 138 * <p>Please note that all the conditions and recommendations applicable to 139 * {@link WebView#postVisualStateCallback} also apply to this API. 140 * 141 * <p>This callback is only called for main frame navigations. 142 * 143 * @param view The {@link android.webkit.WebView} for which the navigation occurred. 144 * @param url The URL corresponding to the page navigation that triggered this callback. 145 */ 146 public void onPageCommitVisible(WebView view, String url) { 147 } 148 149 /** 150 * Notify the host application of a resource request and allow the 151 * application to return the data. If the return value is {@code null}, the WebView 152 * will continue to load the resource as usual. Otherwise, the return 153 * response and data will be used. 154 * 155 * <p>This callback is invoked for a variety of URL schemes (e.g., {@code http(s):}, {@code 156 * data:}, {@code file:}, etc.), not only those schemes which send requests over the network. 157 * This is not called for {@code javascript:} URLs, {@code blob:} URLs, or for assets accessed 158 * via {@code file:///android_asset/} or {@code file:///android_res/} URLs. 159 * 160 * <p>In the case of redirects, this is only called for the initial resource URL, not any 161 * subsequent redirect URLs. 162 * 163 * <p class="note"><b>Note:</b> This method is called on a thread 164 * other than the UI thread so clients should exercise caution 165 * when accessing private data or the view system. 166 * 167 * <p class="note"><b>Note:</b> When Safe Browsing is enabled, these URLs still undergo Safe 168 * Browsing checks. If this is undesired, whitelist the URL with {@link 169 * WebView#setSafeBrowsingWhitelist} or ignore the warning with {@link #onSafeBrowsingHit}. 170 * 171 * @param view The {@link android.webkit.WebView} that is requesting the 172 * resource. 173 * @param url The raw url of the resource. 174 * @return A {@link android.webkit.WebResourceResponse} containing the 175 * response information or {@code null} if the WebView should load the 176 * resource itself. 177 * @deprecated Use {@link #shouldInterceptRequest(WebView, WebResourceRequest) 178 * shouldInterceptRequest(WebView, WebResourceRequest)} instead. 179 */ 180 @Deprecated 181 @Nullable 182 public WebResourceResponse shouldInterceptRequest(WebView view, 183 String url) { 184 return null; 185 } 186 187 /** 188 * Notify the host application of a resource request and allow the 189 * application to return the data. If the return value is {@code null}, the WebView 190 * will continue to load the resource as usual. Otherwise, the return 191 * response and data will be used. 192 * 193 * <p>This callback is invoked for a variety of URL schemes (e.g., {@code http(s):}, {@code 194 * data:}, {@code file:}, etc.), not only those schemes which send requests over the network. 195 * This is not called for {@code javascript:} URLs, {@code blob:} URLs, or for assets accessed 196 * via {@code file:///android_asset/} or {@code file:///android_res/} URLs. 197 * 198 * <p>In the case of redirects, this is only called for the initial resource URL, not any 199 * subsequent redirect URLs. 200 * 201 * <p class="note"><b>Note:</b> This method is called on a thread 202 * other than the UI thread so clients should exercise caution 203 * when accessing private data or the view system. 204 * 205 * <p class="note"><b>Note:</b> When Safe Browsing is enabled, these URLs still undergo Safe 206 * Browsing checks. If this is undesired, whitelist the URL with {@link 207 * WebView#setSafeBrowsingWhitelist} or ignore the warning with {@link #onSafeBrowsingHit}. 208 * 209 * @param view The {@link android.webkit.WebView} that is requesting the 210 * resource. 211 * @param request Object containing the details of the request. 212 * @return A {@link android.webkit.WebResourceResponse} containing the 213 * response information or {@code null} if the WebView should load the 214 * resource itself. 215 */ 216 @Nullable 217 public WebResourceResponse shouldInterceptRequest(WebView view, 218 WebResourceRequest request) { 219 return shouldInterceptRequest(view, request.getUrl().toString()); 220 } 221 222 /** 223 * Notify the host application that there have been an excessive number of 224 * HTTP redirects. As the host application if it would like to continue 225 * trying to load the resource. The default behavior is to send the cancel 226 * message. 227 * 228 * @param view The WebView that is initiating the callback. 229 * @param cancelMsg The message to send if the host wants to cancel 230 * @param continueMsg The message to send if the host wants to continue 231 * @deprecated This method is no longer called. When the WebView encounters 232 * a redirect loop, it will cancel the load. 233 */ 234 @Deprecated 235 public void onTooManyRedirects(WebView view, Message cancelMsg, 236 Message continueMsg) { 237 cancelMsg.sendToTarget(); 238 } 239 240 // These ints must match up to the hidden values in EventHandler. 241 /** Generic error */ 242 public static final int ERROR_UNKNOWN = -1; 243 /** Server or proxy hostname lookup failed */ 244 public static final int ERROR_HOST_LOOKUP = -2; 245 /** Unsupported authentication scheme (not basic or digest) */ 246 public static final int ERROR_UNSUPPORTED_AUTH_SCHEME = -3; 247 /** User authentication failed on server */ 248 public static final int ERROR_AUTHENTICATION = -4; 249 /** User authentication failed on proxy */ 250 public static final int ERROR_PROXY_AUTHENTICATION = -5; 251 /** Failed to connect to the server */ 252 public static final int ERROR_CONNECT = -6; 253 /** Failed to read or write to the server */ 254 public static final int ERROR_IO = -7; 255 /** Connection timed out */ 256 public static final int ERROR_TIMEOUT = -8; 257 /** Too many redirects */ 258 public static final int ERROR_REDIRECT_LOOP = -9; 259 /** Unsupported URI scheme */ 260 public static final int ERROR_UNSUPPORTED_SCHEME = -10; 261 /** Failed to perform SSL handshake */ 262 public static final int ERROR_FAILED_SSL_HANDSHAKE = -11; 263 /** Malformed URL */ 264 public static final int ERROR_BAD_URL = -12; 265 /** Generic file error */ 266 public static final int ERROR_FILE = -13; 267 /** File not found */ 268 public static final int ERROR_FILE_NOT_FOUND = -14; 269 /** Too many requests during this load */ 270 public static final int ERROR_TOO_MANY_REQUESTS = -15; 271 /** Resource load was canceled by Safe Browsing */ 272 public static final int ERROR_UNSAFE_RESOURCE = -16; 273 274 /** @hide */ 275 @IntDef(prefix = { "SAFE_BROWSING_THREAT_" }, value = { 276 SAFE_BROWSING_THREAT_UNKNOWN, 277 SAFE_BROWSING_THREAT_MALWARE, 278 SAFE_BROWSING_THREAT_PHISHING, 279 SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE 280 }) 281 @Retention(RetentionPolicy.SOURCE) 282 public @interface SafeBrowsingThreat {} 283 284 /** The resource was blocked for an unknown reason */ 285 public static final int SAFE_BROWSING_THREAT_UNKNOWN = 0; 286 /** The resource was blocked because it contains malware */ 287 public static final int SAFE_BROWSING_THREAT_MALWARE = 1; 288 /** The resource was blocked because it contains deceptive content */ 289 public static final int SAFE_BROWSING_THREAT_PHISHING = 2; 290 /** The resource was blocked because it contains unwanted software */ 291 public static final int SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE = 3; 292 293 /** 294 * Report an error to the host application. These errors are unrecoverable 295 * (i.e. the main resource is unavailable). The {@code errorCode} parameter 296 * corresponds to one of the {@code ERROR_*} constants. 297 * @param view The WebView that is initiating the callback. 298 * @param errorCode The error code corresponding to an ERROR_* value. 299 * @param description A String describing the error. 300 * @param failingUrl The url that failed to load. 301 * @deprecated Use {@link #onReceivedError(WebView, WebResourceRequest, WebResourceError) 302 * onReceivedError(WebView, WebResourceRequest, WebResourceError)} instead. 303 */ 304 @Deprecated 305 public void onReceivedError(WebView view, int errorCode, 306 String description, String failingUrl) { 307 } 308 309 /** 310 * Report web resource loading error to the host application. These errors usually indicate 311 * inability to connect to the server. Note that unlike the deprecated version of the callback, 312 * the new version will be called for any resource (iframe, image, etc.), not just for the main 313 * page. Thus, it is recommended to perform minimum required work in this callback. 314 * @param view The WebView that is initiating the callback. 315 * @param request The originating request. 316 * @param error Information about the error occurred. 317 */ 318 public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { 319 if (request.isForMainFrame()) { 320 onReceivedError(view, 321 error.getErrorCode(), error.getDescription().toString(), 322 request.getUrl().toString()); 323 } 324 } 325 326 /** 327 * Notify the host application that an HTTP error has been received from the server while 328 * loading a resource. HTTP errors have status codes >= 400. This callback will be called 329 * for any resource (iframe, image, etc.), not just for the main page. Thus, it is recommended 330 * to perform minimum required work in this callback. Note that the content of the server 331 * response may not be provided within the {@code errorResponse} parameter. 332 * @param view The WebView that is initiating the callback. 333 * @param request The originating request. 334 * @param errorResponse Information about the error occurred. 335 */ 336 public void onReceivedHttpError( 337 WebView view, WebResourceRequest request, WebResourceResponse errorResponse) { 338 } 339 340 /** 341 * As the host application if the browser should resend data as the 342 * requested page was a result of a POST. The default is to not resend the 343 * data. 344 * 345 * @param view The WebView that is initiating the callback. 346 * @param dontResend The message to send if the browser should not resend 347 * @param resend The message to send if the browser should resend data 348 */ 349 public void onFormResubmission(WebView view, Message dontResend, 350 Message resend) { 351 dontResend.sendToTarget(); 352 } 353 354 /** 355 * Notify the host application to update its visited links database. 356 * 357 * @param view The WebView that is initiating the callback. 358 * @param url The url being visited. 359 * @param isReload {@code true} if this url is being reloaded. 360 */ 361 public void doUpdateVisitedHistory(WebView view, String url, 362 boolean isReload) { 363 } 364 365 /** 366 * Notify the host application that an SSL error occurred while loading a 367 * resource. The host application must call either handler.cancel() or 368 * handler.proceed(). Note that the decision may be retained for use in 369 * response to future SSL errors. The default behavior is to cancel the 370 * load. 371 * <p> 372 * Applications are advised not to prompt the user about SSL errors, as 373 * the user is unlikely to be able to make an informed security decision 374 * and WebView does not provide any UI for showing the details of the 375 * error in a meaningful way. 376 * <p> 377 * Application overrides of this method may display custom error pages or 378 * silently log issues, but it is strongly recommended to always call 379 * handler.cancel() and never allow proceeding past errors. 380 * 381 * @param view The WebView that is initiating the callback. 382 * @param handler An SslErrorHandler object that will handle the user's 383 * response. 384 * @param error The SSL error object. 385 */ 386 public void onReceivedSslError(WebView view, SslErrorHandler handler, 387 SslError error) { 388 handler.cancel(); 389 } 390 391 /** 392 * Notify the host application to handle a SSL client certificate request. The host application 393 * is responsible for showing the UI if desired and providing the keys. There are three ways to 394 * respond: {@link ClientCertRequest#proceed}, {@link ClientCertRequest#cancel}, or {@link 395 * ClientCertRequest#ignore}. Webview stores the response in memory (for the life of the 396 * application) if {@link ClientCertRequest#proceed} or {@link ClientCertRequest#cancel} is 397 * called and does not call {@code onReceivedClientCertRequest()} again for the same host and 398 * port pair. Webview does not store the response if {@link ClientCertRequest#ignore} 399 * is called. Note that, multiple layers in chromium network stack might be 400 * caching the responses, so the behavior for ignore is only a best case 401 * effort. 402 * 403 * This method is called on the UI thread. During the callback, the 404 * connection is suspended. 405 * 406 * For most use cases, the application program should implement the 407 * {@link android.security.KeyChainAliasCallback} interface and pass it to 408 * {@link android.security.KeyChain#choosePrivateKeyAlias} to start an 409 * activity for the user to choose the proper alias. The keychain activity will 410 * provide the alias through the callback method in the implemented interface. Next 411 * the application should create an async task to call 412 * {@link android.security.KeyChain#getPrivateKey} to receive the key. 413 * 414 * An example implementation of client certificates can be seen at 415 * <A href="https://android.googlesource.com/platform/packages/apps/Browser/+/android-5.1.1_r1/src/com/android/browser/Tab.java"> 416 * AOSP Browser</a> 417 * 418 * The default behavior is to cancel, returning no client certificate. 419 * 420 * @param view The WebView that is initiating the callback 421 * @param request An instance of a {@link ClientCertRequest} 422 * 423 */ 424 public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) { 425 request.cancel(); 426 } 427 428 /** 429 * Notifies the host application that the WebView received an HTTP 430 * authentication request. The host application can use the supplied 431 * {@link HttpAuthHandler} to set the WebView's response to the request. 432 * The default behavior is to cancel the request. 433 * 434 * @param view the WebView that is initiating the callback 435 * @param handler the HttpAuthHandler used to set the WebView's response 436 * @param host the host requiring authentication 437 * @param realm the realm for which authentication is required 438 * @see WebView#getHttpAuthUsernamePassword 439 */ 440 public void onReceivedHttpAuthRequest(WebView view, 441 HttpAuthHandler handler, String host, String realm) { 442 handler.cancel(); 443 } 444 445 /** 446 * Give the host application a chance to handle the key event synchronously. 447 * e.g. menu shortcut key events need to be filtered this way. If return 448 * true, WebView will not handle the key event. If return {@code false}, WebView 449 * will always handle the key event, so none of the super in the view chain 450 * will see the key event. The default behavior returns {@code false}. 451 * 452 * @param view The WebView that is initiating the callback. 453 * @param event The key event. 454 * @return {@code true} if the host application wants to handle the key event 455 * itself, otherwise return {@code false} 456 */ 457 public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) { 458 return false; 459 } 460 461 /** 462 * Notify the host application that a key was not handled by the WebView. 463 * Except system keys, WebView always consumes the keys in the normal flow 464 * or if {@link #shouldOverrideKeyEvent} returns {@code true}. This is called asynchronously 465 * from where the key is dispatched. It gives the host application a chance 466 * to handle the unhandled key events. 467 * 468 * @param view The WebView that is initiating the callback. 469 * @param event The key event. 470 */ 471 public void onUnhandledKeyEvent(WebView view, KeyEvent event) { 472 onUnhandledInputEventInternal(view, event); 473 } 474 475 /** 476 * Notify the host application that a input event was not handled by the WebView. 477 * Except system keys, WebView always consumes input events in the normal flow 478 * or if {@link #shouldOverrideKeyEvent} returns {@code true}. This is called asynchronously 479 * from where the event is dispatched. It gives the host application a chance 480 * to handle the unhandled input events. 481 * 482 * Note that if the event is a {@link android.view.MotionEvent}, then it's lifetime is only 483 * that of the function call. If the WebViewClient wishes to use the event beyond that, then it 484 * <i>must</i> create a copy of the event. 485 * 486 * It is the responsibility of overriders of this method to call 487 * {@link #onUnhandledKeyEvent(WebView, KeyEvent)} 488 * when appropriate if they wish to continue receiving events through it. 489 * 490 * @param view The WebView that is initiating the callback. 491 * @param event The input event. 492 * @removed 493 */ 494 public void onUnhandledInputEvent(WebView view, InputEvent event) { 495 if (event instanceof KeyEvent) { 496 onUnhandledKeyEvent(view, (KeyEvent) event); 497 return; 498 } 499 onUnhandledInputEventInternal(view, event); 500 } 501 502 private void onUnhandledInputEventInternal(WebView view, InputEvent event) { 503 ViewRootImpl root = view.getViewRootImpl(); 504 if (root != null) { 505 root.dispatchUnhandledInputEvent(event); 506 } 507 } 508 509 /** 510 * Notify the host application that the scale applied to the WebView has 511 * changed. 512 * 513 * @param view The WebView that is initiating the callback. 514 * @param oldScale The old scale factor 515 * @param newScale The new scale factor 516 */ 517 public void onScaleChanged(WebView view, float oldScale, float newScale) { 518 } 519 520 /** 521 * Notify the host application that a request to automatically log in the 522 * user has been processed. 523 * @param view The WebView requesting the login. 524 * @param realm The account realm used to look up accounts. 525 * @param account An optional account. If not {@code null}, the account should be 526 * checked against accounts on the device. If it is a valid 527 * account, it should be used to log in the user. 528 * @param args Authenticator specific arguments used to log in the user. 529 */ 530 public void onReceivedLoginRequest(WebView view, String realm, 531 @Nullable String account, String args) { 532 } 533 534 /** 535 * Notify host application that the given WebView's render process has exited. 536 * 537 * Multiple WebView instances may be associated with a single render process; 538 * onRenderProcessGone will be called for each WebView that was affected. 539 * The application's implementation of this callback should only attempt to 540 * clean up the specific WebView given as a parameter, and should not assume 541 * that other WebView instances are affected. 542 * 543 * The given WebView can't be used, and should be removed from the view hierarchy, 544 * all references to it should be cleaned up, e.g any references in the Activity 545 * or other classes saved using {@link android.view.View#findViewById} and similar calls, etc. 546 * 547 * To cause an render process crash for test purpose, the application can 548 * call {@code loadUrl("chrome://crash")} on the WebView. Note that multiple WebView 549 * instances may be affected if they share a render process, not just the 550 * specific WebView which loaded chrome://crash. 551 * 552 * @param view The WebView which needs to be cleaned up. 553 * @param detail the reason why it exited. 554 * @return {@code true} if the host application handled the situation that process has 555 * exited, otherwise, application will crash if render process crashed, 556 * or be killed if render process was killed by the system. 557 */ 558 public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) { 559 return false; 560 } 561 562 /** 563 * Notify the host application that a loading URL has been flagged by Safe Browsing. 564 * 565 * The application must invoke the callback to indicate the preferred response. The default 566 * behavior is to show an interstitial to the user, with the reporting checkbox visible. 567 * 568 * If the application needs to show its own custom interstitial UI, the callback can be invoked 569 * asynchronously with {@link SafeBrowsingResponse#backToSafety} or {@link 570 * SafeBrowsingResponse#proceed}, depending on user response. 571 * 572 * @param view The WebView that hit the malicious resource. 573 * @param request Object containing the details of the request. 574 * @param threatType The reason the resource was caught by Safe Browsing, corresponding to a 575 * {@code SAFE_BROWSING_THREAT_*} value. 576 * @param callback Applications must invoke one of the callback methods. 577 */ 578 public void onSafeBrowsingHit(WebView view, WebResourceRequest request, 579 @SafeBrowsingThreat int threatType, SafeBrowsingResponse callback) { 580 callback.showInterstitial(/* allowReporting */ true); 581 } 582} 583