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