1 /* 2 * Copyright (C) 2006 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.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.annotation.Widget; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.pm.PackageInfo; 27 import android.content.res.Configuration; 28 import android.graphics.Bitmap; 29 import android.graphics.Canvas; 30 import android.graphics.Paint; 31 import android.graphics.Picture; 32 import android.graphics.Rect; 33 import android.graphics.drawable.Drawable; 34 import android.net.Uri; 35 import android.net.http.SslCertificate; 36 import android.os.Build; 37 import android.os.Bundle; 38 import android.os.Handler; 39 import android.os.Looper; 40 import android.os.Message; 41 import android.os.RemoteException; 42 import android.os.StrictMode; 43 import android.print.PrintDocumentAdapter; 44 import android.security.KeyChain; 45 import android.util.AttributeSet; 46 import android.util.Log; 47 import android.util.SparseArray; 48 import android.view.DragEvent; 49 import android.view.KeyEvent; 50 import android.view.MotionEvent; 51 import android.view.View; 52 import android.view.ViewDebug; 53 import android.view.ViewGroup; 54 import android.view.ViewHierarchyEncoder; 55 import android.view.ViewStructure; 56 import android.view.ViewTreeObserver; 57 import android.view.accessibility.AccessibilityEvent; 58 import android.view.accessibility.AccessibilityNodeInfo; 59 import android.view.accessibility.AccessibilityNodeProvider; 60 import android.view.autofill.AutofillValue; 61 import android.view.inputmethod.EditorInfo; 62 import android.view.inputmethod.InputConnection; 63 import android.view.textclassifier.TextClassifier; 64 import android.widget.AbsoluteLayout; 65 66 import java.io.BufferedWriter; 67 import java.io.File; 68 import java.lang.annotation.Retention; 69 import java.lang.annotation.RetentionPolicy; 70 import java.util.List; 71 import java.util.Map; 72 73 /** 74 * <p>A View that displays web pages. This class is the basis upon which you 75 * can roll your own web browser or simply display some online content within your Activity. 76 * It uses the WebKit rendering engine to display 77 * web pages and includes methods to navigate forward and backward 78 * through a history, zoom in and out, perform text searches and more.</p> 79 * <p>Note that, in order for your Activity to access the Internet and load web pages 80 * in a WebView, you must add the {@code INTERNET} permissions to your 81 * Android Manifest file:</p> 82 * <pre><uses-permission android:name="android.permission.INTERNET" /></pre> 83 * 84 * <p>This must be a child of the <a 85 * href="{@docRoot}guide/topics/manifest/manifest-element.html">{@code <manifest>}</a> 86 * element.</p> 87 * 88 * <p>For more information, read 89 * <a href="{@docRoot}guide/webapps/webview.html">Building Web Apps in WebView</a>.</p> 90 * 91 * <h3>Basic usage</h3> 92 * 93 * <p>By default, a WebView provides no browser-like widgets, does not 94 * enable JavaScript and web page errors are ignored. If your goal is only 95 * to display some HTML as a part of your UI, this is probably fine; 96 * the user won't need to interact with the web page beyond reading 97 * it, and the web page won't need to interact with the user. If you 98 * actually want a full-blown web browser, then you probably want to 99 * invoke the Browser application with a URL Intent rather than show it 100 * with a WebView. For example: 101 * <pre> 102 * Uri uri = Uri.parse("https://www.example.com"); 103 * Intent intent = new Intent(Intent.ACTION_VIEW, uri); 104 * startActivity(intent); 105 * </pre> 106 * <p>See {@link android.content.Intent} for more information.</p> 107 * 108 * <p>To provide a WebView in your own Activity, include a {@code <WebView>} in your layout, 109 * or set the entire Activity window as a WebView during {@link 110 * android.app.Activity#onCreate(Bundle) onCreate()}:</p> 111 * <pre class="prettyprint"> 112 * WebView webview = new WebView(this); 113 * setContentView(webview); 114 * </pre> 115 * 116 * <p>Then load the desired web page:</p> 117 * <pre> 118 * // Simplest usage: note that an exception will NOT be thrown 119 * // if there is an error loading this page (see below). 120 * webview.loadUrl("https://example.com/"); 121 * 122 * // OR, you can also load from an HTML string: 123 * String summary = "<html><body>You scored <b>192</b> points.</body></html>"; 124 * webview.loadData(summary, "text/html", null); 125 * // ... although note that there are restrictions on what this HTML can do. 126 * // See the JavaDocs for {@link #loadData(String,String,String) loadData()} and {@link 127 * #loadDataWithBaseURL(String,String,String,String,String) loadDataWithBaseURL()} for more info. 128 * </pre> 129 * 130 * <p>A WebView has several customization points where you can add your 131 * own behavior. These are:</p> 132 * 133 * <ul> 134 * <li>Creating and setting a {@link android.webkit.WebChromeClient} subclass. 135 * This class is called when something that might impact a 136 * browser UI happens, for instance, progress updates and 137 * JavaScript alerts are sent here (see <a 138 * href="{@docRoot}guide/developing/debug-tasks.html#DebuggingWebPages">Debugging Tasks</a>). 139 * </li> 140 * <li>Creating and setting a {@link android.webkit.WebViewClient} subclass. 141 * It will be called when things happen that impact the 142 * rendering of the content, eg, errors or form submissions. You 143 * can also intercept URL loading here (via {@link 144 * android.webkit.WebViewClient#shouldOverrideUrlLoading(WebView,String) 145 * shouldOverrideUrlLoading()}).</li> 146 * <li>Modifying the {@link android.webkit.WebSettings}, such as 147 * enabling JavaScript with {@link android.webkit.WebSettings#setJavaScriptEnabled(boolean) 148 * setJavaScriptEnabled()}. </li> 149 * <li>Injecting Java objects into the WebView using the 150 * {@link android.webkit.WebView#addJavascriptInterface} method. This 151 * method allows you to inject Java objects into a page's JavaScript 152 * context, so that they can be accessed by JavaScript in the page.</li> 153 * </ul> 154 * 155 * <p>Here's a more complicated example, showing error handling, 156 * settings, and progress notification:</p> 157 * 158 * <pre class="prettyprint"> 159 * // Let's display the progress in the activity title bar, like the 160 * // browser app does. 161 * getWindow().requestFeature(Window.FEATURE_PROGRESS); 162 * 163 * webview.getSettings().setJavaScriptEnabled(true); 164 * 165 * final Activity activity = this; 166 * webview.setWebChromeClient(new WebChromeClient() { 167 * public void onProgressChanged(WebView view, int progress) { 168 * // Activities and WebViews measure progress with different scales. 169 * // The progress meter will automatically disappear when we reach 100% 170 * activity.setProgress(progress * 1000); 171 * } 172 * }); 173 * webview.setWebViewClient(new WebViewClient() { 174 * public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { 175 * Toast.makeText(activity, "Oh no! " + description, Toast.LENGTH_SHORT).show(); 176 * } 177 * }); 178 * 179 * webview.loadUrl("https://developer.android.com/"); 180 * </pre> 181 * 182 * <h3>Zoom</h3> 183 * 184 * <p>To enable the built-in zoom, set 185 * {@link #getSettings() WebSettings}.{@link WebSettings#setBuiltInZoomControls(boolean)} 186 * (introduced in API level {@link android.os.Build.VERSION_CODES#CUPCAKE}).</p> 187 * <p>NOTE: Using zoom if either the height or width is set to 188 * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} may lead to undefined behavior 189 * and should be avoided.</p> 190 * 191 * <h3>Cookie and window management</h3> 192 * 193 * <p>For obvious security reasons, your application has its own 194 * cache, cookie store etc.—it does not share the Browser 195 * application's data. 196 * </p> 197 * 198 * <p>By default, requests by the HTML to open new windows are 199 * ignored. This is true whether they be opened by JavaScript or by 200 * the target attribute on a link. You can customize your 201 * {@link WebChromeClient} to provide your own behavior for opening multiple windows, 202 * and render them in whatever manner you want.</p> 203 * 204 * <p>The standard behavior for an Activity is to be destroyed and 205 * recreated when the device orientation or any other configuration changes. This will cause 206 * the WebView to reload the current page. If you don't want that, you 207 * can set your Activity to handle the {@code orientation} and {@code keyboardHidden} 208 * changes, and then just leave the WebView alone. It'll automatically 209 * re-orient itself as appropriate. Read <a 210 * href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime Changes</a> for 211 * more information about how to handle configuration changes during runtime.</p> 212 * 213 * 214 * <h3>Building web pages to support different screen densities</h3> 215 * 216 * <p>The screen density of a device is based on the screen resolution. A screen with low density 217 * has fewer available pixels per inch, where a screen with high density 218 * has more — sometimes significantly more — pixels per inch. The density of a 219 * screen is important because, other things being equal, a UI element (such as a button) whose 220 * height and width are defined in terms of screen pixels will appear larger on the lower density 221 * screen and smaller on the higher density screen. 222 * For simplicity, Android collapses all actual screen densities into three generalized densities: 223 * high, medium, and low.</p> 224 * <p>By default, WebView scales a web page so that it is drawn at a size that matches the default 225 * appearance on a medium density screen. So, it applies 1.5x scaling on a high density screen 226 * (because its pixels are smaller) and 0.75x scaling on a low density screen (because its pixels 227 * are bigger). 228 * Starting with API level {@link android.os.Build.VERSION_CODES#ECLAIR}, WebView supports DOM, CSS, 229 * and meta tag features to help you (as a web developer) target screens with different screen 230 * densities.</p> 231 * <p>Here's a summary of the features you can use to handle different screen densities:</p> 232 * <ul> 233 * <li>The {@code window.devicePixelRatio} DOM property. The value of this property specifies the 234 * default scaling factor used for the current device. For example, if the value of {@code 235 * window.devicePixelRatio} is "1.0", then the device is considered a medium density (mdpi) device 236 * and default scaling is not applied to the web page; if the value is "1.5", then the device is 237 * considered a high density device (hdpi) and the page content is scaled 1.5x; if the 238 * value is "0.75", then the device is considered a low density device (ldpi) and the content is 239 * scaled 0.75x.</li> 240 * <li>The {@code -webkit-device-pixel-ratio} CSS media query. Use this to specify the screen 241 * densities for which this style sheet is to be used. The corresponding value should be either 242 * "0.75", "1", or "1.5", to indicate that the styles are for devices with low density, medium 243 * density, or high density screens, respectively. For example: 244 * <pre> 245 * <link rel="stylesheet" media="screen and (-webkit-device-pixel-ratio:1.5)" href="hdpi.css" /></pre> 246 * <p>The {@code hdpi.css} stylesheet is only used for devices with a screen pixel ration of 1.5, 247 * which is the high density pixel ratio.</p> 248 * </li> 249 * </ul> 250 * 251 * <h3>HTML5 Video support</h3> 252 * 253 * <p>In order to support inline HTML5 video in your application you need to have hardware 254 * acceleration turned on. 255 * </p> 256 * 257 * <h3>Full screen support</h3> 258 * 259 * <p>In order to support full screen — for video or other HTML content — you need to set a 260 * {@link android.webkit.WebChromeClient} and implement both 261 * {@link WebChromeClient#onShowCustomView(View, WebChromeClient.CustomViewCallback)} 262 * and {@link WebChromeClient#onHideCustomView()}. If the implementation of either of these two methods is 263 * missing then the web contents will not be allowed to enter full screen. Optionally you can implement 264 * {@link WebChromeClient#getVideoLoadingProgressView()} to customize the View displayed whilst a video 265 * is loading. 266 * </p> 267 * 268 * <h3>HTML5 Geolocation API support</h3> 269 * 270 * <p>For applications targeting Android N and later releases 271 * (API level > {@link android.os.Build.VERSION_CODES#M}) the geolocation api is only supported on 272 * secure origins such as https. For such applications requests to geolocation api on non-secure 273 * origins are automatically denied without invoking the corresponding 274 * {@link WebChromeClient#onGeolocationPermissionsShowPrompt(String, GeolocationPermissions.Callback)} 275 * method. 276 * </p> 277 * 278 * <h3>Layout size</h3> 279 * <p> 280 * It is recommended to set the WebView layout height to a fixed value or to 281 * {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT} instead of using 282 * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}. 283 * When using {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT} 284 * for the height none of the WebView's parents should use a 285 * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} layout height since that could result in 286 * incorrect sizing of the views. 287 * </p> 288 * 289 * <p>Setting the WebView's height to {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} 290 * enables the following behaviors: 291 * <ul> 292 * <li>The HTML body layout height is set to a fixed value. This means that elements with a height 293 * relative to the HTML body may not be sized correctly. </li> 294 * <li>For applications targeting {@link android.os.Build.VERSION_CODES#KITKAT} and earlier SDKs the 295 * HTML viewport meta tag will be ignored in order to preserve backwards compatibility. </li> 296 * </ul> 297 * </p> 298 * 299 * <p> 300 * Using a layout width of {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} is not 301 * supported. If such a width is used the WebView will attempt to use the width of the parent 302 * instead. 303 * </p> 304 * 305 * <h3>Metrics</h3> 306 * 307 * <p> 308 * WebView may upload anonymous diagnostic data to Google when the user has consented. This data 309 * helps Google improve WebView. Data is collected on a per-app basis for each app which has 310 * instantiated a WebView. An individual app can opt out of this feature by putting the following 311 * tag in its manifest: 312 * <pre> 313 * <meta-data android:name="android.webkit.WebView.MetricsOptOut" 314 * android:value="true" /> 315 * </pre> 316 * </p> 317 * <p> 318 * Data will only be uploaded for a given app if the user has consented AND the app has not opted 319 * out. 320 * </p> 321 * 322 * <h3>Safe Browsing</h3> 323 * 324 * <p> 325 * If Safe Browsing is enabled, WebView will block malicious URLs and present a warning UI to the 326 * user to allow them to navigate back safely or proceed to the malicious page. 327 * </p> 328 * <p> 329 * The recommended way for apps to enable the feature is putting the following tag in the manifest: 330 * </p> 331 * <p> 332 * <pre> 333 * <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing" 334 * android:value="true" /> 335 * </pre> 336 * </p> 337 * 338 */ 339 // Implementation notes. 340 // The WebView is a thin API class that delegates its public API to a backend WebViewProvider 341 // class instance. WebView extends {@link AbsoluteLayout} for backward compatibility reasons. 342 // Methods are delegated to the provider implementation: all public API methods introduced in this 343 // file are fully delegated, whereas public and protected methods from the View base classes are 344 // only delegated where a specific need exists for them to do so. 345 @Widget 346 public class WebView extends AbsoluteLayout 347 implements ViewTreeObserver.OnGlobalFocusChangeListener, 348 ViewGroup.OnHierarchyChangeListener, ViewDebug.HierarchyHandler { 349 350 private static final String LOGTAG = "WebView"; 351 352 // Throwing an exception for incorrect thread usage if the 353 // build target is JB MR2 or newer. Defaults to false, and is 354 // set in the WebView constructor. 355 private static volatile boolean sEnforceThreadChecking = false; 356 357 /** 358 * Transportation object for returning WebView across thread boundaries. 359 */ 360 public class WebViewTransport { 361 private WebView mWebview; 362 363 /** 364 * Sets the WebView to the transportation object. 365 * 366 * @param webview the WebView to transport 367 */ setWebView(WebView webview)368 public synchronized void setWebView(WebView webview) { 369 mWebview = webview; 370 } 371 372 /** 373 * Gets the WebView object. 374 * 375 * @return the transported WebView object 376 */ getWebView()377 public synchronized WebView getWebView() { 378 return mWebview; 379 } 380 } 381 382 /** 383 * URI scheme for telephone number. 384 */ 385 public static final String SCHEME_TEL = "tel:"; 386 /** 387 * URI scheme for email address. 388 */ 389 public static final String SCHEME_MAILTO = "mailto:"; 390 /** 391 * URI scheme for map address. 392 */ 393 public static final String SCHEME_GEO = "geo:0,0?q="; 394 395 /** 396 * Interface to listen for find results. 397 */ 398 public interface FindListener { 399 /** 400 * Notifies the listener about progress made by a find operation. 401 * 402 * @param activeMatchOrdinal the zero-based ordinal of the currently selected match 403 * @param numberOfMatches how many matches have been found 404 * @param isDoneCounting whether the find operation has actually completed. The listener 405 * may be notified multiple times while the 406 * operation is underway, and the numberOfMatches 407 * value should not be considered final unless 408 * isDoneCounting is true. 409 */ onFindResultReceived(int activeMatchOrdinal, int numberOfMatches, boolean isDoneCounting)410 public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches, 411 boolean isDoneCounting); 412 } 413 414 /** 415 * Callback interface supplied to {@link #postVisualStateCallback} for receiving 416 * notifications about the visual state. 417 */ 418 public static abstract class VisualStateCallback { 419 /** 420 * Invoked when the visual state is ready to be drawn in the next {@link #onDraw}. 421 * 422 * @param requestId The identifier passed to {@link #postVisualStateCallback} when this 423 * callback was posted. 424 */ onComplete(long requestId)425 public abstract void onComplete(long requestId); 426 } 427 428 /** 429 * Interface to listen for new pictures as they change. 430 * 431 * @deprecated This interface is now obsolete. 432 */ 433 @Deprecated 434 public interface PictureListener { 435 /** 436 * Used to provide notification that the WebView's picture has changed. 437 * See {@link WebView#capturePicture} for details of the picture. 438 * 439 * @param view the WebView that owns the picture 440 * @param picture the new picture. Applications targeting 441 * {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2} or above 442 * will always receive a null Picture. 443 * @deprecated Deprecated due to internal changes. 444 */ 445 @Deprecated onNewPicture(WebView view, Picture picture)446 public void onNewPicture(WebView view, Picture picture); 447 } 448 449 public static class HitTestResult { 450 /** 451 * Default HitTestResult, where the target is unknown. 452 */ 453 public static final int UNKNOWN_TYPE = 0; 454 /** 455 * @deprecated This type is no longer used. 456 */ 457 @Deprecated 458 public static final int ANCHOR_TYPE = 1; 459 /** 460 * HitTestResult for hitting a phone number. 461 */ 462 public static final int PHONE_TYPE = 2; 463 /** 464 * HitTestResult for hitting a map address. 465 */ 466 public static final int GEO_TYPE = 3; 467 /** 468 * HitTestResult for hitting an email address. 469 */ 470 public static final int EMAIL_TYPE = 4; 471 /** 472 * HitTestResult for hitting an HTML::img tag. 473 */ 474 public static final int IMAGE_TYPE = 5; 475 /** 476 * @deprecated This type is no longer used. 477 */ 478 @Deprecated 479 public static final int IMAGE_ANCHOR_TYPE = 6; 480 /** 481 * HitTestResult for hitting a HTML::a tag with src=http. 482 */ 483 public static final int SRC_ANCHOR_TYPE = 7; 484 /** 485 * HitTestResult for hitting a HTML::a tag with src=http + HTML::img. 486 */ 487 public static final int SRC_IMAGE_ANCHOR_TYPE = 8; 488 /** 489 * HitTestResult for hitting an edit text area. 490 */ 491 public static final int EDIT_TEXT_TYPE = 9; 492 493 private int mType; 494 private String mExtra; 495 496 /** 497 * @hide Only for use by WebViewProvider implementations 498 */ 499 @SystemApi HitTestResult()500 public HitTestResult() { 501 mType = UNKNOWN_TYPE; 502 } 503 504 /** 505 * @hide Only for use by WebViewProvider implementations 506 */ 507 @SystemApi setType(int type)508 public void setType(int type) { 509 mType = type; 510 } 511 512 /** 513 * @hide Only for use by WebViewProvider implementations 514 */ 515 @SystemApi setExtra(String extra)516 public void setExtra(String extra) { 517 mExtra = extra; 518 } 519 520 /** 521 * Gets the type of the hit test result. See the XXX_TYPE constants 522 * defined in this class. 523 * 524 * @return the type of the hit test result 525 */ getType()526 public int getType() { 527 return mType; 528 } 529 530 /** 531 * Gets additional type-dependant information about the result. See 532 * {@link WebView#getHitTestResult()} for details. May either be null 533 * or contain extra information about this result. 534 * 535 * @return additional type-dependant information about the result 536 */ getExtra()537 public String getExtra() { 538 return mExtra; 539 } 540 } 541 542 /** 543 * Constructs a new WebView with a Context object. 544 * 545 * @param context a Context object used to access application assets 546 */ WebView(Context context)547 public WebView(Context context) { 548 this(context, null); 549 } 550 551 /** 552 * Constructs a new WebView with layout parameters. 553 * 554 * @param context a Context object used to access application assets 555 * @param attrs an AttributeSet passed to our parent 556 */ WebView(Context context, AttributeSet attrs)557 public WebView(Context context, AttributeSet attrs) { 558 this(context, attrs, com.android.internal.R.attr.webViewStyle); 559 } 560 561 /** 562 * Constructs a new WebView with layout parameters and a default style. 563 * 564 * @param context a Context object used to access application assets 565 * @param attrs an AttributeSet passed to our parent 566 * @param defStyleAttr an attribute in the current theme that contains a 567 * reference to a style resource that supplies default values for 568 * the view. Can be 0 to not look for defaults. 569 */ WebView(Context context, AttributeSet attrs, int defStyleAttr)570 public WebView(Context context, AttributeSet attrs, int defStyleAttr) { 571 this(context, attrs, defStyleAttr, 0); 572 } 573 574 /** 575 * Constructs a new WebView with layout parameters and a default style. 576 * 577 * @param context a Context object used to access application assets 578 * @param attrs an AttributeSet passed to our parent 579 * @param defStyleAttr an attribute in the current theme that contains a 580 * reference to a style resource that supplies default values for 581 * the view. Can be 0 to not look for defaults. 582 * @param defStyleRes a resource identifier of a style resource that 583 * supplies default values for the view, used only if 584 * defStyleAttr is 0 or can not be found in the theme. Can be 0 585 * to not look for defaults. 586 */ WebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)587 public WebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 588 this(context, attrs, defStyleAttr, defStyleRes, null, false); 589 } 590 591 /** 592 * Constructs a new WebView with layout parameters and a default style. 593 * 594 * @param context a Context object used to access application assets 595 * @param attrs an AttributeSet passed to our parent 596 * @param defStyleAttr an attribute in the current theme that contains a 597 * reference to a style resource that supplies default values for 598 * the view. Can be 0 to not look for defaults. 599 * @param privateBrowsing whether this WebView will be initialized in 600 * private mode 601 * 602 * @deprecated Private browsing is no longer supported directly via 603 * WebView and will be removed in a future release. Prefer using 604 * {@link WebSettings}, {@link WebViewDatabase}, {@link CookieManager} 605 * and {@link WebStorage} for fine-grained control of privacy data. 606 */ 607 @Deprecated WebView(Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing)608 public WebView(Context context, AttributeSet attrs, int defStyleAttr, 609 boolean privateBrowsing) { 610 this(context, attrs, defStyleAttr, 0, null, privateBrowsing); 611 } 612 613 /** 614 * Constructs a new WebView with layout parameters, a default style and a set 615 * of custom JavaScript interfaces to be added to this WebView at initialization 616 * time. This guarantees that these interfaces will be available when the JS 617 * context is initialized. 618 * 619 * @param context a Context object used to access application assets 620 * @param attrs an AttributeSet passed to our parent 621 * @param defStyleAttr an attribute in the current theme that contains a 622 * reference to a style resource that supplies default values for 623 * the view. Can be 0 to not look for defaults. 624 * @param javaScriptInterfaces a Map of interface names, as keys, and 625 * object implementing those interfaces, as 626 * values 627 * @param privateBrowsing whether this WebView will be initialized in 628 * private mode 629 * @hide This is used internally by dumprendertree, as it requires the JavaScript interfaces to 630 * be added synchronously, before a subsequent loadUrl call takes effect. 631 */ WebView(Context context, AttributeSet attrs, int defStyleAttr, Map<String, Object> javaScriptInterfaces, boolean privateBrowsing)632 protected WebView(Context context, AttributeSet attrs, int defStyleAttr, 633 Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) { 634 this(context, attrs, defStyleAttr, 0, javaScriptInterfaces, privateBrowsing); 635 } 636 637 /** 638 * @hide 639 */ 640 @SuppressWarnings("deprecation") // for super() call into deprecated base class constructor. WebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes, Map<String, Object> javaScriptInterfaces, boolean privateBrowsing)641 protected WebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes, 642 Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) { 643 super(context, attrs, defStyleAttr, defStyleRes); 644 645 // WebView is important by default, unless app developer overrode attribute. 646 if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) { 647 setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES); 648 } 649 650 if (context == null) { 651 throw new IllegalArgumentException("Invalid context argument"); 652 } 653 sEnforceThreadChecking = context.getApplicationInfo().targetSdkVersion >= 654 Build.VERSION_CODES.JELLY_BEAN_MR2; 655 checkThread(); 656 657 ensureProviderCreated(); 658 mProvider.init(javaScriptInterfaces, privateBrowsing); 659 // Post condition of creating a webview is the CookieSyncManager.getInstance() is allowed. 660 CookieSyncManager.setGetInstanceIsAllowed(); 661 } 662 663 /** 664 * Specifies whether the horizontal scrollbar has overlay style. 665 * 666 * @deprecated This method has no effect. 667 * @param overlay true if horizontal scrollbar should have overlay style 668 */ 669 @Deprecated setHorizontalScrollbarOverlay(boolean overlay)670 public void setHorizontalScrollbarOverlay(boolean overlay) { 671 } 672 673 /** 674 * Specifies whether the vertical scrollbar has overlay style. 675 * 676 * @deprecated This method has no effect. 677 * @param overlay true if vertical scrollbar should have overlay style 678 */ 679 @Deprecated setVerticalScrollbarOverlay(boolean overlay)680 public void setVerticalScrollbarOverlay(boolean overlay) { 681 } 682 683 /** 684 * Gets whether horizontal scrollbar has overlay style. 685 * 686 * @deprecated This method is now obsolete. 687 * @return true 688 */ 689 @Deprecated overlayHorizontalScrollbar()690 public boolean overlayHorizontalScrollbar() { 691 // The old implementation defaulted to true, so return true for consistency 692 return true; 693 } 694 695 /** 696 * Gets whether vertical scrollbar has overlay style. 697 * 698 * @deprecated This method is now obsolete. 699 * @return false 700 */ 701 @Deprecated overlayVerticalScrollbar()702 public boolean overlayVerticalScrollbar() { 703 // The old implementation defaulted to false, so return false for consistency 704 return false; 705 } 706 707 /** 708 * Gets the visible height (in pixels) of the embedded title bar (if any). 709 * 710 * @deprecated This method is now obsolete. 711 * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} 712 */ 713 @Deprecated getVisibleTitleHeight()714 public int getVisibleTitleHeight() { 715 checkThread(); 716 return mProvider.getVisibleTitleHeight(); 717 } 718 719 /** 720 * Gets the SSL certificate for the main top-level page or null if there is 721 * no certificate (the site is not secure). 722 * 723 * @return the SSL certificate for the main top-level page 724 */ getCertificate()725 public SslCertificate getCertificate() { 726 checkThread(); 727 return mProvider.getCertificate(); 728 } 729 730 /** 731 * Sets the SSL certificate for the main top-level page. 732 * 733 * @deprecated Calling this function has no useful effect, and will be 734 * ignored in future releases. 735 */ 736 @Deprecated setCertificate(SslCertificate certificate)737 public void setCertificate(SslCertificate certificate) { 738 checkThread(); 739 mProvider.setCertificate(certificate); 740 } 741 742 //------------------------------------------------------------------------- 743 // Methods called by activity 744 //------------------------------------------------------------------------- 745 746 /** 747 * Sets a username and password pair for the specified host. This data is 748 * used by the WebView to autocomplete username and password fields in web 749 * forms. Note that this is unrelated to the credentials used for HTTP 750 * authentication. 751 * 752 * @param host the host that required the credentials 753 * @param username the username for the given host 754 * @param password the password for the given host 755 * @see WebViewDatabase#clearUsernamePassword 756 * @see WebViewDatabase#hasUsernamePassword 757 * @deprecated Saving passwords in WebView will not be supported in future versions. 758 */ 759 @Deprecated savePassword(String host, String username, String password)760 public void savePassword(String host, String username, String password) { 761 checkThread(); 762 mProvider.savePassword(host, username, password); 763 } 764 765 /** 766 * Stores HTTP authentication credentials for a given host and realm to the {@link WebViewDatabase} 767 * instance. 768 * 769 * @param host the host to which the credentials apply 770 * @param realm the realm to which the credentials apply 771 * @param username the username 772 * @param password the password 773 * @deprecated Use {@link WebViewDatabase#setHttpAuthUsernamePassword} instead 774 */ 775 @Deprecated setHttpAuthUsernamePassword(String host, String realm, String username, String password)776 public void setHttpAuthUsernamePassword(String host, String realm, 777 String username, String password) { 778 checkThread(); 779 mProvider.setHttpAuthUsernamePassword(host, realm, username, password); 780 } 781 782 /** 783 * Retrieves HTTP authentication credentials for a given host and realm from the {@link 784 * WebViewDatabase} instance. 785 * @param host the host to which the credentials apply 786 * @param realm the realm to which the credentials apply 787 * @return the credentials as a String array, if found. The first element 788 * is the username and the second element is the password. Null if 789 * no credentials are found. 790 * @deprecated Use {@link WebViewDatabase#getHttpAuthUsernamePassword} instead 791 */ 792 @Deprecated getHttpAuthUsernamePassword(String host, String realm)793 public String[] getHttpAuthUsernamePassword(String host, String realm) { 794 checkThread(); 795 return mProvider.getHttpAuthUsernamePassword(host, realm); 796 } 797 798 /** 799 * Destroys the internal state of this WebView. This method should be called 800 * after this WebView has been removed from the view system. No other 801 * methods may be called on this WebView after destroy. 802 */ destroy()803 public void destroy() { 804 checkThread(); 805 mProvider.destroy(); 806 } 807 808 /** 809 * Enables platform notifications of data state and proxy changes. 810 * Notifications are enabled by default. 811 * 812 * @deprecated This method is now obsolete. 813 * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} 814 */ 815 @Deprecated enablePlatformNotifications()816 public static void enablePlatformNotifications() { 817 // noop 818 } 819 820 /** 821 * Disables platform notifications of data state and proxy changes. 822 * Notifications are enabled by default. 823 * 824 * @deprecated This method is now obsolete. 825 * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} 826 */ 827 @Deprecated disablePlatformNotifications()828 public static void disablePlatformNotifications() { 829 // noop 830 } 831 832 /** 833 * Used only by internal tests to free up memory. 834 * 835 * @hide 836 */ freeMemoryForTests()837 public static void freeMemoryForTests() { 838 getFactory().getStatics().freeMemoryForTests(); 839 } 840 841 /** 842 * Informs WebView of the network state. This is used to set 843 * the JavaScript property window.navigator.isOnline and 844 * generates the online/offline event as specified in HTML5, sec. 5.7.7 845 * 846 * @param networkUp a boolean indicating if network is available 847 */ setNetworkAvailable(boolean networkUp)848 public void setNetworkAvailable(boolean networkUp) { 849 checkThread(); 850 mProvider.setNetworkAvailable(networkUp); 851 } 852 853 /** 854 * Saves the state of this WebView used in 855 * {@link android.app.Activity#onSaveInstanceState}. Please note that this 856 * method no longer stores the display data for this WebView. The previous 857 * behavior could potentially leak files if {@link #restoreState} was never 858 * called. 859 * 860 * @param outState the Bundle to store this WebView's state 861 * @return the same copy of the back/forward list used to save the state. If 862 * saveState fails, the returned list will be null. 863 */ saveState(Bundle outState)864 public WebBackForwardList saveState(Bundle outState) { 865 checkThread(); 866 return mProvider.saveState(outState); 867 } 868 869 /** 870 * Saves the current display data to the Bundle given. Used in conjunction 871 * with {@link #saveState}. 872 * @param b a Bundle to store the display data 873 * @param dest the file to store the serialized picture data. Will be 874 * overwritten with this WebView's picture data. 875 * @return true if the picture was successfully saved 876 * @deprecated This method is now obsolete. 877 * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} 878 */ 879 @Deprecated savePicture(Bundle b, final File dest)880 public boolean savePicture(Bundle b, final File dest) { 881 checkThread(); 882 return mProvider.savePicture(b, dest); 883 } 884 885 /** 886 * Restores the display data that was saved in {@link #savePicture}. Used in 887 * conjunction with {@link #restoreState}. Note that this will not work if 888 * this WebView is hardware accelerated. 889 * 890 * @param b a Bundle containing the saved display data 891 * @param src the file where the picture data was stored 892 * @return true if the picture was successfully restored 893 * @deprecated This method is now obsolete. 894 * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} 895 */ 896 @Deprecated restorePicture(Bundle b, File src)897 public boolean restorePicture(Bundle b, File src) { 898 checkThread(); 899 return mProvider.restorePicture(b, src); 900 } 901 902 /** 903 * Restores the state of this WebView from the given Bundle. This method is 904 * intended for use in {@link android.app.Activity#onRestoreInstanceState} 905 * and should be called to restore the state of this WebView. If 906 * it is called after this WebView has had a chance to build state (load 907 * pages, create a back/forward list, etc.) there may be undesirable 908 * side-effects. Please note that this method no longer restores the 909 * display data for this WebView. 910 * 911 * @param inState the incoming Bundle of state 912 * @return the restored back/forward list or null if restoreState failed 913 */ restoreState(Bundle inState)914 public WebBackForwardList restoreState(Bundle inState) { 915 checkThread(); 916 return mProvider.restoreState(inState); 917 } 918 919 /** 920 * Loads the given URL with the specified additional HTTP headers. 921 * <p> 922 * Also see compatibility note on {@link #evaluateJavascript}. 923 * 924 * @param url the URL of the resource to load 925 * @param additionalHttpHeaders the additional headers to be used in the 926 * HTTP request for this URL, specified as a map from name to 927 * value. Note that if this map contains any of the headers 928 * that are set by default by this WebView, such as those 929 * controlling caching, accept types or the User-Agent, their 930 * values may be overridden by this WebView's defaults. 931 */ loadUrl(String url, Map<String, String> additionalHttpHeaders)932 public void loadUrl(String url, Map<String, String> additionalHttpHeaders) { 933 checkThread(); 934 mProvider.loadUrl(url, additionalHttpHeaders); 935 } 936 937 /** 938 * Loads the given URL. 939 * <p> 940 * Also see compatibility note on {@link #evaluateJavascript}. 941 * 942 * @param url the URL of the resource to load 943 */ loadUrl(String url)944 public void loadUrl(String url) { 945 checkThread(); 946 mProvider.loadUrl(url); 947 } 948 949 /** 950 * Loads the URL with postData using "POST" method into this WebView. If url 951 * is not a network URL, it will be loaded with {@link #loadUrl(String)} 952 * instead, ignoring the postData param. 953 * 954 * @param url the URL of the resource to load 955 * @param postData the data will be passed to "POST" request, which must be 956 * be "application/x-www-form-urlencoded" encoded. 957 */ postUrl(String url, byte[] postData)958 public void postUrl(String url, byte[] postData) { 959 checkThread(); 960 if (URLUtil.isNetworkUrl(url)) { 961 mProvider.postUrl(url, postData); 962 } else { 963 mProvider.loadUrl(url); 964 } 965 } 966 967 /** 968 * Loads the given data into this WebView using a 'data' scheme URL. 969 * <p> 970 * Note that JavaScript's same origin policy means that script running in a 971 * page loaded using this method will be unable to access content loaded 972 * using any scheme other than 'data', including 'http(s)'. To avoid this 973 * restriction, use {@link 974 * #loadDataWithBaseURL(String,String,String,String,String) 975 * loadDataWithBaseURL()} with an appropriate base URL. 976 * <p> 977 * The encoding parameter specifies whether the data is base64 or URL 978 * encoded. If the data is base64 encoded, the value of the encoding 979 * parameter must be 'base64'. For all other values of the parameter, 980 * including null, it is assumed that the data uses ASCII encoding for 981 * octets inside the range of safe URL characters and use the standard %xx 982 * hex encoding of URLs for octets outside that range. For example, '#', 983 * '%', '\', '?' should be replaced by %23, %25, %27, %3f respectively. 984 * <p> 985 * The 'data' scheme URL formed by this method uses the default US-ASCII 986 * charset. If you need need to set a different charset, you should form a 987 * 'data' scheme URL which explicitly specifies a charset parameter in the 988 * mediatype portion of the URL and call {@link #loadUrl(String)} instead. 989 * Note that the charset obtained from the mediatype portion of a data URL 990 * always overrides that specified in the HTML or XML document itself. 991 * 992 * @param data a String of data in the given encoding 993 * @param mimeType the MIME type of the data, e.g. 'text/html' 994 * @param encoding the encoding of the data 995 */ loadData(String data, String mimeType, String encoding)996 public void loadData(String data, String mimeType, String encoding) { 997 checkThread(); 998 mProvider.loadData(data, mimeType, encoding); 999 } 1000 1001 /** 1002 * Loads the given data into this WebView, using baseUrl as the base URL for 1003 * the content. The base URL is used both to resolve relative URLs and when 1004 * applying JavaScript's same origin policy. The historyUrl is used for the 1005 * history entry. 1006 * <p> 1007 * Note that content specified in this way can access local device files 1008 * (via 'file' scheme URLs) only if baseUrl specifies a scheme other than 1009 * 'http', 'https', 'ftp', 'ftps', 'about' or 'javascript'. 1010 * <p> 1011 * If the base URL uses the data scheme, this method is equivalent to 1012 * calling {@link #loadData(String,String,String) loadData()} and the 1013 * historyUrl is ignored, and the data will be treated as part of a data: URL. 1014 * If the base URL uses any other scheme, then the data will be loaded into 1015 * the WebView as a plain string (i.e. not part of a data URL) and any URL-encoded 1016 * entities in the string will not be decoded. 1017 * <p> 1018 * Note that the baseUrl is sent in the 'Referer' HTTP header when 1019 * requesting subresources (images, etc.) of the page loaded using this method. 1020 * 1021 * @param baseUrl the URL to use as the page's base URL. If null defaults to 1022 * 'about:blank'. 1023 * @param data a String of data in the given encoding 1024 * @param mimeType the MIMEType of the data, e.g. 'text/html'. If null, 1025 * defaults to 'text/html'. 1026 * @param encoding the encoding of the data 1027 * @param historyUrl the URL to use as the history entry. If null defaults 1028 * to 'about:blank'. If non-null, this must be a valid URL. 1029 */ loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl)1030 public void loadDataWithBaseURL(String baseUrl, String data, 1031 String mimeType, String encoding, String historyUrl) { 1032 checkThread(); 1033 mProvider.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl); 1034 } 1035 1036 /** 1037 * Asynchronously evaluates JavaScript in the context of the currently displayed page. 1038 * If non-null, |resultCallback| will be invoked with any result returned from that 1039 * execution. This method must be called on the UI thread and the callback will 1040 * be made on the UI thread. 1041 * <p> 1042 * Compatibility note. Applications targeting {@link android.os.Build.VERSION_CODES#N} or 1043 * later, JavaScript state from an empty WebView is no longer persisted across navigations like 1044 * {@link #loadUrl(String)}. For example, global variables and functions defined before calling 1045 * {@link #loadUrl(String)} will not exist in the loaded page. Applications should use 1046 * {@link #addJavascriptInterface} instead to persist JavaScript objects across navigations. 1047 * 1048 * @param script the JavaScript to execute. 1049 * @param resultCallback A callback to be invoked when the script execution 1050 * completes with the result of the execution (if any). 1051 * May be null if no notification of the result is required. 1052 */ evaluateJavascript(String script, ValueCallback<String> resultCallback)1053 public void evaluateJavascript(String script, ValueCallback<String> resultCallback) { 1054 checkThread(); 1055 mProvider.evaluateJavaScript(script, resultCallback); 1056 } 1057 1058 /** 1059 * Saves the current view as a web archive. 1060 * 1061 * @param filename the filename where the archive should be placed 1062 */ saveWebArchive(String filename)1063 public void saveWebArchive(String filename) { 1064 checkThread(); 1065 mProvider.saveWebArchive(filename); 1066 } 1067 1068 /** 1069 * Saves the current view as a web archive. 1070 * 1071 * @param basename the filename where the archive should be placed 1072 * @param autoname if false, takes basename to be a file. If true, basename 1073 * is assumed to be a directory in which a filename will be 1074 * chosen according to the URL of the current page. 1075 * @param callback called after the web archive has been saved. The 1076 * parameter for onReceiveValue will either be the filename 1077 * under which the file was saved, or null if saving the 1078 * file failed. 1079 */ saveWebArchive(String basename, boolean autoname, ValueCallback<String> callback)1080 public void saveWebArchive(String basename, boolean autoname, ValueCallback<String> callback) { 1081 checkThread(); 1082 mProvider.saveWebArchive(basename, autoname, callback); 1083 } 1084 1085 /** 1086 * Stops the current load. 1087 */ stopLoading()1088 public void stopLoading() { 1089 checkThread(); 1090 mProvider.stopLoading(); 1091 } 1092 1093 /** 1094 * Reloads the current URL. 1095 */ reload()1096 public void reload() { 1097 checkThread(); 1098 mProvider.reload(); 1099 } 1100 1101 /** 1102 * Gets whether this WebView has a back history item. 1103 * 1104 * @return true iff this WebView has a back history item 1105 */ canGoBack()1106 public boolean canGoBack() { 1107 checkThread(); 1108 return mProvider.canGoBack(); 1109 } 1110 1111 /** 1112 * Goes back in the history of this WebView. 1113 */ goBack()1114 public void goBack() { 1115 checkThread(); 1116 mProvider.goBack(); 1117 } 1118 1119 /** 1120 * Gets whether this WebView has a forward history item. 1121 * 1122 * @return true iff this WebView has a forward history item 1123 */ canGoForward()1124 public boolean canGoForward() { 1125 checkThread(); 1126 return mProvider.canGoForward(); 1127 } 1128 1129 /** 1130 * Goes forward in the history of this WebView. 1131 */ goForward()1132 public void goForward() { 1133 checkThread(); 1134 mProvider.goForward(); 1135 } 1136 1137 /** 1138 * Gets whether the page can go back or forward the given 1139 * number of steps. 1140 * 1141 * @param steps the negative or positive number of steps to move the 1142 * history 1143 */ canGoBackOrForward(int steps)1144 public boolean canGoBackOrForward(int steps) { 1145 checkThread(); 1146 return mProvider.canGoBackOrForward(steps); 1147 } 1148 1149 /** 1150 * Goes to the history item that is the number of steps away from 1151 * the current item. Steps is negative if backward and positive 1152 * if forward. 1153 * 1154 * @param steps the number of steps to take back or forward in the back 1155 * forward list 1156 */ goBackOrForward(int steps)1157 public void goBackOrForward(int steps) { 1158 checkThread(); 1159 mProvider.goBackOrForward(steps); 1160 } 1161 1162 /** 1163 * Gets whether private browsing is enabled in this WebView. 1164 */ isPrivateBrowsingEnabled()1165 public boolean isPrivateBrowsingEnabled() { 1166 checkThread(); 1167 return mProvider.isPrivateBrowsingEnabled(); 1168 } 1169 1170 /** 1171 * Scrolls the contents of this WebView up by half the view size. 1172 * 1173 * @param top true to jump to the top of the page 1174 * @return true if the page was scrolled 1175 */ pageUp(boolean top)1176 public boolean pageUp(boolean top) { 1177 checkThread(); 1178 return mProvider.pageUp(top); 1179 } 1180 1181 /** 1182 * Scrolls the contents of this WebView down by half the page size. 1183 * 1184 * @param bottom true to jump to bottom of page 1185 * @return true if the page was scrolled 1186 */ pageDown(boolean bottom)1187 public boolean pageDown(boolean bottom) { 1188 checkThread(); 1189 return mProvider.pageDown(bottom); 1190 } 1191 1192 /** 1193 * Posts a {@link VisualStateCallback}, which will be called when 1194 * the current state of the WebView is ready to be drawn. 1195 * 1196 * <p>Because updates to the DOM are processed asynchronously, updates to the DOM may not 1197 * immediately be reflected visually by subsequent {@link WebView#onDraw} invocations. The 1198 * {@link VisualStateCallback} provides a mechanism to notify the caller when the contents of 1199 * the DOM at the current time are ready to be drawn the next time the {@link WebView} 1200 * draws.</p> 1201 * 1202 * <p>The next draw after the callback completes is guaranteed to reflect all the updates to the 1203 * DOM up to the point at which the {@link VisualStateCallback} was posted, but it may also 1204 * contain updates applied after the callback was posted.</p> 1205 * 1206 * <p>The state of the DOM covered by this API includes the following: 1207 * <ul> 1208 * <li>primitive HTML elements (div, img, span, etc..)</li> 1209 * <li>images</li> 1210 * <li>CSS animations</li> 1211 * <li>WebGL</li> 1212 * <li>canvas</li> 1213 * </ul> 1214 * It does not include the state of: 1215 * <ul> 1216 * <li>the video tag</li> 1217 * </ul></p> 1218 * 1219 * <p>To guarantee that the {@link WebView} will successfully render the first frame 1220 * after the {@link VisualStateCallback#onComplete} method has been called a set of conditions 1221 * must be met: 1222 * <ul> 1223 * <li>If the {@link WebView}'s visibility is set to {@link View#VISIBLE VISIBLE} then 1224 * the {@link WebView} must be attached to the view hierarchy.</li> 1225 * <li>If the {@link WebView}'s visibility is set to {@link View#INVISIBLE INVISIBLE} 1226 * then the {@link WebView} must be attached to the view hierarchy and must be made 1227 * {@link View#VISIBLE VISIBLE} from the {@link VisualStateCallback#onComplete} method.</li> 1228 * <li>If the {@link WebView}'s visibility is set to {@link View#GONE GONE} then the 1229 * {@link WebView} must be attached to the view hierarchy and its 1230 * {@link AbsoluteLayout.LayoutParams LayoutParams}'s width and height need to be set to fixed 1231 * values and must be made {@link View#VISIBLE VISIBLE} from the 1232 * {@link VisualStateCallback#onComplete} method.</li> 1233 * </ul></p> 1234 * 1235 * <p>When using this API it is also recommended to enable pre-rasterization if the {@link 1236 * WebView} is off screen to avoid flickering. See {@link WebSettings#setOffscreenPreRaster} for 1237 * more details and do consider its caveats.</p> 1238 * 1239 * @param requestId An id that will be returned in the callback to allow callers to match 1240 * requests with callbacks. 1241 * @param callback The callback to be invoked. 1242 */ postVisualStateCallback(long requestId, VisualStateCallback callback)1243 public void postVisualStateCallback(long requestId, VisualStateCallback callback) { 1244 checkThread(); 1245 mProvider.insertVisualStateCallback(requestId, callback); 1246 } 1247 1248 /** 1249 * Clears this WebView so that onDraw() will draw nothing but white background, 1250 * and onMeasure() will return 0 if MeasureSpec is not MeasureSpec.EXACTLY. 1251 * @deprecated Use WebView.loadUrl("about:blank") to reliably reset the view state 1252 * and release page resources (including any running JavaScript). 1253 */ 1254 @Deprecated clearView()1255 public void clearView() { 1256 checkThread(); 1257 mProvider.clearView(); 1258 } 1259 1260 /** 1261 * Gets a new picture that captures the current contents of this WebView. 1262 * The picture is of the entire document being displayed, and is not 1263 * limited to the area currently displayed by this WebView. Also, the 1264 * picture is a static copy and is unaffected by later changes to the 1265 * content being displayed. 1266 * <p> 1267 * Note that due to internal changes, for API levels between 1268 * {@link android.os.Build.VERSION_CODES#HONEYCOMB} and 1269 * {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH} inclusive, the 1270 * picture does not include fixed position elements or scrollable divs. 1271 * <p> 1272 * Note that from {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} the returned picture 1273 * should only be drawn into bitmap-backed Canvas - using any other type of Canvas will involve 1274 * additional conversion at a cost in memory and performance. Also the 1275 * {@link android.graphics.Picture#createFromStream} and 1276 * {@link android.graphics.Picture#writeToStream} methods are not supported on the 1277 * returned object. 1278 * 1279 * @deprecated Use {@link #onDraw} to obtain a bitmap snapshot of the WebView, or 1280 * {@link #saveWebArchive} to save the content to a file. 1281 * 1282 * @return a picture that captures the current contents of this WebView 1283 */ 1284 @Deprecated capturePicture()1285 public Picture capturePicture() { 1286 checkThread(); 1287 return mProvider.capturePicture(); 1288 } 1289 1290 /** 1291 * @deprecated Use {@link #createPrintDocumentAdapter(String)} which requires user 1292 * to provide a print document name. 1293 */ 1294 @Deprecated createPrintDocumentAdapter()1295 public PrintDocumentAdapter createPrintDocumentAdapter() { 1296 checkThread(); 1297 return mProvider.createPrintDocumentAdapter("default"); 1298 } 1299 1300 /** 1301 * Creates a PrintDocumentAdapter that provides the content of this WebView for printing. 1302 * 1303 * The adapter works by converting the WebView contents to a PDF stream. The WebView cannot 1304 * be drawn during the conversion process - any such draws are undefined. It is recommended 1305 * to use a dedicated off screen WebView for the printing. If necessary, an application may 1306 * temporarily hide a visible WebView by using a custom PrintDocumentAdapter instance 1307 * wrapped around the object returned and observing the onStart and onFinish methods. See 1308 * {@link android.print.PrintDocumentAdapter} for more information. 1309 * 1310 * @param documentName The user-facing name of the printed document. See 1311 * {@link android.print.PrintDocumentInfo} 1312 */ createPrintDocumentAdapter(String documentName)1313 public PrintDocumentAdapter createPrintDocumentAdapter(String documentName) { 1314 checkThread(); 1315 return mProvider.createPrintDocumentAdapter(documentName); 1316 } 1317 1318 /** 1319 * Gets the current scale of this WebView. 1320 * 1321 * @return the current scale 1322 * 1323 * @deprecated This method is prone to inaccuracy due to race conditions 1324 * between the web rendering and UI threads; prefer 1325 * {@link WebViewClient#onScaleChanged}. 1326 */ 1327 @Deprecated 1328 @ViewDebug.ExportedProperty(category = "webview") getScale()1329 public float getScale() { 1330 checkThread(); 1331 return mProvider.getScale(); 1332 } 1333 1334 /** 1335 * Sets the initial scale for this WebView. 0 means default. 1336 * The behavior for the default scale depends on the state of 1337 * {@link WebSettings#getUseWideViewPort()} and 1338 * {@link WebSettings#getLoadWithOverviewMode()}. 1339 * If the content fits into the WebView control by width, then 1340 * the zoom is set to 100%. For wide content, the behavior 1341 * depends on the state of {@link WebSettings#getLoadWithOverviewMode()}. 1342 * If its value is true, the content will be zoomed out to be fit 1343 * by width into the WebView control, otherwise not. 1344 * 1345 * If initial scale is greater than 0, WebView starts with this value 1346 * as initial scale. 1347 * Please note that unlike the scale properties in the viewport meta tag, 1348 * this method doesn't take the screen density into account. 1349 * 1350 * @param scaleInPercent the initial scale in percent 1351 */ setInitialScale(int scaleInPercent)1352 public void setInitialScale(int scaleInPercent) { 1353 checkThread(); 1354 mProvider.setInitialScale(scaleInPercent); 1355 } 1356 1357 /** 1358 * Invokes the graphical zoom picker widget for this WebView. This will 1359 * result in the zoom widget appearing on the screen to control the zoom 1360 * level of this WebView. 1361 */ invokeZoomPicker()1362 public void invokeZoomPicker() { 1363 checkThread(); 1364 mProvider.invokeZoomPicker(); 1365 } 1366 1367 /** 1368 * Gets a HitTestResult based on the current cursor node. If a HTML::a 1369 * tag is found and the anchor has a non-JavaScript URL, the HitTestResult 1370 * type is set to SRC_ANCHOR_TYPE and the URL is set in the "extra" field. 1371 * If the anchor does not have a URL or if it is a JavaScript URL, the type 1372 * will be UNKNOWN_TYPE and the URL has to be retrieved through 1373 * {@link #requestFocusNodeHref} asynchronously. If a HTML::img tag is 1374 * found, the HitTestResult type is set to IMAGE_TYPE and the URL is set in 1375 * the "extra" field. A type of 1376 * SRC_IMAGE_ANCHOR_TYPE indicates an anchor with a URL that has an image as 1377 * a child node. If a phone number is found, the HitTestResult type is set 1378 * to PHONE_TYPE and the phone number is set in the "extra" field of 1379 * HitTestResult. If a map address is found, the HitTestResult type is set 1380 * to GEO_TYPE and the address is set in the "extra" field of HitTestResult. 1381 * If an email address is found, the HitTestResult type is set to EMAIL_TYPE 1382 * and the email is set in the "extra" field of HitTestResult. Otherwise, 1383 * HitTestResult type is set to UNKNOWN_TYPE. 1384 */ getHitTestResult()1385 public HitTestResult getHitTestResult() { 1386 checkThread(); 1387 return mProvider.getHitTestResult(); 1388 } 1389 1390 /** 1391 * Requests the anchor or image element URL at the last tapped point. 1392 * If hrefMsg is null, this method returns immediately and does not 1393 * dispatch hrefMsg to its target. If the tapped point hits an image, 1394 * an anchor, or an image in an anchor, the message associates 1395 * strings in named keys in its data. The value paired with the key 1396 * may be an empty string. 1397 * 1398 * @param hrefMsg the message to be dispatched with the result of the 1399 * request. The message data contains three keys. "url" 1400 * returns the anchor's href attribute. "title" returns the 1401 * anchor's text. "src" returns the image's src attribute. 1402 */ requestFocusNodeHref(Message hrefMsg)1403 public void requestFocusNodeHref(Message hrefMsg) { 1404 checkThread(); 1405 mProvider.requestFocusNodeHref(hrefMsg); 1406 } 1407 1408 /** 1409 * Requests the URL of the image last touched by the user. msg will be sent 1410 * to its target with a String representing the URL as its object. 1411 * 1412 * @param msg the message to be dispatched with the result of the request 1413 * as the data member with "url" as key. The result can be null. 1414 */ requestImageRef(Message msg)1415 public void requestImageRef(Message msg) { 1416 checkThread(); 1417 mProvider.requestImageRef(msg); 1418 } 1419 1420 /** 1421 * Gets the URL for the current page. This is not always the same as the URL 1422 * passed to WebViewClient.onPageStarted because although the load for 1423 * that URL has begun, the current page may not have changed. 1424 * 1425 * @return the URL for the current page 1426 */ 1427 @ViewDebug.ExportedProperty(category = "webview") getUrl()1428 public String getUrl() { 1429 checkThread(); 1430 return mProvider.getUrl(); 1431 } 1432 1433 /** 1434 * Gets the original URL for the current page. This is not always the same 1435 * as the URL passed to WebViewClient.onPageStarted because although the 1436 * load for that URL has begun, the current page may not have changed. 1437 * Also, there may have been redirects resulting in a different URL to that 1438 * originally requested. 1439 * 1440 * @return the URL that was originally requested for the current page 1441 */ 1442 @ViewDebug.ExportedProperty(category = "webview") getOriginalUrl()1443 public String getOriginalUrl() { 1444 checkThread(); 1445 return mProvider.getOriginalUrl(); 1446 } 1447 1448 /** 1449 * Gets the title for the current page. This is the title of the current page 1450 * until WebViewClient.onReceivedTitle is called. 1451 * 1452 * @return the title for the current page 1453 */ 1454 @ViewDebug.ExportedProperty(category = "webview") getTitle()1455 public String getTitle() { 1456 checkThread(); 1457 return mProvider.getTitle(); 1458 } 1459 1460 /** 1461 * Gets the favicon for the current page. This is the favicon of the current 1462 * page until WebViewClient.onReceivedIcon is called. 1463 * 1464 * @return the favicon for the current page 1465 */ getFavicon()1466 public Bitmap getFavicon() { 1467 checkThread(); 1468 return mProvider.getFavicon(); 1469 } 1470 1471 /** 1472 * Gets the touch icon URL for the apple-touch-icon <link> element, or 1473 * a URL on this site's server pointing to the standard location of a 1474 * touch icon. 1475 * 1476 * @hide 1477 */ getTouchIconUrl()1478 public String getTouchIconUrl() { 1479 return mProvider.getTouchIconUrl(); 1480 } 1481 1482 /** 1483 * Gets the progress for the current page. 1484 * 1485 * @return the progress for the current page between 0 and 100 1486 */ getProgress()1487 public int getProgress() { 1488 checkThread(); 1489 return mProvider.getProgress(); 1490 } 1491 1492 /** 1493 * Gets the height of the HTML content. 1494 * 1495 * @return the height of the HTML content 1496 */ 1497 @ViewDebug.ExportedProperty(category = "webview") getContentHeight()1498 public int getContentHeight() { 1499 checkThread(); 1500 return mProvider.getContentHeight(); 1501 } 1502 1503 /** 1504 * Gets the width of the HTML content. 1505 * 1506 * @return the width of the HTML content 1507 * @hide 1508 */ 1509 @ViewDebug.ExportedProperty(category = "webview") getContentWidth()1510 public int getContentWidth() { 1511 return mProvider.getContentWidth(); 1512 } 1513 1514 /** 1515 * Pauses all layout, parsing, and JavaScript timers for all WebViews. This 1516 * is a global requests, not restricted to just this WebView. This can be 1517 * useful if the application has been paused. 1518 */ pauseTimers()1519 public void pauseTimers() { 1520 checkThread(); 1521 mProvider.pauseTimers(); 1522 } 1523 1524 /** 1525 * Resumes all layout, parsing, and JavaScript timers for all WebViews. 1526 * This will resume dispatching all timers. 1527 */ resumeTimers()1528 public void resumeTimers() { 1529 checkThread(); 1530 mProvider.resumeTimers(); 1531 } 1532 1533 /** 1534 * Does a best-effort attempt to pause any processing that can be paused 1535 * safely, such as animations and geolocation. Note that this call 1536 * does not pause JavaScript. To pause JavaScript globally, use 1537 * {@link #pauseTimers}. 1538 * 1539 * To resume WebView, call {@link #onResume}. 1540 */ onPause()1541 public void onPause() { 1542 checkThread(); 1543 mProvider.onPause(); 1544 } 1545 1546 /** 1547 * Resumes a WebView after a previous call to {@link #onPause}. 1548 */ onResume()1549 public void onResume() { 1550 checkThread(); 1551 mProvider.onResume(); 1552 } 1553 1554 /** 1555 * Gets whether this WebView is paused, meaning onPause() was called. 1556 * Calling onResume() sets the paused state back to false. 1557 * 1558 * @hide 1559 */ isPaused()1560 public boolean isPaused() { 1561 return mProvider.isPaused(); 1562 } 1563 1564 /** 1565 * Informs this WebView that memory is low so that it can free any available 1566 * memory. 1567 * @deprecated Memory caches are automatically dropped when no longer needed, and in response 1568 * to system memory pressure. 1569 */ 1570 @Deprecated freeMemory()1571 public void freeMemory() { 1572 checkThread(); 1573 mProvider.freeMemory(); 1574 } 1575 1576 /** 1577 * Clears the resource cache. Note that the cache is per-application, so 1578 * this will clear the cache for all WebViews used. 1579 * 1580 * @param includeDiskFiles if false, only the RAM cache is cleared 1581 */ clearCache(boolean includeDiskFiles)1582 public void clearCache(boolean includeDiskFiles) { 1583 checkThread(); 1584 mProvider.clearCache(includeDiskFiles); 1585 } 1586 1587 /** 1588 * Removes the autocomplete popup from the currently focused form field, if 1589 * present. Note this only affects the display of the autocomplete popup, 1590 * it does not remove any saved form data from this WebView's store. To do 1591 * that, use {@link WebViewDatabase#clearFormData}. 1592 */ clearFormData()1593 public void clearFormData() { 1594 checkThread(); 1595 mProvider.clearFormData(); 1596 } 1597 1598 /** 1599 * Tells this WebView to clear its internal back/forward list. 1600 */ clearHistory()1601 public void clearHistory() { 1602 checkThread(); 1603 mProvider.clearHistory(); 1604 } 1605 1606 /** 1607 * Clears the SSL preferences table stored in response to proceeding with 1608 * SSL certificate errors. 1609 */ clearSslPreferences()1610 public void clearSslPreferences() { 1611 checkThread(); 1612 mProvider.clearSslPreferences(); 1613 } 1614 1615 /** 1616 * Clears the client certificate preferences stored in response 1617 * to proceeding/cancelling client cert requests. Note that WebView 1618 * automatically clears these preferences when it receives a 1619 * {@link KeyChain#ACTION_STORAGE_CHANGED} intent. The preferences are 1620 * shared by all the WebViews that are created by the embedder application. 1621 * 1622 * @param onCleared A runnable to be invoked when client certs are cleared. 1623 * The embedder can pass null if not interested in the 1624 * callback. The runnable will be called in UI thread. 1625 */ clearClientCertPreferences(Runnable onCleared)1626 public static void clearClientCertPreferences(Runnable onCleared) { 1627 getFactory().getStatics().clearClientCertPreferences(onCleared); 1628 } 1629 1630 /** 1631 * Starts Safe Browsing initialization. 1632 * <p> 1633 * URL loads are not guaranteed to be protected by Safe Browsing until after {@code callback} is 1634 * invoked with {@code true}. Safe Browsing is not fully supported on all devices. For those 1635 * devices {@code callback} will receive {@code false}. 1636 * <p> 1637 * This does not enable the Safe Browsing feature itself, and should only be called if Safe 1638 * Browsing is enabled by the manifest tag or {@link WebSettings#setSafeBrowsingEnabled}. This 1639 * prepares resources used for Safe Browsing. 1640 * <p> 1641 * This should be called with the Application Context (and will always use the Application 1642 * context to do its work regardless). 1643 * 1644 * @param context Application Context. 1645 * @param callback will be called on the UI thread with {@code true} if initialization is 1646 * successful, {@code false} otherwise. 1647 */ startSafeBrowsing(Context context, ValueCallback<Boolean> callback)1648 public static void startSafeBrowsing(Context context, ValueCallback<Boolean> callback) { 1649 getFactory().getStatics().initSafeBrowsing(context, callback); 1650 } 1651 1652 /** 1653 * Sets the list of domains that are exempt from SafeBrowsing checks. The list is 1654 * global for all the WebViews. 1655 * <p> 1656 * Each rule should take one of these: 1657 * <table> 1658 * <tr><th> Rule </th> <th> Example </th> <th> Matches Subdomain</th> </tr> 1659 * <tr><td> HOSTNAME </td> <td> example.com </td> <td> Yes </td> </tr> 1660 * <tr><td> .HOSTNAME </td> <td> .example.com </td> <td> No </td> </tr> 1661 * <tr><td> IPV4_LITERAL </td> <td> 192.168.1.1 </td> <td> No </td></tr> 1662 * <tr><td> IPV6_LITERAL_WITH_BRACKETS </td><td>[10:20:30:40:50:60:70:80]</td><td>No</td></tr> 1663 * </table> 1664 * <p> 1665 * All other rules, including wildcards, are invalid. 1666 * 1667 * @param urls the list of URLs 1668 * @param callback will be called with true if URLs are successfully added to the whitelist. 1669 * It will be called with false if any URLs are malformed. The callback will be run on 1670 * the UI thread 1671 */ setSafeBrowsingWhitelist(@onNull List<String> urls, @Nullable ValueCallback<Boolean> callback)1672 public static void setSafeBrowsingWhitelist(@NonNull List<String> urls, 1673 @Nullable ValueCallback<Boolean> callback) { 1674 getFactory().getStatics().setSafeBrowsingWhitelist(urls, callback); 1675 } 1676 1677 /** 1678 * Returns a URL pointing to the privacy policy for Safe Browsing reporting. 1679 * 1680 * @return the url pointing to a privacy policy document which can be displayed to users. 1681 */ 1682 @NonNull getSafeBrowsingPrivacyPolicyUrl()1683 public static Uri getSafeBrowsingPrivacyPolicyUrl() { 1684 return getFactory().getStatics().getSafeBrowsingPrivacyPolicyUrl(); 1685 } 1686 1687 /** 1688 * Gets the WebBackForwardList for this WebView. This contains the 1689 * back/forward list for use in querying each item in the history stack. 1690 * This is a copy of the private WebBackForwardList so it contains only a 1691 * snapshot of the current state. Multiple calls to this method may return 1692 * different objects. The object returned from this method will not be 1693 * updated to reflect any new state. 1694 */ copyBackForwardList()1695 public WebBackForwardList copyBackForwardList() { 1696 checkThread(); 1697 return mProvider.copyBackForwardList(); 1698 1699 } 1700 1701 /** 1702 * Registers the listener to be notified as find-on-page operations 1703 * progress. This will replace the current listener. 1704 * 1705 * @param listener an implementation of {@link FindListener} 1706 */ setFindListener(FindListener listener)1707 public void setFindListener(FindListener listener) { 1708 checkThread(); 1709 setupFindListenerIfNeeded(); 1710 mFindListener.mUserFindListener = listener; 1711 } 1712 1713 /** 1714 * Highlights and scrolls to the next match found by 1715 * {@link #findAllAsync}, wrapping around page boundaries as necessary. 1716 * Notifies any registered {@link FindListener}. If {@link #findAllAsync(String)} 1717 * has not been called yet, or if {@link #clearMatches} has been called since the 1718 * last find operation, this function does nothing. 1719 * 1720 * @param forward the direction to search 1721 * @see #setFindListener 1722 */ findNext(boolean forward)1723 public void findNext(boolean forward) { 1724 checkThread(); 1725 mProvider.findNext(forward); 1726 } 1727 1728 /** 1729 * Finds all instances of find on the page and highlights them. 1730 * Notifies any registered {@link FindListener}. 1731 * 1732 * @param find the string to find 1733 * @return the number of occurrences of the String "find" that were found 1734 * @deprecated {@link #findAllAsync} is preferred. 1735 * @see #setFindListener 1736 */ 1737 @Deprecated findAll(String find)1738 public int findAll(String find) { 1739 checkThread(); 1740 StrictMode.noteSlowCall("findAll blocks UI: prefer findAllAsync"); 1741 return mProvider.findAll(find); 1742 } 1743 1744 /** 1745 * Finds all instances of find on the page and highlights them, 1746 * asynchronously. Notifies any registered {@link FindListener}. 1747 * Successive calls to this will cancel any pending searches. 1748 * 1749 * @param find the string to find. 1750 * @see #setFindListener 1751 */ findAllAsync(String find)1752 public void findAllAsync(String find) { 1753 checkThread(); 1754 mProvider.findAllAsync(find); 1755 } 1756 1757 /** 1758 * Starts an ActionMode for finding text in this WebView. Only works if this 1759 * WebView is attached to the view system. 1760 * 1761 * @param text if non-null, will be the initial text to search for. 1762 * Otherwise, the last String searched for in this WebView will 1763 * be used to start. 1764 * @param showIme if true, show the IME, assuming the user will begin typing. 1765 * If false and text is non-null, perform a find all. 1766 * @return true if the find dialog is shown, false otherwise 1767 * @deprecated This method does not work reliably on all Android versions; 1768 * implementing a custom find dialog using WebView.findAllAsync() 1769 * provides a more robust solution. 1770 */ 1771 @Deprecated showFindDialog(String text, boolean showIme)1772 public boolean showFindDialog(String text, boolean showIme) { 1773 checkThread(); 1774 return mProvider.showFindDialog(text, showIme); 1775 } 1776 1777 /** 1778 * Gets the first substring consisting of the address of a physical 1779 * location. Currently, only addresses in the United States are detected, 1780 * and consist of: 1781 * <ul> 1782 * <li>a house number</li> 1783 * <li>a street name</li> 1784 * <li>a street type (Road, Circle, etc), either spelled out or 1785 * abbreviated</li> 1786 * <li>a city name</li> 1787 * <li>a state or territory, either spelled out or two-letter abbr</li> 1788 * <li>an optional 5 digit or 9 digit zip code</li> 1789 * </ul> 1790 * All names must be correctly capitalized, and the zip code, if present, 1791 * must be valid for the state. The street type must be a standard USPS 1792 * spelling or abbreviation. The state or territory must also be spelled 1793 * or abbreviated using USPS standards. The house number may not exceed 1794 * five digits. 1795 * 1796 * @param addr the string to search for addresses 1797 * @return the address, or if no address is found, null 1798 */ findAddress(String addr)1799 public static String findAddress(String addr) { 1800 // TODO: Rewrite this in Java so it is not needed to start up chromium 1801 // Could also be deprecated 1802 return getFactory().getStatics().findAddress(addr); 1803 } 1804 1805 /** 1806 * For apps targeting the L release, WebView has a new default behavior that reduces 1807 * memory footprint and increases performance by intelligently choosing 1808 * the portion of the HTML document that needs to be drawn. These 1809 * optimizations are transparent to the developers. However, under certain 1810 * circumstances, an App developer may want to disable them: 1811 * <ol> 1812 * <li>When an app uses {@link #onDraw} to do own drawing and accesses portions 1813 * of the page that is way outside the visible portion of the page.</li> 1814 * <li>When an app uses {@link #capturePicture} to capture a very large HTML document. 1815 * Note that capturePicture is a deprecated API.</li> 1816 * </ol> 1817 * Enabling drawing the entire HTML document has a significant performance 1818 * cost. This method should be called before any WebViews are created. 1819 */ enableSlowWholeDocumentDraw()1820 public static void enableSlowWholeDocumentDraw() { 1821 getFactory().getStatics().enableSlowWholeDocumentDraw(); 1822 } 1823 1824 /** 1825 * Clears the highlighting surrounding text matches created by 1826 * {@link #findAllAsync}. 1827 */ clearMatches()1828 public void clearMatches() { 1829 checkThread(); 1830 mProvider.clearMatches(); 1831 } 1832 1833 /** 1834 * Queries the document to see if it contains any image references. The 1835 * message object will be dispatched with arg1 being set to 1 if images 1836 * were found and 0 if the document does not reference any images. 1837 * 1838 * @param response the message that will be dispatched with the result 1839 */ documentHasImages(Message response)1840 public void documentHasImages(Message response) { 1841 checkThread(); 1842 mProvider.documentHasImages(response); 1843 } 1844 1845 /** 1846 * Sets the WebViewClient that will receive various notifications and 1847 * requests. This will replace the current handler. 1848 * 1849 * @param client an implementation of WebViewClient 1850 * @see #getWebViewClient 1851 */ setWebViewClient(WebViewClient client)1852 public void setWebViewClient(WebViewClient client) { 1853 checkThread(); 1854 mProvider.setWebViewClient(client); 1855 } 1856 1857 /** 1858 * Gets the WebViewClient. 1859 * 1860 * @return the WebViewClient, or a default client if not yet set 1861 * @see #setWebViewClient 1862 */ getWebViewClient()1863 public WebViewClient getWebViewClient() { 1864 checkThread(); 1865 return mProvider.getWebViewClient(); 1866 } 1867 1868 /** 1869 * Registers the interface to be used when content can not be handled by 1870 * the rendering engine, and should be downloaded instead. This will replace 1871 * the current handler. 1872 * 1873 * @param listener an implementation of DownloadListener 1874 */ setDownloadListener(DownloadListener listener)1875 public void setDownloadListener(DownloadListener listener) { 1876 checkThread(); 1877 mProvider.setDownloadListener(listener); 1878 } 1879 1880 /** 1881 * Sets the chrome handler. This is an implementation of WebChromeClient for 1882 * use in handling JavaScript dialogs, favicons, titles, and the progress. 1883 * This will replace the current handler. 1884 * 1885 * @param client an implementation of WebChromeClient 1886 * @see #getWebChromeClient 1887 */ setWebChromeClient(WebChromeClient client)1888 public void setWebChromeClient(WebChromeClient client) { 1889 checkThread(); 1890 mProvider.setWebChromeClient(client); 1891 } 1892 1893 /** 1894 * Gets the chrome handler. 1895 * 1896 * @return the WebChromeClient, or null if not yet set 1897 * @see #setWebChromeClient 1898 */ getWebChromeClient()1899 public WebChromeClient getWebChromeClient() { 1900 checkThread(); 1901 return mProvider.getWebChromeClient(); 1902 } 1903 1904 /** 1905 * Sets the Picture listener. This is an interface used to receive 1906 * notifications of a new Picture. 1907 * 1908 * @param listener an implementation of WebView.PictureListener 1909 * @deprecated This method is now obsolete. 1910 */ 1911 @Deprecated setPictureListener(PictureListener listener)1912 public void setPictureListener(PictureListener listener) { 1913 checkThread(); 1914 mProvider.setPictureListener(listener); 1915 } 1916 1917 /** 1918 * Injects the supplied Java object into this WebView. The object is 1919 * injected into the JavaScript context of the main frame, using the 1920 * supplied name. This allows the Java object's methods to be 1921 * accessed from JavaScript. For applications targeted to API 1922 * level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} 1923 * and above, only public methods that are annotated with 1924 * {@link android.webkit.JavascriptInterface} can be accessed from JavaScript. 1925 * For applications targeted to API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN} or below, 1926 * all public methods (including the inherited ones) can be accessed, see the 1927 * important security note below for implications. 1928 * <p> Note that injected objects will not appear in JavaScript until the page is next 1929 * (re)loaded. JavaScript should be enabled before injecting the object. For example: 1930 * <pre> 1931 * class JsObject { 1932 * {@literal @}JavascriptInterface 1933 * public String toString() { return "injectedObject"; } 1934 * } 1935 * webview.getSettings().setJavaScriptEnabled(true); 1936 * webView.addJavascriptInterface(new JsObject(), "injectedObject"); 1937 * webView.loadData("<!DOCTYPE html><title></title>", "text/html", null); 1938 * webView.loadUrl("javascript:alert(injectedObject.toString())");</pre> 1939 * <p> 1940 * <strong>IMPORTANT:</strong> 1941 * <ul> 1942 * <li> This method can be used to allow JavaScript to control the host 1943 * application. This is a powerful feature, but also presents a security 1944 * risk for apps targeting {@link android.os.Build.VERSION_CODES#JELLY_BEAN} or earlier. 1945 * Apps that target a version later than {@link android.os.Build.VERSION_CODES#JELLY_BEAN} 1946 * are still vulnerable if the app runs on a device running Android earlier than 4.2. 1947 * The most secure way to use this method is to target {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} 1948 * and to ensure the method is called only when running on Android 4.2 or later. 1949 * With these older versions, JavaScript could use reflection to access an 1950 * injected object's public fields. Use of this method in a WebView 1951 * containing untrusted content could allow an attacker to manipulate the 1952 * host application in unintended ways, executing Java code with the 1953 * permissions of the host application. Use extreme care when using this 1954 * method in a WebView which could contain untrusted content.</li> 1955 * <li> JavaScript interacts with Java object on a private, background 1956 * thread of this WebView. Care is therefore required to maintain thread 1957 * safety. 1958 * </li> 1959 * <li> The Java object's fields are not accessible.</li> 1960 * <li> For applications targeted to API level {@link android.os.Build.VERSION_CODES#LOLLIPOP} 1961 * and above, methods of injected Java objects are enumerable from 1962 * JavaScript.</li> 1963 * </ul> 1964 * 1965 * @param object the Java object to inject into this WebView's JavaScript 1966 * context. Null values are ignored. 1967 * @param name the name used to expose the object in JavaScript 1968 */ addJavascriptInterface(Object object, String name)1969 public void addJavascriptInterface(Object object, String name) { 1970 checkThread(); 1971 mProvider.addJavascriptInterface(object, name); 1972 } 1973 1974 /** 1975 * Removes a previously injected Java object from this WebView. Note that 1976 * the removal will not be reflected in JavaScript until the page is next 1977 * (re)loaded. See {@link #addJavascriptInterface}. 1978 * 1979 * @param name the name used to expose the object in JavaScript 1980 */ removeJavascriptInterface(String name)1981 public void removeJavascriptInterface(String name) { 1982 checkThread(); 1983 mProvider.removeJavascriptInterface(name); 1984 } 1985 1986 /** 1987 * Creates a message channel to communicate with JS and returns the message 1988 * ports that represent the endpoints of this message channel. The HTML5 message 1989 * channel functionality is described 1990 * <a href="https://html.spec.whatwg.org/multipage/comms.html#messagechannel">here 1991 * </a> 1992 * 1993 * <p>The returned message channels are entangled and already in started state.</p> 1994 * 1995 * @return the two message ports that form the message channel. 1996 */ createWebMessageChannel()1997 public WebMessagePort[] createWebMessageChannel() { 1998 checkThread(); 1999 return mProvider.createWebMessageChannel(); 2000 } 2001 2002 /** 2003 * Post a message to main frame. The embedded application can restrict the 2004 * messages to a certain target origin. See 2005 * <a href="https://html.spec.whatwg.org/multipage/comms.html#posting-messages"> 2006 * HTML5 spec</a> for how target origin can be used. 2007 * <p> 2008 * A target origin can be set as a wildcard ("*"). However this is not recommended. 2009 * See the page above for security issues. 2010 * 2011 * @param message the WebMessage 2012 * @param targetOrigin the target origin. 2013 */ postWebMessage(WebMessage message, Uri targetOrigin)2014 public void postWebMessage(WebMessage message, Uri targetOrigin) { 2015 checkThread(); 2016 mProvider.postMessageToMainFrame(message, targetOrigin); 2017 } 2018 2019 /** 2020 * Gets the WebSettings object used to control the settings for this 2021 * WebView. 2022 * 2023 * @return a WebSettings object that can be used to control this WebView's 2024 * settings 2025 */ getSettings()2026 public WebSettings getSettings() { 2027 checkThread(); 2028 return mProvider.getSettings(); 2029 } 2030 2031 /** 2032 * Enables debugging of web contents (HTML / CSS / JavaScript) 2033 * loaded into any WebViews of this application. This flag can be enabled 2034 * in order to facilitate debugging of web layouts and JavaScript 2035 * code running inside WebViews. Please refer to WebView documentation 2036 * for the debugging guide. 2037 * 2038 * The default is false. 2039 * 2040 * @param enabled whether to enable web contents debugging 2041 */ setWebContentsDebuggingEnabled(boolean enabled)2042 public static void setWebContentsDebuggingEnabled(boolean enabled) { 2043 getFactory().getStatics().setWebContentsDebuggingEnabled(enabled); 2044 } 2045 2046 /** 2047 * Gets the list of currently loaded plugins. 2048 * 2049 * @return the list of currently loaded plugins 2050 * @deprecated This was used for Gears, which has been deprecated. 2051 * @hide 2052 */ 2053 @Deprecated getPluginList()2054 public static synchronized PluginList getPluginList() { 2055 return new PluginList(); 2056 } 2057 2058 /** 2059 * @deprecated This was used for Gears, which has been deprecated. 2060 * @hide 2061 */ 2062 @Deprecated refreshPlugins(boolean reloadOpenPages)2063 public void refreshPlugins(boolean reloadOpenPages) { 2064 checkThread(); 2065 } 2066 2067 /** 2068 * Puts this WebView into text selection mode. Do not rely on this 2069 * functionality; it will be deprecated in the future. 2070 * 2071 * @deprecated This method is now obsolete. 2072 * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} 2073 */ 2074 @Deprecated emulateShiftHeld()2075 public void emulateShiftHeld() { 2076 checkThread(); 2077 } 2078 2079 /** 2080 * @deprecated WebView no longer needs to implement 2081 * ViewGroup.OnHierarchyChangeListener. This method does nothing now. 2082 */ 2083 @Override 2084 // Cannot add @hide as this can always be accessed via the interface. 2085 @Deprecated onChildViewAdded(View parent, View child)2086 public void onChildViewAdded(View parent, View child) {} 2087 2088 /** 2089 * @deprecated WebView no longer needs to implement 2090 * ViewGroup.OnHierarchyChangeListener. This method does nothing now. 2091 */ 2092 @Override 2093 // Cannot add @hide as this can always be accessed via the interface. 2094 @Deprecated onChildViewRemoved(View p, View child)2095 public void onChildViewRemoved(View p, View child) {} 2096 2097 /** 2098 * @deprecated WebView should not have implemented 2099 * ViewTreeObserver.OnGlobalFocusChangeListener. This method does nothing now. 2100 */ 2101 @Override 2102 // Cannot add @hide as this can always be accessed via the interface. 2103 @Deprecated onGlobalFocusChanged(View oldFocus, View newFocus)2104 public void onGlobalFocusChanged(View oldFocus, View newFocus) { 2105 } 2106 2107 /** 2108 * @deprecated Only the default case, true, will be supported in a future version. 2109 */ 2110 @Deprecated setMapTrackballToArrowKeys(boolean setMap)2111 public void setMapTrackballToArrowKeys(boolean setMap) { 2112 checkThread(); 2113 mProvider.setMapTrackballToArrowKeys(setMap); 2114 } 2115 2116 flingScroll(int vx, int vy)2117 public void flingScroll(int vx, int vy) { 2118 checkThread(); 2119 mProvider.flingScroll(vx, vy); 2120 } 2121 2122 /** 2123 * Gets the zoom controls for this WebView, as a separate View. The caller 2124 * is responsible for inserting this View into the layout hierarchy. 2125 * <p/> 2126 * API level {@link android.os.Build.VERSION_CODES#CUPCAKE} introduced 2127 * built-in zoom mechanisms for the WebView, as opposed to these separate 2128 * zoom controls. The built-in mechanisms are preferred and can be enabled 2129 * using {@link WebSettings#setBuiltInZoomControls}. 2130 * 2131 * @deprecated the built-in zoom mechanisms are preferred 2132 * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN} 2133 */ 2134 @Deprecated getZoomControls()2135 public View getZoomControls() { 2136 checkThread(); 2137 return mProvider.getZoomControls(); 2138 } 2139 2140 /** 2141 * Gets whether this WebView can be zoomed in. 2142 * 2143 * @return true if this WebView can be zoomed in 2144 * 2145 * @deprecated This method is prone to inaccuracy due to race conditions 2146 * between the web rendering and UI threads; prefer 2147 * {@link WebViewClient#onScaleChanged}. 2148 */ 2149 @Deprecated canZoomIn()2150 public boolean canZoomIn() { 2151 checkThread(); 2152 return mProvider.canZoomIn(); 2153 } 2154 2155 /** 2156 * Gets whether this WebView can be zoomed out. 2157 * 2158 * @return true if this WebView can be zoomed out 2159 * 2160 * @deprecated This method is prone to inaccuracy due to race conditions 2161 * between the web rendering and UI threads; prefer 2162 * {@link WebViewClient#onScaleChanged}. 2163 */ 2164 @Deprecated canZoomOut()2165 public boolean canZoomOut() { 2166 checkThread(); 2167 return mProvider.canZoomOut(); 2168 } 2169 2170 /** 2171 * Performs a zoom operation in this WebView. 2172 * 2173 * @param zoomFactor the zoom factor to apply. The zoom factor will be clamped to the WebView's 2174 * zoom limits. This value must be in the range 0.01 to 100.0 inclusive. 2175 */ zoomBy(float zoomFactor)2176 public void zoomBy(float zoomFactor) { 2177 checkThread(); 2178 if (zoomFactor < 0.01) 2179 throw new IllegalArgumentException("zoomFactor must be greater than 0.01."); 2180 if (zoomFactor > 100.0) 2181 throw new IllegalArgumentException("zoomFactor must be less than 100."); 2182 mProvider.zoomBy(zoomFactor); 2183 } 2184 2185 /** 2186 * Performs zoom in in this WebView. 2187 * 2188 * @return true if zoom in succeeds, false if no zoom changes 2189 */ zoomIn()2190 public boolean zoomIn() { 2191 checkThread(); 2192 return mProvider.zoomIn(); 2193 } 2194 2195 /** 2196 * Performs zoom out in this WebView. 2197 * 2198 * @return true if zoom out succeeds, false if no zoom changes 2199 */ zoomOut()2200 public boolean zoomOut() { 2201 checkThread(); 2202 return mProvider.zoomOut(); 2203 } 2204 2205 /** 2206 * @deprecated This method is now obsolete. 2207 * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} 2208 */ 2209 @Deprecated debugDump()2210 public void debugDump() { 2211 checkThread(); 2212 } 2213 2214 /** 2215 * See {@link ViewDebug.HierarchyHandler#dumpViewHierarchyWithProperties(BufferedWriter, int)} 2216 * @hide 2217 */ 2218 @Override dumpViewHierarchyWithProperties(BufferedWriter out, int level)2219 public void dumpViewHierarchyWithProperties(BufferedWriter out, int level) { 2220 mProvider.dumpViewHierarchyWithProperties(out, level); 2221 } 2222 2223 /** 2224 * See {@link ViewDebug.HierarchyHandler#findHierarchyView(String, int)} 2225 * @hide 2226 */ 2227 @Override findHierarchyView(String className, int hashCode)2228 public View findHierarchyView(String className, int hashCode) { 2229 return mProvider.findHierarchyView(className, hashCode); 2230 } 2231 2232 /** @hide */ 2233 @IntDef({ 2234 RENDERER_PRIORITY_WAIVED, 2235 RENDERER_PRIORITY_BOUND, 2236 RENDERER_PRIORITY_IMPORTANT 2237 }) 2238 @Retention(RetentionPolicy.SOURCE) 2239 public @interface RendererPriority {} 2240 2241 /** 2242 * The renderer associated with this WebView is bound with 2243 * {@link Context#BIND_WAIVE_PRIORITY}. At this priority level 2244 * {@link WebView} renderers will be strong targets for out of memory 2245 * killing. 2246 * 2247 * Use with {@link #setRendererPriorityPolicy}. 2248 */ 2249 public static final int RENDERER_PRIORITY_WAIVED = 0; 2250 /** 2251 * The renderer associated with this WebView is bound with 2252 * the default priority for services. 2253 * 2254 * Use with {@link #setRendererPriorityPolicy}. 2255 */ 2256 public static final int RENDERER_PRIORITY_BOUND = 1; 2257 /** 2258 * The renderer associated with this WebView is bound with 2259 * {@link Context#BIND_IMPORTANT}. 2260 * 2261 * Use with {@link #setRendererPriorityPolicy}. 2262 */ 2263 public static final int RENDERER_PRIORITY_IMPORTANT = 2; 2264 2265 /** 2266 * Set the renderer priority policy for this {@link WebView}. The 2267 * priority policy will be used to determine whether an out of 2268 * process renderer should be considered to be a target for OOM 2269 * killing. 2270 * 2271 * Because a renderer can be associated with more than one 2272 * WebView, the final priority it is computed as the maximum of 2273 * any attached WebViews. When a WebView is destroyed it will 2274 * cease to be considerered when calculating the renderer 2275 * priority. Once no WebViews remain associated with the renderer, 2276 * the priority of the renderer will be reduced to 2277 * {@link #RENDERER_PRIORITY_WAIVED}. 2278 * 2279 * The default policy is to set the priority to 2280 * {@link #RENDERER_PRIORITY_IMPORTANT} regardless of visibility, 2281 * and this should not be changed unless the caller also handles 2282 * renderer crashes with 2283 * {@link WebViewClient#onRenderProcessGone}. Any other setting 2284 * will result in WebView renderers being killed by the system 2285 * more aggressively than the application. 2286 * 2287 * @param rendererRequestedPriority the minimum priority at which 2288 * this WebView desires the renderer process to be bound. 2289 * @param waivedWhenNotVisible if true, this flag specifies that 2290 * when this WebView is not visible, it will be treated as 2291 * if it had requested a priority of 2292 * {@link #RENDERER_PRIORITY_WAIVED}. 2293 */ setRendererPriorityPolicy( @endererPriority int rendererRequestedPriority, boolean waivedWhenNotVisible)2294 public void setRendererPriorityPolicy( 2295 @RendererPriority int rendererRequestedPriority, 2296 boolean waivedWhenNotVisible) { 2297 mProvider.setRendererPriorityPolicy(rendererRequestedPriority, waivedWhenNotVisible); 2298 } 2299 2300 /** 2301 * Get the requested renderer priority for this WebView. 2302 * 2303 * @return the requested renderer priority policy. 2304 */ 2305 @RendererPriority getRendererRequestedPriority()2306 public int getRendererRequestedPriority() { 2307 return mProvider.getRendererRequestedPriority(); 2308 } 2309 2310 /** 2311 * Return whether this WebView requests a priority of 2312 * {@link #RENDERER_PRIORITY_WAIVED} when not visible. 2313 * 2314 * @return whether this WebView requests a priority of 2315 * {@link #RENDERER_PRIORITY_WAIVED} when not visible. 2316 */ getRendererPriorityWaivedWhenNotVisible()2317 public boolean getRendererPriorityWaivedWhenNotVisible() { 2318 return mProvider.getRendererPriorityWaivedWhenNotVisible(); 2319 } 2320 2321 /** 2322 * Sets the {@link TextClassifier} for this WebView. 2323 */ setTextClassifier(@ullable TextClassifier textClassifier)2324 public void setTextClassifier(@Nullable TextClassifier textClassifier) { 2325 mProvider.setTextClassifier(textClassifier); 2326 } 2327 2328 /** 2329 * Returns the {@link TextClassifier} used by this WebView. 2330 * If no TextClassifier has been set, this WebView uses the default set by the system. 2331 */ 2332 @NonNull getTextClassifier()2333 public TextClassifier getTextClassifier() { 2334 return mProvider.getTextClassifier(); 2335 } 2336 2337 //------------------------------------------------------------------------- 2338 // Interface for WebView providers 2339 //------------------------------------------------------------------------- 2340 2341 /** 2342 * Gets the WebViewProvider. Used by providers to obtain the underlying 2343 * implementation, e.g. when the application responds to 2344 * WebViewClient.onCreateWindow() request. 2345 * 2346 * @hide WebViewProvider is not public API. 2347 */ 2348 @SystemApi getWebViewProvider()2349 public WebViewProvider getWebViewProvider() { 2350 return mProvider; 2351 } 2352 2353 /** 2354 * Callback interface, allows the provider implementation to access non-public methods 2355 * and fields, and make super-class calls in this WebView instance. 2356 * @hide Only for use by WebViewProvider implementations 2357 */ 2358 @SystemApi 2359 public class PrivateAccess { 2360 // ---- Access to super-class methods ---- super_getScrollBarStyle()2361 public int super_getScrollBarStyle() { 2362 return WebView.super.getScrollBarStyle(); 2363 } 2364 super_scrollTo(int scrollX, int scrollY)2365 public void super_scrollTo(int scrollX, int scrollY) { 2366 WebView.super.scrollTo(scrollX, scrollY); 2367 } 2368 super_computeScroll()2369 public void super_computeScroll() { 2370 WebView.super.computeScroll(); 2371 } 2372 super_onHoverEvent(MotionEvent event)2373 public boolean super_onHoverEvent(MotionEvent event) { 2374 return WebView.super.onHoverEvent(event); 2375 } 2376 super_performAccessibilityAction(int action, Bundle arguments)2377 public boolean super_performAccessibilityAction(int action, Bundle arguments) { 2378 return WebView.super.performAccessibilityActionInternal(action, arguments); 2379 } 2380 super_performLongClick()2381 public boolean super_performLongClick() { 2382 return WebView.super.performLongClick(); 2383 } 2384 super_setFrame(int left, int top, int right, int bottom)2385 public boolean super_setFrame(int left, int top, int right, int bottom) { 2386 return WebView.super.setFrame(left, top, right, bottom); 2387 } 2388 super_dispatchKeyEvent(KeyEvent event)2389 public boolean super_dispatchKeyEvent(KeyEvent event) { 2390 return WebView.super.dispatchKeyEvent(event); 2391 } 2392 super_onGenericMotionEvent(MotionEvent event)2393 public boolean super_onGenericMotionEvent(MotionEvent event) { 2394 return WebView.super.onGenericMotionEvent(event); 2395 } 2396 super_requestFocus(int direction, Rect previouslyFocusedRect)2397 public boolean super_requestFocus(int direction, Rect previouslyFocusedRect) { 2398 return WebView.super.requestFocus(direction, previouslyFocusedRect); 2399 } 2400 super_setLayoutParams(ViewGroup.LayoutParams params)2401 public void super_setLayoutParams(ViewGroup.LayoutParams params) { 2402 WebView.super.setLayoutParams(params); 2403 } 2404 super_startActivityForResult(Intent intent, int requestCode)2405 public void super_startActivityForResult(Intent intent, int requestCode) { 2406 WebView.super.startActivityForResult(intent, requestCode); 2407 } 2408 2409 // ---- Access to non-public methods ---- overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)2410 public void overScrollBy(int deltaX, int deltaY, 2411 int scrollX, int scrollY, 2412 int scrollRangeX, int scrollRangeY, 2413 int maxOverScrollX, int maxOverScrollY, 2414 boolean isTouchEvent) { 2415 WebView.this.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, 2416 maxOverScrollX, maxOverScrollY, isTouchEvent); 2417 } 2418 awakenScrollBars(int duration)2419 public void awakenScrollBars(int duration) { 2420 WebView.this.awakenScrollBars(duration); 2421 } 2422 awakenScrollBars(int duration, boolean invalidate)2423 public void awakenScrollBars(int duration, boolean invalidate) { 2424 WebView.this.awakenScrollBars(duration, invalidate); 2425 } 2426 getVerticalScrollFactor()2427 public float getVerticalScrollFactor() { 2428 return WebView.this.getVerticalScrollFactor(); 2429 } 2430 getHorizontalScrollFactor()2431 public float getHorizontalScrollFactor() { 2432 return WebView.this.getHorizontalScrollFactor(); 2433 } 2434 setMeasuredDimension(int measuredWidth, int measuredHeight)2435 public void setMeasuredDimension(int measuredWidth, int measuredHeight) { 2436 WebView.this.setMeasuredDimension(measuredWidth, measuredHeight); 2437 } 2438 onScrollChanged(int l, int t, int oldl, int oldt)2439 public void onScrollChanged(int l, int t, int oldl, int oldt) { 2440 WebView.this.onScrollChanged(l, t, oldl, oldt); 2441 } 2442 getHorizontalScrollbarHeight()2443 public int getHorizontalScrollbarHeight() { 2444 return WebView.this.getHorizontalScrollbarHeight(); 2445 } 2446 super_onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)2447 public void super_onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, 2448 int l, int t, int r, int b) { 2449 WebView.super.onDrawVerticalScrollBar(canvas, scrollBar, l, t, r, b); 2450 } 2451 2452 // ---- Access to (non-public) fields ---- 2453 /** Raw setter for the scroll X value, without invoking onScrollChanged handlers etc. */ setScrollXRaw(int scrollX)2454 public void setScrollXRaw(int scrollX) { 2455 WebView.this.mScrollX = scrollX; 2456 } 2457 2458 /** Raw setter for the scroll Y value, without invoking onScrollChanged handlers etc. */ setScrollYRaw(int scrollY)2459 public void setScrollYRaw(int scrollY) { 2460 WebView.this.mScrollY = scrollY; 2461 } 2462 2463 } 2464 2465 //------------------------------------------------------------------------- 2466 // Package-private internal stuff 2467 //------------------------------------------------------------------------- 2468 2469 // Only used by android.webkit.FindActionModeCallback. setFindDialogFindListener(FindListener listener)2470 void setFindDialogFindListener(FindListener listener) { 2471 checkThread(); 2472 setupFindListenerIfNeeded(); 2473 mFindListener.mFindDialogFindListener = listener; 2474 } 2475 2476 // Only used by android.webkit.FindActionModeCallback. notifyFindDialogDismissed()2477 void notifyFindDialogDismissed() { 2478 checkThread(); 2479 mProvider.notifyFindDialogDismissed(); 2480 } 2481 2482 //------------------------------------------------------------------------- 2483 // Private internal stuff 2484 //------------------------------------------------------------------------- 2485 2486 private WebViewProvider mProvider; 2487 2488 /** 2489 * In addition to the FindListener that the user may set via the WebView.setFindListener 2490 * API, FindActionModeCallback will register it's own FindListener. We keep them separate 2491 * via this class so that the two FindListeners can potentially exist at once. 2492 */ 2493 private class FindListenerDistributor implements FindListener { 2494 private FindListener mFindDialogFindListener; 2495 private FindListener mUserFindListener; 2496 2497 @Override onFindResultReceived(int activeMatchOrdinal, int numberOfMatches, boolean isDoneCounting)2498 public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches, 2499 boolean isDoneCounting) { 2500 if (mFindDialogFindListener != null) { 2501 mFindDialogFindListener.onFindResultReceived(activeMatchOrdinal, numberOfMatches, 2502 isDoneCounting); 2503 } 2504 2505 if (mUserFindListener != null) { 2506 mUserFindListener.onFindResultReceived(activeMatchOrdinal, numberOfMatches, 2507 isDoneCounting); 2508 } 2509 } 2510 } 2511 private FindListenerDistributor mFindListener; 2512 setupFindListenerIfNeeded()2513 private void setupFindListenerIfNeeded() { 2514 if (mFindListener == null) { 2515 mFindListener = new FindListenerDistributor(); 2516 mProvider.setFindListener(mFindListener); 2517 } 2518 } 2519 ensureProviderCreated()2520 private void ensureProviderCreated() { 2521 checkThread(); 2522 if (mProvider == null) { 2523 // As this can get called during the base class constructor chain, pass the minimum 2524 // number of dependencies here; the rest are deferred to init(). 2525 mProvider = getFactory().createWebView(this, new PrivateAccess()); 2526 } 2527 } 2528 getFactory()2529 private static WebViewFactoryProvider getFactory() { 2530 return WebViewFactory.getProvider(); 2531 } 2532 2533 private final Looper mWebViewThread = Looper.myLooper(); 2534 checkThread()2535 private void checkThread() { 2536 // Ignore mWebViewThread == null because this can be called during in the super class 2537 // constructor, before this class's own constructor has even started. 2538 if (mWebViewThread != null && Looper.myLooper() != mWebViewThread) { 2539 Throwable throwable = new Throwable( 2540 "A WebView method was called on thread '" + 2541 Thread.currentThread().getName() + "'. " + 2542 "All WebView methods must be called on the same thread. " + 2543 "(Expected Looper " + mWebViewThread + " called on " + Looper.myLooper() + 2544 ", FYI main Looper is " + Looper.getMainLooper() + ")"); 2545 Log.w(LOGTAG, Log.getStackTraceString(throwable)); 2546 StrictMode.onWebViewMethodCalledOnWrongThread(throwable); 2547 2548 if (sEnforceThreadChecking) { 2549 throw new RuntimeException(throwable); 2550 } 2551 } 2552 } 2553 2554 //------------------------------------------------------------------------- 2555 // Override View methods 2556 //------------------------------------------------------------------------- 2557 2558 // TODO: Add a test that enumerates all methods in ViewDelegte & ScrollDelegate, and ensures 2559 // there's a corresponding override (or better, caller) for each of them in here. 2560 2561 @Override onAttachedToWindow()2562 protected void onAttachedToWindow() { 2563 super.onAttachedToWindow(); 2564 mProvider.getViewDelegate().onAttachedToWindow(); 2565 } 2566 2567 /** @hide */ 2568 @Override onDetachedFromWindowInternal()2569 protected void onDetachedFromWindowInternal() { 2570 mProvider.getViewDelegate().onDetachedFromWindow(); 2571 super.onDetachedFromWindowInternal(); 2572 } 2573 2574 /** @hide */ 2575 @Override onMovedToDisplay(int displayId, Configuration config)2576 public void onMovedToDisplay(int displayId, Configuration config) { 2577 mProvider.getViewDelegate().onMovedToDisplay(displayId, config); 2578 } 2579 2580 @Override setLayoutParams(ViewGroup.LayoutParams params)2581 public void setLayoutParams(ViewGroup.LayoutParams params) { 2582 mProvider.getViewDelegate().setLayoutParams(params); 2583 } 2584 2585 @Override setOverScrollMode(int mode)2586 public void setOverScrollMode(int mode) { 2587 super.setOverScrollMode(mode); 2588 // This method may be called in the constructor chain, before the WebView provider is 2589 // created. 2590 ensureProviderCreated(); 2591 mProvider.getViewDelegate().setOverScrollMode(mode); 2592 } 2593 2594 @Override setScrollBarStyle(int style)2595 public void setScrollBarStyle(int style) { 2596 mProvider.getViewDelegate().setScrollBarStyle(style); 2597 super.setScrollBarStyle(style); 2598 } 2599 2600 @Override computeHorizontalScrollRange()2601 protected int computeHorizontalScrollRange() { 2602 return mProvider.getScrollDelegate().computeHorizontalScrollRange(); 2603 } 2604 2605 @Override computeHorizontalScrollOffset()2606 protected int computeHorizontalScrollOffset() { 2607 return mProvider.getScrollDelegate().computeHorizontalScrollOffset(); 2608 } 2609 2610 @Override computeVerticalScrollRange()2611 protected int computeVerticalScrollRange() { 2612 return mProvider.getScrollDelegate().computeVerticalScrollRange(); 2613 } 2614 2615 @Override computeVerticalScrollOffset()2616 protected int computeVerticalScrollOffset() { 2617 return mProvider.getScrollDelegate().computeVerticalScrollOffset(); 2618 } 2619 2620 @Override computeVerticalScrollExtent()2621 protected int computeVerticalScrollExtent() { 2622 return mProvider.getScrollDelegate().computeVerticalScrollExtent(); 2623 } 2624 2625 @Override computeScroll()2626 public void computeScroll() { 2627 mProvider.getScrollDelegate().computeScroll(); 2628 } 2629 2630 @Override onHoverEvent(MotionEvent event)2631 public boolean onHoverEvent(MotionEvent event) { 2632 return mProvider.getViewDelegate().onHoverEvent(event); 2633 } 2634 2635 @Override onTouchEvent(MotionEvent event)2636 public boolean onTouchEvent(MotionEvent event) { 2637 return mProvider.getViewDelegate().onTouchEvent(event); 2638 } 2639 2640 @Override onGenericMotionEvent(MotionEvent event)2641 public boolean onGenericMotionEvent(MotionEvent event) { 2642 return mProvider.getViewDelegate().onGenericMotionEvent(event); 2643 } 2644 2645 @Override onTrackballEvent(MotionEvent event)2646 public boolean onTrackballEvent(MotionEvent event) { 2647 return mProvider.getViewDelegate().onTrackballEvent(event); 2648 } 2649 2650 @Override onKeyDown(int keyCode, KeyEvent event)2651 public boolean onKeyDown(int keyCode, KeyEvent event) { 2652 return mProvider.getViewDelegate().onKeyDown(keyCode, event); 2653 } 2654 2655 @Override onKeyUp(int keyCode, KeyEvent event)2656 public boolean onKeyUp(int keyCode, KeyEvent event) { 2657 return mProvider.getViewDelegate().onKeyUp(keyCode, event); 2658 } 2659 2660 @Override onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)2661 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { 2662 return mProvider.getViewDelegate().onKeyMultiple(keyCode, repeatCount, event); 2663 } 2664 2665 /* 2666 TODO: These are not currently implemented in WebViewClassic, but it seems inconsistent not 2667 to be delegating them too. 2668 2669 @Override 2670 public boolean onKeyPreIme(int keyCode, KeyEvent event) { 2671 return mProvider.getViewDelegate().onKeyPreIme(keyCode, event); 2672 } 2673 @Override 2674 public boolean onKeyLongPress(int keyCode, KeyEvent event) { 2675 return mProvider.getViewDelegate().onKeyLongPress(keyCode, event); 2676 } 2677 @Override 2678 public boolean onKeyShortcut(int keyCode, KeyEvent event) { 2679 return mProvider.getViewDelegate().onKeyShortcut(keyCode, event); 2680 } 2681 */ 2682 2683 @Override getAccessibilityNodeProvider()2684 public AccessibilityNodeProvider getAccessibilityNodeProvider() { 2685 AccessibilityNodeProvider provider = 2686 mProvider.getViewDelegate().getAccessibilityNodeProvider(); 2687 return provider == null ? super.getAccessibilityNodeProvider() : provider; 2688 } 2689 2690 @Deprecated 2691 @Override shouldDelayChildPressedState()2692 public boolean shouldDelayChildPressedState() { 2693 return mProvider.getViewDelegate().shouldDelayChildPressedState(); 2694 } 2695 2696 @Override getAccessibilityClassName()2697 public CharSequence getAccessibilityClassName() { 2698 return WebView.class.getName(); 2699 } 2700 2701 @Override onProvideVirtualStructure(ViewStructure structure)2702 public void onProvideVirtualStructure(ViewStructure structure) { 2703 mProvider.getViewDelegate().onProvideVirtualStructure(structure); 2704 } 2705 2706 /** 2707 * {@inheritDoc} 2708 * 2709 * <p>The {@link ViewStructure} traditionally represents a {@link View}, while for web pages 2710 * it represent HTML nodes. Hence, it's necessary to "map" the HTML properties in a way that is 2711 * understood by the {@link android.service.autofill.AutofillService} implementations: 2712 * 2713 * <ol> 2714 * <li>Only the HTML nodes inside a {@code FORM} are generated. 2715 * <li>The source of the HTML is set using {@link ViewStructure#setWebDomain(String)} in the 2716 * node representing the WebView. 2717 * <li>If a web page has multiple {@code FORM}s, only the data for the current form is 2718 * represented—if the user taps a field from another form, then the current autofill 2719 * context is canceled (by calling {@link android.view.autofill.AutofillManager#cancel()} and 2720 * a new context is created for that {@code FORM}. 2721 * <li>Similarly, if the page has {@code IFRAME} nodes, they are not initially represented in 2722 * the view structure until the user taps a field from a {@code FORM} inside the 2723 * {@code IFRAME}, in which case it would be treated the same way as multiple forms described 2724 * above, except that the {@link ViewStructure#setWebDomain(String) web domain} of the 2725 * {@code FORM} contains the {@code src} attribute from the {@code IFRAME} node. 2726 * <li>The W3C autofill field ({@code autocomplete} tag attribute) maps to 2727 * {@link ViewStructure#setAutofillHints(String[])}. 2728 * <li>If the view is editable, the {@link ViewStructure#setAutofillType(int)} and 2729 * {@link ViewStructure#setAutofillValue(AutofillValue)} must be set. 2730 * <li>The {@code placeholder} attribute maps to {@link ViewStructure#setHint(CharSequence)}. 2731 * <li>Other HTML attributes can be represented through 2732 * {@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}. 2733 * </ol> 2734 * 2735 * <p>If the WebView implementation can determine that the value of a field was set statically 2736 * (for example, not through Javascript), it should also call 2737 * {@code structure.setDataIsSensitive(false)}. 2738 * 2739 * <p>For example, an HTML form with 2 fields for username and password: 2740 * 2741 * <pre class="prettyprint"> 2742 * <input type="text" name="username" id="user" value="Type your username" autocomplete="username" placeholder="Email or username"> 2743 * <input type="password" name="password" id="pass" autocomplete="current-password" placeholder="Password"> 2744 * </pre> 2745 * 2746 * <p>Would map to: 2747 * 2748 * <pre class="prettyprint"> 2749 * int index = structure.addChildCount(2); 2750 * ViewStructure username = structure.newChild(index); 2751 * username.setAutofillId(structure.getAutofillId(), 1); // id 1 - first child 2752 * username.setAutofillHints("username"); 2753 * username.setHtmlInfo(username.newHtmlInfoBuilder("input") 2754 * .addAttribute("type", "text") 2755 * .addAttribute("name", "username") 2756 * .build()); 2757 * username.setHint("Email or username"); 2758 * username.setAutofillType(View.AUTOFILL_TYPE_TEXT); 2759 * username.setAutofillValue(AutofillValue.forText("Type your username")); 2760 * // Value of the field is not sensitive because it was created statically and not changed. 2761 * username.setDataIsSensitive(false); 2762 * 2763 * ViewStructure password = structure.newChild(index + 1); 2764 * username.setAutofillId(structure, 2); // id 2 - second child 2765 * password.setAutofillHints("current-password"); 2766 * password.setHtmlInfo(password.newHtmlInfoBuilder("input") 2767 * .addAttribute("type", "password") 2768 * .addAttribute("name", "password") 2769 * .build()); 2770 * password.setHint("Password"); 2771 * password.setAutofillType(View.AUTOFILL_TYPE_TEXT); 2772 * </pre> 2773 */ 2774 @Override onProvideAutofillVirtualStructure(ViewStructure structure, int flags)2775 public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) { 2776 mProvider.getViewDelegate().onProvideAutofillVirtualStructure(structure, flags); 2777 } 2778 2779 @Override autofill(SparseArray<AutofillValue>values)2780 public void autofill(SparseArray<AutofillValue>values) { 2781 mProvider.getViewDelegate().autofill(values); 2782 } 2783 2784 /** @hide */ 2785 @Override onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info)2786 public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { 2787 super.onInitializeAccessibilityNodeInfoInternal(info); 2788 mProvider.getViewDelegate().onInitializeAccessibilityNodeInfo(info); 2789 } 2790 2791 /** @hide */ 2792 @Override onInitializeAccessibilityEventInternal(AccessibilityEvent event)2793 public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) { 2794 super.onInitializeAccessibilityEventInternal(event); 2795 mProvider.getViewDelegate().onInitializeAccessibilityEvent(event); 2796 } 2797 2798 /** @hide */ 2799 @Override performAccessibilityActionInternal(int action, Bundle arguments)2800 public boolean performAccessibilityActionInternal(int action, Bundle arguments) { 2801 return mProvider.getViewDelegate().performAccessibilityAction(action, arguments); 2802 } 2803 2804 /** @hide */ 2805 @Override onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)2806 protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, 2807 int l, int t, int r, int b) { 2808 mProvider.getViewDelegate().onDrawVerticalScrollBar(canvas, scrollBar, l, t, r, b); 2809 } 2810 2811 @Override onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)2812 protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) { 2813 mProvider.getViewDelegate().onOverScrolled(scrollX, scrollY, clampedX, clampedY); 2814 } 2815 2816 @Override onWindowVisibilityChanged(int visibility)2817 protected void onWindowVisibilityChanged(int visibility) { 2818 super.onWindowVisibilityChanged(visibility); 2819 mProvider.getViewDelegate().onWindowVisibilityChanged(visibility); 2820 } 2821 2822 @Override onDraw(Canvas canvas)2823 protected void onDraw(Canvas canvas) { 2824 mProvider.getViewDelegate().onDraw(canvas); 2825 } 2826 2827 @Override performLongClick()2828 public boolean performLongClick() { 2829 return mProvider.getViewDelegate().performLongClick(); 2830 } 2831 2832 @Override onConfigurationChanged(Configuration newConfig)2833 protected void onConfigurationChanged(Configuration newConfig) { 2834 mProvider.getViewDelegate().onConfigurationChanged(newConfig); 2835 } 2836 2837 /** 2838 * Creates a new InputConnection for an InputMethod to interact with the WebView. 2839 * This is similar to {@link View#onCreateInputConnection} but note that WebView 2840 * calls InputConnection methods on a thread other than the UI thread. 2841 * If these methods are overridden, then the overriding methods should respect 2842 * thread restrictions when calling View methods or accessing data. 2843 */ 2844 @Override onCreateInputConnection(EditorInfo outAttrs)2845 public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 2846 return mProvider.getViewDelegate().onCreateInputConnection(outAttrs); 2847 } 2848 2849 @Override onDragEvent(DragEvent event)2850 public boolean onDragEvent(DragEvent event) { 2851 return mProvider.getViewDelegate().onDragEvent(event); 2852 } 2853 2854 @Override onVisibilityChanged(View changedView, int visibility)2855 protected void onVisibilityChanged(View changedView, int visibility) { 2856 super.onVisibilityChanged(changedView, visibility); 2857 // This method may be called in the constructor chain, before the WebView provider is 2858 // created. 2859 ensureProviderCreated(); 2860 mProvider.getViewDelegate().onVisibilityChanged(changedView, visibility); 2861 } 2862 2863 @Override onWindowFocusChanged(boolean hasWindowFocus)2864 public void onWindowFocusChanged(boolean hasWindowFocus) { 2865 mProvider.getViewDelegate().onWindowFocusChanged(hasWindowFocus); 2866 super.onWindowFocusChanged(hasWindowFocus); 2867 } 2868 2869 @Override onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect)2870 protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { 2871 mProvider.getViewDelegate().onFocusChanged(focused, direction, previouslyFocusedRect); 2872 super.onFocusChanged(focused, direction, previouslyFocusedRect); 2873 } 2874 2875 /** @hide */ 2876 @Override setFrame(int left, int top, int right, int bottom)2877 protected boolean setFrame(int left, int top, int right, int bottom) { 2878 return mProvider.getViewDelegate().setFrame(left, top, right, bottom); 2879 } 2880 2881 @Override onSizeChanged(int w, int h, int ow, int oh)2882 protected void onSizeChanged(int w, int h, int ow, int oh) { 2883 super.onSizeChanged(w, h, ow, oh); 2884 mProvider.getViewDelegate().onSizeChanged(w, h, ow, oh); 2885 } 2886 2887 @Override onScrollChanged(int l, int t, int oldl, int oldt)2888 protected void onScrollChanged(int l, int t, int oldl, int oldt) { 2889 super.onScrollChanged(l, t, oldl, oldt); 2890 mProvider.getViewDelegate().onScrollChanged(l, t, oldl, oldt); 2891 } 2892 2893 @Override dispatchKeyEvent(KeyEvent event)2894 public boolean dispatchKeyEvent(KeyEvent event) { 2895 return mProvider.getViewDelegate().dispatchKeyEvent(event); 2896 } 2897 2898 @Override requestFocus(int direction, Rect previouslyFocusedRect)2899 public boolean requestFocus(int direction, Rect previouslyFocusedRect) { 2900 return mProvider.getViewDelegate().requestFocus(direction, previouslyFocusedRect); 2901 } 2902 2903 @Override onMeasure(int widthMeasureSpec, int heightMeasureSpec)2904 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 2905 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 2906 mProvider.getViewDelegate().onMeasure(widthMeasureSpec, heightMeasureSpec); 2907 } 2908 2909 @Override requestChildRectangleOnScreen(View child, Rect rect, boolean immediate)2910 public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate) { 2911 return mProvider.getViewDelegate().requestChildRectangleOnScreen(child, rect, immediate); 2912 } 2913 2914 @Override setBackgroundColor(int color)2915 public void setBackgroundColor(int color) { 2916 mProvider.getViewDelegate().setBackgroundColor(color); 2917 } 2918 2919 @Override setLayerType(int layerType, Paint paint)2920 public void setLayerType(int layerType, Paint paint) { 2921 super.setLayerType(layerType, paint); 2922 mProvider.getViewDelegate().setLayerType(layerType, paint); 2923 } 2924 2925 @Override dispatchDraw(Canvas canvas)2926 protected void dispatchDraw(Canvas canvas) { 2927 mProvider.getViewDelegate().preDispatchDraw(canvas); 2928 super.dispatchDraw(canvas); 2929 } 2930 2931 @Override onStartTemporaryDetach()2932 public void onStartTemporaryDetach() { 2933 super.onStartTemporaryDetach(); 2934 mProvider.getViewDelegate().onStartTemporaryDetach(); 2935 } 2936 2937 @Override onFinishTemporaryDetach()2938 public void onFinishTemporaryDetach() { 2939 super.onFinishTemporaryDetach(); 2940 mProvider.getViewDelegate().onFinishTemporaryDetach(); 2941 } 2942 2943 @Override getHandler()2944 public Handler getHandler() { 2945 return mProvider.getViewDelegate().getHandler(super.getHandler()); 2946 } 2947 2948 @Override findFocus()2949 public View findFocus() { 2950 return mProvider.getViewDelegate().findFocus(super.findFocus()); 2951 } 2952 2953 /** 2954 * If WebView has already been loaded into the current process this method will return the 2955 * package that was used to load it. Otherwise, the package that would be used if the WebView 2956 * was loaded right now will be returned; this does not cause WebView to be loaded, so this 2957 * information may become outdated at any time. 2958 * The WebView package changes either when the current WebView package is updated, disabled, or 2959 * uninstalled. It can also be changed through a Developer Setting. 2960 * If the WebView package changes, any app process that has loaded WebView will be killed. The 2961 * next time the app starts and loads WebView it will use the new WebView package instead. 2962 * @return the current WebView package, or null if there is none. 2963 */ getCurrentWebViewPackage()2964 public static PackageInfo getCurrentWebViewPackage() { 2965 PackageInfo webviewPackage = WebViewFactory.getLoadedPackageInfo(); 2966 if (webviewPackage != null) { 2967 return webviewPackage; 2968 } 2969 2970 try { 2971 return WebViewFactory.getUpdateService().getCurrentWebViewPackage(); 2972 } catch (RemoteException e) { 2973 throw e.rethrowFromSystemServer(); 2974 } 2975 } 2976 2977 /** 2978 * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}. 2979 * 2980 * @param requestCode The integer request code originally supplied to 2981 * startActivityForResult(), allowing you to identify who this 2982 * result came from. 2983 * @param resultCode The integer result code returned by the child activity 2984 * through its setResult(). 2985 * @param data An Intent, which can return result data to the caller 2986 * (various data can be attached to Intent "extras"). 2987 * @hide 2988 */ 2989 @Override onActivityResult(int requestCode, int resultCode, Intent data)2990 public void onActivityResult(int requestCode, int resultCode, Intent data) { 2991 mProvider.getViewDelegate().onActivityResult(requestCode, resultCode, data); 2992 } 2993 2994 /** @hide */ 2995 @Override encodeProperties(@onNull ViewHierarchyEncoder encoder)2996 protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) { 2997 super.encodeProperties(encoder); 2998 2999 checkThread(); 3000 encoder.addProperty("webview:contentHeight", mProvider.getContentHeight()); 3001 encoder.addProperty("webview:contentWidth", mProvider.getContentWidth()); 3002 encoder.addProperty("webview:scale", mProvider.getScale()); 3003 encoder.addProperty("webview:title", mProvider.getTitle()); 3004 encoder.addProperty("webview:url", mProvider.getUrl()); 3005 encoder.addProperty("webview:originalUrl", mProvider.getOriginalUrl()); 3006 } 3007 } 3008