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