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