ContentView.java revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package org.chromium.content.browser;
6
7import android.app.Activity;
8import android.content.Context;
9import android.content.res.Configuration;
10import android.graphics.Bitmap;
11import android.graphics.Canvas;
12import android.graphics.Rect;
13import android.os.Build;
14import android.util.AttributeSet;
15import android.view.KeyEvent;
16import android.view.MotionEvent;
17import android.view.View;
18import android.view.accessibility.AccessibilityEvent;
19import android.view.accessibility.AccessibilityNodeInfo;
20import android.view.inputmethod.EditorInfo;
21import android.view.inputmethod.InputConnection;
22import android.widget.FrameLayout;
23
24import com.google.common.annotations.VisibleForTesting;
25
26import org.chromium.content.common.TraceEvent;
27import org.chromium.ui.WindowAndroid;
28
29/**
30 * The containing view for {@link ContentViewCore} that exists in the Android UI hierarchy and
31 * exposes the various {@link View} functionality to it.
32 *
33 * TODO(joth): Remove any methods overrides from this class that were added for WebView
34 *             compatibility.
35 */
36public class ContentView extends FrameLayout
37        implements ContentViewCore.InternalAccessDelegate, PageInfo {
38
39    private final ContentViewCore mContentViewCore;
40
41    private float mCurrentTouchOffsetX;
42    private float mCurrentTouchOffsetY;
43
44    /**
45     * Creates an instance of a ContentView.
46     * @param context The Context the view is running in, through which it can
47     *                access the current theme, resources, etc.
48     * @param nativeWebContents A pointer to the native web contents.
49     * @param windowAndroid An instance of the WindowAndroid.
50     * @return A ContentView instance.
51     */
52    public static ContentView newInstance(Context context, int nativeWebContents,
53            WindowAndroid windowAndroid) {
54        return newInstance(context, nativeWebContents, windowAndroid, null,
55                android.R.attr.webViewStyle);
56    }
57
58    /**
59     * Creates an instance of a ContentView.
60     * @param context The Context the view is running in, through which it can
61     *                access the current theme, resources, etc.
62     * @param nativeWebContents A pointer to the native web contents.
63     * @param windowAndroid An instance of the WindowAndroid.
64     * @param attrs The attributes of the XML tag that is inflating the view.
65     * @return A ContentView instance.
66     */
67    public static ContentView newInstance(Context context, int nativeWebContents,
68            WindowAndroid windowAndroid, AttributeSet attrs) {
69        // TODO(klobag): use the WebViewStyle as the default style for now. It enables scrollbar.
70        // When ContentView is moved to framework, we can define its own style in the res.
71        return newInstance(context, nativeWebContents, windowAndroid, attrs,
72                android.R.attr.webViewStyle);
73    }
74
75    /**
76     * Creates an instance of a ContentView.
77     * @param context The Context the view is running in, through which it can
78     *                access the current theme, resources, etc.
79     * @param nativeWebContents A pointer to the native web contents.
80     * @param windowAndroid An instance of the WindowAndroid.
81     * @param attrs The attributes of the XML tag that is inflating the view.
82     * @param defStyle The default style to apply to this view.
83     * @return A ContentView instance.
84     */
85    public static ContentView newInstance(Context context, int nativeWebContents,
86            WindowAndroid windowAndroid, AttributeSet attrs, int defStyle) {
87        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
88            return new ContentView(context, nativeWebContents, windowAndroid, attrs, defStyle);
89        } else {
90            return new JellyBeanContentView(context, nativeWebContents, windowAndroid, attrs,
91                    defStyle);
92        }
93    }
94
95    protected ContentView(Context context, int nativeWebContents, WindowAndroid windowAndroid,
96            AttributeSet attrs, int defStyle) {
97        super(context, attrs, defStyle);
98
99        if (getScrollBarStyle() == View.SCROLLBARS_INSIDE_OVERLAY) {
100            setHorizontalScrollBarEnabled(false);
101            setVerticalScrollBarEnabled(false);
102        }
103
104        setFocusable(true);
105        setFocusableInTouchMode(true);
106
107        mContentViewCore = new ContentViewCore(context);
108        mContentViewCore.initialize(this, this, nativeWebContents, windowAndroid,
109                Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN ?
110                ContentViewCore.INPUT_EVENTS_DELIVERED_AT_VSYNC :
111                ContentViewCore.INPUT_EVENTS_DELIVERED_IMMEDIATELY);
112    }
113
114    // PageInfo implementation.
115
116    @Override
117    public String getUrl() {
118        return mContentViewCore.getUrl();
119    }
120
121    @Override
122    public String getTitle() {
123        return mContentViewCore.getTitle();
124    }
125
126    @Override
127    public boolean isReadyForSnapshot() {
128        return !isCrashed() && isReady();
129    }
130
131    @Override
132    public Bitmap getBitmap() {
133        return getBitmap(getWidth(), getHeight());
134    }
135
136    @Override
137    public Bitmap getBitmap(int width, int height) {
138        return mContentViewCore.getBitmap(width, height);
139    }
140
141    @Override
142    public int getBackgroundColor() {
143        return mContentViewCore.getBackgroundColor();
144    }
145
146    @Override
147    public View getView() {
148        return this;
149    }
150
151    /**
152     * @return The core component of the ContentView that handles JNI communication.  Should only be
153     *         used for passing to native.
154     */
155    public ContentViewCore getContentViewCore() {
156        return mContentViewCore;
157    }
158
159    /**
160     * @return The cache of scales and positions used to convert coordinates from/to CSS.
161     */
162    public RenderCoordinates getRenderCoordinates() {
163        return mContentViewCore.getRenderCoordinates();
164    }
165
166    /**
167     * Returns true if the given Activity has hardware acceleration enabled
168     * in its manifest, or in its foreground window.
169     *
170     * TODO(husky): Remove when ContentViewCore.initialize() is refactored (see TODO there)
171     * TODO(dtrainor) This is still used by other classes.  Make sure to pull some version of this
172     * out before removing it.
173     */
174    public static boolean hasHardwareAcceleration(Activity activity) {
175        return ContentViewCore.hasHardwareAcceleration(activity);
176    }
177
178    /**
179     * Destroy the internal state of the WebView. This method may only be called
180     * after the WebView has been removed from the view system. No other methods
181     * may be called on this WebView after this method has been called.
182     */
183    public void destroy() {
184        mContentViewCore.destroy();
185    }
186
187    /**
188     * Returns true initially, false after destroy() has been called.
189     * It is illegal to call any other public method after destroy().
190     */
191    public boolean isAlive() {
192        return mContentViewCore.isAlive();
193    }
194
195    /**
196     * For internal use. Throws IllegalStateException if mNativeContentView is 0.
197     * Use this to ensure we get a useful Java stack trace, rather than a native
198     * crash dump, from use-after-destroy bugs in Java code.
199     */
200    void checkIsAlive() throws IllegalStateException {
201        mContentViewCore.checkIsAlive();
202    }
203
204    public void setContentViewClient(ContentViewClient client) {
205        mContentViewCore.setContentViewClient(client);
206    }
207
208    @VisibleForTesting
209    public ContentViewClient getContentViewClient() {
210        return mContentViewCore.getContentViewClient();
211    }
212
213    /**
214     * Load url without fixing up the url string. Consumers of ContentView are responsible for
215     * ensuring the URL passed in is properly formatted (i.e. the scheme has been added if left
216     * off during user input).
217     *
218     * @param params Parameters for this load.
219     */
220    public void loadUrl(LoadUrlParams params) {
221        mContentViewCore.loadUrl(params);
222    }
223
224    /**
225     * Stops loading the current web contents.
226     */
227    public void stopLoading() {
228        mContentViewCore.stopLoading();
229    }
230
231    /**
232     * @return Whether the current WebContents has a previous navigation entry.
233     */
234    public boolean canGoBack() {
235        return mContentViewCore.canGoBack();
236    }
237
238    /**
239     * @return Whether the current WebContents has a navigation entry after the current one.
240     */
241    public boolean canGoForward() {
242        return mContentViewCore.canGoForward();
243    }
244
245    /**
246     * @param offset The offset into the navigation history.
247     * @return Whether we can move in history by given offset
248     */
249    public boolean canGoToOffset(int offset) {
250        return mContentViewCore.canGoToOffset(offset);
251    }
252
253    /**
254     * Navigates to the specified offset from the "current entry". Does nothing if the offset is out
255     * of bounds.
256     * @param offset The offset into the navigation history.
257     */
258    public void goToOffset(int offset) {
259        mContentViewCore.goToOffset(offset);
260    }
261
262    /**
263     * Goes to the navigation entry before the current one.
264     */
265    public void goBack() {
266        mContentViewCore.goBack();
267    }
268
269    /**
270     * Goes to the navigation entry following the current one.
271     */
272    public void goForward() {
273        mContentViewCore.goForward();
274    }
275
276    /**
277     * Reload the current page.
278     */
279    public void reload() {
280        mContentViewCore.reload();
281    }
282
283    /**
284     * Clears the WebView's page history in both the backwards and forwards
285     * directions.
286     */
287    public void clearHistory() {
288        mContentViewCore.clearHistory();
289    }
290
291    /**
292     * Start profiling the update speed. You must call {@link #stopFpsProfiling}
293     * to stop profiling.
294     */
295    @VisibleForTesting
296    public void startFpsProfiling() {
297        // TODO(nileshagrawal): Implement this.
298    }
299
300    /**
301     * Stop profiling the update speed.
302     */
303    @VisibleForTesting
304    public float stopFpsProfiling() {
305        // TODO(nileshagrawal): Implement this.
306        return 0.0f;
307    }
308
309    /**
310     * Fling the ContentView from the current position.
311     * @param x Fling touch starting position
312     * @param y Fling touch starting position
313     * @param velocityX Initial velocity of the fling (X) measured in pixels per second.
314     * @param velocityY Initial velocity of the fling (Y) measured in pixels per second.
315     */
316    @VisibleForTesting
317    public void fling(long timeMs, int x, int y, int velocityX, int velocityY) {
318        mContentViewCore.getContentViewGestureHandler().fling(timeMs, x, y, velocityX, velocityY);
319    }
320
321    /**
322     * Start pinch zoom. You must call {@link #pinchEnd} to stop.
323     */
324    @VisibleForTesting
325    public void pinchBegin(long timeMs, int x, int y) {
326        mContentViewCore.getContentViewGestureHandler().pinchBegin(timeMs, x, y);
327    }
328
329    /**
330     * Stop pinch zoom.
331     */
332    @VisibleForTesting
333    public void pinchEnd(long timeMs) {
334        mContentViewCore.getContentViewGestureHandler().pinchEnd(timeMs);
335    }
336
337    void setIgnoreSingleTap(boolean value) {
338        mContentViewCore.getContentViewGestureHandler().setIgnoreSingleTap(value);
339    }
340
341    /** @see ContentViewGestureHandler#setIgnoreRemainingTouchEvents */
342    public void setIgnoreRemainingTouchEvents() {
343        mContentViewCore.getContentViewGestureHandler().setIgnoreRemainingTouchEvents();
344    }
345
346    /**
347     * Modify the ContentView magnification level. The effect of calling this
348     * method is exactly as after "pinch zoom".
349     *
350     * @param timeMs The event time in milliseconds.
351     * @param delta The ratio of the new magnification level over the current
352     *            magnification level.
353     * @param anchorX The magnification anchor (X) in the current view
354     *            coordinate.
355     * @param anchorY The magnification anchor (Y) in the current view
356     *            coordinate.
357     */
358    @VisibleForTesting
359    public void pinchBy(long timeMs, int anchorX, int anchorY, float delta) {
360        mContentViewCore.getContentViewGestureHandler().pinchBy(timeMs, anchorX, anchorY, delta);
361    }
362
363    /**
364     * Injects the passed JavaScript code in the current page and evaluates it.
365     *
366     * @throws IllegalStateException If the ContentView has been destroyed.
367     */
368    public void evaluateJavaScript(String script) throws IllegalStateException {
369        mContentViewCore.evaluateJavaScript(script, null);
370    }
371
372    /**
373     * This method should be called when the containing activity is paused.
374     **/
375    public void onActivityPause() {
376        mContentViewCore.onActivityPause();
377    }
378
379    /**
380     * This method should be called when the containing activity is resumed.
381     **/
382    public void onActivityResume() {
383        mContentViewCore.onActivityResume();
384    }
385
386    /**
387     * To be called when the ContentView is shown.
388     **/
389    public void onShow() {
390        mContentViewCore.onShow();
391    }
392
393    /**
394     * To be called when the ContentView is hidden.
395     **/
396    public void onHide() {
397        mContentViewCore.onHide();
398    }
399
400    /**
401     * Return the ContentSettings object used to retrieve the settings for this
402     * ContentView.
403     * @return A ContentSettings object that can be used to retrieve this ContentView's
404     *         settings.
405     */
406    public ContentSettings getContentSettings() {
407        return mContentViewCore.getContentSettings();
408    }
409
410    /**
411     * Hides the select action bar.
412     */
413    public void hideSelectActionBar() {
414        mContentViewCore.hideSelectActionBar();
415    }
416
417    // FrameLayout overrides.
418
419    // Needed by ContentViewCore.InternalAccessDelegate
420    @Override
421    public boolean drawChild(Canvas canvas, View child, long drawingTime) {
422        return super.drawChild(canvas, child, drawingTime);
423    }
424
425    @Override
426    protected void onSizeChanged(int w, int h, int ow, int oh) {
427        TraceEvent.begin();
428        super.onSizeChanged(w, h, ow, oh);
429        mContentViewCore.onSizeChanged(w, h, ow, oh);
430        TraceEvent.end();
431    }
432
433    @Override
434    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
435        return mContentViewCore.onCreateInputConnection(outAttrs);
436    }
437
438    @Override
439    public boolean onCheckIsTextEditor() {
440        return mContentViewCore.onCheckIsTextEditor();
441    }
442
443    @Override
444    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
445        TraceEvent.begin();
446        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
447        mContentViewCore.onFocusChanged(gainFocus);
448        TraceEvent.end();
449    }
450
451    @Override
452    public void onWindowFocusChanged(boolean hasWindowFocus) {
453        super.onWindowFocusChanged(hasWindowFocus);
454        mContentViewCore.onWindowFocusChanged(hasWindowFocus);
455    }
456
457    @Override
458    public boolean onKeyUp(int keyCode, KeyEvent event) {
459        return mContentViewCore.onKeyUp(keyCode, event);
460    }
461
462    @Override
463    public boolean dispatchKeyEventPreIme(KeyEvent event) {
464        return mContentViewCore.dispatchKeyEventPreIme(event);
465    }
466
467    @Override
468    public boolean dispatchKeyEvent(KeyEvent event) {
469        if (isFocused()) {
470            return mContentViewCore.dispatchKeyEvent(event);
471        } else {
472            return super.dispatchKeyEvent(event);
473        }
474    }
475
476    @Override
477    public boolean onTouchEvent(MotionEvent event) {
478        MotionEvent offset = createOffsetMotionEvent(event);
479        boolean consumed = mContentViewCore.onTouchEvent(offset);
480        offset.recycle();
481        return consumed;
482    }
483
484    /**
485     * Mouse move events are sent on hover enter, hover move and hover exit.
486     * They are sent on hover exit because sometimes it acts as both a hover
487     * move and hover exit.
488     */
489    @Override
490    public boolean onHoverEvent(MotionEvent event) {
491        MotionEvent offset = createOffsetMotionEvent(event);
492        boolean consumed = mContentViewCore.onHoverEvent(offset);
493        offset.recycle();
494        return consumed;
495    }
496
497    @Override
498    public boolean onGenericMotionEvent(MotionEvent event) {
499        return mContentViewCore.onGenericMotionEvent(event);
500    }
501
502    @Override
503    public boolean performLongClick() {
504        return false;
505    }
506
507    /**
508     * Sets the current amount to offset incoming touch events by.  This is used to handle content
509     * moving and not lining up properly with the android input system.
510     * @param dx The X offset in pixels to shift touch events.
511     * @param dy The Y offset in pixels to shift touch events.
512     */
513    public void setCurrentMotionEventOffsets(float dx, float dy) {
514        mCurrentTouchOffsetX = dx;
515        mCurrentTouchOffsetY = dy;
516    }
517
518    private MotionEvent createOffsetMotionEvent(MotionEvent src) {
519        MotionEvent dst = MotionEvent.obtain(src);
520        dst.offsetLocation(mCurrentTouchOffsetX, mCurrentTouchOffsetY);
521        return dst;
522    }
523
524    @Override
525    protected void onConfigurationChanged(Configuration newConfig) {
526        mContentViewCore.onConfigurationChanged(newConfig);
527    }
528
529    /**
530     * Currently the ContentView scrolling happens in the native side. In
531     * the Java view system, it is always pinned at (0, 0). scrollBy() and scrollTo()
532     * are overridden, so that View's mScrollX and mScrollY will be unchanged at
533     * (0, 0). This is critical for drawing ContentView correctly.
534     */
535    @Override
536    public void scrollBy(int x, int y) {
537        mContentViewCore.scrollBy(x, y);
538    }
539
540    @Override
541    public void scrollTo(int x, int y) {
542        mContentViewCore.scrollTo(x, y);
543    }
544
545    @Override
546    protected int computeHorizontalScrollExtent() {
547        // TODO (dtrainor): Need to expose scroll events properly to public. Either make getScroll*
548        // work or expose computeHorizontalScrollOffset()/computeVerticalScrollOffset as public.
549        return mContentViewCore.computeHorizontalScrollExtent();
550    }
551
552    @Override
553    protected int computeHorizontalScrollOffset() {
554        return mContentViewCore.computeHorizontalScrollOffset();
555    }
556
557    @Override
558    protected int computeHorizontalScrollRange() {
559        return mContentViewCore.computeHorizontalScrollRange();
560    }
561
562    @Override
563    protected int computeVerticalScrollExtent() {
564        return mContentViewCore.computeVerticalScrollExtent();
565    }
566
567    @Override
568    protected int computeVerticalScrollOffset() {
569        return mContentViewCore.computeVerticalScrollOffset();
570    }
571
572    @Override
573    protected int computeVerticalScrollRange() {
574        return mContentViewCore.computeVerticalScrollRange();
575    }
576
577    // End FrameLayout overrides.
578
579    @Override
580    public boolean awakenScrollBars(int startDelay, boolean invalidate) {
581        return mContentViewCore.awakenScrollBars(startDelay, invalidate);
582    }
583
584    @Override
585    public boolean awakenScrollBars() {
586        return super.awakenScrollBars();
587    }
588
589    public int getSingleTapX()  {
590        return mContentViewCore.getContentViewGestureHandler().getSingleTapX();
591    }
592
593    public int getSingleTapY()  {
594        return mContentViewCore.getContentViewGestureHandler().getSingleTapY();
595    }
596
597    @Override
598    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
599        super.onInitializeAccessibilityNodeInfo(info);
600        mContentViewCore.onInitializeAccessibilityNodeInfo(info);
601    }
602
603    /**
604     * Fills in scrolling values for AccessibilityEvents.
605     * @param event Event being fired.
606     */
607    @Override
608    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
609        super.onInitializeAccessibilityEvent(event);
610        mContentViewCore.onInitializeAccessibilityEvent(event);
611    }
612
613    @Override
614    protected void onAttachedToWindow() {
615        super.onAttachedToWindow();
616        mContentViewCore.onAttachedToWindow();
617    }
618
619    @Override
620    protected void onDetachedFromWindow() {
621        super.onDetachedFromWindow();
622        mContentViewCore.onDetachedFromWindow();
623    }
624
625    @Override
626    protected void onVisibilityChanged(View changedView, int visibility) {
627        super.onVisibilityChanged(changedView, visibility);
628        mContentViewCore.onVisibilityChanged(changedView, visibility);
629    }
630
631    /**
632     * Register the delegate to be used when content can not be handled by
633     * the rendering engine, and should be downloaded instead. This will replace
634     * the current delegate.
635     * @param delegate An implementation of ContentViewDownloadDelegate.
636     */
637    public void setDownloadDelegate(ContentViewDownloadDelegate delegate) {
638        mContentViewCore.setDownloadDelegate(delegate);
639    }
640
641    // Called by DownloadController.
642    ContentViewDownloadDelegate getDownloadDelegate() {
643        return mContentViewCore.getDownloadDelegate();
644    }
645
646    public boolean getUseDesktopUserAgent() {
647        return mContentViewCore.getUseDesktopUserAgent();
648    }
649
650    /**
651     * Set whether or not we're using a desktop user agent for the currently loaded page.
652     * @param override If true, use a desktop user agent.  Use a mobile one otherwise.
653     * @param reloadOnChange Reload the page if the UA has changed.
654     */
655    public void setUseDesktopUserAgent(boolean override, boolean reloadOnChange) {
656        mContentViewCore.setUseDesktopUserAgent(override, reloadOnChange);
657    }
658
659    /**
660     * @return Whether the native ContentView has crashed.
661     */
662    public boolean isCrashed() {
663        return mContentViewCore.isCrashed();
664    }
665
666    /**
667     * @return Whether a reload happens when this ContentView is activated.
668     */
669    public boolean needsReload() {
670        return mContentViewCore.needsReload();
671    }
672
673    /**
674     * Checks whether the WebView can be zoomed in.
675     *
676     * @return True if the WebView can be zoomed in.
677     */
678    // This method uses the term 'zoom' for legacy reasons, but relates
679    // to what chrome calls the 'page scale factor'.
680    public boolean canZoomIn() {
681        return mContentViewCore.canZoomIn();
682    }
683
684    /**
685     * Checks whether the WebView can be zoomed out.
686     *
687     * @return True if the WebView can be zoomed out.
688     */
689    // This method uses the term 'zoom' for legacy reasons, but relates
690    // to what chrome calls the 'page scale factor'.
691    public boolean canZoomOut() {
692        return mContentViewCore.canZoomOut();
693    }
694
695    /**
696     * Zooms in the WebView by 25% (or less if that would result in zooming in
697     * more than possible).
698     *
699     * @return True if there was a zoom change, false otherwise.
700     */
701    // This method uses the term 'zoom' for legacy reasons, but relates
702    // to what chrome calls the 'page scale factor'.
703    public boolean zoomIn() {
704        return mContentViewCore.zoomIn();
705    }
706
707    /**
708     * Zooms out the WebView by 20% (or less if that would result in zooming out
709     * more than possible).
710     *
711     * @return True if there was a zoom change, false otherwise.
712     */
713    // This method uses the term 'zoom' for legacy reasons, but relates
714    // to what chrome calls the 'page scale factor'.
715    public boolean zoomOut() {
716        return mContentViewCore.zoomOut();
717    }
718
719    /**
720     * Resets the zoom factor of the WebView.
721     *
722     * @return True if there was a zoom change, false otherwise.
723     */
724    // This method uses the term 'zoom' for legacy reasons, but relates
725    // to what chrome calls the 'page scale factor'.
726    public boolean zoomReset() {
727        return mContentViewCore.zoomReset();
728    }
729
730    /**
731     * Return the current scale of the WebView
732     * @return The current scale.
733     */
734    public float getScale() {
735        return mContentViewCore.getScale();
736    }
737
738    /**
739     * If the view is ready to draw contents to the screen. In hardware mode,
740     * the initialization of the surface texture may not occur until after the
741     * view has been added to the layout. This method will return {@code true}
742     * once the texture is actually ready.
743     */
744    public boolean isReady() {
745        return mContentViewCore.isReady();
746    }
747
748    /**
749     * Returns whether or not accessibility injection is being used.
750     */
751    public boolean isInjectingAccessibilityScript() {
752        return mContentViewCore.isInjectingAccessibilityScript();
753    }
754
755    /**
756     * Enable or disable accessibility features.
757     */
758    public void setAccessibilityState(boolean state) {
759        mContentViewCore.setAccessibilityState(state);
760    }
761
762    /**
763     * Stop any TTS notifications that are currently going on.
764     */
765    public void stopCurrentAccessibilityNotifications() {
766        mContentViewCore.stopCurrentAccessibilityNotifications();
767    }
768
769    /**
770     * Inform WebKit that Fullscreen mode has been exited by the user.
771     */
772    public void exitFullscreen() {
773        mContentViewCore.exitFullscreen();
774    }
775
776    /**
777     * Return content scroll y.
778     *
779     * @return The vertical scroll position in pixels.
780     */
781    public int getContentScrollY() {
782        return mContentViewCore.computeVerticalScrollOffset();
783    }
784
785    /**
786     * Return content height.
787     *
788     * @return The height of the content in pixels.
789     */
790    public int getContentHeight() {
791        return mContentViewCore.computeVerticalScrollRange();
792    }
793
794    ///////////////////////////////////////////////////////////////////////////////////////////////
795    //              Start Implementation of ContentViewCore.InternalAccessDelegate               //
796    ///////////////////////////////////////////////////////////////////////////////////////////////
797
798    @Override
799    public boolean super_onKeyUp(int keyCode, KeyEvent event) {
800        return super.onKeyUp(keyCode, event);
801    }
802
803    @Override
804    public boolean super_dispatchKeyEventPreIme(KeyEvent event) {
805        return super.dispatchKeyEventPreIme(event);
806    }
807
808    @Override
809    public boolean super_dispatchKeyEvent(KeyEvent event) {
810        return super.dispatchKeyEvent(event);
811    }
812
813    @Override
814    public boolean super_onGenericMotionEvent(MotionEvent event) {
815        return super.onGenericMotionEvent(event);
816    }
817
818    @Override
819    public void super_onConfigurationChanged(Configuration newConfig) {
820        super.onConfigurationChanged(newConfig);
821    }
822
823    @Override
824    public boolean super_awakenScrollBars(int startDelay, boolean invalidate) {
825        return super.awakenScrollBars(startDelay, invalidate);
826    }
827
828    ///////////////////////////////////////////////////////////////////////////////////////////////
829    //                End Implementation of ContentViewCore.InternalAccessDelegate               //
830    ///////////////////////////////////////////////////////////////////////////////////////////////
831}
832