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.FlaggedApi; 20 import android.annotation.IntDef; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.compat.annotation.ChangeId; 24 import android.compat.annotation.EnabledAfter; 25 import android.content.Intent; 26 import android.content.pm.ActivityInfo; 27 import android.graphics.Bitmap; 28 import android.net.Uri; 29 import android.os.Message; 30 import android.view.View; 31 32 import java.lang.annotation.Retention; 33 import java.lang.annotation.RetentionPolicy; 34 35 public class WebChromeClient { 36 37 /** 38 * Tell the host application the current progress of loading a page. 39 * @param view The WebView that initiated the callback. 40 * @param newProgress Current page loading progress, represented by 41 * an integer between 0 and 100. 42 */ onProgressChanged(WebView view, int newProgress)43 public void onProgressChanged(WebView view, int newProgress) {} 44 45 /** 46 * Notify the host application of a change in the document title. 47 * @param view The WebView that initiated the callback. 48 * @param title A String containing the new title of the document. 49 */ onReceivedTitle(WebView view, String title)50 public void onReceivedTitle(WebView view, String title) {} 51 52 /** 53 * Notify the host application of a new favicon for the current page. 54 * @param view The WebView that initiated the callback. 55 * @param icon A Bitmap containing the favicon for the current page. 56 */ onReceivedIcon(WebView view, Bitmap icon)57 public void onReceivedIcon(WebView view, Bitmap icon) {} 58 59 /** 60 * Notify the host application of the url for an apple-touch-icon. 61 * @param view The WebView that initiated the callback. 62 * @param url The icon url. 63 * @param precomposed {@code true} if the url is for a precomposed touch icon. 64 */ onReceivedTouchIconUrl(WebView view, String url, boolean precomposed)65 public void onReceivedTouchIconUrl(WebView view, String url, 66 boolean precomposed) {} 67 68 /** 69 * A callback interface used by the host application to notify 70 * the current page that its custom view has been dismissed. 71 */ 72 public interface CustomViewCallback { 73 /** 74 * Invoked when the host application dismisses the 75 * custom view. 76 */ onCustomViewHidden()77 public void onCustomViewHidden(); 78 } 79 80 /** 81 * Notify the host application that the current page has entered full screen mode. After this 82 * call, web content will no longer be rendered in the WebView, but will instead be rendered 83 * in {@code view}. The host application should add this View to a Window which is configured 84 * with {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN} flag in order to 85 * actually display this web content full screen. 86 * 87 * <p>The application may explicitly exit fullscreen mode by invoking {@code callback} (ex. when 88 * the user presses the back button). However, this is generally not necessary as the web page 89 * will often show its own UI to close out of fullscreen. Regardless of how the WebView exits 90 * fullscreen mode, WebView will invoke {@link #onHideCustomView()}, signaling for the 91 * application to remove the custom View. 92 * 93 * <p>If this method is not overridden, WebView will report to the web page it does not support 94 * fullscreen mode and will not honor the web page's request to run in fullscreen mode. 95 * 96 * <p class="note"><b>Note:</b> if overriding this method, the application must also override 97 * {@link #onHideCustomView()}. 98 * 99 * @param view is the View object to be shown. 100 * @param callback invoke this callback to request the page to exit 101 * full screen mode. 102 */ onShowCustomView(View view, CustomViewCallback callback)103 public void onShowCustomView(View view, CustomViewCallback callback) {}; 104 105 /** 106 * Notify the host application that the current page would 107 * like to show a custom View in a particular orientation. 108 * @param view is the View object to be shown. 109 * @param requestedOrientation An orientation constant as used in 110 * {@link ActivityInfo#screenOrientation ActivityInfo.screenOrientation}. 111 * @param callback is the callback to be invoked if and when the view 112 * is dismissed. 113 * @deprecated This method supports the obsolete plugin mechanism, 114 * and will not be invoked in future 115 */ 116 @Deprecated onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback)117 public void onShowCustomView(View view, int requestedOrientation, 118 CustomViewCallback callback) {}; 119 120 /** 121 * Notify the host application that the current page has exited full screen mode. The host 122 * application must hide the custom View (the View which was previously passed to {@link 123 * #onShowCustomView(View, CustomViewCallback) onShowCustomView()}). After this call, web 124 * content will render in the original WebView again. 125 * 126 * <p class="note"><b>Note:</b> if overriding this method, the application must also override 127 * {@link #onShowCustomView(View, CustomViewCallback) onShowCustomView()}. 128 */ onHideCustomView()129 public void onHideCustomView() {} 130 131 /** 132 * Request the host application to create a new window. If the host 133 * application chooses to honor this request, it should return {@code true} from 134 * this method, create a new WebView to host the window, insert it into the 135 * View system and send the supplied resultMsg message to its target with 136 * the new WebView as an argument. If the host application chooses not to 137 * honor the request, it should return {@code false} from this method. The default 138 * implementation of this method does nothing and hence returns {@code false}. 139 * <p> 140 * Applications should typically not allow windows to be created when the 141 * {@code isUserGesture} flag is false, as this may be an unwanted popup. 142 * <p> 143 * Applications should be careful how they display the new window: don't simply 144 * overlay it over the existing WebView as this may mislead the user about which 145 * site they are viewing. If your application displays the URL of the main page, 146 * make sure to also display the URL of the new window in a similar fashion. If 147 * your application does not display URLs, consider disallowing the creation of 148 * new windows entirely. 149 * <p class="note"><b>Note:</b> There is no trustworthy way to tell which page 150 * requested the new window: the request might originate from a third-party iframe 151 * inside the WebView. 152 * 153 * @param view The WebView from which the request for a new window 154 * originated. 155 * @param isDialog {@code true} if the new window should be a dialog, rather than 156 * a full-size window. 157 * @param isUserGesture {@code true} if the request was initiated by a user gesture, 158 * such as the user clicking a link. 159 * @param resultMsg The message to send when once a new WebView has been 160 * created. resultMsg.obj is a 161 * {@link WebView.WebViewTransport} object. This should be 162 * used to transport the new WebView, by calling 163 * {@link WebView.WebViewTransport#setWebView(WebView) 164 * WebView.WebViewTransport.setWebView(WebView)}. 165 * @return This method should return {@code true} if the host application will 166 * create a new window, in which case resultMsg should be sent to 167 * its target. Otherwise, this method should return {@code false}. Returning 168 * {@code false} from this method but also sending resultMsg will result in 169 * undefined behavior. 170 */ onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg)171 public boolean onCreateWindow(WebView view, boolean isDialog, 172 boolean isUserGesture, Message resultMsg) { 173 return false; 174 } 175 176 /** 177 * Request display and focus for this WebView. This may happen due to 178 * another WebView opening a link in this WebView and requesting that this 179 * WebView be displayed. 180 * @param view The WebView that needs to be focused. 181 */ onRequestFocus(WebView view)182 public void onRequestFocus(WebView view) {} 183 184 /** 185 * Notify the host application to close the given WebView and remove it 186 * from the view system if necessary. At this point, WebCore has stopped 187 * any loading in this window and has removed any cross-scripting ability 188 * in javascript. 189 * <p> 190 * As with {@link #onCreateWindow}, the application should ensure that any 191 * URL or security indicator displayed is updated so that the user can tell 192 * that the page they were interacting with has been closed. 193 * 194 * @param window The WebView that needs to be closed. 195 */ onCloseWindow(WebView window)196 public void onCloseWindow(WebView window) {} 197 198 /** 199 * Notify the host application that the web page wants to display a 200 * JavaScript {@code alert()} dialog. 201 * <p>The default behavior if this method returns {@code false} or is not 202 * overridden is to show a dialog containing the alert message and suspend 203 * JavaScript execution until the dialog is dismissed. 204 * <p>To show a custom dialog, the app should return {@code true} from this 205 * method, in which case the default dialog will not be shown and JavaScript 206 * execution will be suspended. The app should call 207 * {@code JsResult.confirm()} when the custom dialog is dismissed such that 208 * JavaScript execution can be resumed. 209 * <p>To suppress the dialog and allow JavaScript execution to 210 * continue, call {@code JsResult.confirm()} immediately and then return 211 * {@code true}. 212 * <p>Note that if the {@link WebChromeClient} is set to be {@code null}, 213 * or if {@link WebChromeClient} is not set at all, the default dialog will 214 * be suppressed and Javascript execution will continue immediately. 215 * <p>Note that the default dialog does not inherit the {@link 216 * android.view.Display#FLAG_SECURE} flag from the parent window. 217 * 218 * @param view The WebView that initiated the callback. 219 * @param url The url of the page requesting the dialog. 220 * @param message Message to be displayed in the window. 221 * @param result A JsResult to confirm that the user closed the window. 222 * @return boolean {@code true} if the request is handled or ignored. 223 * {@code false} if WebView needs to show the default dialog. 224 */ onJsAlert(WebView view, String url, String message, JsResult result)225 public boolean onJsAlert(WebView view, String url, String message, 226 JsResult result) { 227 return false; 228 } 229 230 /** 231 * Notify the host application that the web page wants to display a 232 * JavaScript {@code confirm()} dialog. 233 * <p>The default behavior if this method returns {@code false} or is not 234 * overridden is to show a dialog containing the message and suspend 235 * JavaScript execution until the dialog is dismissed. The default dialog 236 * will return {@code true} to the JavaScript {@code confirm()} code when 237 * the user presses the 'confirm' button, and will return {@code false} to 238 * the JavaScript code when the user presses the 'cancel' button or 239 * dismisses the dialog. 240 * <p>To show a custom dialog, the app should return {@code true} from this 241 * method, in which case the default dialog will not be shown and JavaScript 242 * execution will be suspended. The app should call 243 * {@code JsResult.confirm()} or {@code JsResult.cancel()} when the custom 244 * dialog is dismissed. 245 * <p>To suppress the dialog and allow JavaScript execution to continue, 246 * call {@code JsResult.confirm()} or {@code JsResult.cancel()} immediately 247 * and then return {@code true}. 248 * <p>Note that if the {@link WebChromeClient} is set to be {@code null}, 249 * or if {@link WebChromeClient} is not set at all, the default dialog will 250 * be suppressed and the default value of {@code false} will be returned to 251 * the JavaScript code immediately. 252 * <p>Note that the default dialog does not inherit the {@link 253 * android.view.Display#FLAG_SECURE} flag from the parent window. 254 * 255 * @param view The WebView that initiated the callback. 256 * @param url The url of the page requesting the dialog. 257 * @param message Message to be displayed in the window. 258 * @param result A JsResult used to send the user's response to 259 * javascript. 260 * @return boolean {@code true} if the request is handled or ignored. 261 * {@code false} if WebView needs to show the default dialog. 262 */ onJsConfirm(WebView view, String url, String message, JsResult result)263 public boolean onJsConfirm(WebView view, String url, String message, 264 JsResult result) { 265 return false; 266 } 267 268 /** 269 * Notify the host application that the web page wants to display a 270 * JavaScript {@code prompt()} dialog. 271 * <p>The default behavior if this method returns {@code false} or is not 272 * overridden is to show a dialog containing the message and suspend 273 * JavaScript execution until the dialog is dismissed. Once the dialog is 274 * dismissed, JavaScript {@code prompt()} will return the string that the 275 * user typed in, or null if the user presses the 'cancel' button. 276 * <p>To show a custom dialog, the app should return {@code true} from this 277 * method, in which case the default dialog will not be shown and JavaScript 278 * execution will be suspended. The app should call 279 * {@code JsPromptResult.confirm(result)} when the custom dialog is 280 * dismissed. 281 * <p>To suppress the dialog and allow JavaScript execution to continue, 282 * call {@code JsPromptResult.confirm(result)} immediately and then 283 * return {@code true}. 284 * <p>Note that if the {@link WebChromeClient} is set to be {@code null}, 285 * or if {@link WebChromeClient} is not set at all, the default dialog will 286 * be suppressed and {@code null} will be returned to the JavaScript code 287 * immediately. 288 * <p>Note that the default dialog does not inherit the {@link 289 * android.view.Display#FLAG_SECURE} flag from the parent window. 290 * 291 * @param view The WebView that initiated the callback. 292 * @param url The url of the page requesting the dialog. 293 * @param message Message to be displayed in the window. 294 * @param defaultValue The default value displayed in the prompt dialog. 295 * @param result A JsPromptResult used to send the user's reponse to 296 * javascript. 297 * @return boolean {@code true} if the request is handled or ignored. 298 * {@code false} if WebView needs to show the default dialog. 299 */ onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)300 public boolean onJsPrompt(WebView view, String url, String message, 301 String defaultValue, JsPromptResult result) { 302 return false; 303 } 304 305 /** 306 * Notify the host application that the web page wants to confirm navigation 307 * from JavaScript {@code onbeforeunload}. 308 * <p>The default behavior if this method returns {@code false} or is not 309 * overridden is to show a dialog containing the message and suspend 310 * JavaScript execution until the dialog is dismissed. The default dialog 311 * will continue the navigation if the user confirms the navigation, and 312 * will stop the navigation if the user wants to stay on the current page. 313 * <p>To show a custom dialog, the app should return {@code true} from this 314 * method, in which case the default dialog will not be shown and JavaScript 315 * execution will be suspended. When the custom dialog is dismissed, the 316 * app should call {@code JsResult.confirm()} to continue the navigation or, 317 * {@code JsResult.cancel()} to stay on the current page. 318 * <p>To suppress the dialog and allow JavaScript execution to continue, 319 * call {@code JsResult.confirm()} or {@code JsResult.cancel()} immediately 320 * and then return {@code true}. 321 * <p>Note that if the {@link WebChromeClient} is set to be {@code null}, 322 * or if {@link WebChromeClient} is not set at all, the default dialog will 323 * be suppressed and the navigation will be resumed immediately. 324 * <p>Note that the default dialog does not inherit the {@link 325 * android.view.Display#FLAG_SECURE} flag from the parent window. 326 * 327 * @param view The WebView that initiated the callback. 328 * @param url The url of the page requesting the dialog. 329 * @param message Message to be displayed in the window. 330 * @param result A JsResult used to send the user's response to 331 * javascript. 332 * @return boolean {@code true} if the request is handled or ignored. 333 * {@code false} if WebView needs to show the default dialog. 334 */ onJsBeforeUnload(WebView view, String url, String message, JsResult result)335 public boolean onJsBeforeUnload(WebView view, String url, String message, 336 JsResult result) { 337 return false; 338 } 339 340 /** 341 * Tell the client that the quota has been exceeded for the Web SQL Database 342 * API for a particular origin and request a new quota. The client must 343 * respond by invoking the 344 * {@link WebStorage.QuotaUpdater#updateQuota(long) updateQuota(long)} 345 * method of the supplied {@link WebStorage.QuotaUpdater} instance. The 346 * minimum value that can be set for the new quota is the current quota. The 347 * default implementation responds with the current quota, so the quota will 348 * not be increased. 349 * @param url The URL of the page that triggered the notification 350 * @param databaseIdentifier The identifier of the database where the quota 351 * was exceeded. 352 * @param quota The quota for the origin, in bytes 353 * @param estimatedDatabaseSize The estimated size of the offending 354 * database, in bytes 355 * @param totalQuota The total quota for all origins, in bytes 356 * @param quotaUpdater An instance of {@link WebStorage.QuotaUpdater} which 357 * must be used to inform the WebView of the new quota. 358 * @deprecated This method is no longer called; WebView now uses the HTML5 / JavaScript Quota 359 * Management API. 360 */ 361 @Deprecated onExceededDatabaseQuota(String url, String databaseIdentifier, long quota, long estimatedDatabaseSize, long totalQuota, WebStorage.QuotaUpdater quotaUpdater)362 public void onExceededDatabaseQuota(String url, String databaseIdentifier, 363 long quota, long estimatedDatabaseSize, long totalQuota, 364 WebStorage.QuotaUpdater quotaUpdater) { 365 // This default implementation passes the current quota back to WebCore. 366 // WebCore will interpret this that new quota was declined. 367 quotaUpdater.updateQuota(quota); 368 } 369 370 /** 371 * Notify the host application that the Application Cache has reached the 372 * maximum size. The client must respond by invoking the 373 * {@link WebStorage.QuotaUpdater#updateQuota(long) updateQuota(long)} 374 * method of the supplied {@link WebStorage.QuotaUpdater} instance. The 375 * minimum value that can be set for the new quota is the current quota. The 376 * default implementation responds with the current quota, so the quota will 377 * not be increased. 378 * @param requiredStorage The amount of storage required by the Application 379 * Cache operation that triggered this notification, 380 * in bytes. 381 * @param quota the current maximum Application Cache size, in bytes 382 * @param quotaUpdater An instance of {@link WebStorage.QuotaUpdater} which 383 * must be used to inform the WebView of the new quota. 384 * @deprecated This method is no longer called; WebView now uses the HTML5 / JavaScript Quota 385 * Management API. 386 * @removed This method is no longer called; WebView now uses the HTML5 / JavaScript Quota 387 * Management API. 388 */ 389 @Deprecated onReachedMaxAppCacheSize(long requiredStorage, long quota, WebStorage.QuotaUpdater quotaUpdater)390 public void onReachedMaxAppCacheSize(long requiredStorage, long quota, 391 WebStorage.QuotaUpdater quotaUpdater) { 392 quotaUpdater.updateQuota(quota); 393 } 394 395 /** 396 * Notify the host application that web content from the specified origin 397 * is attempting to use the Geolocation API, but no permission state is 398 * currently set for that origin. The host application should invoke the 399 * specified callback with the desired permission state. See 400 * {@link GeolocationPermissions} for details. 401 * 402 * <p>Note that for applications targeting Android N and later SDKs 403 * (API level > {@link android.os.Build.VERSION_CODES#M}) 404 * this method is only called for requests originating from secure 405 * origins such as https. On non-secure origins geolocation requests 406 * are automatically denied. 407 * 408 * @param origin The origin of the web content attempting to use the 409 * Geolocation API. 410 * @param callback The callback to use to set the permission state for the 411 * origin. 412 */ onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback)413 public void onGeolocationPermissionsShowPrompt(String origin, 414 GeolocationPermissions.Callback callback) {} 415 416 /** 417 * Notify the host application that a request for Geolocation permissions, 418 * made with a previous call to 419 * {@link #onGeolocationPermissionsShowPrompt(String,GeolocationPermissions.Callback) onGeolocationPermissionsShowPrompt()} 420 * has been canceled. Any related UI should therefore be hidden. 421 */ onGeolocationPermissionsHidePrompt()422 public void onGeolocationPermissionsHidePrompt() {} 423 424 /** 425 * Notify the host application that web content is requesting permission to 426 * access the specified resources and the permission currently isn't granted 427 * or denied. The host application must invoke {@link PermissionRequest#grant(String[])} 428 * or {@link PermissionRequest#deny()}. 429 * 430 * If this method isn't overridden, the permission is denied. 431 * 432 * @param request the PermissionRequest from current web content. 433 */ onPermissionRequest(PermissionRequest request)434 public void onPermissionRequest(PermissionRequest request) { 435 request.deny(); 436 } 437 438 /** 439 * Notify the host application that the given permission request 440 * has been canceled. Any related UI should therefore be hidden. 441 * 442 * @param request the PermissionRequest that needs be canceled. 443 */ onPermissionRequestCanceled(PermissionRequest request)444 public void onPermissionRequestCanceled(PermissionRequest request) {} 445 446 /** 447 * Tell the client that a JavaScript execution timeout has occured. And the 448 * client may decide whether or not to interrupt the execution. If the 449 * client returns {@code true}, the JavaScript will be interrupted. If the client 450 * returns {@code false}, the execution will continue. Note that in the case of 451 * continuing execution, the timeout counter will be reset, and the callback 452 * will continue to occur if the script does not finish at the next check 453 * point. 454 * @return boolean Whether the JavaScript execution should be interrupted. 455 * @deprecated This method is no longer supported and will not be invoked. 456 */ 457 // This method was only called when using the JSC javascript engine. V8 became 458 // the default JS engine with Froyo and support for building with JSC was 459 // removed in b/5495373. V8 does not have a mechanism for making a callback such 460 // as this. 461 @Deprecated onJsTimeout()462 public boolean onJsTimeout() { 463 return true; 464 } 465 466 /** 467 * Report a JavaScript error message to the host application. The ChromeClient 468 * should override this to process the log message as they see fit. 469 * @param message The error message to report. 470 * @param lineNumber The line number of the error. 471 * @param sourceID The name of the source file that caused the error. 472 * @deprecated Use {@link #onConsoleMessage(ConsoleMessage) onConsoleMessage(ConsoleMessage)} 473 * instead. 474 */ 475 @Deprecated onConsoleMessage(String message, int lineNumber, String sourceID)476 public void onConsoleMessage(String message, int lineNumber, String sourceID) { } 477 478 /** 479 * Report a JavaScript console message to the host application. The ChromeClient 480 * should override this to process the log message as they see fit. 481 * @param consoleMessage Object containing details of the console message. 482 * @return {@code true} if the message is handled by the client. 483 */ onConsoleMessage(ConsoleMessage consoleMessage)484 public boolean onConsoleMessage(ConsoleMessage consoleMessage) { 485 // Call the old version of this function for backwards compatability. 486 onConsoleMessage(consoleMessage.message(), consoleMessage.lineNumber(), 487 consoleMessage.sourceId()); 488 return false; 489 } 490 491 /** 492 * When not playing, video elements are represented by a 'poster' image. The 493 * image to use can be specified by the poster attribute of the video tag in 494 * HTML. If the attribute is absent, then a default poster will be used. This 495 * method allows the ChromeClient to provide that default image. 496 * 497 * @return Bitmap The image to use as a default poster, or {@code null} if no such image is 498 * available. 499 */ 500 @Nullable getDefaultVideoPoster()501 public Bitmap getDefaultVideoPoster() { 502 return null; 503 } 504 505 /** 506 * Obtains a View to be displayed while buffering of full screen video is taking 507 * place. The host application can override this method to provide a View 508 * containing a spinner or similar. 509 * 510 * @return View The View to be displayed whilst the video is loading. 511 */ 512 @Nullable getVideoLoadingProgressView()513 public View getVideoLoadingProgressView() { 514 return null; 515 } 516 517 /** Obtains a list of all visited history items, used for link coloring 518 */ getVisitedHistory(ValueCallback<String[]> callback)519 public void getVisitedHistory(ValueCallback<String[]> callback) { 520 } 521 522 /** 523 * Tell the client to show a file chooser. 524 * 525 * This is called to handle HTML forms with 'file' input type, in response to the 526 * user pressing the "Select File" button. 527 * To cancel the request, call <code>filePathCallback.onReceiveValue(null)</code> and 528 * return {@code true}. 529 * 530 * <p class="note"><b>Note:</b> WebView does not enforce any restrictions on 531 * the chosen file(s). WebView can access all files that your app can access. 532 * In case the file(s) are chosen through an untrusted source such as a third-party 533 * app, it is your own app's responsibility to check what the returned Uris 534 * refer to before calling the {@code filePathCallback}. See 535 * {@link FileChooserParams#createIntent} and {@link FileChooserParams#parseResult} for more 536 * details. 537 * 538 * @param webView The WebView instance that is initiating the request. 539 * @param filePathCallback Invoke this callback to supply the list of paths to files to upload, 540 * or {@code null} to cancel. Must only be called if the 541 * {@link #onShowFileChooser} implementation returns {@code true}. 542 * @param fileChooserParams Describes the mode of file chooser to be opened, and options to be 543 * used with it. 544 * @return {@code true} if filePathCallback will be invoked, {@code false} to use default 545 * handling. 546 * 547 * @see FileChooserParams 548 */ onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams)549 public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, 550 FileChooserParams fileChooserParams) { 551 return false; 552 } 553 554 /** 555 * Parameters used in the {@link #onShowFileChooser} method. 556 */ 557 public static abstract class FileChooserParams { 558 /** 559 * Enable File System Access for webview. 560 * 561 * File System Access JS APIs window.showOpenFileChooser(), showDirectoryChooser(), and 562 * showSaveFilePicker() will invoke #onFileChooser(). Additional MODE_OPEN_FOLDER will be 563 * returned by #getMode(), #getIntent() will return ACTION_OPEN_DOCUMENT, 564 * ACTION_OPEN_DOCUMENT_TREE, and ACTION_CREATE_DOCUMENT rather than the current 565 * ACTION_GET_CONTENT, and new function #getPermissionMode() will be available. 566 * 567 * @hide 568 */ 569 @ChangeId 570 @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.VANILLA_ICE_CREAM) 571 @FlaggedApi(android.webkit.Flags.FLAG_FILE_SYSTEM_ACCESS) 572 @SystemApi 573 public static final long ENABLE_FILE_SYSTEM_ACCESS = 364980165L; 574 575 /** @hide */ 576 @IntDef(prefix = { "MODE_" }, value = { 577 MODE_OPEN, 578 MODE_OPEN_MULTIPLE, 579 MODE_OPEN_FOLDER, 580 MODE_SAVE, 581 }) 582 @Retention(RetentionPolicy.SOURCE) 583 public @interface Mode {} 584 585 /** Open single file. Requires that the file exists before allowing the user to pick it. */ 586 public static final int MODE_OPEN = 0; 587 /** Like Open but allows multiple files to be selected. */ 588 public static final int MODE_OPEN_MULTIPLE = 1; 589 /** Like Open but allows a folder to be selected. */ 590 @FlaggedApi(android.webkit.Flags.FLAG_FILE_SYSTEM_ACCESS) 591 public static final int MODE_OPEN_FOLDER = 2; 592 /** Allows picking a nonexistent file and saving it. */ 593 public static final int MODE_SAVE = 3; 594 595 /** @hide */ 596 @IntDef(prefix = { "PERMISSION_MODE_" }, value = { 597 PERMISSION_MODE_READ, 598 PERMISSION_MODE_READ_WRITE, 599 }) 600 @Retention(RetentionPolicy.SOURCE) 601 public @interface PermissionMode {} 602 603 /** File or directory should be opened for reading only. */ 604 @FlaggedApi(android.webkit.Flags.FLAG_FILE_SYSTEM_ACCESS) 605 public static final int PERMISSION_MODE_READ = 0; 606 /** File or directory should be opened for read and write. */ 607 @FlaggedApi(android.webkit.Flags.FLAG_FILE_SYSTEM_ACCESS) 608 public static final int PERMISSION_MODE_READ_WRITE = 1; 609 610 /** 611 * Parse the result returned by the file picker activity. This method should be used with 612 * {@link #createIntent}. Refer to {@link #createIntent} for how to use it. 613 * 614 * <p class="note"><b>Note:</b> The intent returned by the file picker activity 615 * should be treated as untrusted. A third-party app handling the implicit 616 * intent created by {@link #createIntent} might return Uris that the third-party 617 * app itself does not have access to, such as your own app's sensitive data files. 618 * WebView does not enforce any restrictions on the returned Uris. It is the 619 * app's responsibility to ensure that the untrusted source (such as a third-party 620 * app) has access the Uris it has returned and that the Uris are not pointing 621 * to any sensitive data files.</p> 622 * 623 * @param resultCode the integer result code returned by the file picker activity. 624 * @param data the intent returned by the file picker activity. 625 * @return the Uris of selected file(s) or {@code null} if the resultCode indicates 626 * activity canceled or any other error. 627 */ 628 @Nullable parseResult(int resultCode, Intent data)629 public static Uri[] parseResult(int resultCode, Intent data) { 630 return WebViewFactory.getProvider().getStatics().parseFileChooserResult(resultCode, data); 631 } 632 633 /** 634 * Returns file chooser mode. 635 */ 636 @Mode getMode()637 public abstract int getMode(); 638 639 /** 640 * Returns an array of acceptable MIME types. The returned MIME type 641 * could be partial such as audio/*. The array will be empty if no 642 * acceptable types are specified. 643 */ getAcceptTypes()644 public abstract String[] getAcceptTypes(); 645 646 /** 647 * Returns preference for a live media captured value (e.g. Camera, Microphone). 648 * True indicates capture is enabled, {@code false} disabled. 649 * 650 * Use <code>getAcceptTypes</code> to determine suitable capture devices. 651 */ isCaptureEnabled()652 public abstract boolean isCaptureEnabled(); 653 654 /** 655 * Returns the title to use for this file selector. If {@code null} a default title should 656 * be used. 657 */ 658 @Nullable getTitle()659 public abstract CharSequence getTitle(); 660 661 /** 662 * The file name of a default selection if specified, or {@code null}. 663 */ 664 @Nullable getFilenameHint()665 public abstract String getFilenameHint(); 666 667 /** 668 * Returns permission mode {@link #PERMISSION_MODE_READ} or 669 * {@link #PERMISSION_MODE_READ_WRITE} which indicates the intended mode for opening a file 670 * or directory. 671 * 672 * This can be used to determine whether an Intent such as 673 * {@link android.content.Intent#ACTION_OPEN_DOCUMENT} should be used rather than 674 * {@link android.content.Intent#ACTION_GET_CONTENT} to choose files. 675 */ 676 @FlaggedApi(Flags.FLAG_FILE_SYSTEM_ACCESS) 677 @PermissionMode getPermissionMode()678 public int getPermissionMode() { 679 return PERMISSION_MODE_READ; 680 } 681 682 /** 683 * Creates an intent that would start a file picker for file selection. 684 * The Intent supports choosing files from simple file sources available 685 * on the device. Some advanced sources (for example, live media capture) 686 * may not be supported and applications wishing to support these sources 687 * or more advanced file operations should build their own Intent. 688 * 689 * <p>How to use: 690 * <ol> 691 * <li>Build an intent using {@link #createIntent}</li> 692 * <li>Fire the intent using {@link android.app.Activity#startActivityForResult}.</li> 693 * <li>Check for ActivityNotFoundException and take a user friendly action if thrown.</li> 694 * <li>Listen the result using {@link android.app.Activity#onActivityResult}</li> 695 * <li>Parse the result using {@link #parseResult} only if media capture was not 696 * requested.</li> 697 * <li>Send the result using filePathCallback of {@link 698 * WebChromeClient#onShowFileChooser}</li> 699 * </ol> 700 * 701 * <p class="note"><b>Note:</b> The created intent may be handled by 702 * third-party applications on device. The received result must be treated 703 * as untrusted as it can contain Uris pointing to your own app's sensitive 704 * data files. Your app should check the resultant Uris in {@link #parseResult} 705 * before calling the <code>filePathCallback</code>.</p> 706 * 707 * @return an Intent that supports basic file chooser sources. 708 */ createIntent()709 public abstract Intent createIntent(); 710 } 711 712 /** 713 * Tell the client to open a file chooser. 714 * @param uploadFile A ValueCallback to set the URI of the file to upload. 715 * onReceiveValue must be called to wake up the thread.a 716 * @param acceptType The value of the 'accept' attribute of the input tag 717 * associated with this file picker. 718 * @param capture The value of the 'capture' attribute of the input tag 719 * associated with this file picker. 720 * 721 * @deprecated Use {@link #onShowFileChooser} instead. 722 * @hide This method was not published in any SDK version. 723 */ 724 @SystemApi 725 @Deprecated openFileChooser(ValueCallback<Uri> uploadFile, String acceptType, String capture)726 public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType, String capture) { 727 uploadFile.onReceiveValue(null); 728 } 729 } 730