1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.webkit;
18
19import android.annotation.Nullable;
20import android.annotation.SystemApi;
21import android.content.Intent;
22import android.content.pm.ActivityInfo;
23import android.graphics.Bitmap;
24import android.net.Uri;
25import android.os.Message;
26import android.view.View;
27
28public class WebChromeClient {
29
30    /**
31     * Tell the host application the current progress of loading a page.
32     * @param view The WebView that initiated the callback.
33     * @param newProgress Current page loading progress, represented by
34     *                    an integer between 0 and 100.
35     */
36    public void onProgressChanged(WebView view, int newProgress) {}
37
38    /**
39     * Notify the host application of a change in the document title.
40     * @param view The WebView that initiated the callback.
41     * @param title A String containing the new title of the document.
42     */
43    public void onReceivedTitle(WebView view, String title) {}
44
45    /**
46     * Notify the host application of a new favicon for the current page.
47     * @param view The WebView that initiated the callback.
48     * @param icon A Bitmap containing the favicon for the current page.
49     */
50    public void onReceivedIcon(WebView view, Bitmap icon) {}
51
52    /**
53     * Notify the host application of the url for an apple-touch-icon.
54     * @param view The WebView that initiated the callback.
55     * @param url The icon url.
56     * @param precomposed {@code true} if the url is for a precomposed touch icon.
57     */
58    public void onReceivedTouchIconUrl(WebView view, String url,
59            boolean precomposed) {}
60
61    /**
62     * A callback interface used by the host application to notify
63     * the current page that its custom view has been dismissed.
64     */
65    public interface CustomViewCallback {
66        /**
67         * Invoked when the host application dismisses the
68         * custom view.
69         */
70        public void onCustomViewHidden();
71    }
72
73    /**
74     * Notify the host application that the current page has entered full
75     * screen mode. The host application must show the custom View which
76     * contains the web contents — video or other HTML content —
77     * in full screen mode. Also see "Full screen support" documentation on
78     * {@link WebView}.
79     * @param view is the View object to be shown.
80     * @param callback invoke this callback to request the page to exit
81     * full screen mode.
82     */
83    public void onShowCustomView(View view, CustomViewCallback callback) {};
84
85    /**
86     * Notify the host application that the current page would
87     * like to show a custom View in a particular orientation.
88     * @param view is the View object to be shown.
89     * @param requestedOrientation An orientation constant as used in
90     * {@link ActivityInfo#screenOrientation ActivityInfo.screenOrientation}.
91     * @param callback is the callback to be invoked if and when the view
92     * is dismissed.
93     * @deprecated This method supports the obsolete plugin mechanism,
94     * and will not be invoked in future
95     */
96    @Deprecated
97    public void onShowCustomView(View view, int requestedOrientation,
98            CustomViewCallback callback) {};
99
100    /**
101     * Notify the host application that the current page has exited full
102     * screen mode. The host application must hide the custom View, ie. the
103     * View passed to {@link #onShowCustomView} when the content entered fullscreen.
104     * Also see "Full screen support" documentation on {@link WebView}.
105     */
106    public void onHideCustomView() {}
107
108    /**
109     * Request the host application to create a new window. If the host
110     * application chooses to honor this request, it should return {@code true} from
111     * this method, create a new WebView to host the window, insert it into the
112     * View system and send the supplied resultMsg message to its target with
113     * the new WebView as an argument. If the host application chooses not to
114     * honor the request, it should return {@code false} from this method. The default
115     * implementation of this method does nothing and hence returns {@code false}.
116     * <p>
117     * Applications should typically not allow windows to be created when the
118     * {@code isUserGesture} flag is false, as this may be an unwanted popup.
119     * <p>
120     * Applications should be careful how they display the new window: don't simply
121     * overlay it over the existing WebView as this may mislead the user about which
122     * site they are viewing. If your application displays the URL of the main page,
123     * make sure to also display the URL of the new window in a similar fashion. If
124     * your application does not display URLs, consider disallowing the creation of
125     * new windows entirely.
126     * <p class="note"><b>Note:</b> There is no trustworthy way to tell which page
127     * requested the new window: the request might originate from a third-party iframe
128     * inside the WebView.
129     *
130     * @param view The WebView from which the request for a new window
131     *             originated.
132     * @param isDialog {@code true} if the new window should be a dialog, rather than
133     *                 a full-size window.
134     * @param isUserGesture {@code true} if the request was initiated by a user gesture,
135     *                      such as the user clicking a link.
136     * @param resultMsg The message to send when once a new WebView has been
137     *                  created. resultMsg.obj is a
138     *                  {@link WebView.WebViewTransport} object. This should be
139     *                  used to transport the new WebView, by calling
140     *                  {@link WebView.WebViewTransport#setWebView(WebView)
141     *                  WebView.WebViewTransport.setWebView(WebView)}.
142     * @return This method should return {@code true} if the host application will
143     *         create a new window, in which case resultMsg should be sent to
144     *         its target. Otherwise, this method should return {@code false}. Returning
145     *         {@code false} from this method but also sending resultMsg will result in
146     *         undefined behavior.
147     */
148    public boolean onCreateWindow(WebView view, boolean isDialog,
149            boolean isUserGesture, Message resultMsg) {
150        return false;
151    }
152
153    /**
154     * Request display and focus for this WebView. This may happen due to
155     * another WebView opening a link in this WebView and requesting that this
156     * WebView be displayed.
157     * @param view The WebView that needs to be focused.
158     */
159    public void onRequestFocus(WebView view) {}
160
161    /**
162     * Notify the host application to close the given WebView and remove it
163     * from the view system if necessary. At this point, WebCore has stopped
164     * any loading in this window and has removed any cross-scripting ability
165     * in javascript.
166     * <p>
167     * As with {@link #onCreateWindow}, the application should ensure that any
168     * URL or security indicator displayed is updated so that the user can tell
169     * that the page they were interacting with has been closed.
170     *
171     * @param window The WebView that needs to be closed.
172     */
173    public void onCloseWindow(WebView window) {}
174
175    /**
176     * Tell the client to display a javascript alert dialog.  If the client
177     * returns {@code true}, WebView will assume that the client will handle the
178     * dialog.  If the client returns {@code false}, it will continue execution.
179     * @param view The WebView that initiated the callback.
180     * @param url The url of the page requesting the dialog.
181     * @param message Message to be displayed in the window.
182     * @param result A JsResult to confirm that the user hit enter.
183     * @return boolean Whether the client will handle the alert dialog.
184     */
185    public boolean onJsAlert(WebView view, String url, String message,
186            JsResult result) {
187        return false;
188    }
189
190    /**
191     * Tell the client to display a confirm dialog to the user. If the client
192     * returns {@code true}, WebView will assume that the client will handle the
193     * confirm dialog and call the appropriate JsResult method. If the
194     * client returns false, a default value of {@code false} will be returned to
195     * javascript. The default behavior is to return {@code false}.
196     * @param view The WebView that initiated the callback.
197     * @param url The url of the page requesting the dialog.
198     * @param message Message to be displayed in the window.
199     * @param result A JsResult used to send the user's response to
200     *               javascript.
201     * @return boolean Whether the client will handle the confirm dialog.
202     */
203    public boolean onJsConfirm(WebView view, String url, String message,
204            JsResult result) {
205        return false;
206    }
207
208    /**
209     * Tell the client to display a prompt dialog to the user. If the client
210     * returns {@code true}, WebView will assume that the client will handle the
211     * prompt dialog and call the appropriate JsPromptResult method. If the
212     * client returns false, a default value of {@code false} will be returned to to
213     * javascript. The default behavior is to return {@code false}.
214     * @param view The WebView that initiated the callback.
215     * @param url The url of the page requesting the dialog.
216     * @param message Message to be displayed in the window.
217     * @param defaultValue The default value displayed in the prompt dialog.
218     * @param result A JsPromptResult used to send the user's reponse to
219     *               javascript.
220     * @return boolean Whether the client will handle the prompt dialog.
221     */
222    public boolean onJsPrompt(WebView view, String url, String message,
223            String defaultValue, JsPromptResult result) {
224        return false;
225    }
226
227    /**
228     * Tell the client to display a dialog to confirm navigation away from the
229     * current page. This is the result of the onbeforeunload javascript event.
230     * If the client returns {@code true}, WebView will assume that the client will
231     * handle the confirm dialog and call the appropriate JsResult method. If
232     * the client returns {@code false}, a default value of {@code true} will be returned to
233     * javascript to accept navigation away from the current page. The default
234     * behavior is to return {@code false}. Setting the JsResult to {@code true} will navigate
235     * away from the current page, {@code false} will cancel the navigation.
236     * @param view The WebView that initiated the callback.
237     * @param url The url of the page requesting the dialog.
238     * @param message Message to be displayed in the window.
239     * @param result A JsResult used to send the user's response to
240     *               javascript.
241     * @return boolean Whether the client will handle the confirm dialog.
242     */
243    public boolean onJsBeforeUnload(WebView view, String url, String message,
244            JsResult result) {
245        return false;
246    }
247
248   /**
249    * Tell the client that the quota has been exceeded for the Web SQL Database
250    * API for a particular origin and request a new quota. The client must
251    * respond by invoking the
252    * {@link WebStorage.QuotaUpdater#updateQuota(long) updateQuota(long)}
253    * method of the supplied {@link WebStorage.QuotaUpdater} instance. The
254    * minimum value that can be set for the new quota is the current quota. The
255    * default implementation responds with the current quota, so the quota will
256    * not be increased.
257    * @param url The URL of the page that triggered the notification
258    * @param databaseIdentifier The identifier of the database where the quota
259    *                           was exceeded.
260    * @param quota The quota for the origin, in bytes
261    * @param estimatedDatabaseSize The estimated size of the offending
262    *                              database, in bytes
263    * @param totalQuota The total quota for all origins, in bytes
264    * @param quotaUpdater An instance of {@link WebStorage.QuotaUpdater} which
265    *                     must be used to inform the WebView of the new quota.
266    * @deprecated This method is no longer called; WebView now uses the HTML5 / JavaScript Quota
267    *             Management API.
268    */
269    @Deprecated
270    public void onExceededDatabaseQuota(String url, String databaseIdentifier,
271            long quota, long estimatedDatabaseSize, long totalQuota,
272            WebStorage.QuotaUpdater quotaUpdater) {
273        // This default implementation passes the current quota back to WebCore.
274        // WebCore will interpret this that new quota was declined.
275        quotaUpdater.updateQuota(quota);
276    }
277
278   /**
279    * Notify the host application that the Application Cache has reached the
280    * maximum size. The client must respond by invoking the
281    * {@link WebStorage.QuotaUpdater#updateQuota(long) updateQuota(long)}
282    * method of the supplied {@link WebStorage.QuotaUpdater} instance. The
283    * minimum value that can be set for the new quota is the current quota. The
284    * default implementation responds with the current quota, so the quota will
285    * not be increased.
286    * @param requiredStorage The amount of storage required by the Application
287    *                        Cache operation that triggered this notification,
288    *                        in bytes.
289    * @param quota the current maximum Application Cache size, in bytes
290    * @param quotaUpdater An instance of {@link WebStorage.QuotaUpdater} which
291    *                     must be used to inform the WebView of the new quota.
292    * @deprecated This method is no longer called; WebView now uses the HTML5 / JavaScript Quota
293    *             Management API.
294    */
295    @Deprecated
296    public void onReachedMaxAppCacheSize(long requiredStorage, long quota,
297            WebStorage.QuotaUpdater quotaUpdater) {
298        quotaUpdater.updateQuota(quota);
299    }
300
301    /**
302     * Notify the host application that web content from the specified origin
303     * is attempting to use the Geolocation API, but no permission state is
304     * currently set for that origin. The host application should invoke the
305     * specified callback with the desired permission state. See
306     * {@link GeolocationPermissions} for details.
307     *
308     * <p>Note that for applications targeting Android N and later SDKs
309     * (API level > {@link android.os.Build.VERSION_CODES#M})
310     * this method is only called for requests originating from secure
311     * origins such as https. On non-secure origins geolocation requests
312     * are automatically denied.
313     *
314     * @param origin The origin of the web content attempting to use the
315     *               Geolocation API.
316     * @param callback The callback to use to set the permission state for the
317     *                 origin.
318     */
319    public void onGeolocationPermissionsShowPrompt(String origin,
320            GeolocationPermissions.Callback callback) {}
321
322    /**
323     * Notify the host application that a request for Geolocation permissions,
324     * made with a previous call to
325     * {@link #onGeolocationPermissionsShowPrompt(String,GeolocationPermissions.Callback) onGeolocationPermissionsShowPrompt()}
326     * has been canceled. Any related UI should therefore be hidden.
327     */
328    public void onGeolocationPermissionsHidePrompt() {}
329
330    /**
331     * Notify the host application that web content is requesting permission to
332     * access the specified resources and the permission currently isn't granted
333     * or denied. The host application must invoke {@link PermissionRequest#grant(String[])}
334     * or {@link PermissionRequest#deny()}.
335     *
336     * If this method isn't overridden, the permission is denied.
337     *
338     * @param request the PermissionRequest from current web content.
339     */
340    public void onPermissionRequest(PermissionRequest request) {
341        request.deny();
342    }
343
344    /**
345     * Notify the host application that the given permission request
346     * has been canceled. Any related UI should therefore be hidden.
347     *
348     * @param request the PermissionRequest that needs be canceled.
349     */
350    public void onPermissionRequestCanceled(PermissionRequest request) {}
351
352    /**
353     * Tell the client that a JavaScript execution timeout has occured. And the
354     * client may decide whether or not to interrupt the execution. If the
355     * client returns {@code true}, the JavaScript will be interrupted. If the client
356     * returns {@code false}, the execution will continue. Note that in the case of
357     * continuing execution, the timeout counter will be reset, and the callback
358     * will continue to occur if the script does not finish at the next check
359     * point.
360     * @return boolean Whether the JavaScript execution should be interrupted.
361     * @deprecated This method is no longer supported and will not be invoked.
362     */
363    // This method was only called when using the JSC javascript engine. V8 became
364    // the default JS engine with Froyo and support for building with JSC was
365    // removed in b/5495373. V8 does not have a mechanism for making a callback such
366    // as this.
367    @Deprecated
368    public boolean onJsTimeout() {
369        return true;
370    }
371
372    /**
373     * Report a JavaScript error message to the host application. The ChromeClient
374     * should override this to process the log message as they see fit.
375     * @param message The error message to report.
376     * @param lineNumber The line number of the error.
377     * @param sourceID The name of the source file that caused the error.
378     * @deprecated Use {@link #onConsoleMessage(ConsoleMessage) onConsoleMessage(ConsoleMessage)}
379     *      instead.
380     */
381    @Deprecated
382    public void onConsoleMessage(String message, int lineNumber, String sourceID) { }
383
384    /**
385     * Report a JavaScript console message to the host application. The ChromeClient
386     * should override this to process the log message as they see fit.
387     * @param consoleMessage Object containing details of the console message.
388     * @return {@code true} if the message is handled by the client.
389     */
390    public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
391        // Call the old version of this function for backwards compatability.
392        onConsoleMessage(consoleMessage.message(), consoleMessage.lineNumber(),
393                consoleMessage.sourceId());
394        return false;
395    }
396
397    /**
398     * When not playing, video elements are represented by a 'poster' image. The
399     * image to use can be specified by the poster attribute of the video tag in
400     * HTML. If the attribute is absent, then a default poster will be used. This
401     * method allows the ChromeClient to provide that default image.
402     *
403     * @return Bitmap The image to use as a default poster, or {@code null} if no such image is
404     * available.
405     */
406    @Nullable
407    public Bitmap getDefaultVideoPoster() {
408        return null;
409    }
410
411    /**
412     * Obtains a View to be displayed while buffering of full screen video is taking
413     * place. The host application can override this method to provide a View
414     * containing a spinner or similar.
415     *
416     * @return View The View to be displayed whilst the video is loading.
417     */
418    @Nullable
419    public View getVideoLoadingProgressView() {
420        return null;
421    }
422
423    /** Obtains a list of all visited history items, used for link coloring
424     */
425    public void getVisitedHistory(ValueCallback<String[]> callback) {
426    }
427
428    /**
429     * Tell the client to show a file chooser.
430     *
431     * This is called to handle HTML forms with 'file' input type, in response to the
432     * user pressing the "Select File" button.
433     * To cancel the request, call <code>filePathCallback.onReceiveValue(null)</code> and
434     * return {@code true}.
435     *
436     * @param webView The WebView instance that is initiating the request.
437     * @param filePathCallback Invoke this callback to supply the list of paths to files to upload,
438     *                         or {@code null} to cancel. Must only be called if the
439     *                         {@link #onShowFileChooser} implementation returns {@code true}.
440     * @param fileChooserParams Describes the mode of file chooser to be opened, and options to be
441     *                          used with it.
442     * @return {@code true} if filePathCallback will be invoked, {@code false} to use default
443     *         handling.
444     *
445     * @see FileChooserParams
446     */
447    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
448            FileChooserParams fileChooserParams) {
449        return false;
450    }
451
452    /**
453     * Parameters used in the {@link #onShowFileChooser} method.
454     */
455    public static abstract class FileChooserParams {
456        /** Open single file. Requires that the file exists before allowing the user to pick it. */
457        public static final int MODE_OPEN = 0;
458        /** Like Open but allows multiple files to be selected. */
459        public static final int MODE_OPEN_MULTIPLE = 1;
460        /** Like Open but allows a folder to be selected. The implementation should enumerate
461            all files selected by this operation.
462            This feature is not supported at the moment.
463            @hide */
464        public static final int MODE_OPEN_FOLDER = 2;
465        /**  Allows picking a nonexistent file and saving it. */
466        public static final int MODE_SAVE = 3;
467
468        /**
469         * Parse the result returned by the file picker activity. This method should be used with
470         * {@link #createIntent}. Refer to {@link #createIntent} for how to use it.
471         *
472         * @param resultCode the integer result code returned by the file picker activity.
473         * @param data the intent returned by the file picker activity.
474         * @return the Uris of selected file(s) or {@code null} if the resultCode indicates
475         *         activity canceled or any other error.
476         */
477        @Nullable
478        public static Uri[] parseResult(int resultCode, Intent data) {
479            return WebViewFactory.getProvider().getStatics().parseFileChooserResult(resultCode, data);
480        }
481
482        /**
483         * Returns file chooser mode.
484         */
485        public abstract int getMode();
486
487        /**
488         * Returns an array of acceptable MIME types. The returned MIME type
489         * could be partial such as audio/*. The array will be empty if no
490         * acceptable types are specified.
491         */
492        public abstract String[] getAcceptTypes();
493
494        /**
495         * Returns preference for a live media captured value (e.g. Camera, Microphone).
496         * True indicates capture is enabled, {@code false} disabled.
497         *
498         * Use <code>getAcceptTypes</code> to determine suitable capture devices.
499         */
500        public abstract boolean isCaptureEnabled();
501
502        /**
503         * Returns the title to use for this file selector. If {@code null} a default title should
504         * be used.
505         */
506        @Nullable
507        public abstract CharSequence getTitle();
508
509        /**
510         * The file name of a default selection if specified, or {@code null}.
511         */
512        @Nullable
513        public abstract String getFilenameHint();
514
515        /**
516         * Creates an intent that would start a file picker for file selection.
517         * The Intent supports choosing files from simple file sources available
518         * on the device. Some advanced sources (for example, live media capture)
519         * may not be supported and applications wishing to support these sources
520         * or more advanced file operations should build their own Intent.
521         *
522         * <pre>
523         * How to use:
524         * 1. Build an intent using {@link #createIntent}
525         * 2. Fire the intent using {@link android.app.Activity#startActivityForResult}.
526         * 3. Check for ActivityNotFoundException and take a user friendly action if thrown.
527         * 4. Listen the result using {@link android.app.Activity#onActivityResult}
528         * 5. Parse the result using {@link #parseResult} only if media capture was not requested.
529         * 6. Send the result using filePathCallback of {@link WebChromeClient#onShowFileChooser}
530         * </pre>
531         *
532         * @return an Intent that supports basic file chooser sources.
533         */
534        public abstract Intent createIntent();
535    }
536
537    /**
538     * Tell the client to open a file chooser.
539     * @param uploadFile A ValueCallback to set the URI of the file to upload.
540     *      onReceiveValue must be called to wake up the thread.a
541     * @param acceptType The value of the 'accept' attribute of the input tag
542     *         associated with this file picker.
543     * @param capture The value of the 'capture' attribute of the input tag
544     *         associated with this file picker.
545     *
546     * @deprecated Use {@link #onShowFileChooser} instead.
547     * @hide This method was not published in any SDK version.
548     */
549    @SystemApi
550    @Deprecated
551    public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType, String capture) {
552        uploadFile.onReceiveValue(null);
553    }
554}
555