1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package com
.android
.webview
.chromium
;
7 import android
.content
.Context
;
8 import android
.content
.res
.Configuration
;
9 import android
.graphics
.Bitmap
;
10 import android
.graphics
.Canvas
;
11 import android
.graphics
.Paint
;
12 import android
.graphics
.Picture
;
13 import android
.graphics
.Rect
;
14 import android
.graphics
.drawable
.Drawable
;
15 import android
.net
.http
.SslCertificate
;
16 import android
.os
.Build
;
17 import android
.os
.Bundle
;
18 import android
.os
.Handler
;
19 import android
.os
.Looper
;
20 import android
.os
.Message
;
21 import android
.print
.PrintDocumentAdapter
;
22 import android
.util
.Log
;
23 import android
.view
.KeyEvent
;
24 import android
.view
.MotionEvent
;
25 import android
.view
.View
;
26 import android
.view
.ViewGroup
;
27 import android
.view
.accessibility
.AccessibilityEvent
;
28 import android
.view
.accessibility
.AccessibilityNodeInfo
;
29 import android
.view
.accessibility
.AccessibilityNodeProvider
;
30 import android
.view
.inputmethod
.EditorInfo
;
31 import android
.view
.inputmethod
.InputConnection
;
32 import android
.webkit
.DownloadListener
;
33 import android
.webkit
.FindActionModeCallback
;
34 import android
.webkit
.ValueCallback
;
35 import android
.webkit
.WebBackForwardList
;
36 import android
.webkit
.WebChromeClient
;
37 import android
.webkit
.WebChromeClient
.CustomViewCallback
;
38 import android
.webkit
.WebSettings
;
39 import android
.webkit
.WebView
;
40 import android
.webkit
.WebViewClient
;
41 import android
.webkit
.WebViewProvider
;
42 import android
.widget
.TextView
;
44 import org
.chromium
.android_webview
.AwContents
;
45 import org
.chromium
.android_webview
.AwContentsStatics
;
46 import org
.chromium
.android_webview
.AwPrintDocumentAdapter
;
47 import org
.chromium
.android_webview
.AwSettings
;
48 import org
.chromium
.base
.ThreadUtils
;
49 import org
.chromium
.base
.annotations
.SuppressFBWarnings
;
50 import org
.chromium
.content
.browser
.SmartClipProvider
;
52 import java
.io
.BufferedWriter
;
55 import java
.util
.Queue
;
56 import java
.util
.concurrent
.Callable
;
57 import java
.util
.concurrent
.ConcurrentLinkedQueue
;
58 import java
.util
.concurrent
.FutureTask
;
59 import java
.util
.concurrent
.TimeUnit
;
62 * This class is the delegate to which WebViewProxy forwards all API calls.
64 * Most of the actual functionality is implemented by AwContents (or ContentViewCore within
65 * it). This class also contains WebView-specific APIs that require the creation of other
66 * adapters (otherwise org.chromium.content would depend on the webview.chromium package)
67 * and a small set of no-op deprecated APIs.
69 @SuppressWarnings("deprecation")
70 class WebViewChromium
implements WebViewProvider
, WebViewProvider
.ScrollDelegate
,
71 WebViewProvider
.ViewDelegate
, SmartClipProvider
{
72 private class WebViewChromiumRunQueue
{
73 public WebViewChromiumRunQueue() {
74 mQueue
= new ConcurrentLinkedQueue
<Runnable
>();
77 public void addTask(Runnable task
) {
79 if (mFactory
.hasStarted()) {
80 ThreadUtils
.runOnUiThread(new Runnable() {
89 public void drainQueue() {
90 if (mQueue
== null || mQueue
.isEmpty()) {
94 Runnable task
= mQueue
.poll();
95 while (task
!= null) {
101 private Queue
<Runnable
> mQueue
;
104 private WebViewChromiumRunQueue mRunQueue
;
106 private static final String TAG
= WebViewChromium
.class.getSimpleName();
108 // The WebView that this WebViewChromium is the provider for.
110 // Lets us access protected View-derived methods on the WebView instance we're backing.
111 WebView
.PrivateAccess mWebViewPrivate
;
112 // The client adapter class.
113 private WebViewContentsClientAdapter mContentsClientAdapter
;
114 // The wrapped Context.
115 private Context mContext
;
117 // Variables for functionality provided by this adapter ---------------------------------------
118 private ContentSettingsAdapter mWebSettings
;
119 // The WebView wrapper for ContentViewCore and required browser compontents.
120 private AwContents mAwContents
;
121 // Non-null if this webview is using the GL accelerated draw path.
122 private DrawGLFunctor mGLfunctor
;
124 private final WebView
.HitTestResult mHitTestResult
;
126 private final int mAppTargetSdkVersion
;
128 private WebViewChromiumFactoryProvider mFactory
;
130 private static boolean sRecordWholeDocumentEnabledByApi
= false;
131 static void enableSlowWholeDocumentDraw() {
132 sRecordWholeDocumentEnabledByApi
= true;
135 // This does not touch any global / non-threadsafe state, but note that
136 // init is ofter called right after and is NOT threadsafe.
137 public WebViewChromium(WebViewChromiumFactoryProvider factory
, WebView webView
,
138 WebView
.PrivateAccess webViewPrivate
) {
140 mWebViewPrivate
= webViewPrivate
;
141 mHitTestResult
= new WebView
.HitTestResult();
142 mContext
= ResourcesContextWrapperFactory
.get(mWebView
.getContext());
143 mAppTargetSdkVersion
= mContext
.getApplicationInfo().targetSdkVersion
;
145 mRunQueue
= new WebViewChromiumRunQueue();
146 factory
.getWebViewDelegate().addWebViewAssetPath(mWebView
.getContext());
149 static void completeWindowCreation(WebView parent
, WebView child
) {
150 AwContents parentContents
= ((WebViewChromium
) parent
.getWebViewProvider()).mAwContents
;
151 AwContents childContents
=
152 child
== null ?
null : ((WebViewChromium
) child
.getWebViewProvider()).mAwContents
;
153 parentContents
.supplyContentsForPopup(childContents
);
156 private <T
> T
runBlockingFuture(FutureTask
<T
> task
) {
157 if (!mFactory
.hasStarted()) throw new RuntimeException("Must be started before we block!");
158 if (ThreadUtils
.runningOnUiThread()) {
159 throw new IllegalStateException("This method should only be called off the UI thread");
161 mRunQueue
.addTask(task
);
163 return task
.get(4, TimeUnit
.SECONDS
);
164 } catch (java
.util
.concurrent
.TimeoutException e
) {
165 throw new RuntimeException("Probable deadlock detected due to WebView API being called "
166 + "on incorrect thread while the UI thread is blocked.", e
);
167 } catch (Exception e
) {
168 throw new RuntimeException(e
);
172 // We have a 4 second timeout to try to detect deadlocks to detect and aid in debuggin
174 // Do not call this method while on the UI thread!
175 private void runVoidTaskOnUiThreadBlocking(Runnable r
) {
176 FutureTask
<Void
> task
= new FutureTask
<Void
>(r
, null);
177 runBlockingFuture(task
);
180 private <T
> T
runOnUiThreadBlocking(Callable
<T
> c
) {
181 return runBlockingFuture(new FutureTask
<T
>(c
));
184 // WebViewProvider methods --------------------------------------------------------------------
187 // BUG=6790250 |javaScriptInterfaces| was only ever used by the obsolete DumpRenderTree
188 // so is ignored. TODO: remove it from WebViewProvider.
189 public void init(final Map
<String
, Object
> javaScriptInterfaces
,
190 final boolean privateBrowsing
) {
191 if (privateBrowsing
) {
192 mFactory
.startYourEngines(true);
193 final String msg
= "Private browsing is not supported in WebView.";
194 if (mAppTargetSdkVersion
>= Build
.VERSION_CODES
.KITKAT
) {
195 throw new IllegalArgumentException(msg
);
198 TextView warningLabel
= new TextView(mContext
);
199 warningLabel
.setText(mContext
.getString(R
.string
.private_browsing_warning
));
200 mWebView
.addView(warningLabel
);
204 // We will defer real initialization until we know which thread to do it on, unless:
205 // - we are on the main thread already (common case),
206 // - the app is targeting >= JB MR2, in which case checkThread enforces that all usage
207 // comes from a single thread. (Note in JB MR2 this exception was in WebView.java).
208 if (mAppTargetSdkVersion
>= Build
.VERSION_CODES
.JELLY_BEAN_MR2
) {
209 mFactory
.startYourEngines(false);
211 } else if (!mFactory
.hasStarted()) {
212 if (Looper
.myLooper() == Looper
.getMainLooper()) {
213 mFactory
.startYourEngines(true);
217 final boolean isAccessFromFileURLsGrantedByDefault
=
218 mAppTargetSdkVersion
< Build
.VERSION_CODES
.JELLY_BEAN
;
219 final boolean areLegacyQuirksEnabled
= mAppTargetSdkVersion
< Build
.VERSION_CODES
.KITKAT
;
221 mContentsClientAdapter
=
222 new WebViewContentsClientAdapter(mWebView
, mContext
, mFactory
.getWebViewDelegate());
223 mWebSettings
= new ContentSettingsAdapter(new AwSettings(
224 mContext
, isAccessFromFileURLsGrantedByDefault
, areLegacyQuirksEnabled
));
226 if (mAppTargetSdkVersion
< Build
.VERSION_CODES
.LOLLIPOP
) {
227 // Prior to Lollipop we always allowed third party cookies and mixed content.
228 mWebSettings
.setMixedContentMode(WebSettings
.MIXED_CONTENT_ALWAYS_ALLOW
);
229 mWebSettings
.setAcceptThirdPartyCookies(true);
230 mWebSettings
.getAwSettings().setZeroLayoutHeightDisablesViewportQuirk(true);
233 mRunQueue
.addTask(new Runnable() {
237 if (privateBrowsing
) {
238 // Intentionally irreversibly disable the webview instance, so that private
239 // user data cannot leak through misuse of a non-privateBrowing WebView
240 // instance. Can't just null out mAwContents as we never null-check it
248 private void initForReal() {
249 mAwContents
= new AwContents(mFactory
.getBrowserContext(), mWebView
, mContext
,
250 new InternalAccessAdapter(), new WebViewNativeGLDelegate(), mContentsClientAdapter
,
251 mWebSettings
.getAwSettings());
253 if (mAppTargetSdkVersion
>= Build
.VERSION_CODES
.KITKAT
) {
254 // On KK and above, favicons are automatically downloaded as the method
255 // old apps use to enable that behavior is deprecated.
256 AwContents
.setShouldDownloadFavicons();
259 AwContentsStatics
.setRecordFullDocument(sRecordWholeDocumentEnabledByApi
260 || mAppTargetSdkVersion
< Build
.VERSION_CODES
.LOLLIPOP
);
262 if (mAppTargetSdkVersion
< Build
.VERSION_CODES
.LOLLIPOP
) {
263 // Prior to Lollipop, JavaScript objects injected via addJavascriptInterface
264 // were not inspectable.
265 mAwContents
.disableJavascriptInterfacesInspection();
268 // TODO: This assumes AwContents ignores second Paint param.
269 mAwContents
.setLayerType(mWebView
.getLayerType(), null);
272 void startYourEngine() {
273 mRunQueue
.drainQueue();
276 private RuntimeException
createThreadException() {
277 return new IllegalStateException(
278 "Calling View methods on another thread than the UI thread.");
281 private boolean checkNeedsPost() {
282 boolean needsPost
= !mFactory
.hasStarted() || !ThreadUtils
.runningOnUiThread();
283 if (!needsPost
&& mAwContents
== null) {
284 throw new IllegalStateException("AwContents must be created if we are not posting!");
289 // Intentionally not static, as no need to check thread on static methods
290 private void checkThread() {
291 if (!ThreadUtils
.runningOnUiThread()) {
292 final RuntimeException threadViolation
= createThreadException();
293 ThreadUtils
.postOnUiThread(new Runnable() {
296 throw threadViolation
;
299 throw createThreadException();
304 public void setHorizontalScrollbarOverlay(final boolean overlay
) {
305 if (checkNeedsPost()) {
306 mRunQueue
.addTask(new Runnable() {
309 setHorizontalScrollbarOverlay(overlay
);
314 mAwContents
.setHorizontalScrollbarOverlay(overlay
);
318 public void setVerticalScrollbarOverlay(final boolean overlay
) {
319 if (checkNeedsPost()) {
320 mRunQueue
.addTask(new Runnable() {
323 setVerticalScrollbarOverlay(overlay
);
328 mAwContents
.setVerticalScrollbarOverlay(overlay
);
332 public boolean overlayHorizontalScrollbar() {
333 mFactory
.startYourEngines(false);
334 if (checkNeedsPost()) {
335 boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
337 public Boolean
call() {
338 return overlayHorizontalScrollbar();
343 return mAwContents
.overlayHorizontalScrollbar();
347 public boolean overlayVerticalScrollbar() {
348 mFactory
.startYourEngines(false);
349 if (checkNeedsPost()) {
350 boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
352 public Boolean
call() {
353 return overlayVerticalScrollbar();
358 return mAwContents
.overlayVerticalScrollbar();
362 public int getVisibleTitleHeight() {
363 // This is deprecated in WebView and should always return 0.
368 public SslCertificate
getCertificate() {
369 mFactory
.startYourEngines(true);
370 if (checkNeedsPost()) {
371 SslCertificate ret
= runOnUiThreadBlocking(new Callable
<SslCertificate
>() {
373 public SslCertificate
call() {
374 return getCertificate();
379 return mAwContents
.getCertificate();
383 public void setCertificate(SslCertificate certificate
) {
388 public void savePassword(String host
, String username
, String password
) {
389 // This is a deprecated API: intentional no-op.
393 public void setHttpAuthUsernamePassword(
394 final String host
, final String realm
, final String username
, final String password
) {
395 if (checkNeedsPost()) {
396 mRunQueue
.addTask(new Runnable() {
399 setHttpAuthUsernamePassword(host
, realm
, username
, password
);
404 mAwContents
.setHttpAuthUsernamePassword(host
, realm
, username
, password
);
408 public String
[] getHttpAuthUsernamePassword(final String host
, final String realm
) {
409 mFactory
.startYourEngines(true);
410 if (checkNeedsPost()) {
411 String
[] ret
= runOnUiThreadBlocking(new Callable
<String
[]>() {
413 public String
[] call() {
414 return getHttpAuthUsernamePassword(host
, realm
);
419 return mAwContents
.getHttpAuthUsernamePassword(host
, realm
);
423 public void destroy() {
424 if (checkNeedsPost()) {
425 mRunQueue
.addTask(new Runnable() {
434 mAwContents
.destroy();
435 if (mGLfunctor
!= null) {
436 mGLfunctor
.destroy();
442 public void setNetworkAvailable(final boolean networkUp
) {
443 // Note that this purely toggles the JS navigator.online property.
444 // It does not in affect chromium or network stack state in any way.
445 if (checkNeedsPost()) {
446 mRunQueue
.addTask(new Runnable() {
449 setNetworkAvailable(networkUp
);
454 mAwContents
.setNetworkAvailable(networkUp
);
458 public WebBackForwardList
saveState(final Bundle outState
) {
459 mFactory
.startYourEngines(true);
460 if (checkNeedsPost()) {
461 WebBackForwardList ret
= runOnUiThreadBlocking(new Callable
<WebBackForwardList
>() {
463 public WebBackForwardList
call() {
464 return saveState(outState
);
469 if (outState
== null) return null;
470 if (!mAwContents
.saveState(outState
)) return null;
471 return copyBackForwardList();
475 public boolean savePicture(Bundle b
, File dest
) {
476 // Intentional no-op: hidden method on WebView.
481 public boolean restorePicture(Bundle b
, File src
) {
482 // Intentional no-op: hidden method on WebView.
487 public WebBackForwardList
restoreState(final Bundle inState
) {
488 mFactory
.startYourEngines(true);
489 if (checkNeedsPost()) {
490 WebBackForwardList ret
= runOnUiThreadBlocking(new Callable
<WebBackForwardList
>() {
492 public WebBackForwardList
call() {
493 return restoreState(inState
);
498 if (inState
== null) return null;
499 if (!mAwContents
.restoreState(inState
)) return null;
500 return copyBackForwardList();
504 public void loadUrl(final String url
, final Map
<String
, String
> additionalHttpHeaders
) {
505 mFactory
.startYourEngines(true);
506 if (checkNeedsPost()) {
507 // Disallowed in WebView API for apps targetting a new SDK
508 assert mAppTargetSdkVersion
< Build
.VERSION_CODES
.JELLY_BEAN_MR2
;
509 mRunQueue
.addTask(new Runnable() {
512 mAwContents
.loadUrl(url
, additionalHttpHeaders
);
517 mAwContents
.loadUrl(url
, additionalHttpHeaders
);
521 public void loadUrl(final String url
) {
522 mFactory
.startYourEngines(true);
523 if (checkNeedsPost()) {
524 // Disallowed in WebView API for apps targetting a new SDK
525 assert mAppTargetSdkVersion
< Build
.VERSION_CODES
.JELLY_BEAN_MR2
;
526 mRunQueue
.addTask(new Runnable() {
529 mAwContents
.loadUrl(url
);
534 mAwContents
.loadUrl(url
);
538 public void postUrl(final String url
, final byte[] postData
) {
539 mFactory
.startYourEngines(true);
540 if (checkNeedsPost()) {
541 // Disallowed in WebView API for apps targetting a new SDK
542 assert mAppTargetSdkVersion
< Build
.VERSION_CODES
.JELLY_BEAN_MR2
;
543 mRunQueue
.addTask(new Runnable() {
546 mAwContents
.postUrl(url
, postData
);
551 mAwContents
.postUrl(url
, postData
);
555 public void loadData(final String data
, final String mimeType
, final String encoding
) {
556 mFactory
.startYourEngines(true);
557 if (checkNeedsPost()) {
558 // Disallowed in WebView API for apps targetting a new SDK
559 assert mAppTargetSdkVersion
< Build
.VERSION_CODES
.JELLY_BEAN_MR2
;
560 mRunQueue
.addTask(new Runnable() {
563 mAwContents
.loadData(data
, mimeType
, encoding
);
568 mAwContents
.loadData(data
, mimeType
, encoding
);
572 public void loadDataWithBaseURL(final String baseUrl
, final String data
, final String mimeType
,
573 final String encoding
, final String historyUrl
) {
574 mFactory
.startYourEngines(true);
575 if (checkNeedsPost()) {
576 // Disallowed in WebView API for apps targetting a new SDK
577 assert mAppTargetSdkVersion
< Build
.VERSION_CODES
.JELLY_BEAN_MR2
;
578 mRunQueue
.addTask(new Runnable() {
581 mAwContents
.loadDataWithBaseURL(baseUrl
, data
, mimeType
, encoding
, historyUrl
);
586 mAwContents
.loadDataWithBaseURL(baseUrl
, data
, mimeType
, encoding
, historyUrl
);
589 public void evaluateJavaScript(String script
, ValueCallback
<String
> resultCallback
) {
591 mAwContents
.evaluateJavaScript(script
, resultCallback
);
595 public void saveWebArchive(String filename
) {
596 saveWebArchive(filename
, false, null);
600 public void saveWebArchive(final String basename
, final boolean autoname
,
601 final ValueCallback
<String
> callback
) {
602 if (checkNeedsPost()) {
603 mRunQueue
.addTask(new Runnable() {
606 saveWebArchive(basename
, autoname
, callback
);
611 mAwContents
.saveWebArchive(basename
, autoname
, callback
);
615 public void stopLoading() {
616 if (checkNeedsPost()) {
617 mRunQueue
.addTask(new Runnable() {
626 mAwContents
.stopLoading();
630 public void reload() {
631 if (checkNeedsPost()) {
632 mRunQueue
.addTask(new Runnable() {
640 mAwContents
.reload();
644 public boolean canGoBack() {
645 mFactory
.startYourEngines(true);
646 if (checkNeedsPost()) {
647 Boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
649 public Boolean
call() {
655 return mAwContents
.canGoBack();
659 public void goBack() {
660 if (checkNeedsPost()) {
661 mRunQueue
.addTask(new Runnable() {
669 mAwContents
.goBack();
673 public boolean canGoForward() {
674 mFactory
.startYourEngines(true);
675 if (checkNeedsPost()) {
676 Boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
678 public Boolean
call() {
679 return canGoForward();
684 return mAwContents
.canGoForward();
688 public void goForward() {
689 if (checkNeedsPost()) {
690 mRunQueue
.addTask(new Runnable() {
698 mAwContents
.goForward();
702 public boolean canGoBackOrForward(final int steps
) {
703 mFactory
.startYourEngines(true);
704 if (checkNeedsPost()) {
705 Boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
707 public Boolean
call() {
708 return canGoBackOrForward(steps
);
713 return mAwContents
.canGoBackOrForward(steps
);
717 public void goBackOrForward(final int steps
) {
718 if (checkNeedsPost()) {
719 mRunQueue
.addTask(new Runnable() {
722 goBackOrForward(steps
);
727 mAwContents
.goBackOrForward(steps
);
731 public boolean isPrivateBrowsingEnabled() {
732 // Not supported in this WebView implementation.
737 public boolean pageUp(final boolean top
) {
738 mFactory
.startYourEngines(true);
739 if (checkNeedsPost()) {
740 Boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
742 public Boolean
call() {
748 return mAwContents
.pageUp(top
);
752 public boolean pageDown(final boolean bottom
) {
753 mFactory
.startYourEngines(true);
754 if (checkNeedsPost()) {
755 Boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
757 public Boolean
call() {
758 return pageDown(bottom
);
763 return mAwContents
.pageDown(bottom
);
767 public void clearView() {
768 if (checkNeedsPost()) {
769 mRunQueue
.addTask(new Runnable() {
777 mAwContents
.clearView();
781 public Picture
capturePicture() {
782 mFactory
.startYourEngines(true);
783 if (checkNeedsPost()) {
784 Picture ret
= runOnUiThreadBlocking(new Callable
<Picture
>() {
786 public Picture
call() {
787 return capturePicture();
792 return mAwContents
.capturePicture();
796 public float getScale() {
797 // No checkThread() as it is mostly thread safe (workaround for b/10652991).
798 mFactory
.startYourEngines(true);
799 return mAwContents
.getScale();
803 public void setInitialScale(final int scaleInPercent
) {
804 // No checkThread() as it is thread safe
805 mWebSettings
.getAwSettings().setInitialPageScale(scaleInPercent
);
809 public void invokeZoomPicker() {
810 if (checkNeedsPost()) {
811 mRunQueue
.addTask(new Runnable() {
819 mAwContents
.invokeZoomPicker();
823 public WebView
.HitTestResult
getHitTestResult() {
824 mFactory
.startYourEngines(true);
825 if (checkNeedsPost()) {
826 WebView
.HitTestResult ret
=
827 runOnUiThreadBlocking(new Callable
<WebView
.HitTestResult
>() {
829 public WebView
.HitTestResult
call() {
830 return getHitTestResult();
835 AwContents
.HitTestData data
= mAwContents
.getLastHitTestResult();
836 mHitTestResult
.setType(data
.hitTestResultType
);
837 mHitTestResult
.setExtra(data
.hitTestResultExtraData
);
838 return mHitTestResult
;
842 public void requestFocusNodeHref(final Message hrefMsg
) {
843 if (checkNeedsPost()) {
844 mRunQueue
.addTask(new Runnable() {
847 requestFocusNodeHref(hrefMsg
);
852 mAwContents
.requestFocusNodeHref(hrefMsg
);
856 public void requestImageRef(final Message msg
) {
857 if (checkNeedsPost()) {
858 mRunQueue
.addTask(new Runnable() {
861 requestImageRef(msg
);
866 mAwContents
.requestImageRef(msg
);
870 public String
getUrl() {
871 mFactory
.startYourEngines(true);
872 if (checkNeedsPost()) {
873 String ret
= runOnUiThreadBlocking(new Callable
<String
>() {
875 public String
call() {
881 return mAwContents
.getUrl();
885 public String
getOriginalUrl() {
886 mFactory
.startYourEngines(true);
887 if (checkNeedsPost()) {
888 String ret
= runOnUiThreadBlocking(new Callable
<String
>() {
890 public String
call() {
891 return getOriginalUrl();
896 return mAwContents
.getOriginalUrl();
900 public String
getTitle() {
901 mFactory
.startYourEngines(true);
902 if (checkNeedsPost()) {
903 String ret
= runOnUiThreadBlocking(new Callable
<String
>() {
905 public String
call() {
911 return mAwContents
.getTitle();
915 public Bitmap
getFavicon() {
916 mFactory
.startYourEngines(true);
917 if (checkNeedsPost()) {
918 Bitmap ret
= runOnUiThreadBlocking(new Callable
<Bitmap
>() {
920 public Bitmap
call() {
926 return mAwContents
.getFavicon();
930 public String
getTouchIconUrl() {
931 // Intentional no-op: hidden method on WebView.
936 public int getProgress() {
937 if (mAwContents
== null) return 100;
938 // No checkThread() because the value is cached java side (workaround for b/10533304).
939 return mAwContents
.getMostRecentProgress();
943 public int getContentHeight() {
944 if (mAwContents
== null) return 0;
945 // No checkThread() as it is mostly thread safe (workaround for b/10594869).
946 return mAwContents
.getContentHeightCss();
950 public int getContentWidth() {
951 if (mAwContents
== null) return 0;
952 // No checkThread() as it is mostly thread safe (workaround for b/10594869).
953 return mAwContents
.getContentWidthCss();
957 public void pauseTimers() {
958 if (checkNeedsPost()) {
959 mRunQueue
.addTask(new Runnable() {
967 mAwContents
.pauseTimers();
971 public void resumeTimers() {
972 if (checkNeedsPost()) {
973 mRunQueue
.addTask(new Runnable() {
981 mAwContents
.resumeTimers();
985 public void onPause() {
986 if (checkNeedsPost()) {
987 mRunQueue
.addTask(new Runnable() {
995 mAwContents
.onPause();
999 public void onResume() {
1000 if (checkNeedsPost()) {
1001 mRunQueue
.addTask(new Runnable() {
1009 mAwContents
.onResume();
1013 public boolean isPaused() {
1014 mFactory
.startYourEngines(true);
1015 if (checkNeedsPost()) {
1016 Boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
1018 public Boolean
call() {
1024 return mAwContents
.isPaused();
1028 public void freeMemory() {
1029 // Intentional no-op. Memory is managed automatically by Chromium.
1033 public void clearCache(final boolean includeDiskFiles
) {
1034 if (checkNeedsPost()) {
1035 mRunQueue
.addTask(new Runnable() {
1038 clearCache(includeDiskFiles
);
1043 mAwContents
.clearCache(includeDiskFiles
);
1047 * This is a poorly named method, but we keep it for historical reasons.
1050 public void clearFormData() {
1051 if (checkNeedsPost()) {
1052 mRunQueue
.addTask(new Runnable() {
1060 mAwContents
.hideAutofillPopup();
1064 public void clearHistory() {
1065 if (checkNeedsPost()) {
1066 mRunQueue
.addTask(new Runnable() {
1074 mAwContents
.clearHistory();
1078 public void clearSslPreferences() {
1079 if (checkNeedsPost()) {
1080 mRunQueue
.addTask(new Runnable() {
1083 clearSslPreferences();
1088 mAwContents
.clearSslPreferences();
1092 public WebBackForwardList
copyBackForwardList() {
1093 mFactory
.startYourEngines(true);
1094 if (checkNeedsPost()) {
1095 WebBackForwardList ret
= runOnUiThreadBlocking(new Callable
<WebBackForwardList
>() {
1097 public WebBackForwardList
call() {
1098 return copyBackForwardList();
1103 return new WebBackForwardListChromium(mAwContents
.getNavigationHistory());
1107 public void setFindListener(WebView
.FindListener listener
) {
1108 mContentsClientAdapter
.setFindListener(listener
);
1112 public void findNext(final boolean forwards
) {
1113 if (checkNeedsPost()) {
1114 mRunQueue
.addTask(new Runnable() {
1122 mAwContents
.findNext(forwards
);
1126 public int findAll(final String searchString
) {
1127 findAllAsync(searchString
);
1132 public void findAllAsync(final String searchString
) {
1133 if (checkNeedsPost()) {
1134 mRunQueue
.addTask(new Runnable() {
1137 findAllAsync(searchString
);
1142 mAwContents
.findAllAsync(searchString
);
1145 @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE")
1147 public boolean showFindDialog(final String text
, final boolean showIme
) {
1148 mFactory
.startYourEngines(false);
1149 if (checkNeedsPost()) {
1152 if (mWebView
.getParent() == null) {
1156 FindActionModeCallback findAction
= new FindActionModeCallback(mContext
);
1157 if (findAction
== null) {
1161 mWebView
.startActionMode(findAction
);
1162 findAction
.setWebView(mWebView
);
1164 findAction
.showSoftInput();
1168 findAction
.setText(text
);
1169 findAction
.findAll();
1176 public void notifyFindDialogDismissed() {
1177 if (checkNeedsPost()) {
1178 mRunQueue
.addTask(new Runnable() {
1181 notifyFindDialogDismissed();
1190 public void clearMatches() {
1191 if (checkNeedsPost()) {
1192 mRunQueue
.addTask(new Runnable() {
1200 mAwContents
.clearMatches();
1204 public void documentHasImages(final Message response
) {
1205 if (checkNeedsPost()) {
1206 mRunQueue
.addTask(new Runnable() {
1209 documentHasImages(response
);
1214 mAwContents
.documentHasImages(response
);
1218 public void setWebViewClient(WebViewClient client
) {
1219 mContentsClientAdapter
.setWebViewClient(client
);
1223 public void setDownloadListener(DownloadListener listener
) {
1224 mContentsClientAdapter
.setDownloadListener(listener
);
1228 public void setWebChromeClient(WebChromeClient client
) {
1229 mWebSettings
.getAwSettings().setFullscreenSupported(doesSupportFullscreen(client
));
1230 mContentsClientAdapter
.setWebChromeClient(client
);
1234 * Returns true if the supplied {@link WebChromeClient} supports fullscreen.
1236 * <p>For fullscreen support, implementations of {@link WebChromeClient#onShowCustomView}
1237 * and {@link WebChromeClient#onHideCustomView()} are required.
1239 private boolean doesSupportFullscreen(WebChromeClient client
) {
1240 if (client
== null) {
1243 Class
<?
> clientClass
= client
.getClass();
1244 boolean foundShowMethod
= false;
1245 boolean foundHideMethod
= false;
1246 while (clientClass
!= WebChromeClient
.class && (!foundShowMethod
|| !foundHideMethod
)) {
1247 if (!foundShowMethod
) {
1249 clientClass
.getDeclaredMethod(
1250 "onShowCustomView", View
.class, CustomViewCallback
.class);
1251 foundShowMethod
= true;
1252 } catch (NoSuchMethodException e
) {
1253 // Intentionally empty.
1257 if (!foundHideMethod
) {
1259 clientClass
.getDeclaredMethod("onHideCustomView");
1260 foundHideMethod
= true;
1261 } catch (NoSuchMethodException e
) {
1262 // Intentionally empty.
1265 clientClass
= clientClass
.getSuperclass();
1267 return foundShowMethod
&& foundHideMethod
;
1271 @SuppressWarnings("deprecation")
1272 public void setPictureListener(final WebView
.PictureListener listener
) {
1273 if (checkNeedsPost()) {
1274 mRunQueue
.addTask(new Runnable() {
1277 setPictureListener(listener
);
1282 mContentsClientAdapter
.setPictureListener(listener
);
1283 mAwContents
.enableOnNewPicture(
1284 listener
!= null, mAppTargetSdkVersion
>= Build
.VERSION_CODES
.JELLY_BEAN_MR2
);
1288 public void addJavascriptInterface(final Object obj
, final String interfaceName
) {
1289 if (checkNeedsPost()) {
1290 mRunQueue
.addTask(new Runnable() {
1293 addJavascriptInterface(obj
, interfaceName
);
1298 mAwContents
.addJavascriptInterface(obj
, interfaceName
);
1302 public void removeJavascriptInterface(final String interfaceName
) {
1303 if (checkNeedsPost()) {
1304 mRunQueue
.addTask(new Runnable() {
1307 removeJavascriptInterface(interfaceName
);
1312 mAwContents
.removeJavascriptInterface(interfaceName
);
1316 public WebSettings
getSettings() {
1317 return mWebSettings
;
1321 public void setMapTrackballToArrowKeys(boolean setMap
) {
1322 // This is a deprecated API: intentional no-op.
1326 public void flingScroll(final int vx
, final int vy
) {
1327 if (checkNeedsPost()) {
1328 mRunQueue
.addTask(new Runnable() {
1331 flingScroll(vx
, vy
);
1336 mAwContents
.flingScroll(vx
, vy
);
1340 public View
getZoomControls() {
1341 mFactory
.startYourEngines(false);
1342 if (checkNeedsPost()) {
1346 // This was deprecated in 2009 and hidden in JB MR1, so just provide the minimum needed
1347 // to stop very out-dated applications from crashing.
1348 Log
.w(TAG
, "WebView doesn't support getZoomControls");
1349 return mAwContents
.getSettings().supportZoom() ?
new View(mContext
) : null;
1353 public boolean canZoomIn() {
1354 if (checkNeedsPost()) {
1357 return mAwContents
.canZoomIn();
1361 public boolean canZoomOut() {
1362 if (checkNeedsPost()) {
1365 return mAwContents
.canZoomOut();
1369 public boolean zoomIn() {
1370 mFactory
.startYourEngines(true);
1371 if (checkNeedsPost()) {
1372 boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
1374 public Boolean
call() {
1380 return mAwContents
.zoomIn();
1384 public boolean zoomOut() {
1385 mFactory
.startYourEngines(true);
1386 if (checkNeedsPost()) {
1387 boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
1389 public Boolean
call() {
1395 return mAwContents
.zoomOut();
1398 // TODO(paulmiller) Return void for consistency with AwContents.zoomBy and WebView.zoomBy -
1399 // tricky because frameworks WebViewProvider.zoomBy must change simultaneously
1401 public boolean zoomBy(float factor
) {
1402 mFactory
.startYourEngines(true);
1403 // This is an L API and therefore we can enforce stricter threading constraints.
1405 mAwContents
.zoomBy(factor
);
1410 public void dumpViewHierarchyWithProperties(BufferedWriter out
, int level
) {
1411 // Intentional no-op
1415 public View
findHierarchyView(String className
, int hashCode
) {
1416 // Intentional no-op
1420 // WebViewProvider glue methods ---------------------------------------------------------------
1423 // This needs to be kept thread safe!
1424 public WebViewProvider
.ViewDelegate
getViewDelegate() {
1429 // This needs to be kept thread safe!
1430 public WebViewProvider
.ScrollDelegate
getScrollDelegate() {
1434 // WebViewProvider.ViewDelegate implementation ------------------------------------------------
1436 // TODO: remove from WebViewProvider and use default implementation from
1439 public boolean shouldDelayChildPressedState() {
1440 mFactory
.startYourEngines(false);
1441 if (checkNeedsPost()) {
1442 boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
1444 public Boolean
call() {
1445 return shouldDelayChildPressedState();
1454 public AccessibilityNodeProvider
getAccessibilityNodeProvider() {
1455 mFactory
.startYourEngines(false);
1456 if (checkNeedsPost()) {
1457 AccessibilityNodeProvider ret
=
1458 runOnUiThreadBlocking(new Callable
<AccessibilityNodeProvider
>() {
1460 public AccessibilityNodeProvider
call() {
1461 return getAccessibilityNodeProvider();
1466 return mAwContents
.getAccessibilityNodeProvider();
1470 public void onInitializeAccessibilityNodeInfo(final AccessibilityNodeInfo info
) {
1471 mFactory
.startYourEngines(false);
1472 if (checkNeedsPost()) {
1473 runVoidTaskOnUiThreadBlocking(new Runnable() {
1476 onInitializeAccessibilityNodeInfo(info
);
1481 mAwContents
.onInitializeAccessibilityNodeInfo(info
);
1485 public void onInitializeAccessibilityEvent(final AccessibilityEvent event
) {
1486 mFactory
.startYourEngines(false);
1487 if (checkNeedsPost()) {
1488 runVoidTaskOnUiThreadBlocking(new Runnable() {
1491 onInitializeAccessibilityEvent(event
);
1496 mAwContents
.onInitializeAccessibilityEvent(event
);
1500 public boolean performAccessibilityAction(final int action
, final Bundle arguments
) {
1501 mFactory
.startYourEngines(false);
1502 if (checkNeedsPost()) {
1503 boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
1505 public Boolean
call() {
1506 return performAccessibilityAction(action
, arguments
);
1511 if (mAwContents
.supportsAccessibilityAction(action
)) {
1512 return mAwContents
.performAccessibilityAction(action
, arguments
);
1514 return mWebViewPrivate
.super_performAccessibilityAction(action
, arguments
);
1518 public void setOverScrollMode(final int mode
) {
1519 // This gets called from the android.view.View c'tor that WebView inherits from. This
1520 // causes the method to be called when mAwContents == null.
1521 // It's safe to ignore these calls however since AwContents will read the current value of
1522 // this setting when it's created.
1523 if (mAwContents
== null) return;
1525 if (checkNeedsPost()) {
1526 mRunQueue
.addTask(new Runnable() {
1529 setOverScrollMode(mode
);
1534 mAwContents
.setOverScrollMode(mode
);
1538 public void setScrollBarStyle(final int style
) {
1539 if (checkNeedsPost()) {
1540 mRunQueue
.addTask(new Runnable() {
1543 setScrollBarStyle(style
);
1548 mAwContents
.setScrollBarStyle(style
);
1552 public void onDrawVerticalScrollBar(final Canvas canvas
, final Drawable scrollBar
, final int l
,
1553 final int t
, final int r
, final int b
) {
1554 // WebViewClassic was overriding this method to handle rubberband over-scroll. Since
1555 // WebViewChromium doesn't support that the vanilla implementation of this method can be
1557 mWebViewPrivate
.super_onDrawVerticalScrollBar(canvas
, scrollBar
, l
, t
, r
, b
);
1561 public void onOverScrolled(final int scrollX
, final int scrollY
,
1562 final boolean clampedX
, final boolean clampedY
) {
1563 if (checkNeedsPost()) {
1564 mRunQueue
.addTask(new Runnable() {
1567 onOverScrolled(scrollX
, scrollY
, clampedX
, clampedY
);
1572 mAwContents
.onContainerViewOverScrolled(scrollX
, scrollY
, clampedX
, clampedY
);
1576 public void onWindowVisibilityChanged(final int visibility
) {
1577 if (checkNeedsPost()) {
1578 mRunQueue
.addTask(new Runnable() {
1581 onWindowVisibilityChanged(visibility
);
1586 mAwContents
.onWindowVisibilityChanged(visibility
);
1590 public void onDraw(final Canvas canvas
) {
1591 mFactory
.startYourEngines(true);
1592 if (checkNeedsPost()) {
1593 runVoidTaskOnUiThreadBlocking(new Runnable() {
1601 mAwContents
.onDraw(canvas
);
1605 public void setLayoutParams(final ViewGroup
.LayoutParams layoutParams
) {
1606 // This API is our strongest signal from the View system that this
1607 // WebView is going to be bound to a View hierarchy and so at this
1608 // point we must bind Chromium's UI thread to the current thread.
1609 mFactory
.startYourEngines(false);
1611 mWebViewPrivate
.super_setLayoutParams(layoutParams
);
1615 public boolean performLongClick() {
1616 // Return false unless the WebView is attached to a View with a parent
1617 return mWebView
.getParent() != null ? mWebViewPrivate
.super_performLongClick() : false;
1621 public void onConfigurationChanged(final Configuration newConfig
) {
1622 if (checkNeedsPost()) {
1623 mRunQueue
.addTask(new Runnable() {
1626 onConfigurationChanged(newConfig
);
1631 mAwContents
.onConfigurationChanged(newConfig
);
1635 public InputConnection
onCreateInputConnection(final EditorInfo outAttrs
) {
1636 mFactory
.startYourEngines(false);
1637 if (checkNeedsPost()) {
1640 return mAwContents
.onCreateInputConnection(outAttrs
);
1644 public boolean onKeyMultiple(final int keyCode
, final int repeatCount
, final KeyEvent event
) {
1645 mFactory
.startYourEngines(false);
1646 if (checkNeedsPost()) {
1647 boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
1649 public Boolean
call() {
1650 return onKeyMultiple(keyCode
, repeatCount
, event
);
1659 public boolean onKeyDown(final int keyCode
, final KeyEvent event
) {
1660 mFactory
.startYourEngines(false);
1661 if (checkNeedsPost()) {
1662 boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
1664 public Boolean
call() {
1665 return onKeyDown(keyCode
, event
);
1674 public boolean onKeyUp(final int keyCode
, final KeyEvent event
) {
1675 mFactory
.startYourEngines(false);
1676 if (checkNeedsPost()) {
1677 boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
1679 public Boolean
call() {
1680 return onKeyUp(keyCode
, event
);
1685 return mAwContents
.onKeyUp(keyCode
, event
);
1689 public void onAttachedToWindow() {
1690 // This API is our strongest signal from the View system that this
1691 // WebView is going to be bound to a View hierarchy and so at this
1692 // point we must bind Chromium's UI thread to the current thread.
1693 mFactory
.startYourEngines(false);
1695 mAwContents
.onAttachedToWindow();
1699 public void onDetachedFromWindow() {
1700 if (checkNeedsPost()) {
1701 mRunQueue
.addTask(new Runnable() {
1704 onDetachedFromWindow();
1710 mAwContents
.onDetachedFromWindow();
1714 public void onVisibilityChanged(final View changedView
, final int visibility
) {
1715 // The AwContents will find out the container view visibility before the first draw so we
1716 // can safely ignore onVisibilityChanged callbacks that happen before init().
1717 if (mAwContents
== null) return;
1719 if (checkNeedsPost()) {
1720 mRunQueue
.addTask(new Runnable() {
1723 onVisibilityChanged(changedView
, visibility
);
1728 mAwContents
.onVisibilityChanged(changedView
, visibility
);
1732 public void onWindowFocusChanged(final boolean hasWindowFocus
) {
1733 if (checkNeedsPost()) {
1734 mRunQueue
.addTask(new Runnable() {
1737 onWindowFocusChanged(hasWindowFocus
);
1742 mAwContents
.onWindowFocusChanged(hasWindowFocus
);
1746 public void onFocusChanged(
1747 final boolean focused
, final int direction
, final Rect previouslyFocusedRect
) {
1748 if (checkNeedsPost()) {
1749 mRunQueue
.addTask(new Runnable() {
1752 onFocusChanged(focused
, direction
, previouslyFocusedRect
);
1757 mAwContents
.onFocusChanged(focused
, direction
, previouslyFocusedRect
);
1761 public boolean setFrame(final int left
, final int top
, final int right
, final int bottom
) {
1762 return mWebViewPrivate
.super_setFrame(left
, top
, right
, bottom
);
1766 public void onSizeChanged(final int w
, final int h
, final int ow
, final int oh
) {
1767 if (checkNeedsPost()) {
1768 mRunQueue
.addTask(new Runnable() {
1771 onSizeChanged(w
, h
, ow
, oh
);
1776 mAwContents
.onSizeChanged(w
, h
, ow
, oh
);
1780 public void onScrollChanged(final int l
, final int t
, final int oldl
, final int oldt
) {
1781 if (checkNeedsPost()) {
1782 mRunQueue
.addTask(new Runnable() {
1785 onScrollChanged(l
, t
, oldl
, oldt
);
1790 mAwContents
.onContainerViewScrollChanged(l
, t
, oldl
, oldt
);
1794 public boolean dispatchKeyEvent(final KeyEvent event
) {
1795 mFactory
.startYourEngines(false);
1796 if (checkNeedsPost()) {
1797 boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
1799 public Boolean
call() {
1800 return dispatchKeyEvent(event
);
1805 return mAwContents
.dispatchKeyEvent(event
);
1809 public boolean onTouchEvent(final MotionEvent ev
) {
1810 mFactory
.startYourEngines(false);
1811 if (checkNeedsPost()) {
1812 boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
1814 public Boolean
call() {
1815 return onTouchEvent(ev
);
1820 return mAwContents
.onTouchEvent(ev
);
1824 public boolean onHoverEvent(final MotionEvent event
) {
1825 mFactory
.startYourEngines(false);
1826 if (checkNeedsPost()) {
1827 boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
1829 public Boolean
call() {
1830 return onHoverEvent(event
);
1835 return mAwContents
.onHoverEvent(event
);
1839 public boolean onGenericMotionEvent(final MotionEvent event
) {
1840 mFactory
.startYourEngines(false);
1841 if (checkNeedsPost()) {
1842 boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
1844 public Boolean
call() {
1845 return onGenericMotionEvent(event
);
1850 return mAwContents
.onGenericMotionEvent(event
);
1854 public boolean onTrackballEvent(MotionEvent ev
) {
1855 // Trackball event not handled, which eventually gets converted to DPAD keyevents
1860 public boolean requestFocus(final int direction
, final Rect previouslyFocusedRect
) {
1861 mFactory
.startYourEngines(false);
1862 if (checkNeedsPost()) {
1863 boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
1865 public Boolean
call() {
1866 return requestFocus(direction
, previouslyFocusedRect
);
1871 mAwContents
.requestFocus();
1872 return mWebViewPrivate
.super_requestFocus(direction
, previouslyFocusedRect
);
1876 public void onMeasure(final int widthMeasureSpec
, final int heightMeasureSpec
) {
1877 mFactory
.startYourEngines(false);
1878 if (checkNeedsPost()) {
1879 runVoidTaskOnUiThreadBlocking(new Runnable() {
1882 onMeasure(widthMeasureSpec
, heightMeasureSpec
);
1887 mAwContents
.onMeasure(widthMeasureSpec
, heightMeasureSpec
);
1891 public boolean requestChildRectangleOnScreen(
1892 final View child
, final Rect rect
, final boolean immediate
) {
1893 mFactory
.startYourEngines(false);
1894 if (checkNeedsPost()) {
1895 boolean ret
= runOnUiThreadBlocking(new Callable
<Boolean
>() {
1897 public Boolean
call() {
1898 return requestChildRectangleOnScreen(child
, rect
, immediate
);
1903 return mAwContents
.requestChildRectangleOnScreen(child
, rect
, immediate
);
1907 public void setBackgroundColor(final int color
) {
1908 mFactory
.startYourEngines(false);
1909 if (checkNeedsPost()) {
1910 ThreadUtils
.postOnUiThread(new Runnable() {
1913 setBackgroundColor(color
);
1918 mAwContents
.setBackgroundColor(color
);
1922 public void setLayerType(final int layerType
, final Paint paint
) {
1923 // This can be called from WebView constructor in which case mAwContents
1924 // is still null. We set the layer type in initForReal in that case.
1925 if (mAwContents
== null) return;
1926 if (checkNeedsPost()) {
1927 ThreadUtils
.postOnUiThread(new Runnable() {
1930 setLayerType(layerType
, paint
);
1935 mAwContents
.setLayerType(layerType
, paint
);
1938 // Remove from superclass
1939 public void preDispatchDraw(Canvas canvas
) {
1940 // TODO(leandrogracia): remove this method from WebViewProvider if we think
1941 // we won't need it again.
1944 public void onStartTemporaryDetach() {
1945 mAwContents
.onStartTemporaryDetach();
1948 public void onFinishTemporaryDetach() {
1949 mAwContents
.onFinishTemporaryDetach();
1952 // WebViewProvider.ScrollDelegate implementation ----------------------------------------------
1955 public int computeHorizontalScrollRange() {
1956 mFactory
.startYourEngines(false);
1957 if (checkNeedsPost()) {
1958 int ret
= runOnUiThreadBlocking(new Callable
<Integer
>() {
1960 public Integer
call() {
1961 return computeHorizontalScrollRange();
1966 return mAwContents
.computeHorizontalScrollRange();
1970 public int computeHorizontalScrollOffset() {
1971 mFactory
.startYourEngines(false);
1972 if (checkNeedsPost()) {
1973 int ret
= runOnUiThreadBlocking(new Callable
<Integer
>() {
1975 public Integer
call() {
1976 return computeHorizontalScrollOffset();
1981 return mAwContents
.computeHorizontalScrollOffset();
1985 public int computeVerticalScrollRange() {
1986 mFactory
.startYourEngines(false);
1987 if (checkNeedsPost()) {
1988 int ret
= runOnUiThreadBlocking(new Callable
<Integer
>() {
1990 public Integer
call() {
1991 return computeVerticalScrollRange();
1996 return mAwContents
.computeVerticalScrollRange();
2000 public int computeVerticalScrollOffset() {
2001 mFactory
.startYourEngines(false);
2002 if (checkNeedsPost()) {
2003 int ret
= runOnUiThreadBlocking(new Callable
<Integer
>() {
2005 public Integer
call() {
2006 return computeVerticalScrollOffset();
2011 return mAwContents
.computeVerticalScrollOffset();
2015 public int computeVerticalScrollExtent() {
2016 mFactory
.startYourEngines(false);
2017 if (checkNeedsPost()) {
2018 int ret
= runOnUiThreadBlocking(new Callable
<Integer
>() {
2020 public Integer
call() {
2021 return computeVerticalScrollExtent();
2026 return mAwContents
.computeVerticalScrollExtent();
2030 public void computeScroll() {
2031 mFactory
.startYourEngines(false);
2032 if (checkNeedsPost()) {
2033 runVoidTaskOnUiThreadBlocking(new Runnable() {
2041 mAwContents
.computeScroll();
2045 public PrintDocumentAdapter
createPrintDocumentAdapter(String documentName
) {
2047 return new AwPrintDocumentAdapter(mAwContents
.getPdfExporter(), documentName
);
2050 // AwContents.NativeGLDelegate implementation --------------------------------------
2051 private class WebViewNativeGLDelegate
implements AwContents
.NativeGLDelegate
{
2053 public boolean requestDrawGL(Canvas canvas
, boolean waitForCompletion
, View containerView
) {
2054 if (mGLfunctor
== null) {
2055 mGLfunctor
= new DrawGLFunctor(
2056 mAwContents
.getAwDrawGLViewContext(), mFactory
.getWebViewDelegate());
2058 return mGLfunctor
.requestDrawGL(canvas
, containerView
, waitForCompletion
);
2062 public void detachGLFunctor() {
2063 if (mGLfunctor
!= null) {
2064 mGLfunctor
.detach();
2069 // AwContents.InternalAccessDelegate implementation --------------------------------------
2070 private class InternalAccessAdapter
implements AwContents
.InternalAccessDelegate
{
2072 public boolean drawChild(Canvas arg0
, View arg1
, long arg2
) {
2077 public boolean super_onKeyUp(int arg0
, KeyEvent arg1
) {
2078 // Intentional no-op
2083 public boolean super_dispatchKeyEventPreIme(KeyEvent arg0
) {
2088 public boolean super_dispatchKeyEvent(KeyEvent event
) {
2089 return mWebViewPrivate
.super_dispatchKeyEvent(event
);
2093 public boolean super_onGenericMotionEvent(MotionEvent arg0
) {
2094 return mWebViewPrivate
.super_onGenericMotionEvent(arg0
);
2098 public void super_onConfigurationChanged(Configuration arg0
) {
2099 // Intentional no-op
2103 public int super_getScrollBarStyle() {
2104 return mWebViewPrivate
.super_getScrollBarStyle();
2108 public boolean awakenScrollBars() {
2109 mWebViewPrivate
.awakenScrollBars(0);
2110 // TODO: modify the WebView.PrivateAccess to provide a return value.
2115 public boolean super_awakenScrollBars(int arg0
, boolean arg1
) {
2120 public void onScrollChanged(int l
, int t
, int oldl
, int oldt
) {
2121 // Intentional no-op.
2122 // Chromium calls this directly to trigger accessibility events. That isn't needed
2123 // for WebView since super_scrollTo invokes onScrollChanged for us.
2127 public void overScrollBy(int deltaX
, int deltaY
, int scrollX
, int scrollY
, int scrollRangeX
,
2128 int scrollRangeY
, int maxOverScrollX
, int maxOverScrollY
, boolean isTouchEvent
) {
2129 mWebViewPrivate
.overScrollBy(deltaX
, deltaY
, scrollX
, scrollY
, scrollRangeX
,
2130 scrollRangeY
, maxOverScrollX
, maxOverScrollY
, isTouchEvent
);
2134 public void super_scrollTo(int scrollX
, int scrollY
) {
2135 mWebViewPrivate
.super_scrollTo(scrollX
, scrollY
);
2139 public void setMeasuredDimension(int measuredWidth
, int measuredHeight
) {
2140 mWebViewPrivate
.setMeasuredDimension(measuredWidth
, measuredHeight
);
2144 public boolean super_onHoverEvent(MotionEvent event
) {
2145 return mWebViewPrivate
.super_onHoverEvent(event
);
2149 // Implements SmartClipProvider
2151 public void extractSmartClipData(int x
, int y
, int width
, int height
) {
2153 mAwContents
.extractSmartClipData(x
, y
, width
, height
);
2156 // Implements SmartClipProvider
2158 public void setSmartClipResultHandler(final Handler resultHandler
) {
2160 mAwContents
.setSmartClipResultHandler(resultHandler
);