WebViewChromium.java revision 9cf31969a3e2e33d750b881ac6a4b3e980a5952a
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.webview.chromium; 18 19import android.content.res.Configuration; 20import android.graphics.Bitmap; 21import android.graphics.Canvas; 22import android.graphics.Paint; 23import android.graphics.Picture; 24import android.graphics.Rect; 25import android.graphics.drawable.Drawable; 26import android.net.http.SslCertificate; 27import android.os.Build; 28import android.os.Bundle; 29import android.os.CancellationSignal; 30import android.os.Message; 31import android.util.Base64; 32import android.util.Log; 33import android.view.HardwareCanvas; 34import android.view.KeyEvent; 35import android.view.MotionEvent; 36import android.view.View; 37import android.view.View.MeasureSpec; 38import android.view.ViewGroup; 39import android.view.accessibility.AccessibilityEvent; 40import android.view.accessibility.AccessibilityNodeInfo; 41import android.view.accessibility.AccessibilityNodeProvider; 42import android.view.inputmethod.EditorInfo; 43import android.view.inputmethod.InputConnection; 44import android.webkit.DownloadListener; 45import android.webkit.FindActionModeCallback; 46import android.webkit.JavascriptInterface; 47import android.webkit.ValueCallback; 48import android.webkit.WebBackForwardList; 49import android.webkit.WebChromeClient; 50import android.webkit.WebSettings; 51import android.webkit.WebView; 52import android.webkit.WebViewClient; 53import android.webkit.WebViewProvider; 54import android.widget.TextView; 55 56import org.chromium.android_webview.AwBrowserContext; 57import org.chromium.android_webview.AwContents; 58import org.chromium.base.ThreadUtils; 59import org.chromium.content.browser.LoadUrlParams; 60import org.chromium.net.NetworkChangeNotifier; 61 62import java.io.BufferedWriter; 63import java.io.File; 64import java.io.OutputStream; 65import java.lang.annotation.Annotation; 66import java.util.HashMap; 67import java.util.Map; 68 69/** 70 * This class is the delegate to which WebViewProxy forwards all API calls. 71 * 72 * Most of the actual functionality is implemented by AwContents (or ContentViewCore within 73 * it). This class also contains WebView-specific APIs that require the creation of other 74 * adapters (otherwise org.chromium.content would depend on the webview.chromium package) 75 * and a small set of no-op deprecated APIs. 76 */ 77class WebViewChromium implements WebViewProvider, 78 WebViewProvider.ScrollDelegate, WebViewProvider.ViewDelegate { 79 80 private static final String TAG = WebViewChromium.class.getSimpleName(); 81 82 // The WebView that this WebViewChromium is the provider for. 83 WebView mWebView; 84 // Lets us access protected View-derived methods on the WebView instance we're backing. 85 WebView.PrivateAccess mWebViewPrivate; 86 // The client adapter class. 87 private WebViewContentsClientAdapter mContentsClientAdapter; 88 89 // Variables for functionality provided by this adapter --------------------------------------- 90 // WebSettings adapter, lazily initialized in the getter 91 private WebSettings mWebSettings; 92 // The WebView wrapper for ContentViewCore and required browser compontents. 93 private AwContents mAwContents; 94 // Non-null if this webview is using the GL accelerated draw path. 95 private DrawGLFunctor mGLfunctor; 96 97 private AwBrowserContext mBrowserContext; 98 99 private final WebView.HitTestResult mHitTestResult; 100 101 private final int mAppTargetSdkVersion; 102 103 public WebViewChromium(WebView webView, WebView.PrivateAccess webViewPrivate, 104 AwBrowserContext browserContext) { 105 checkThread(); 106 mWebView = webView; 107 mWebViewPrivate = webViewPrivate; 108 mHitTestResult = new WebView.HitTestResult(); 109 mBrowserContext = browserContext; 110 mAppTargetSdkVersion = mWebView.getContext().getApplicationInfo().targetSdkVersion; 111 } 112 113 static void completeWindowCreation(WebView parent, WebView child) { 114 AwContents parentContents = ((WebViewChromium) parent.getWebViewProvider()).mAwContents; 115 AwContents childContents = 116 child == null ? null : ((WebViewChromium) child.getWebViewProvider()).mAwContents; 117 parentContents.supplyContentsForPopup(childContents); 118 } 119 120 // WebViewProvider methods -------------------------------------------------------------------- 121 122 @Override 123 public void init(Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) { 124 // BUG=6790250 |javaScriptInterfaces| was only ever used by the obsolete DumpRenderTree 125 // so is ignored. TODO: remove it from WebViewProvider. 126 final boolean isAccessFromFileURLsGrantedByDefault = 127 mAppTargetSdkVersion < Build.VERSION_CODES.JELLY_BEAN; 128 mContentsClientAdapter = new WebViewContentsClientAdapter(mWebView); 129 mAwContents = new AwContents(mBrowserContext, mWebView, new InternalAccessAdapter(), 130 mContentsClientAdapter, isAccessFromFileURLsGrantedByDefault); 131 132 if (privateBrowsing) { 133 final String msg = "Private browsing is not supported in WebView."; 134 if (mAppTargetSdkVersion >= Build.VERSION_CODES.KEY_LIME_PIE) { 135 throw new IllegalArgumentException(msg); 136 } else { 137 Log.w(TAG, msg); 138 // Intentionally irreversibly disable the webview instance, so that private 139 // user data cannot leak through misuse of a non-privateBrowing WebView instance. 140 // Can't just null out mAwContents as we never null-check it before use. 141 mAwContents.destroy(); 142 TextView warningLabel = new TextView(mWebView.getContext()); 143 warningLabel.setText(mWebView.getContext().getString( 144 com.android.internal.R.string.webviewchromium_private_browsing_warning)); 145 mWebView.addView(warningLabel); 146 } 147 } 148 149 } 150 151 private RuntimeException createThreadException() { 152 return new IllegalStateException("Calling View methods on another thread than the UI " + 153 "thread. PLEASE FILE A BUG! go/klp-webview-bug"); 154 } 155 156 // Intentionally not static, as no need to check thread on static methods 157 private void checkThread() { 158 if (!ThreadUtils.runningOnUiThread()) { 159 final RuntimeException threadViolation = createThreadException(); 160 ThreadUtils.postOnUiThread(new Runnable() { 161 @Override 162 public void run() { 163 throw threadViolation; 164 } 165 }); 166 throw createThreadException(); 167 } 168 } 169 170 @Override 171 public void setHorizontalScrollbarOverlay(boolean overlay) { 172 checkThread(); 173 mAwContents.setHorizontalScrollbarOverlay(overlay); 174 } 175 176 @Override 177 public void setVerticalScrollbarOverlay(boolean overlay) { 178 checkThread(); 179 mAwContents.setVerticalScrollbarOverlay(overlay); 180 } 181 182 @Override 183 public boolean overlayHorizontalScrollbar() { 184 checkThread(); 185 return mAwContents.overlayHorizontalScrollbar(); 186 } 187 188 @Override 189 public boolean overlayVerticalScrollbar() { 190 checkThread(); 191 return mAwContents.overlayVerticalScrollbar(); 192 } 193 194 @Override 195 public int getVisibleTitleHeight() { 196 // This is deprecated in WebView and should always return 0. 197 return 0; 198 } 199 200 @Override 201 public SslCertificate getCertificate() { 202 checkThread(); 203 return mAwContents.getCertificate(); 204 } 205 206 @Override 207 public void setCertificate(SslCertificate certificate) { 208 checkThread(); 209 UnimplementedWebViewApi.invoke(); 210 } 211 212 @Override 213 public void savePassword(String host, String username, String password) { 214 // This is a deprecated API: intentional no-op. 215 } 216 217 @Override 218 public void setHttpAuthUsernamePassword(String host, String realm, String username, 219 String password) { 220 checkThread(); 221 mAwContents.setHttpAuthUsernamePassword(host, realm, username, password); 222 } 223 224 @Override 225 public String[] getHttpAuthUsernamePassword(String host, String realm) { 226 checkThread(); 227 return mAwContents.getHttpAuthUsernamePassword(host, realm); 228 } 229 230 @Override 231 public void destroy() { 232 checkThread(); 233 mAwContents.destroy(); 234 if (mGLfunctor != null) { 235 mGLfunctor.destroy(); 236 mGLfunctor = null; 237 } 238 } 239 240 @Override 241 public void setNetworkAvailable(boolean networkUp) { 242 checkThread(); 243 // Note that this purely toggles the JS navigator.online property. 244 // It does not in affect chromium or network stack state in any way. 245 mAwContents.setNetworkAvailable(networkUp); 246 } 247 248 @Override 249 public WebBackForwardList saveState(Bundle outState) { 250 checkThread(); 251 if (outState == null) return null; 252 if (!mAwContents.saveState(outState)) return null; 253 return copyBackForwardList(); 254 } 255 256 @Override 257 public boolean savePicture(Bundle b, File dest) { 258 // Intentional no-op: hidden method on WebView. 259 return false; 260 } 261 262 @Override 263 public boolean restorePicture(Bundle b, File src) { 264 // Intentional no-op: hidden method on WebView. 265 return false; 266 } 267 268 @Override 269 public WebBackForwardList restoreState(Bundle inState) { 270 checkThread(); 271 if (inState == null) return null; 272 if (!mAwContents.restoreState(inState)) return null; 273 return copyBackForwardList(); 274 } 275 276 @Override 277 public void loadUrl(String url, Map<String, String> additionalHttpHeaders) { 278 // TODO: We may actually want to do some sanity checks here (like filter about://chrome). 279 280 // For backwards compatibility, apps targeting less than K will have JS URLs evaluated 281 // directly and any result of the evaluation will not replace the current page content. 282 // Matching Chrome behavior more closely; apps targetting >= K that load a JS URL will 283 // have the result of that URL replace the content of the current page. 284 final String JAVASCRIPT_SCHEME = "javascript:"; 285 if (mAppTargetSdkVersion < Build.VERSION_CODES.KEY_LIME_PIE && 286 url.startsWith(JAVASCRIPT_SCHEME)) { 287 mAwContents.evaluateJavaScriptEvenIfNotYetNavigated( 288 url.substring(JAVASCRIPT_SCHEME.length())); 289 return; 290 } 291 292 LoadUrlParams params = new LoadUrlParams(url); 293 if (additionalHttpHeaders != null) params.setExtraHeaders(additionalHttpHeaders); 294 loadUrlOnUiThread(params); 295 } 296 297 @Override 298 public void loadUrl(String url) { 299 loadUrl(url, null); 300 } 301 302 @Override 303 public void postUrl(String url, byte[] postData) { 304 LoadUrlParams params = LoadUrlParams.createLoadHttpPostParams(url, postData); 305 Map<String,String> headers = new HashMap<String,String>(); 306 headers.put("Content-Type", "application/x-www-form-urlencoded"); 307 params.setExtraHeaders(headers); 308 loadUrlOnUiThread(params); 309 } 310 311 private static boolean isBase64Encoded(String encoding) { 312 return "base64".equals(encoding); 313 } 314 315 @Override 316 public void loadData(String data, String mimeType, String encoding) { 317 loadUrlOnUiThread(LoadUrlParams.createLoadDataParams( 318 data, mimeType, isBase64Encoded(encoding))); 319 } 320 321 @Override 322 public void loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, 323 String historyUrl) { 324 LoadUrlParams loadUrlParams; 325 326 if (baseUrl != null && baseUrl.startsWith("data:")) { 327 // For backwards compatibility with WebViewClassic, we use the value of |encoding| 328 // as the charset, as long as it's not "base64". 329 boolean isBase64 = isBase64Encoded(encoding); 330 loadUrlParams = LoadUrlParams.createLoadDataParamsWithBaseUrl( 331 data, mimeType, isBase64, baseUrl, historyUrl, isBase64 ? null : encoding); 332 } else { 333 if (baseUrl == null || baseUrl.length() == 0) baseUrl = "about:blank"; 334 // When loading data with a non-data: base URL, the classic WebView would effectively 335 // "dump" that string of data into the WebView without going through regular URL 336 // loading steps such as decoding URL-encoded entities. We achieve this same behavior by 337 // base64 encoding the data that is passed here and then loading that as a data: URL. 338 try { 339 loadUrlParams = LoadUrlParams.createLoadDataParamsWithBaseUrl( 340 Base64.encodeToString(data.getBytes("utf-8"), Base64.DEFAULT), mimeType, 341 true, baseUrl, historyUrl, "utf-8"); 342 } catch (java.io.UnsupportedEncodingException e) { 343 Log.wtf(TAG, "Unable to load data string " + data, e); 344 return; 345 } 346 } 347 loadUrlOnUiThread(loadUrlParams); 348 } 349 350 private void loadUrlOnUiThread(final LoadUrlParams loadUrlParams) { 351 if (ThreadUtils.runningOnUiThread()) { 352 mAwContents.loadUrl(loadUrlParams); 353 } else { 354 // Disallowed in WebView API for apps targetting a new SDK 355 assert mAppTargetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2; 356 ThreadUtils.postOnUiThread(new Runnable() { 357 @Override 358 public void run() { 359 mAwContents.loadUrl(loadUrlParams); 360 } 361 }); 362 } 363 } 364 365 public void evaluateJavaScript(String script, ValueCallback<String> resultCallback) { 366 checkThread(); 367 mAwContents.evaluateJavaScript(script, resultCallback); 368 } 369 370 @Override 371 public void saveWebArchive(String filename) { 372 checkThread(); 373 saveWebArchive(filename, false, null); 374 } 375 376 @Override 377 public void saveWebArchive(String basename, boolean autoname, ValueCallback<String> callback) { 378 checkThread(); 379 mAwContents.saveWebArchive(basename, autoname, callback); 380 } 381 382 @Override 383 public void stopLoading() { 384 checkThread(); 385 mAwContents.stopLoading(); 386 } 387 388 @Override 389 public void reload() { 390 checkThread(); 391 mAwContents.reload(); 392 } 393 394 @Override 395 public boolean canGoBack() { 396 checkThread(); 397 return mAwContents.canGoBack(); 398 } 399 400 @Override 401 public void goBack() { 402 checkThread(); 403 mAwContents.goBack(); 404 } 405 406 @Override 407 public boolean canGoForward() { 408 checkThread(); 409 return mAwContents.canGoForward(); 410 } 411 412 @Override 413 public void goForward() { 414 checkThread(); 415 mAwContents.goForward(); 416 } 417 418 @Override 419 public boolean canGoBackOrForward(int steps) { 420 checkThread(); 421 return mAwContents.canGoBackOrForward(steps); 422 } 423 424 @Override 425 public void goBackOrForward(int steps) { 426 checkThread(); 427 mAwContents.goBackOrForward(steps); 428 } 429 430 @Override 431 public boolean isPrivateBrowsingEnabled() { 432 // Not supported in this WebView implementation. 433 return false; 434 } 435 436 @Override 437 public boolean pageUp(boolean top) { 438 checkThread(); 439 return mAwContents.pageUp(top); 440 } 441 442 @Override 443 public boolean pageDown(boolean bottom) { 444 checkThread(); 445 return mAwContents.pageDown(bottom); 446 } 447 448 @Override 449 public void clearView() { 450 checkThread(); 451 UnimplementedWebViewApi.invoke(); 452 } 453 454 @Override 455 public Picture capturePicture() { 456 checkThread(); 457 return mAwContents.capturePicture(); 458 } 459 460 @Override 461 public void exportToPdf(OutputStream stream, int width, int height, 462 ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal) { 463 checkThread(); 464 mAwContents.getPdfExporter().exportToPdf(stream, width, height, resultCallback, 465 cancellationSignal); 466 } 467 468 @Override 469 public float getScale() { 470 checkThread(); 471 return mAwContents.getScale(); 472 } 473 474 @Override 475 public void setInitialScale(int scaleInPercent) { 476 checkThread(); 477 mAwContents.getSettings().setInitialPageScale(scaleInPercent); 478 } 479 480 @Override 481 public void invokeZoomPicker() { 482 checkThread(); 483 mAwContents.invokeZoomPicker(); 484 } 485 486 @Override 487 public WebView.HitTestResult getHitTestResult() { 488 checkThread(); 489 AwContents.HitTestData data = mAwContents.getLastHitTestResult(); 490 mHitTestResult.setType(data.hitTestResultType); 491 mHitTestResult.setExtra(data.hitTestResultExtraData); 492 return mHitTestResult; 493 } 494 495 @Override 496 public void requestFocusNodeHref(Message hrefMsg) { 497 checkThread(); 498 mAwContents.requestFocusNodeHref(hrefMsg); 499 } 500 501 @Override 502 public void requestImageRef(Message msg) { 503 checkThread(); 504 mAwContents.requestImageRef(msg); 505 } 506 507 @Override 508 public String getUrl() { 509 checkThread(); 510 String url = mAwContents.getUrl(); 511 if (url == null || url.trim().isEmpty()) return null; 512 return url; 513 } 514 515 @Override 516 public String getOriginalUrl() { 517 checkThread(); 518 String url = mAwContents.getOriginalUrl(); 519 if (url == null || url.trim().isEmpty()) return null; 520 return url; 521 } 522 523 @Override 524 public String getTitle() { 525 checkThread(); 526 return mAwContents.getTitle(); 527 } 528 529 @Override 530 public Bitmap getFavicon() { 531 checkThread(); 532 return mAwContents.getFavicon(); 533 } 534 535 @Override 536 public String getTouchIconUrl() { 537 // Intentional no-op: hidden method on WebView. 538 return null; 539 } 540 541 @Override 542 public int getProgress() { 543 // No checkThread() because the value is cached java side (workaround for b/10533304). 544 return mAwContents.getMostRecentProgress(); 545 } 546 547 @Override 548 public int getContentHeight() { 549 checkThread(); 550 return mAwContents.getContentHeightCss(); 551 } 552 553 @Override 554 public int getContentWidth() { 555 checkThread(); 556 return mAwContents.getContentWidthCss(); 557 } 558 559 @Override 560 public void pauseTimers() { 561 checkThread(); 562 mAwContents.pauseTimers(); 563 } 564 565 @Override 566 public void resumeTimers() { 567 checkThread(); 568 mAwContents.resumeTimers(); 569 } 570 571 @Override 572 public void onPause() { 573 checkThread(); 574 mAwContents.onPause(); 575 } 576 577 @Override 578 public void onResume() { 579 checkThread(); 580 mAwContents.onResume(); 581 } 582 583 @Override 584 public boolean isPaused() { 585 checkThread(); 586 return mAwContents.isPaused(); 587 } 588 589 @Override 590 public void freeMemory() { 591 checkThread(); 592 UnimplementedWebViewApi.invoke(); 593 } 594 595 @Override 596 public void clearCache(boolean includeDiskFiles) { 597 checkThread(); 598 mAwContents.clearCache(includeDiskFiles); 599 } 600 601 /** 602 * This is a poorly named method, but we keep it for historical reasons. 603 */ 604 @Override 605 public void clearFormData() { 606 checkThread(); 607 mAwContents.hideAutofillPopup(); 608 } 609 610 @Override 611 public void clearHistory() { 612 checkThread(); 613 mAwContents.clearHistory(); 614 } 615 616 @Override 617 public void clearSslPreferences() { 618 checkThread(); 619 mAwContents.clearSslPreferences(); 620 } 621 622 @Override 623 public WebBackForwardList copyBackForwardList() { 624 checkThread(); 625 return new WebBackForwardListChromium( 626 mAwContents.getNavigationHistory()); 627 } 628 629 @Override 630 public void setFindListener(WebView.FindListener listener) { 631 checkThread(); 632 mContentsClientAdapter.setFindListener(listener); 633 } 634 635 @Override 636 public void findNext(boolean forwards) { 637 checkThread(); 638 mAwContents.findNext(forwards); 639 } 640 641 @Override 642 public int findAll(String searchString) { 643 checkThread(); 644 mAwContents.findAllAsync(searchString); 645 return 0; 646 } 647 648 @Override 649 public void findAllAsync(String searchString) { 650 checkThread(); 651 mAwContents.findAllAsync(searchString); 652 } 653 654 @Override 655 public boolean showFindDialog(String text, boolean showIme) { 656 checkThread(); 657 if (mWebView.getParent() == null) { 658 return false; 659 } 660 661 FindActionModeCallback findAction = new FindActionModeCallback(mWebView.getContext()); 662 if (findAction == null) { 663 return false; 664 } 665 666 mWebView.startActionMode(findAction); 667 findAction.setWebView(mWebView); 668 if (showIme) { 669 findAction.showSoftInput(); 670 } 671 672 if (text != null) { 673 findAction.setText(text); 674 findAction.findAll(); 675 } 676 677 return true; 678 } 679 680 @Override 681 public void notifyFindDialogDismissed() { 682 checkThread(); 683 clearMatches(); 684 } 685 686 @Override 687 public void clearMatches() { 688 checkThread(); 689 mAwContents.clearMatches(); 690 } 691 692 @Override 693 public void documentHasImages(Message response) { 694 checkThread(); 695 mAwContents.documentHasImages(response); 696 } 697 698 @Override 699 public void setWebViewClient(WebViewClient client) { 700 checkThread(); 701 mContentsClientAdapter.setWebViewClient(client); 702 } 703 704 @Override 705 public void setDownloadListener(DownloadListener listener) { 706 checkThread(); 707 mContentsClientAdapter.setDownloadListener(listener); 708 } 709 710 @Override 711 public void setWebChromeClient(WebChromeClient client) { 712 checkThread(); 713 mContentsClientAdapter.setWebChromeClient(client); 714 } 715 716 @Override 717 public void setPictureListener(WebView.PictureListener listener) { 718 checkThread(); 719 mContentsClientAdapter.setPictureListener(listener); 720 mAwContents.enableOnNewPicture(listener != null, 721 mAppTargetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN_MR2); 722 } 723 724 @Override 725 public void addJavascriptInterface(Object obj, String interfaceName) { 726 checkThread(); 727 Class<? extends Annotation> requiredAnnotation = null; 728 if (mAppTargetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 729 requiredAnnotation = JavascriptInterface.class; 730 } 731 mAwContents.addPossiblyUnsafeJavascriptInterface(obj, interfaceName, requiredAnnotation); 732 } 733 734 @Override 735 public void removeJavascriptInterface(String interfaceName) { 736 checkThread(); 737 mAwContents.removeJavascriptInterface(interfaceName); 738 } 739 740 @Override 741 public WebSettings getSettings() { 742 checkThread(); 743 if (mWebSettings == null) { 744 mWebSettings = new ContentSettingsAdapter(mAwContents.getSettings()); 745 } 746 return mWebSettings; 747 } 748 749 @Override 750 public void setMapTrackballToArrowKeys(boolean setMap) { 751 checkThread(); 752 // This is a deprecated API: intentional no-op. 753 } 754 755 @Override 756 public void flingScroll(int vx, int vy) { 757 checkThread(); 758 mAwContents.flingScroll(vx, vy); 759 } 760 761 @Override 762 public View getZoomControls() { 763 checkThread(); 764 // This was deprecated in 2009 and hidden in JB MR1, so just provide the minimum needed 765 // to stop very out-dated applications from crashing. 766 Log.w(TAG, "WebView doesn't support getZoomControls"); 767 return mAwContents.getSettings().supportZoom() ? new View(mWebView.getContext()) : null; 768 } 769 770 @Override 771 public boolean canZoomIn() { 772 checkThread(); 773 return mAwContents.canZoomIn(); 774 } 775 776 @Override 777 public boolean canZoomOut() { 778 checkThread(); 779 return mAwContents.canZoomOut(); 780 } 781 782 @Override 783 public boolean zoomIn() { 784 checkThread(); 785 return mAwContents.zoomIn(); 786 } 787 788 @Override 789 public boolean zoomOut() { 790 checkThread(); 791 return mAwContents.zoomOut(); 792 } 793 794 @Override 795 public void dumpViewHierarchyWithProperties(BufferedWriter out, int level) { 796 checkThread(); 797 UnimplementedWebViewApi.invoke(); 798 } 799 800 @Override 801 public View findHierarchyView(String className, int hashCode) { 802 checkThread(); 803 UnimplementedWebViewApi.invoke(); 804 return null; 805 } 806 807 // WebViewProvider glue methods --------------------------------------------------------------- 808 809 @Override 810 // This needs to be kept thread safe! 811 public WebViewProvider.ViewDelegate getViewDelegate() { 812 return this; 813 } 814 815 @Override 816 public WebViewProvider.ScrollDelegate getScrollDelegate() { 817 checkThread(); 818 return this; 819 } 820 821 822 // WebViewProvider.ViewDelegate implementation ------------------------------------------------ 823 824 // TODO: remove from WebViewProvider and use default implementation from 825 // ViewGroup. 826 // @Override 827 public boolean shouldDelayChildPressedState() { 828 checkThread(); 829 return true; 830 } 831 832// @Override 833 public AccessibilityNodeProvider getAccessibilityNodeProvider() { 834 checkThread(); 835 return mAwContents.getAccessibilityNodeProvider(); 836 } 837 838 @Override 839 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 840 checkThread(); 841 mAwContents.onInitializeAccessibilityNodeInfo(info); 842 } 843 844 @Override 845 public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 846 checkThread(); 847 mAwContents.onInitializeAccessibilityEvent(event); 848 } 849 850 @Override 851 public boolean performAccessibilityAction(int action, Bundle arguments) { 852 checkThread(); 853 if (mAwContents.supportsAccessibilityAction(action)) { 854 return mAwContents.performAccessibilityAction(action, arguments); 855 } 856 return mWebViewPrivate.super_performAccessibilityAction(action, arguments); 857 } 858 859 @Override 860 public void setOverScrollMode(int mode) { 861 checkThread(); 862 // This gets called from the android.view.View c'tor that WebView inherits from. This 863 // causes the method to be called when mAwContents == null. 864 // It's safe to ignore these calls however since AwContents will read the current value of 865 // this setting when it's created. 866 if (mAwContents != null) { 867 mAwContents.setOverScrollMode(mode); 868 } 869 } 870 871 @Override 872 public void setScrollBarStyle(int style) { 873 checkThread(); 874 mAwContents.setScrollBarStyle(style); 875 } 876 877 @Override 878 public void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, 879 int l, int t, int r, int b) { 880 checkThread(); 881 // WebViewClassic was overriding this method to handle rubberband over-scroll. Since 882 // WebViewChromium doesn't support that the vanilla implementation of this method can be 883 // used. 884 mWebViewPrivate.super_onDrawVerticalScrollBar(canvas, scrollBar, l, t, r, b); 885 } 886 887 @Override 888 public void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) { 889 checkThread(); 890 mAwContents.onContainerViewOverScrolled(scrollX, scrollY, clampedX, clampedY); 891 } 892 893 @Override 894 public void onWindowVisibilityChanged(int visibility) { 895 checkThread(); 896 mAwContents.onWindowVisibilityChanged(visibility); 897 } 898 899 @Override 900 public void onDraw(Canvas canvas) { 901 checkThread(); 902 mAwContents.onDraw(canvas); 903 } 904 905 @Override 906 public void setLayoutParams(ViewGroup.LayoutParams layoutParams) { 907 checkThread(); 908 // TODO: This is the minimum implementation for HTMLViewer 909 // bringup. Likely will need to go up to ContentViewCore for 910 // a complete implementation. 911 mWebViewPrivate.super_setLayoutParams(layoutParams); 912 } 913 914 @Override 915 public boolean performLongClick() { 916 checkThread(); 917 return mWebViewPrivate.super_performLongClick(); 918 } 919 920 @Override 921 public void onConfigurationChanged(Configuration newConfig) { 922 checkThread(); 923 mAwContents.onConfigurationChanged(newConfig); 924 } 925 926 @Override 927 public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 928 checkThread(); 929 return mAwContents.onCreateInputConnection(outAttrs); 930 } 931 932 @Override 933 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { 934 checkThread(); 935 UnimplementedWebViewApi.invoke(); 936 return false; 937 } 938 939 @Override 940 public boolean onKeyDown(int keyCode, KeyEvent event) { 941 checkThread(); 942 UnimplementedWebViewApi.invoke(); 943 return false; 944 } 945 946 @Override 947 public boolean onKeyUp(int keyCode, KeyEvent event) { 948 checkThread(); 949 return mAwContents.onKeyUp(keyCode, event); 950 } 951 952 @Override 953 public void onAttachedToWindow() { 954 checkThread(); 955 mAwContents.onAttachedToWindow(); 956 } 957 958 @Override 959 public void onDetachedFromWindow() { 960 checkThread(); 961 mAwContents.onDetachedFromWindow(); 962 if (mGLfunctor != null) { 963 mGLfunctor.detach(); 964 } 965 } 966 967 @Override 968 public void onVisibilityChanged(View changedView, int visibility) { 969 checkThread(); 970 // The AwContents will find out the container view visibility before the first draw so we 971 // can safely ignore onVisibilityChanged callbacks that happen before init(). 972 if (mAwContents != null) { 973 mAwContents.onVisibilityChanged(changedView, visibility); 974 } 975 } 976 977 @Override 978 public void onWindowFocusChanged(boolean hasWindowFocus) { 979 checkThread(); 980 mAwContents.onWindowFocusChanged(hasWindowFocus); 981 } 982 983 @Override 984 public void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { 985 checkThread(); 986 mAwContents.onFocusChanged(focused, direction, previouslyFocusedRect); 987 } 988 989 @Override 990 public boolean setFrame(int left, int top, int right, int bottom) { 991 // TODO(joth): This is the minimum implementation for initial 992 // bringup. Likely will need to go up to AwContents for a complete 993 // implementation, e.g. setting the compositor visible region (to 994 // avoid painting tiles that are offscreen due to the view's position). 995 checkThread(); 996 return mWebViewPrivate.super_setFrame(left, top, right, bottom); 997 } 998 999 @Override 1000 public void onSizeChanged(int w, int h, int ow, int oh) { 1001 checkThread(); 1002 mAwContents.onSizeChanged(w, h, ow, oh); 1003 } 1004 1005 @Override 1006 public void onScrollChanged(int l, int t, int oldl, int oldt) { 1007 checkThread(); 1008 } 1009 1010 @Override 1011 public boolean dispatchKeyEvent(KeyEvent event) { 1012 checkThread(); 1013 return mAwContents.dispatchKeyEvent(event); 1014 } 1015 1016 @Override 1017 public boolean onTouchEvent(MotionEvent ev) { 1018 checkThread(); 1019 return mAwContents.onTouchEvent(ev); 1020 } 1021 1022 @Override 1023 public boolean onHoverEvent(MotionEvent event) { 1024 checkThread(); 1025 return mAwContents.onHoverEvent(event); 1026 } 1027 1028 @Override 1029 public boolean onGenericMotionEvent(MotionEvent event) { 1030 checkThread(); 1031 return mAwContents.onGenericMotionEvent(event); 1032 } 1033 1034 @Override 1035 public boolean onTrackballEvent(MotionEvent ev) { 1036 checkThread(); 1037 // Trackball event not handled, which eventually gets converted to DPAD keyevents 1038 return false; 1039 } 1040 1041 @Override 1042 public boolean requestFocus(int direction, Rect previouslyFocusedRect) { 1043 checkThread(); 1044 mAwContents.requestFocus(); 1045 return mWebViewPrivate.super_requestFocus(direction, previouslyFocusedRect); 1046 } 1047 1048 @Override 1049 public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 1050 checkThread(); 1051 mAwContents.onMeasure(widthMeasureSpec, heightMeasureSpec); 1052 } 1053 1054 @Override 1055 public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate) { 1056 checkThread(); 1057 UnimplementedWebViewApi.invoke(); 1058 return false; 1059 } 1060 1061 @Override 1062 public void setBackgroundColor(final int color) { 1063 if (ThreadUtils.runningOnUiThread()) { 1064 mAwContents.setBackgroundColor(color); 1065 } else { 1066 // Disallowed in WebView API for apps targetting a new SDK 1067 assert mAppTargetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2; 1068 ThreadUtils.postOnUiThread(new Runnable() { 1069 @Override 1070 public void run() { 1071 mAwContents.setBackgroundColor(color); 1072 } 1073 }); 1074 } 1075 } 1076 1077 @Override 1078 public void setLayerType(int layerType, Paint paint) { 1079 checkThread(); 1080 UnimplementedWebViewApi.invoke(); 1081 } 1082 1083 @Override 1084 public void preDispatchDraw(Canvas canvas) { 1085 checkThread(); 1086 // TODO(leandrogracia): remove this method from WebViewProvider if we think 1087 // we won't need it again. 1088 } 1089 1090 // WebViewProvider.ScrollDelegate implementation ---------------------------------------------- 1091 1092 @Override 1093 public int computeHorizontalScrollRange() { 1094 checkThread(); 1095 return mAwContents.computeHorizontalScrollRange(); 1096 } 1097 1098 @Override 1099 public int computeHorizontalScrollOffset() { 1100 checkThread(); 1101 return mAwContents.computeHorizontalScrollOffset(); 1102 } 1103 1104 @Override 1105 public int computeVerticalScrollRange() { 1106 checkThread(); 1107 return mAwContents.computeVerticalScrollRange(); 1108 } 1109 1110 @Override 1111 public int computeVerticalScrollOffset() { 1112 checkThread(); 1113 return mAwContents.computeVerticalScrollOffset(); 1114 } 1115 1116 @Override 1117 public int computeVerticalScrollExtent() { 1118 checkThread(); 1119 return mAwContents.computeVerticalScrollExtent(); 1120 } 1121 1122 @Override 1123 public void computeScroll() { 1124 checkThread(); 1125 mAwContents.computeScroll(); 1126 } 1127 1128 // AwContents.InternalAccessDelegate implementation -------------------------------------- 1129 private class InternalAccessAdapter implements AwContents.InternalAccessDelegate { 1130 @Override 1131 public boolean drawChild(Canvas arg0, View arg1, long arg2) { 1132 UnimplementedWebViewApi.invoke(); 1133 return false; 1134 } 1135 1136 @Override 1137 public boolean super_onKeyUp(int arg0, KeyEvent arg1) { 1138 UnimplementedWebViewApi.invoke(); 1139 return false; 1140 } 1141 1142 @Override 1143 public boolean super_dispatchKeyEventPreIme(KeyEvent arg0) { 1144 UnimplementedWebViewApi.invoke(); 1145 return false; 1146 } 1147 1148 @Override 1149 public boolean super_dispatchKeyEvent(KeyEvent event) { 1150 return mWebViewPrivate.super_dispatchKeyEvent(event); 1151 } 1152 1153 @Override 1154 public boolean super_onGenericMotionEvent(MotionEvent arg0) { 1155 UnimplementedWebViewApi.invoke(); 1156 return false; 1157 } 1158 1159 @Override 1160 public void super_onConfigurationChanged(Configuration arg0) { 1161 UnimplementedWebViewApi.invoke(); 1162 } 1163 1164 @Override 1165 public int super_getScrollBarStyle() { 1166 return mWebViewPrivate.super_getScrollBarStyle(); 1167 } 1168 1169 @Override 1170 public boolean awakenScrollBars() { 1171 mWebViewPrivate.awakenScrollBars(0); 1172 // TODO: modify the WebView.PrivateAccess to provide a return value. 1173 return true; 1174 } 1175 1176 @Override 1177 public boolean super_awakenScrollBars(int arg0, boolean arg1) { 1178 // TODO: need method on WebView.PrivateAccess? 1179 UnimplementedWebViewApi.invoke(); 1180 return false; 1181 } 1182 1183 @Override 1184 public void onScrollChanged(int l, int t, int oldl, int oldt) { 1185 mWebViewPrivate.setScrollXRaw(l); 1186 mWebViewPrivate.setScrollYRaw(t); 1187 mWebViewPrivate.onScrollChanged(l, t, oldl, oldt); 1188 } 1189 1190 @Override 1191 public void overScrollBy(int deltaX, int deltaY, 1192 int scrollX, int scrollY, 1193 int scrollRangeX, int scrollRangeY, 1194 int maxOverScrollX, int maxOverScrollY, 1195 boolean isTouchEvent) { 1196 mWebViewPrivate.overScrollBy(deltaX, deltaY, scrollX, scrollY, 1197 scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); 1198 } 1199 1200 @Override 1201 public void super_scrollTo(int scrollX, int scrollY) { 1202 mWebViewPrivate.super_scrollTo(scrollX, scrollY); 1203 } 1204 1205 @Override 1206 public void setMeasuredDimension(int measuredWidth, int measuredHeight) { 1207 mWebViewPrivate.setMeasuredDimension(measuredWidth, measuredHeight); 1208 } 1209 1210 @Override 1211 public boolean requestDrawGL(Canvas canvas) { 1212 if (mGLfunctor == null) { 1213 mGLfunctor = new DrawGLFunctor(mAwContents.getAwDrawGLViewContext()); 1214 } 1215 return mGLfunctor.requestDrawGL((HardwareCanvas)canvas, mWebView.getViewRootImpl()); 1216 } 1217 } 1218} 1219