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