WebViewChromium.java revision 3411fdf2737f3f0dd0c1fa20045356cf89f34edd
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.Log;
31import android.view.HardwareCanvas;
32import android.view.KeyEvent;
33import android.view.MotionEvent;
34import android.view.View;
35import android.view.View.MeasureSpec;
36import android.view.ViewGroup;
37import android.view.accessibility.AccessibilityEvent;
38import android.view.accessibility.AccessibilityNodeInfo;
39import android.view.inputmethod.EditorInfo;
40import android.view.inputmethod.InputConnection;
41import android.webkit.DownloadListener;
42import android.webkit.JavascriptInterface;
43import android.webkit.ValueCallback;
44import android.webkit.WebBackForwardList;
45import android.webkit.WebChromeClient;
46import android.webkit.WebSettings;
47import android.webkit.WebView;
48import android.webkit.WebViewClient;
49import android.webkit.WebViewProvider;
50
51import org.chromium.android_webview.AwContents;
52import org.chromium.android_webview.AwNativeWindow;
53import org.chromium.content.browser.ContentViewCore;
54import org.chromium.content.browser.LoadUrlParams;
55import org.chromium.net.NetworkChangeNotifier;
56
57import java.io.BufferedWriter;
58import java.io.File;
59import java.lang.annotation.Annotation;
60import java.util.Map;
61
62/**
63 * This class is the delegate to which WebViewProxy forwards all API calls.
64 *
65 * Most of the actual functionality is implemented by AwContents (or ContentViewCore within
66 * it). This class also contains WebView-specific APIs that require the creation of other
67 * adapters (otherwise org.chromium.content would depend on the webview.chromium package)
68 * and a small set of no-op deprecated APIs.
69 */
70class WebViewChromium implements WebViewProvider,
71          WebViewProvider.ScrollDelegate, WebViewProvider.ViewDelegate {
72
73    private static final String TAG = WebViewChromium.class.getSimpleName();
74
75    // The WebView that this WebViewChromium is the provider for.
76    WebView mWebView;
77    // Lets us access protected View-derived methods on the WebView instance we're backing.
78    WebView.PrivateAccess mWebViewPrivate;
79    // The client adapter class.
80    private WebViewContentsClientAdapter mContentsClientAdapter;
81
82    // Variables for functionality provided by this adapter ---------------------------------------
83    // WebSettings adapter, lazily initialized in the getter
84    private WebSettings mWebSettings;
85    // The WebView wrapper for ContentViewCore and required browser compontents.
86    private AwContents mAwContents;
87    // Non-null if this webview is using the GL accelerated draw path.
88    private DrawGLFunctor mGLfunctor;
89
90    private final WebView.HitTestResult mHitTestResult;
91
92    public WebViewChromium(WebView webView, WebView.PrivateAccess webViewPrivate) {
93        mWebView = webView;
94        mWebViewPrivate = webViewPrivate;
95        mHitTestResult = new WebView.HitTestResult();
96    }
97
98    static void completeWindowCreation(WebView parent, WebView child) {
99        AwContents parentContents = ((WebViewChromium) parent.getWebViewProvider()).mAwContents;
100        AwContents childContents = ((WebViewChromium) child.getWebViewProvider()).mAwContents;
101        parentContents.supplyContentsForPopup(childContents);
102    }
103
104    // WebViewProvider methods --------------------------------------------------------------------
105
106    @Override
107    public void init(Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) {
108        // TODO: BUG=6790250 javaScriptInterfaces were only ever used by DumpRenderTree and should
109        // probably be implemented as a hidden hook in WebViewClassic.
110
111        final boolean isAccessFromFileURLsGrantedByDefault =
112                mWebView.getContext().getApplicationInfo().targetSdkVersion <
113                Build.VERSION_CODES.JELLY_BEAN;
114        mContentsClientAdapter = new WebViewContentsClientAdapter(mWebView);
115        mAwContents = new AwContents(mWebView, new InternalAccessAdapter(), mContentsClientAdapter,
116                new AwNativeWindow(mWebView.getContext()), privateBrowsing,
117                isAccessFromFileURLsGrantedByDefault);
118
119        // At this point we now have the native AwContents and WebContents created and code
120        // that requires them can now be called.
121    }
122
123    @Override
124    public void setHorizontalScrollbarOverlay(boolean overlay) {
125        UnimplementedWebViewApi.invoke();
126    }
127
128    @Override
129    public void setVerticalScrollbarOverlay(boolean overlay) {
130        UnimplementedWebViewApi.invoke();
131    }
132
133    @Override
134    public boolean overlayHorizontalScrollbar() {
135        UnimplementedWebViewApi.invoke();
136        return false;
137    }
138
139    @Override
140    public boolean overlayVerticalScrollbar() {
141        UnimplementedWebViewApi.invoke();
142        return false;
143    }
144
145    @Override
146    public int getVisibleTitleHeight() {
147        // This is deprecated in WebView and should always return 0.
148        return 0;
149    }
150
151    @Override
152    public SslCertificate getCertificate() {
153        return mAwContents.getCertificate();
154    }
155
156    @Override
157    public void setCertificate(SslCertificate certificate) {
158        UnimplementedWebViewApi.invoke();
159    }
160
161    @Override
162    public void savePassword(String host, String username, String password) {
163        UnimplementedWebViewApi.invoke();
164    }
165
166    @Override
167    public void setHttpAuthUsernamePassword(String host, String realm, String username,
168                                            String password) {
169        mAwContents.setHttpAuthUsernamePassword(host, realm, username, password);
170    }
171
172    @Override
173    public String[] getHttpAuthUsernamePassword(String host, String realm) {
174        return mAwContents.getHttpAuthUsernamePassword(host, realm);
175    }
176
177    @Override
178    public void destroy() {
179        mAwContents.destroy();
180        if (mGLfunctor != null) {
181            mGLfunctor.destroy();
182            mGLfunctor = null;
183        }
184    }
185
186    @Override
187    public void setNetworkAvailable(boolean networkUp) {
188        NetworkChangeNotifier.forceConnectivityState(networkUp);
189    }
190
191    @Override
192    public WebBackForwardList saveState(Bundle outState) {
193        if (outState == null) return null;
194        if (!mAwContents.saveState(outState)) return null;
195        return copyBackForwardList();
196    }
197
198    @Override
199    public boolean savePicture(Bundle b, File dest) {
200        UnimplementedWebViewApi.invoke();
201        return false;
202    }
203
204    @Override
205    public boolean restorePicture(Bundle b, File src) {
206        UnimplementedWebViewApi.invoke();
207        return false;
208    }
209
210    @Override
211    public WebBackForwardList restoreState(Bundle inState) {
212        if (inState == null) return null;
213        if (!mAwContents.restoreState(inState)) return null;
214        return copyBackForwardList();
215    }
216
217    @Override
218    public void loadUrl(String url, Map<String, String> additionalHttpHeaders) {
219        // TODO: We may actually want to do some sanity checks here (like filter about://chrome).
220        LoadUrlParams params = new LoadUrlParams(url);
221        if (additionalHttpHeaders != null) params.setExtraHeaders(additionalHttpHeaders);
222        mAwContents.loadUrl(params);
223    }
224
225    @Override
226    public void loadUrl(String url) {
227        loadUrl(url, null);
228    }
229
230    @Override
231    public void postUrl(String url, byte[] postData) {
232        mAwContents.loadUrl(LoadUrlParams.createLoadHttpPostParams(
233                url, postData));
234    }
235
236    private static boolean isBase64Encoded(String encoding) {
237        return "base64".equals(encoding);
238    }
239
240    @Override
241    public void loadData(String data, String mimeType, String encoding) {
242        mAwContents.loadUrl(LoadUrlParams.createLoadDataParams(
243                  data, mimeType, isBase64Encoded(encoding)));
244    }
245
246    @Override
247    public void loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding,
248                                    String historyUrl) {
249        if (baseUrl == null || baseUrl.length() == 0) baseUrl = "about:blank";
250        mAwContents.loadUrl(LoadUrlParams.createLoadDataParamsWithBaseUrl(
251                data, mimeType, isBase64Encoded(encoding), baseUrl, historyUrl));
252    }
253
254    @Override
255    public void saveWebArchive(String filename) {
256        saveWebArchive(filename, false, null);
257    }
258
259    @Override
260    public void saveWebArchive(String basename, boolean autoname, ValueCallback<String> callback) {
261        mAwContents.saveWebArchive(basename, autoname, callback);
262    }
263
264    @Override
265    public void stopLoading() {
266        mAwContents.getContentViewCore().stopLoading();
267    }
268
269    @Override
270    public void reload() {
271        mAwContents.getContentViewCore().reload();
272    }
273
274    @Override
275    public boolean canGoBack() {
276        return mAwContents.getContentViewCore().canGoBack();
277    }
278
279    @Override
280    public void goBack() {
281        mAwContents.getContentViewCore().goBack();
282    }
283
284    @Override
285    public boolean canGoForward() {
286        return mAwContents.getContentViewCore().canGoForward();
287    }
288
289    @Override
290    public void goForward() {
291        mAwContents.getContentViewCore().goForward();
292    }
293
294    @Override
295    public boolean canGoBackOrForward(int steps) {
296        return mAwContents.getContentViewCore().canGoToOffset(steps);
297    }
298
299    @Override
300    public void goBackOrForward(int steps) {
301        mAwContents.getContentViewCore().goToOffset(steps);
302    }
303
304    @Override
305    public boolean isPrivateBrowsingEnabled() {
306        UnimplementedWebViewApi.invoke();
307        return false;
308    }
309
310    @Override
311    public boolean pageUp(boolean top) {
312        return mAwContents.getContentViewCore().pageUp(top);
313    }
314
315    @Override
316    public boolean pageDown(boolean bottom) {
317        return mAwContents.getContentViewCore().pageDown(bottom);
318    }
319
320    @Override
321    public void clearView() {
322        UnimplementedWebViewApi.invoke();
323    }
324
325    @Override
326    public Picture capturePicture() {
327        UnimplementedWebViewApi.invoke();
328        return null;
329    }
330
331    @Override
332    public float getScale() {
333        return mAwContents.getContentViewCore().getScale();
334    }
335
336    @Override
337    public void setInitialScale(int scaleInPercent) {
338        UnimplementedWebViewApi.invoke();
339    }
340
341    @Override
342    public void invokeZoomPicker() {
343        mAwContents.getContentViewCore().invokeZoomPicker();
344    }
345
346    @Override
347    public WebView.HitTestResult getHitTestResult() {
348        AwContents.HitTestData data = mAwContents.getLastHitTestResult();
349        mHitTestResult.setType(data.hitTestResultType);
350        mHitTestResult.setExtra(data.hitTestResultExtraData);
351        return mHitTestResult;
352    }
353
354    @Override
355    public void requestFocusNodeHref(Message hrefMsg) {
356        mAwContents.requestFocusNodeHref(hrefMsg);
357    }
358
359    @Override
360    public void requestImageRef(Message msg) {
361        mAwContents.requestImageRef(msg);
362    }
363
364    @Override
365    public String getUrl() {
366        String url =  mAwContents.getContentViewCore().getUrl();
367        if (url == null || url.trim().isEmpty()) return null;
368        return url;
369    }
370
371    @Override
372    public String getOriginalUrl() {
373        String url =  mAwContents.getOriginalUrl();
374        if (url == null || url.trim().isEmpty()) return null;
375        return url;
376    }
377
378    @Override
379    public String getTitle() {
380        return mAwContents.getContentViewCore().getTitle();
381    }
382
383    @Override
384    public Bitmap getFavicon() {
385        UnimplementedWebViewApi.invoke();
386        return null;
387    }
388
389    @Override
390    public String getTouchIconUrl() {
391        UnimplementedWebViewApi.invoke();
392        return null;
393    }
394
395    @Override
396    public int getProgress() {
397        return mAwContents.getMostRecentProgress();
398    }
399
400    @Override
401    public int getContentHeight() {
402        return mAwContents.getContentViewCore().getContentHeight();
403    }
404
405    @Override
406    public int getContentWidth() {
407        return mAwContents.getContentViewCore().getContentWidth();
408    }
409
410    @Override
411    public void pauseTimers() {
412        mAwContents.pauseTimers();
413    }
414
415    @Override
416    public void resumeTimers() {
417        mAwContents.resumeTimers();
418    }
419
420    @Override
421    public void onPause() {
422        mAwContents.onPause();
423    }
424
425    @Override
426    public void onResume() {
427        mAwContents.onResume();
428    }
429
430    @Override
431    public boolean isPaused() {
432        return mAwContents.isPaused();
433    }
434
435    @Override
436    public void freeMemory() {
437        UnimplementedWebViewApi.invoke();
438    }
439
440    @Override
441    public void clearCache(boolean includeDiskFiles) {
442        mAwContents.clearCache(includeDiskFiles);
443    }
444
445    @Override
446    public void clearFormData() {
447        UnimplementedWebViewApi.invoke();
448    }
449
450    @Override
451    public void clearHistory() {
452        mAwContents.getContentViewCore().clearHistory();
453    }
454
455    @Override
456    public void clearSslPreferences() {
457        mAwContents.getContentViewCore().clearSslPreferences();
458    }
459
460    @Override
461    public WebBackForwardList copyBackForwardList() {
462        return new WebBackForwardListChromium(
463                mAwContents.getContentViewCore().getNavigationHistory());
464    }
465
466    @Override
467    public void setFindListener(WebView.FindListener listener) {
468        mContentsClientAdapter.setFindListener(listener);
469    }
470
471    @Override
472    public void findNext(boolean forwards) {
473        mAwContents.findNext(forwards);
474    }
475
476    @Override
477    public int findAll(String searchString) {
478        return mAwContents.findAllSync(searchString);
479    }
480
481    @Override
482    public void findAllAsync(String searchString) {
483        mAwContents.findAllAsync(searchString);
484    }
485
486    @Override
487    public boolean showFindDialog(String text, boolean showIme) {
488        UnimplementedWebViewApi.invoke();
489        return false;
490    }
491
492    @Override
493    public void clearMatches() {
494        mAwContents.clearMatches();
495    }
496
497    @Override
498    public void documentHasImages(Message response) {
499        mAwContents.documentHasImages(response);
500    }
501
502    @Override
503    public void setWebViewClient(WebViewClient client) {
504        mContentsClientAdapter.setWebViewClient(client);
505    }
506
507    @Override
508    public void setDownloadListener(DownloadListener listener) {
509        mContentsClientAdapter.setDownloadListener(listener);
510    }
511
512    @Override
513    public void setWebChromeClient(WebChromeClient client) {
514        mContentsClientAdapter.setWebChromeClient(client);
515    }
516
517    @Override
518    public void setPictureListener(WebView.PictureListener listener) {
519        mContentsClientAdapter.setPictureListener(listener);
520    }
521
522    @Override
523    public void addJavascriptInterface(Object obj, String interfaceName) {
524        Class<? extends Annotation> requiredAnnotation = null;
525        if (mWebView.getContext().getApplicationInfo().targetSdkVersion >=
526                Build.VERSION_CODES.JELLY_BEAN_MR1) {
527           requiredAnnotation = JavascriptInterface.class;
528        }
529        mAwContents.getContentViewCore().addPossiblyUnsafeJavascriptInterface(obj, interfaceName,
530            requiredAnnotation);
531    }
532
533    @Override
534    public void removeJavascriptInterface(String interfaceName) {
535        mAwContents.getContentViewCore().removeJavascriptInterface(interfaceName);
536    }
537
538    @Override
539    public WebSettings getSettings() {
540        if (mWebSettings == null) {
541            mWebSettings = new ContentSettingsAdapter(
542                    mAwContents.getContentViewCore().getContentSettings(),
543                    mAwContents.getSettings());
544        }
545        return mWebSettings;
546    }
547
548    @Override
549    public void setMapTrackballToArrowKeys(boolean setMap) {
550        // This is a deprecated API: intentional no-op.
551    }
552
553    @Override
554    public void flingScroll(int vx, int vy) {
555        mAwContents.getContentViewCore().flingScroll(vx, vy);
556    }
557
558    @Override
559    public View getZoomControls() {
560        // This was deprecated in 2009 and hidden in JB MR1, so just provide the minimum needed
561        // to stop very out-dated applications from crashing.
562        Log.w(TAG, "WebView doesn't support getZoomControls");
563        return mAwContents.getContentViewCore().getContentSettings().supportZoom() ?
564            new View(mWebView.getContext()) : null;
565    }
566
567    @Override
568    public boolean canZoomIn() {
569        return mAwContents.getContentViewCore().canZoomIn();
570    }
571
572    @Override
573    public boolean canZoomOut() {
574        return mAwContents.getContentViewCore().canZoomOut();
575    }
576
577    @Override
578    public boolean zoomIn() {
579        return mAwContents.getContentViewCore().zoomIn();
580    }
581
582    @Override
583    public boolean zoomOut() {
584        return mAwContents.getContentViewCore().zoomOut();
585    }
586
587    // TODO: This should  @Override the base class method, but the method
588    // exists only in the Android-master source. So to keep compiling on both
589    // Android-master and Android-jb-dev, omit the annotation. When we no longer
590    // need to build with jb-dev, add the annotation.
591    public void dumpViewHierarchyWithProperties(BufferedWriter out, int level) {
592        UnimplementedWebViewApi.invoke();
593    }
594
595    // TODO: This should  @Override the base class method, but the method
596    // exists only in the Android-master source. So to keep compiling on both
597    // Android-master and Android-jb-dev, omit the annotation. When we no longer
598    // need to build with jb-dev, add the annotation.
599    public View findHierarchyView(String className, int hashCode) {
600        UnimplementedWebViewApi.invoke();
601        return null;
602    }
603
604    // WebViewProvider glue methods ---------------------------------------------------------------
605
606    @Override
607    public WebViewProvider.ViewDelegate getViewDelegate() {
608        return this;
609    }
610
611    @Override
612    public WebViewProvider.ScrollDelegate getScrollDelegate() {
613        return this;
614    }
615
616
617    // WebViewProvider JB migration methods -------------------------------------------------------
618
619    // TODO: These methods are removed from the base class in
620    // Android-master, but we keep them here to ensure that the glue
621    // layer builds in an Android-jb-dev tree. Once we no longer
622    // need to compile the glue against jb-dev, remove this method.
623
624    public void debugDump() {
625        // This is deprecated and now does nothing.
626    }
627
628    public void emulateShiftHeld() {
629        // This is deprecated and now does nothing.
630    }
631
632    // WebViewProvider.ViewDelegate implementation ------------------------------------------------
633
634    @Override
635    public boolean shouldDelayChildPressedState() {
636        UnimplementedWebViewApi.invoke();
637        return false;
638    }
639
640    @Override
641    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
642        mAwContents.getContentViewCore().onInitializeAccessibilityNodeInfo(info);
643    }
644
645    @Override
646    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
647        mAwContents.getContentViewCore().onInitializeAccessibilityEvent(event);
648    }
649
650    // TODO: Update WebView to mimic ContentView implementation for the
651    // real View#performAccessibilityAction(int, Bundle).  This method has different behavior.
652    // See ContentViewCore#performAccessibilityAction(int, Bundle) for more details.
653    @Override
654    public boolean performAccessibilityAction(int action, Bundle arguments) {
655        return mAwContents.getContentViewCore().performAccessibilityAction(action, arguments);
656    }
657
658    @Override
659    public void setOverScrollMode(int mode) {
660        UnimplementedWebViewApi.invoke();
661    }
662
663    @Override
664    public void setScrollBarStyle(int style) {
665        UnimplementedWebViewApi.invoke();
666    }
667
668    @Override
669    public void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
670                                        int l, int t, int r, int b) {
671        UnimplementedWebViewApi.invoke();
672    }
673
674    @Override
675    public void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
676        UnimplementedWebViewApi.invoke();
677    }
678
679    @Override
680    public void onWindowVisibilityChanged(int visibility) {
681        mAwContents.onWindowVisibilityChanged(visibility);
682    }
683
684    @Override
685    public void onDraw(Canvas canvas) {
686        if (canvas.isHardwareAccelerated() && mAwContents.onPrepareDrawGL(canvas)) {
687            if (mGLfunctor == null) {
688                mGLfunctor = new DrawGLFunctor(mAwContents.getAwDrawGLViewContext());
689            }
690            mGLfunctor.requestDrawGL((HardwareCanvas) canvas, mWebView.getViewRootImpl());
691        } else {
692          mAwContents.onDraw(canvas);
693        }
694    }
695
696    @Override
697    public void setLayoutParams(ViewGroup.LayoutParams layoutParams) {
698        // TODO: This is the minimum implementation for HTMLViewer
699        // bringup. Likely will need to go up to ContentViewCore for
700        // a complete implementation.
701        mWebViewPrivate.super_setLayoutParams(layoutParams);
702    }
703
704    @Override
705    public boolean performLongClick() {
706        return mWebViewPrivate.super_performLongClick();
707    }
708
709    @Override
710    public void onConfigurationChanged(Configuration newConfig) {
711        mAwContents.onConfigurationChanged(newConfig);
712    }
713
714    @Override
715    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
716        return mAwContents.getContentViewCore().onCreateInputConnection(outAttrs);
717    }
718
719    @Override
720    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
721        UnimplementedWebViewApi.invoke();
722        return false;
723    }
724
725    @Override
726    public boolean onKeyDown(int keyCode, KeyEvent event) {
727        UnimplementedWebViewApi.invoke();
728        return false;
729    }
730
731    @Override
732    public boolean onKeyUp(int keyCode, KeyEvent event) {
733        return mAwContents.getContentViewCore().onKeyUp(keyCode, event);
734    }
735
736    @Override
737    public void onAttachedToWindow() {
738        mAwContents.onAttachedToWindow();
739    }
740
741    @Override
742    public void onDetachedFromWindow() {
743        mAwContents.onDetachedFromWindow();
744        if (mGLfunctor != null) {
745            mGLfunctor.detach();
746        }
747    }
748
749    @Override
750    public void onVisibilityChanged(View changedView, int visibility) {
751        mAwContents.onVisibilityChanged(changedView, visibility);
752    }
753
754    @Override
755    public void onWindowFocusChanged(boolean hasWindowFocus) {
756        mAwContents.onWindowFocusChanged(hasWindowFocus);
757    }
758
759    @Override
760    public void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
761        mAwContents.onFocusChanged(focused, direction, previouslyFocusedRect);
762    }
763
764    @Override
765    public boolean setFrame(int left, int top, int right, int bottom) {
766        // TODO(joth): This is the minimum implementation for initial
767        // bringup. Likely will need to go up to AwContents for a complete
768        // implementation, e.g. setting the compositor visible region (to
769        // avoid painting tiles that are offscreen due to the view's position).
770        return mWebViewPrivate.super_setFrame(left, top, right, bottom);
771    }
772
773    @Override
774    public void onSizeChanged(int w, int h, int ow, int oh) {
775        mAwContents.onSizeChanged(w, h, ow, oh);
776    }
777
778    @Override
779    public void onScrollChanged(int l, int t, int oldl, int oldt) {
780    }
781
782    @Override
783    public boolean dispatchKeyEvent(KeyEvent event) {
784        return mAwContents.getContentViewCore().dispatchKeyEvent(event);
785    }
786
787    @Override
788    public boolean onTouchEvent(MotionEvent ev) {
789        return mAwContents.onTouchEvent(ev);
790    }
791
792    @Override
793    public boolean onHoverEvent(MotionEvent event) {
794        return mAwContents.onHoverEvent(event);
795    }
796
797    @Override
798    public boolean onGenericMotionEvent(MotionEvent event) {
799        return mAwContents.onGenericMotionEvent(event);
800    }
801
802    @Override
803    public boolean onTrackballEvent(MotionEvent ev) {
804        // Trackball event not handled, which eventually gets converted to DPAD keyevents
805        return false;
806    }
807
808    @Override
809    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
810        return mWebViewPrivate.super_requestFocus(direction, previouslyFocusedRect);
811    }
812
813    @Override
814    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
815        // TODO(boliu): This is to get around the fact that onMeasure is not
816        // implemented yet but some cts tests depends on non-zero behavior.
817        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
818        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
819        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
820        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
821        if (heightMode != MeasureSpec.EXACTLY &&
822            widthMode != MeasureSpec.EXACTLY) {
823            mWebViewPrivate.setMeasuredDimension(widthSize, heightSize);
824        }
825        UnimplementedWebViewApi.invoke();
826    }
827
828    @Override
829    public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate) {
830        UnimplementedWebViewApi.invoke();
831        return false;
832    }
833
834    @Override
835    public void setBackgroundColor(int color) {
836        UnimplementedWebViewApi.invoke();
837    }
838
839    @Override
840    public void setLayerType(int layerType, Paint paint) {
841        UnimplementedWebViewApi.invoke();
842    }
843
844    // No @Override for now to keep bots happy.
845    public void preDispatchDraw(Canvas canvas) {
846        // ContentViewCore handles drawing the scroll internally, therefore
847        // we need to compensate for the canvas transform already applied
848        // by the framework due to changes to the WebView's scrollX/Y.
849        canvas.translate(mWebView.getScrollX(), mWebView.getScrollY());
850    }
851
852    // WebViewProvider.ScrollDelegate implementation ----------------------------------------------
853
854    @Override
855    public int computeHorizontalScrollRange() {
856        return mAwContents.getContentViewCore().computeHorizontalScrollRange();
857    }
858
859    @Override
860    public int computeHorizontalScrollOffset() {
861        return mAwContents.getContentViewCore().computeHorizontalScrollOffset();
862    }
863
864    @Override
865    public int computeVerticalScrollRange() {
866        return mAwContents.getContentViewCore().computeVerticalScrollRange();
867    }
868
869    @Override
870    public int computeVerticalScrollOffset() {
871        return mAwContents.getContentViewCore().computeVerticalScrollOffset();
872    }
873
874    @Override
875    public int computeVerticalScrollExtent() {
876        return mAwContents.getContentViewCore().computeVerticalScrollExtent();
877    }
878
879    @Override
880    public void computeScroll() {
881        // BUG=http://b/6029133
882        UnimplementedWebViewApi.invoke();
883    }
884
885    // ContentViewCore.InternalAccessDelegate implementation --------------------------------------
886    private class InternalAccessAdapter implements ContentViewCore.InternalAccessDelegate {
887
888        @Override
889        public boolean drawChild(Canvas arg0, View arg1, long arg2) {
890            UnimplementedWebViewApi.invoke();
891            return false;
892        }
893
894        @Override
895        public boolean super_onKeyUp(int arg0, KeyEvent arg1) {
896            UnimplementedWebViewApi.invoke();
897            return false;
898        }
899
900        @Override
901        public boolean super_dispatchKeyEventPreIme(KeyEvent arg0) {
902            UnimplementedWebViewApi.invoke();
903            return false;
904        }
905
906        @Override
907        public boolean super_dispatchKeyEvent(KeyEvent event) {
908            return mWebViewPrivate.super_dispatchKeyEvent(event);
909        }
910
911        @Override
912        public boolean super_onGenericMotionEvent(MotionEvent arg0) {
913            UnimplementedWebViewApi.invoke();
914            return false;
915        }
916
917        @Override
918        public void super_onConfigurationChanged(Configuration arg0) {
919            UnimplementedWebViewApi.invoke();
920        }
921
922        @Override
923        public void onScrollChanged(int l, int t, int oldl, int oldt) {
924            mWebViewPrivate.setScrollXRaw(l);
925            mWebViewPrivate.setScrollYRaw(t);
926            mWebViewPrivate.onScrollChanged(l, t, oldl, oldt);
927        }
928
929        @Override
930        public boolean awakenScrollBars() {
931            mWebViewPrivate.awakenScrollBars(0);
932            // TODO: modify the WebView.PrivateAccess to provide a return value.
933            return true;
934        }
935
936        @Override
937        public boolean super_awakenScrollBars(int arg0, boolean arg1) {
938            // TODO: need method on WebView.PrivateAccess?
939            UnimplementedWebViewApi.invoke();
940            return false;
941        }
942
943        // TODO: Remove this method. It is not planned to get upstreamed.
944        // @Override
945        public void onSurfaceTextureUpdated() {
946        }
947    }
948}
949