• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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