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