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