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