Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / android_webview / glue / java / src / com / android / webview / chromium / WebViewChromium.java
blobdd543d56cda4cd08255b7d90db7209ccb0ef1296
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;
53 import java.io.File;
54 import java.util.Map;
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;
61 /**
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) {
78 mQueue.add(task);
79 if (mFactory.hasStarted()) {
80 ThreadUtils.runOnUiThread(new Runnable() {
81 @Override
82 public void run() {
83 drainQueue();
85 });
89 public void drainQueue() {
90 if (mQueue == null || mQueue.isEmpty()) {
91 return;
94 Runnable task = mQueue.poll();
95 while (task != null) {
96 task.run();
97 task = mQueue.poll();
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.
109 WebView mWebView;
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) {
139 mWebView = webView;
140 mWebViewPrivate = webViewPrivate;
141 mHitTestResult = new WebView.HitTestResult();
142 mContext = ResourcesContextWrapperFactory.get(mWebView.getContext());
143 mAppTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
144 mFactory = factory;
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);
162 try {
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
173 // deadlocks.
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 --------------------------------------------------------------------
186 @Override
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);
196 } else {
197 Log.w(TAG, 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);
210 checkThread();
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() {
234 @Override
235 public void run() {
236 initForReal();
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
241 // before use.
242 destroy();
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!");
286 return needsPost;
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() {
294 @Override
295 public void run() {
296 throw threadViolation;
299 throw createThreadException();
303 @Override
304 public void setHorizontalScrollbarOverlay(final boolean overlay) {
305 if (checkNeedsPost()) {
306 mRunQueue.addTask(new Runnable() {
307 @Override
308 public void run() {
309 setHorizontalScrollbarOverlay(overlay);
312 return;
314 mAwContents.setHorizontalScrollbarOverlay(overlay);
317 @Override
318 public void setVerticalScrollbarOverlay(final boolean overlay) {
319 if (checkNeedsPost()) {
320 mRunQueue.addTask(new Runnable() {
321 @Override
322 public void run() {
323 setVerticalScrollbarOverlay(overlay);
326 return;
328 mAwContents.setVerticalScrollbarOverlay(overlay);
331 @Override
332 public boolean overlayHorizontalScrollbar() {
333 mFactory.startYourEngines(false);
334 if (checkNeedsPost()) {
335 boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
336 @Override
337 public Boolean call() {
338 return overlayHorizontalScrollbar();
341 return ret;
343 return mAwContents.overlayHorizontalScrollbar();
346 @Override
347 public boolean overlayVerticalScrollbar() {
348 mFactory.startYourEngines(false);
349 if (checkNeedsPost()) {
350 boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
351 @Override
352 public Boolean call() {
353 return overlayVerticalScrollbar();
356 return ret;
358 return mAwContents.overlayVerticalScrollbar();
361 @Override
362 public int getVisibleTitleHeight() {
363 // This is deprecated in WebView and should always return 0.
364 return 0;
367 @Override
368 public SslCertificate getCertificate() {
369 mFactory.startYourEngines(true);
370 if (checkNeedsPost()) {
371 SslCertificate ret = runOnUiThreadBlocking(new Callable<SslCertificate>() {
372 @Override
373 public SslCertificate call() {
374 return getCertificate();
377 return ret;
379 return mAwContents.getCertificate();
382 @Override
383 public void setCertificate(SslCertificate certificate) {
384 // intentional no-op
387 @Override
388 public void savePassword(String host, String username, String password) {
389 // This is a deprecated API: intentional no-op.
392 @Override
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() {
397 @Override
398 public void run() {
399 setHttpAuthUsernamePassword(host, realm, username, password);
402 return;
404 mAwContents.setHttpAuthUsernamePassword(host, realm, username, password);
407 @Override
408 public String[] getHttpAuthUsernamePassword(final String host, final String realm) {
409 mFactory.startYourEngines(true);
410 if (checkNeedsPost()) {
411 String[] ret = runOnUiThreadBlocking(new Callable<String[]>() {
412 @Override
413 public String[] call() {
414 return getHttpAuthUsernamePassword(host, realm);
417 return ret;
419 return mAwContents.getHttpAuthUsernamePassword(host, realm);
422 @Override
423 public void destroy() {
424 if (checkNeedsPost()) {
425 mRunQueue.addTask(new Runnable() {
426 @Override
427 public void run() {
428 destroy();
431 return;
434 mAwContents.destroy();
435 if (mGLfunctor != null) {
436 mGLfunctor.destroy();
437 mGLfunctor = null;
441 @Override
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() {
447 @Override
448 public void run() {
449 setNetworkAvailable(networkUp);
452 return;
454 mAwContents.setNetworkAvailable(networkUp);
457 @Override
458 public WebBackForwardList saveState(final Bundle outState) {
459 mFactory.startYourEngines(true);
460 if (checkNeedsPost()) {
461 WebBackForwardList ret = runOnUiThreadBlocking(new Callable<WebBackForwardList>() {
462 @Override
463 public WebBackForwardList call() {
464 return saveState(outState);
467 return ret;
469 if (outState == null) return null;
470 if (!mAwContents.saveState(outState)) return null;
471 return copyBackForwardList();
474 @Override
475 public boolean savePicture(Bundle b, File dest) {
476 // Intentional no-op: hidden method on WebView.
477 return false;
480 @Override
481 public boolean restorePicture(Bundle b, File src) {
482 // Intentional no-op: hidden method on WebView.
483 return false;
486 @Override
487 public WebBackForwardList restoreState(final Bundle inState) {
488 mFactory.startYourEngines(true);
489 if (checkNeedsPost()) {
490 WebBackForwardList ret = runOnUiThreadBlocking(new Callable<WebBackForwardList>() {
491 @Override
492 public WebBackForwardList call() {
493 return restoreState(inState);
496 return ret;
498 if (inState == null) return null;
499 if (!mAwContents.restoreState(inState)) return null;
500 return copyBackForwardList();
503 @Override
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() {
510 @Override
511 public void run() {
512 mAwContents.loadUrl(url, additionalHttpHeaders);
515 return;
517 mAwContents.loadUrl(url, additionalHttpHeaders);
520 @Override
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() {
527 @Override
528 public void run() {
529 mAwContents.loadUrl(url);
532 return;
534 mAwContents.loadUrl(url);
537 @Override
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() {
544 @Override
545 public void run() {
546 mAwContents.postUrl(url, postData);
549 return;
551 mAwContents.postUrl(url, postData);
554 @Override
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() {
561 @Override
562 public void run() {
563 mAwContents.loadData(data, mimeType, encoding);
566 return;
568 mAwContents.loadData(data, mimeType, encoding);
571 @Override
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() {
579 @Override
580 public void run() {
581 mAwContents.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
584 return;
586 mAwContents.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
589 public void evaluateJavaScript(String script, ValueCallback<String> resultCallback) {
590 checkThread();
591 mAwContents.evaluateJavaScript(script, resultCallback);
594 @Override
595 public void saveWebArchive(String filename) {
596 saveWebArchive(filename, false, null);
599 @Override
600 public void saveWebArchive(final String basename, final boolean autoname,
601 final ValueCallback<String> callback) {
602 if (checkNeedsPost()) {
603 mRunQueue.addTask(new Runnable() {
604 @Override
605 public void run() {
606 saveWebArchive(basename, autoname, callback);
609 return;
611 mAwContents.saveWebArchive(basename, autoname, callback);
614 @Override
615 public void stopLoading() {
616 if (checkNeedsPost()) {
617 mRunQueue.addTask(new Runnable() {
618 @Override
619 public void run() {
620 stopLoading();
623 return;
626 mAwContents.stopLoading();
629 @Override
630 public void reload() {
631 if (checkNeedsPost()) {
632 mRunQueue.addTask(new Runnable() {
633 @Override
634 public void run() {
635 reload();
638 return;
640 mAwContents.reload();
643 @Override
644 public boolean canGoBack() {
645 mFactory.startYourEngines(true);
646 if (checkNeedsPost()) {
647 Boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
648 @Override
649 public Boolean call() {
650 return canGoBack();
653 return ret;
655 return mAwContents.canGoBack();
658 @Override
659 public void goBack() {
660 if (checkNeedsPost()) {
661 mRunQueue.addTask(new Runnable() {
662 @Override
663 public void run() {
664 goBack();
667 return;
669 mAwContents.goBack();
672 @Override
673 public boolean canGoForward() {
674 mFactory.startYourEngines(true);
675 if (checkNeedsPost()) {
676 Boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
677 @Override
678 public Boolean call() {
679 return canGoForward();
682 return ret;
684 return mAwContents.canGoForward();
687 @Override
688 public void goForward() {
689 if (checkNeedsPost()) {
690 mRunQueue.addTask(new Runnable() {
691 @Override
692 public void run() {
693 goForward();
696 return;
698 mAwContents.goForward();
701 @Override
702 public boolean canGoBackOrForward(final int steps) {
703 mFactory.startYourEngines(true);
704 if (checkNeedsPost()) {
705 Boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
706 @Override
707 public Boolean call() {
708 return canGoBackOrForward(steps);
711 return ret;
713 return mAwContents.canGoBackOrForward(steps);
716 @Override
717 public void goBackOrForward(final int steps) {
718 if (checkNeedsPost()) {
719 mRunQueue.addTask(new Runnable() {
720 @Override
721 public void run() {
722 goBackOrForward(steps);
725 return;
727 mAwContents.goBackOrForward(steps);
730 @Override
731 public boolean isPrivateBrowsingEnabled() {
732 // Not supported in this WebView implementation.
733 return false;
736 @Override
737 public boolean pageUp(final boolean top) {
738 mFactory.startYourEngines(true);
739 if (checkNeedsPost()) {
740 Boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
741 @Override
742 public Boolean call() {
743 return pageUp(top);
746 return ret;
748 return mAwContents.pageUp(top);
751 @Override
752 public boolean pageDown(final boolean bottom) {
753 mFactory.startYourEngines(true);
754 if (checkNeedsPost()) {
755 Boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
756 @Override
757 public Boolean call() {
758 return pageDown(bottom);
761 return ret;
763 return mAwContents.pageDown(bottom);
766 @Override
767 public void clearView() {
768 if (checkNeedsPost()) {
769 mRunQueue.addTask(new Runnable() {
770 @Override
771 public void run() {
772 clearView();
775 return;
777 mAwContents.clearView();
780 @Override
781 public Picture capturePicture() {
782 mFactory.startYourEngines(true);
783 if (checkNeedsPost()) {
784 Picture ret = runOnUiThreadBlocking(new Callable<Picture>() {
785 @Override
786 public Picture call() {
787 return capturePicture();
790 return ret;
792 return mAwContents.capturePicture();
795 @Override
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();
802 @Override
803 public void setInitialScale(final int scaleInPercent) {
804 // No checkThread() as it is thread safe
805 mWebSettings.getAwSettings().setInitialPageScale(scaleInPercent);
808 @Override
809 public void invokeZoomPicker() {
810 if (checkNeedsPost()) {
811 mRunQueue.addTask(new Runnable() {
812 @Override
813 public void run() {
814 invokeZoomPicker();
817 return;
819 mAwContents.invokeZoomPicker();
822 @Override
823 public WebView.HitTestResult getHitTestResult() {
824 mFactory.startYourEngines(true);
825 if (checkNeedsPost()) {
826 WebView.HitTestResult ret =
827 runOnUiThreadBlocking(new Callable<WebView.HitTestResult>() {
828 @Override
829 public WebView.HitTestResult call() {
830 return getHitTestResult();
833 return ret;
835 AwContents.HitTestData data = mAwContents.getLastHitTestResult();
836 mHitTestResult.setType(data.hitTestResultType);
837 mHitTestResult.setExtra(data.hitTestResultExtraData);
838 return mHitTestResult;
841 @Override
842 public void requestFocusNodeHref(final Message hrefMsg) {
843 if (checkNeedsPost()) {
844 mRunQueue.addTask(new Runnable() {
845 @Override
846 public void run() {
847 requestFocusNodeHref(hrefMsg);
850 return;
852 mAwContents.requestFocusNodeHref(hrefMsg);
855 @Override
856 public void requestImageRef(final Message msg) {
857 if (checkNeedsPost()) {
858 mRunQueue.addTask(new Runnable() {
859 @Override
860 public void run() {
861 requestImageRef(msg);
864 return;
866 mAwContents.requestImageRef(msg);
869 @Override
870 public String getUrl() {
871 mFactory.startYourEngines(true);
872 if (checkNeedsPost()) {
873 String ret = runOnUiThreadBlocking(new Callable<String>() {
874 @Override
875 public String call() {
876 return getUrl();
879 return ret;
881 return mAwContents.getUrl();
884 @Override
885 public String getOriginalUrl() {
886 mFactory.startYourEngines(true);
887 if (checkNeedsPost()) {
888 String ret = runOnUiThreadBlocking(new Callable<String>() {
889 @Override
890 public String call() {
891 return getOriginalUrl();
894 return ret;
896 return mAwContents.getOriginalUrl();
899 @Override
900 public String getTitle() {
901 mFactory.startYourEngines(true);
902 if (checkNeedsPost()) {
903 String ret = runOnUiThreadBlocking(new Callable<String>() {
904 @Override
905 public String call() {
906 return getTitle();
909 return ret;
911 return mAwContents.getTitle();
914 @Override
915 public Bitmap getFavicon() {
916 mFactory.startYourEngines(true);
917 if (checkNeedsPost()) {
918 Bitmap ret = runOnUiThreadBlocking(new Callable<Bitmap>() {
919 @Override
920 public Bitmap call() {
921 return getFavicon();
924 return ret;
926 return mAwContents.getFavicon();
929 @Override
930 public String getTouchIconUrl() {
931 // Intentional no-op: hidden method on WebView.
932 return null;
935 @Override
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();
942 @Override
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();
949 @Override
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();
956 @Override
957 public void pauseTimers() {
958 if (checkNeedsPost()) {
959 mRunQueue.addTask(new Runnable() {
960 @Override
961 public void run() {
962 pauseTimers();
965 return;
967 mAwContents.pauseTimers();
970 @Override
971 public void resumeTimers() {
972 if (checkNeedsPost()) {
973 mRunQueue.addTask(new Runnable() {
974 @Override
975 public void run() {
976 resumeTimers();
979 return;
981 mAwContents.resumeTimers();
984 @Override
985 public void onPause() {
986 if (checkNeedsPost()) {
987 mRunQueue.addTask(new Runnable() {
988 @Override
989 public void run() {
990 onPause();
993 return;
995 mAwContents.onPause();
998 @Override
999 public void onResume() {
1000 if (checkNeedsPost()) {
1001 mRunQueue.addTask(new Runnable() {
1002 @Override
1003 public void run() {
1004 onResume();
1007 return;
1009 mAwContents.onResume();
1012 @Override
1013 public boolean isPaused() {
1014 mFactory.startYourEngines(true);
1015 if (checkNeedsPost()) {
1016 Boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
1017 @Override
1018 public Boolean call() {
1019 return isPaused();
1022 return ret;
1024 return mAwContents.isPaused();
1027 @Override
1028 public void freeMemory() {
1029 // Intentional no-op. Memory is managed automatically by Chromium.
1032 @Override
1033 public void clearCache(final boolean includeDiskFiles) {
1034 if (checkNeedsPost()) {
1035 mRunQueue.addTask(new Runnable() {
1036 @Override
1037 public void run() {
1038 clearCache(includeDiskFiles);
1041 return;
1043 mAwContents.clearCache(includeDiskFiles);
1047 * This is a poorly named method, but we keep it for historical reasons.
1049 @Override
1050 public void clearFormData() {
1051 if (checkNeedsPost()) {
1052 mRunQueue.addTask(new Runnable() {
1053 @Override
1054 public void run() {
1055 clearFormData();
1058 return;
1060 mAwContents.hideAutofillPopup();
1063 @Override
1064 public void clearHistory() {
1065 if (checkNeedsPost()) {
1066 mRunQueue.addTask(new Runnable() {
1067 @Override
1068 public void run() {
1069 clearHistory();
1072 return;
1074 mAwContents.clearHistory();
1077 @Override
1078 public void clearSslPreferences() {
1079 if (checkNeedsPost()) {
1080 mRunQueue.addTask(new Runnable() {
1081 @Override
1082 public void run() {
1083 clearSslPreferences();
1086 return;
1088 mAwContents.clearSslPreferences();
1091 @Override
1092 public WebBackForwardList copyBackForwardList() {
1093 mFactory.startYourEngines(true);
1094 if (checkNeedsPost()) {
1095 WebBackForwardList ret = runOnUiThreadBlocking(new Callable<WebBackForwardList>() {
1096 @Override
1097 public WebBackForwardList call() {
1098 return copyBackForwardList();
1101 return ret;
1103 return new WebBackForwardListChromium(mAwContents.getNavigationHistory());
1106 @Override
1107 public void setFindListener(WebView.FindListener listener) {
1108 mContentsClientAdapter.setFindListener(listener);
1111 @Override
1112 public void findNext(final boolean forwards) {
1113 if (checkNeedsPost()) {
1114 mRunQueue.addTask(new Runnable() {
1115 @Override
1116 public void run() {
1117 findNext(forwards);
1120 return;
1122 mAwContents.findNext(forwards);
1125 @Override
1126 public int findAll(final String searchString) {
1127 findAllAsync(searchString);
1128 return 0;
1131 @Override
1132 public void findAllAsync(final String searchString) {
1133 if (checkNeedsPost()) {
1134 mRunQueue.addTask(new Runnable() {
1135 @Override
1136 public void run() {
1137 findAllAsync(searchString);
1140 return;
1142 mAwContents.findAllAsync(searchString);
1145 @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE")
1146 @Override
1147 public boolean showFindDialog(final String text, final boolean showIme) {
1148 mFactory.startYourEngines(false);
1149 if (checkNeedsPost()) {
1150 return false;
1152 if (mWebView.getParent() == null) {
1153 return false;
1156 FindActionModeCallback findAction = new FindActionModeCallback(mContext);
1157 if (findAction == null) {
1158 return false;
1161 mWebView.startActionMode(findAction);
1162 findAction.setWebView(mWebView);
1163 if (showIme) {
1164 findAction.showSoftInput();
1167 if (text != null) {
1168 findAction.setText(text);
1169 findAction.findAll();
1172 return true;
1175 @Override
1176 public void notifyFindDialogDismissed() {
1177 if (checkNeedsPost()) {
1178 mRunQueue.addTask(new Runnable() {
1179 @Override
1180 public void run() {
1181 notifyFindDialogDismissed();
1184 return;
1186 clearMatches();
1189 @Override
1190 public void clearMatches() {
1191 if (checkNeedsPost()) {
1192 mRunQueue.addTask(new Runnable() {
1193 @Override
1194 public void run() {
1195 clearMatches();
1198 return;
1200 mAwContents.clearMatches();
1203 @Override
1204 public void documentHasImages(final Message response) {
1205 if (checkNeedsPost()) {
1206 mRunQueue.addTask(new Runnable() {
1207 @Override
1208 public void run() {
1209 documentHasImages(response);
1212 return;
1214 mAwContents.documentHasImages(response);
1217 @Override
1218 public void setWebViewClient(WebViewClient client) {
1219 mContentsClientAdapter.setWebViewClient(client);
1222 @Override
1223 public void setDownloadListener(DownloadListener listener) {
1224 mContentsClientAdapter.setDownloadListener(listener);
1227 @Override
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) {
1241 return false;
1243 Class<?> clientClass = client.getClass();
1244 boolean foundShowMethod = false;
1245 boolean foundHideMethod = false;
1246 while (clientClass != WebChromeClient.class && (!foundShowMethod || !foundHideMethod)) {
1247 if (!foundShowMethod) {
1248 try {
1249 clientClass.getDeclaredMethod(
1250 "onShowCustomView", View.class, CustomViewCallback.class);
1251 foundShowMethod = true;
1252 } catch (NoSuchMethodException e) {
1253 // Intentionally empty.
1257 if (!foundHideMethod) {
1258 try {
1259 clientClass.getDeclaredMethod("onHideCustomView");
1260 foundHideMethod = true;
1261 } catch (NoSuchMethodException e) {
1262 // Intentionally empty.
1265 clientClass = clientClass.getSuperclass();
1267 return foundShowMethod && foundHideMethod;
1270 @Override
1271 @SuppressWarnings("deprecation")
1272 public void setPictureListener(final WebView.PictureListener listener) {
1273 if (checkNeedsPost()) {
1274 mRunQueue.addTask(new Runnable() {
1275 @Override
1276 public void run() {
1277 setPictureListener(listener);
1280 return;
1282 mContentsClientAdapter.setPictureListener(listener);
1283 mAwContents.enableOnNewPicture(
1284 listener != null, mAppTargetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN_MR2);
1287 @Override
1288 public void addJavascriptInterface(final Object obj, final String interfaceName) {
1289 if (checkNeedsPost()) {
1290 mRunQueue.addTask(new Runnable() {
1291 @Override
1292 public void run() {
1293 addJavascriptInterface(obj, interfaceName);
1296 return;
1298 mAwContents.addJavascriptInterface(obj, interfaceName);
1301 @Override
1302 public void removeJavascriptInterface(final String interfaceName) {
1303 if (checkNeedsPost()) {
1304 mRunQueue.addTask(new Runnable() {
1305 @Override
1306 public void run() {
1307 removeJavascriptInterface(interfaceName);
1310 return;
1312 mAwContents.removeJavascriptInterface(interfaceName);
1315 @Override
1316 public WebSettings getSettings() {
1317 return mWebSettings;
1320 @Override
1321 public void setMapTrackballToArrowKeys(boolean setMap) {
1322 // This is a deprecated API: intentional no-op.
1325 @Override
1326 public void flingScroll(final int vx, final int vy) {
1327 if (checkNeedsPost()) {
1328 mRunQueue.addTask(new Runnable() {
1329 @Override
1330 public void run() {
1331 flingScroll(vx, vy);
1334 return;
1336 mAwContents.flingScroll(vx, vy);
1339 @Override
1340 public View getZoomControls() {
1341 mFactory.startYourEngines(false);
1342 if (checkNeedsPost()) {
1343 return null;
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;
1352 @Override
1353 public boolean canZoomIn() {
1354 if (checkNeedsPost()) {
1355 return false;
1357 return mAwContents.canZoomIn();
1360 @Override
1361 public boolean canZoomOut() {
1362 if (checkNeedsPost()) {
1363 return false;
1365 return mAwContents.canZoomOut();
1368 @Override
1369 public boolean zoomIn() {
1370 mFactory.startYourEngines(true);
1371 if (checkNeedsPost()) {
1372 boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
1373 @Override
1374 public Boolean call() {
1375 return zoomIn();
1378 return ret;
1380 return mAwContents.zoomIn();
1383 @Override
1384 public boolean zoomOut() {
1385 mFactory.startYourEngines(true);
1386 if (checkNeedsPost()) {
1387 boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
1388 @Override
1389 public Boolean call() {
1390 return zoomOut();
1393 return ret;
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
1400 @Override
1401 public boolean zoomBy(float factor) {
1402 mFactory.startYourEngines(true);
1403 // This is an L API and therefore we can enforce stricter threading constraints.
1404 checkThread();
1405 mAwContents.zoomBy(factor);
1406 return true;
1409 @Override
1410 public void dumpViewHierarchyWithProperties(BufferedWriter out, int level) {
1411 // Intentional no-op
1414 @Override
1415 public View findHierarchyView(String className, int hashCode) {
1416 // Intentional no-op
1417 return null;
1420 // WebViewProvider glue methods ---------------------------------------------------------------
1422 @Override
1423 // This needs to be kept thread safe!
1424 public WebViewProvider.ViewDelegate getViewDelegate() {
1425 return this;
1428 @Override
1429 // This needs to be kept thread safe!
1430 public WebViewProvider.ScrollDelegate getScrollDelegate() {
1431 return this;
1434 // WebViewProvider.ViewDelegate implementation ------------------------------------------------
1436 // TODO: remove from WebViewProvider and use default implementation from
1437 // ViewGroup.
1438 @Override
1439 public boolean shouldDelayChildPressedState() {
1440 mFactory.startYourEngines(false);
1441 if (checkNeedsPost()) {
1442 boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
1443 @Override
1444 public Boolean call() {
1445 return shouldDelayChildPressedState();
1448 return ret;
1450 return true;
1453 @Override
1454 public AccessibilityNodeProvider getAccessibilityNodeProvider() {
1455 mFactory.startYourEngines(false);
1456 if (checkNeedsPost()) {
1457 AccessibilityNodeProvider ret =
1458 runOnUiThreadBlocking(new Callable<AccessibilityNodeProvider>() {
1459 @Override
1460 public AccessibilityNodeProvider call() {
1461 return getAccessibilityNodeProvider();
1464 return ret;
1466 return mAwContents.getAccessibilityNodeProvider();
1469 @Override
1470 public void onInitializeAccessibilityNodeInfo(final AccessibilityNodeInfo info) {
1471 mFactory.startYourEngines(false);
1472 if (checkNeedsPost()) {
1473 runVoidTaskOnUiThreadBlocking(new Runnable() {
1474 @Override
1475 public void run() {
1476 onInitializeAccessibilityNodeInfo(info);
1479 return;
1481 mAwContents.onInitializeAccessibilityNodeInfo(info);
1484 @Override
1485 public void onInitializeAccessibilityEvent(final AccessibilityEvent event) {
1486 mFactory.startYourEngines(false);
1487 if (checkNeedsPost()) {
1488 runVoidTaskOnUiThreadBlocking(new Runnable() {
1489 @Override
1490 public void run() {
1491 onInitializeAccessibilityEvent(event);
1494 return;
1496 mAwContents.onInitializeAccessibilityEvent(event);
1499 @Override
1500 public boolean performAccessibilityAction(final int action, final Bundle arguments) {
1501 mFactory.startYourEngines(false);
1502 if (checkNeedsPost()) {
1503 boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
1504 @Override
1505 public Boolean call() {
1506 return performAccessibilityAction(action, arguments);
1509 return ret;
1511 if (mAwContents.supportsAccessibilityAction(action)) {
1512 return mAwContents.performAccessibilityAction(action, arguments);
1514 return mWebViewPrivate.super_performAccessibilityAction(action, arguments);
1517 @Override
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() {
1527 @Override
1528 public void run() {
1529 setOverScrollMode(mode);
1532 return;
1534 mAwContents.setOverScrollMode(mode);
1537 @Override
1538 public void setScrollBarStyle(final int style) {
1539 if (checkNeedsPost()) {
1540 mRunQueue.addTask(new Runnable() {
1541 @Override
1542 public void run() {
1543 setScrollBarStyle(style);
1546 return;
1548 mAwContents.setScrollBarStyle(style);
1551 @Override
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
1556 // used.
1557 mWebViewPrivate.super_onDrawVerticalScrollBar(canvas, scrollBar, l, t, r, b);
1560 @Override
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() {
1565 @Override
1566 public void run() {
1567 onOverScrolled(scrollX, scrollY, clampedX, clampedY);
1570 return;
1572 mAwContents.onContainerViewOverScrolled(scrollX, scrollY, clampedX, clampedY);
1575 @Override
1576 public void onWindowVisibilityChanged(final int visibility) {
1577 if (checkNeedsPost()) {
1578 mRunQueue.addTask(new Runnable() {
1579 @Override
1580 public void run() {
1581 onWindowVisibilityChanged(visibility);
1584 return;
1586 mAwContents.onWindowVisibilityChanged(visibility);
1589 @Override
1590 public void onDraw(final Canvas canvas) {
1591 mFactory.startYourEngines(true);
1592 if (checkNeedsPost()) {
1593 runVoidTaskOnUiThreadBlocking(new Runnable() {
1594 @Override
1595 public void run() {
1596 onDraw(canvas);
1599 return;
1601 mAwContents.onDraw(canvas);
1604 @Override
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);
1610 checkThread();
1611 mWebViewPrivate.super_setLayoutParams(layoutParams);
1614 @Override
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;
1620 @Override
1621 public void onConfigurationChanged(final Configuration newConfig) {
1622 if (checkNeedsPost()) {
1623 mRunQueue.addTask(new Runnable() {
1624 @Override
1625 public void run() {
1626 onConfigurationChanged(newConfig);
1629 return;
1631 mAwContents.onConfigurationChanged(newConfig);
1634 @Override
1635 public InputConnection onCreateInputConnection(final EditorInfo outAttrs) {
1636 mFactory.startYourEngines(false);
1637 if (checkNeedsPost()) {
1638 return null;
1640 return mAwContents.onCreateInputConnection(outAttrs);
1643 @Override
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>() {
1648 @Override
1649 public Boolean call() {
1650 return onKeyMultiple(keyCode, repeatCount, event);
1653 return ret;
1655 return false;
1658 @Override
1659 public boolean onKeyDown(final int keyCode, final KeyEvent event) {
1660 mFactory.startYourEngines(false);
1661 if (checkNeedsPost()) {
1662 boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
1663 @Override
1664 public Boolean call() {
1665 return onKeyDown(keyCode, event);
1668 return ret;
1670 return false;
1673 @Override
1674 public boolean onKeyUp(final int keyCode, final KeyEvent event) {
1675 mFactory.startYourEngines(false);
1676 if (checkNeedsPost()) {
1677 boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
1678 @Override
1679 public Boolean call() {
1680 return onKeyUp(keyCode, event);
1683 return ret;
1685 return mAwContents.onKeyUp(keyCode, event);
1688 @Override
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);
1694 checkThread();
1695 mAwContents.onAttachedToWindow();
1698 @Override
1699 public void onDetachedFromWindow() {
1700 if (checkNeedsPost()) {
1701 mRunQueue.addTask(new Runnable() {
1702 @Override
1703 public void run() {
1704 onDetachedFromWindow();
1707 return;
1710 mAwContents.onDetachedFromWindow();
1713 @Override
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() {
1721 @Override
1722 public void run() {
1723 onVisibilityChanged(changedView, visibility);
1726 return;
1728 mAwContents.onVisibilityChanged(changedView, visibility);
1731 @Override
1732 public void onWindowFocusChanged(final boolean hasWindowFocus) {
1733 if (checkNeedsPost()) {
1734 mRunQueue.addTask(new Runnable() {
1735 @Override
1736 public void run() {
1737 onWindowFocusChanged(hasWindowFocus);
1740 return;
1742 mAwContents.onWindowFocusChanged(hasWindowFocus);
1745 @Override
1746 public void onFocusChanged(
1747 final boolean focused, final int direction, final Rect previouslyFocusedRect) {
1748 if (checkNeedsPost()) {
1749 mRunQueue.addTask(new Runnable() {
1750 @Override
1751 public void run() {
1752 onFocusChanged(focused, direction, previouslyFocusedRect);
1755 return;
1757 mAwContents.onFocusChanged(focused, direction, previouslyFocusedRect);
1760 @Override
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);
1765 @Override
1766 public void onSizeChanged(final int w, final int h, final int ow, final int oh) {
1767 if (checkNeedsPost()) {
1768 mRunQueue.addTask(new Runnable() {
1769 @Override
1770 public void run() {
1771 onSizeChanged(w, h, ow, oh);
1774 return;
1776 mAwContents.onSizeChanged(w, h, ow, oh);
1779 @Override
1780 public void onScrollChanged(final int l, final int t, final int oldl, final int oldt) {
1781 if (checkNeedsPost()) {
1782 mRunQueue.addTask(new Runnable() {
1783 @Override
1784 public void run() {
1785 onScrollChanged(l, t, oldl, oldt);
1788 return;
1790 mAwContents.onContainerViewScrollChanged(l, t, oldl, oldt);
1793 @Override
1794 public boolean dispatchKeyEvent(final KeyEvent event) {
1795 mFactory.startYourEngines(false);
1796 if (checkNeedsPost()) {
1797 boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
1798 @Override
1799 public Boolean call() {
1800 return dispatchKeyEvent(event);
1803 return ret;
1805 return mAwContents.dispatchKeyEvent(event);
1808 @Override
1809 public boolean onTouchEvent(final MotionEvent ev) {
1810 mFactory.startYourEngines(false);
1811 if (checkNeedsPost()) {
1812 boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
1813 @Override
1814 public Boolean call() {
1815 return onTouchEvent(ev);
1818 return ret;
1820 return mAwContents.onTouchEvent(ev);
1823 @Override
1824 public boolean onHoverEvent(final MotionEvent event) {
1825 mFactory.startYourEngines(false);
1826 if (checkNeedsPost()) {
1827 boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
1828 @Override
1829 public Boolean call() {
1830 return onHoverEvent(event);
1833 return ret;
1835 return mAwContents.onHoverEvent(event);
1838 @Override
1839 public boolean onGenericMotionEvent(final MotionEvent event) {
1840 mFactory.startYourEngines(false);
1841 if (checkNeedsPost()) {
1842 boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
1843 @Override
1844 public Boolean call() {
1845 return onGenericMotionEvent(event);
1848 return ret;
1850 return mAwContents.onGenericMotionEvent(event);
1853 @Override
1854 public boolean onTrackballEvent(MotionEvent ev) {
1855 // Trackball event not handled, which eventually gets converted to DPAD keyevents
1856 return false;
1859 @Override
1860 public boolean requestFocus(final int direction, final Rect previouslyFocusedRect) {
1861 mFactory.startYourEngines(false);
1862 if (checkNeedsPost()) {
1863 boolean ret = runOnUiThreadBlocking(new Callable<Boolean>() {
1864 @Override
1865 public Boolean call() {
1866 return requestFocus(direction, previouslyFocusedRect);
1869 return ret;
1871 mAwContents.requestFocus();
1872 return mWebViewPrivate.super_requestFocus(direction, previouslyFocusedRect);
1875 @Override
1876 public void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
1877 mFactory.startYourEngines(false);
1878 if (checkNeedsPost()) {
1879 runVoidTaskOnUiThreadBlocking(new Runnable() {
1880 @Override
1881 public void run() {
1882 onMeasure(widthMeasureSpec, heightMeasureSpec);
1885 return;
1887 mAwContents.onMeasure(widthMeasureSpec, heightMeasureSpec);
1890 @Override
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>() {
1896 @Override
1897 public Boolean call() {
1898 return requestChildRectangleOnScreen(child, rect, immediate);
1901 return ret;
1903 return mAwContents.requestChildRectangleOnScreen(child, rect, immediate);
1906 @Override
1907 public void setBackgroundColor(final int color) {
1908 mFactory.startYourEngines(false);
1909 if (checkNeedsPost()) {
1910 ThreadUtils.postOnUiThread(new Runnable() {
1911 @Override
1912 public void run() {
1913 setBackgroundColor(color);
1916 return;
1918 mAwContents.setBackgroundColor(color);
1921 @Override
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() {
1928 @Override
1929 public void run() {
1930 setLayerType(layerType, paint);
1933 return;
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 ----------------------------------------------
1954 @Override
1955 public int computeHorizontalScrollRange() {
1956 mFactory.startYourEngines(false);
1957 if (checkNeedsPost()) {
1958 int ret = runOnUiThreadBlocking(new Callable<Integer>() {
1959 @Override
1960 public Integer call() {
1961 return computeHorizontalScrollRange();
1964 return ret;
1966 return mAwContents.computeHorizontalScrollRange();
1969 @Override
1970 public int computeHorizontalScrollOffset() {
1971 mFactory.startYourEngines(false);
1972 if (checkNeedsPost()) {
1973 int ret = runOnUiThreadBlocking(new Callable<Integer>() {
1974 @Override
1975 public Integer call() {
1976 return computeHorizontalScrollOffset();
1979 return ret;
1981 return mAwContents.computeHorizontalScrollOffset();
1984 @Override
1985 public int computeVerticalScrollRange() {
1986 mFactory.startYourEngines(false);
1987 if (checkNeedsPost()) {
1988 int ret = runOnUiThreadBlocking(new Callable<Integer>() {
1989 @Override
1990 public Integer call() {
1991 return computeVerticalScrollRange();
1994 return ret;
1996 return mAwContents.computeVerticalScrollRange();
1999 @Override
2000 public int computeVerticalScrollOffset() {
2001 mFactory.startYourEngines(false);
2002 if (checkNeedsPost()) {
2003 int ret = runOnUiThreadBlocking(new Callable<Integer>() {
2004 @Override
2005 public Integer call() {
2006 return computeVerticalScrollOffset();
2009 return ret;
2011 return mAwContents.computeVerticalScrollOffset();
2014 @Override
2015 public int computeVerticalScrollExtent() {
2016 mFactory.startYourEngines(false);
2017 if (checkNeedsPost()) {
2018 int ret = runOnUiThreadBlocking(new Callable<Integer>() {
2019 @Override
2020 public Integer call() {
2021 return computeVerticalScrollExtent();
2024 return ret;
2026 return mAwContents.computeVerticalScrollExtent();
2029 @Override
2030 public void computeScroll() {
2031 mFactory.startYourEngines(false);
2032 if (checkNeedsPost()) {
2033 runVoidTaskOnUiThreadBlocking(new Runnable() {
2034 @Override
2035 public void run() {
2036 computeScroll();
2039 return;
2041 mAwContents.computeScroll();
2044 @Override
2045 public PrintDocumentAdapter createPrintDocumentAdapter(String documentName) {
2046 checkThread();
2047 return new AwPrintDocumentAdapter(mAwContents.getPdfExporter(), documentName);
2050 // AwContents.NativeGLDelegate implementation --------------------------------------
2051 private class WebViewNativeGLDelegate implements AwContents.NativeGLDelegate {
2052 @Override
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);
2061 @Override
2062 public void detachGLFunctor() {
2063 if (mGLfunctor != null) {
2064 mGLfunctor.detach();
2069 // AwContents.InternalAccessDelegate implementation --------------------------------------
2070 private class InternalAccessAdapter implements AwContents.InternalAccessDelegate {
2071 @Override
2072 public boolean drawChild(Canvas arg0, View arg1, long arg2) {
2073 return false;
2076 @Override
2077 public boolean super_onKeyUp(int arg0, KeyEvent arg1) {
2078 // Intentional no-op
2079 return false;
2082 @Override
2083 public boolean super_dispatchKeyEventPreIme(KeyEvent arg0) {
2084 return false;
2087 @Override
2088 public boolean super_dispatchKeyEvent(KeyEvent event) {
2089 return mWebViewPrivate.super_dispatchKeyEvent(event);
2092 @Override
2093 public boolean super_onGenericMotionEvent(MotionEvent arg0) {
2094 return mWebViewPrivate.super_onGenericMotionEvent(arg0);
2097 @Override
2098 public void super_onConfigurationChanged(Configuration arg0) {
2099 // Intentional no-op
2102 @Override
2103 public int super_getScrollBarStyle() {
2104 return mWebViewPrivate.super_getScrollBarStyle();
2107 @Override
2108 public boolean awakenScrollBars() {
2109 mWebViewPrivate.awakenScrollBars(0);
2110 // TODO: modify the WebView.PrivateAccess to provide a return value.
2111 return true;
2114 @Override
2115 public boolean super_awakenScrollBars(int arg0, boolean arg1) {
2116 return false;
2119 @Override
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.
2126 @Override
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);
2133 @Override
2134 public void super_scrollTo(int scrollX, int scrollY) {
2135 mWebViewPrivate.super_scrollTo(scrollX, scrollY);
2138 @Override
2139 public void setMeasuredDimension(int measuredWidth, int measuredHeight) {
2140 mWebViewPrivate.setMeasuredDimension(measuredWidth, measuredHeight);
2143 // @Override
2144 public boolean super_onHoverEvent(MotionEvent event) {
2145 return mWebViewPrivate.super_onHoverEvent(event);
2149 // Implements SmartClipProvider
2150 @Override
2151 public void extractSmartClipData(int x, int y, int width, int height) {
2152 checkThread();
2153 mAwContents.extractSmartClipData(x, y, width, height);
2156 // Implements SmartClipProvider
2157 @Override
2158 public void setSmartClipResultHandler(final Handler resultHandler) {
2159 checkThread();
2160 mAwContents.setSmartClipResultHandler(resultHandler);