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