EMMA Coverage Report (generated Fri Aug 23 16:39:17 PDT 2013)
[all classes][org.chromium.content.browser]

COVERAGE SUMMARY FOR SOURCE FILE [ContentViewCore.java]

nameclass, %method, %block, %line, %
ContentViewCore.java63%  (12/19)58%  (169/292)56%  (2405/4305)57%  (538.4/943)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ContentViewCore$100%   (0/1)0%   (0/2)0%   (0/16)0%   (0/3)
ContentViewCore$10 (ContentViewCore, MotionEvent): void 0%   (0/1)0%   (0/9)0%   (0/1)
run (): void 0%   (0/1)0%   (0/7)0%   (0/2)
     
class ContentViewCore$140%   (0/1)0%   (0/2)0%   (0/31)0%   (0/8)
ContentViewCore$14 (ContentViewCore): void 0%   (0/1)0%   (0/6)0%   (0/1)
run (): void 0%   (0/1)0%   (0/25)0%   (0/7)
     
class ContentViewCore$150%   (0/1)0%   (0/2)0%   (0/15)0%   (0/3)
ContentViewCore$15 (ContentViewCore, Handler): void 0%   (0/1)0%   (0/7)0%   (0/1)
onChange (boolean, Uri): void 0%   (0/1)0%   (0/8)0%   (0/2)
     
class ContentViewCore$6$10%   (0/1)0%   (0/3)0%   (0/42)0%   (0/5)
<static initializer> 0%   (0/1)0%   (0/8)0%   (0/1)
ContentViewCore$6$1 (ContentViewCore$6, PopupZoomer): void 0%   (0/1)0%   (0/9)0%   (0/1)
run (): void 0%   (0/1)0%   (0/25)0%   (0/4)
     
class ContentViewCore$6$20%   (0/1)0%   (0/3)0%   (0/47)0%   (0/6)
<static initializer> 0%   (0/1)0%   (0/8)0%   (0/1)
ContentViewCore$6$2 (ContentViewCore$6, PopupZoomer): void 0%   (0/1)0%   (0/9)0%   (0/1)
run (): void 0%   (0/1)0%   (0/30)0%   (0/5)
     
class ContentViewCore$80%   (0/1)0%   (0/2)0%   (0/17)0%   (0/4)
ContentViewCore$8 (ContentViewCore): void 0%   (0/1)0%   (0/6)0%   (0/1)
run (): void 0%   (0/1)0%   (0/11)0%   (0/3)
     
class ContentViewCore$90%   (0/1)0%   (0/2)0%   (0/17)0%   (0/4)
ContentViewCore$9 (ContentViewCore): void 0%   (0/1)0%   (0/6)0%   (0/1)
run (): void 0%   (0/1)0%   (0/11)0%   (0/3)
     
class ContentViewCore$7100% (1/1)33%  (1/3)12%  (6/49)12%  (1/8)
onLongPress (View, MotionEvent): boolean 0%   (0/1)0%   (0/19)0%   (0/3)
onSingleTap (View, MotionEvent): boolean 0%   (0/1)0%   (0/24)0%   (0/4)
ContentViewCore$7 (ContentViewCore): void 100% (1/1)100% (6/6)100% (1/1)
     
class ContentViewCore$3$1100% (1/1)50%  (1/2)15%  (7/46)12%  (1/8)
onReceiveResult (int, Bundle): void 0%   (0/1)0%   (0/39)0%   (0/7)
ContentViewCore$3$1 (ContentViewCore$3, Handler): void 100% (1/1)100% (7/7)100% (1/1)
     
class ContentViewCore$6100% (1/1)33%  (1/3)21%  (6/28)20%  (1/5)
onPopupZoomerHidden (PopupZoomer): void 0%   (0/1)0%   (0/11)0%   (0/2)
onPopupZoomerShown (PopupZoomer): void 0%   (0/1)0%   (0/11)0%   (0/2)
ContentViewCore$6 (ContentViewCore): void 100% (1/1)100% (6/6)100% (1/1)
     
class ContentViewCore$12100% (1/1)60%  (3/5)40%  (19/48)60%  (6/10)
getLineHeight (): int 0%   (0/1)0%   (0/9)0%   (0/1)
setCursorPosition (int, int): void 0%   (0/1)0%   (0/20)0%   (0/3)
ContentViewCore$12 (ContentViewCore, View): void 100% (1/1)100% (7/7)100% (1/1)
paste (): void 100% (1/1)100% (9/9)100% (3/3)
showHandle (): void 100% (1/1)100% (3/3)100% (2/2)
     
class ContentViewCore$13100% (1/1)38%  (3/8)45%  (24/53)51%  (5.6/11)
copy (): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
cut (): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
getSelectedText (): String 0%   (0/1)0%   (0/4)0%   (0/1)
paste (): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
selectAll (): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
onDestroyActionMode (): void 100% (1/1)74%  (14/19)91%  (3.6/4)
ContentViewCore$13 (ContentViewCore): void 100% (1/1)100% (6/6)100% (1/1)
isSelectionEditable (): boolean 100% (1/1)100% (4/4)100% (1/1)
     
class ContentViewCore100% (1/1)60%  (139/232)59%  (2090/3571)59%  (480.7/819)
access$1000 (ContentViewCore): Rect 0%   (0/1)0%   (0/3)0%   (0/1)
access$1300 (ContentViewCore, int, long, float, float, boolean): void 0%   (0/1)0%   (0/8)0%   (0/1)
access$1400 (ContentViewCore, int, long, float, float, boolean): void 0%   (0/1)0%   (0/8)0%   (0/1)
access$1500 (ContentViewCore, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
access$1600 (ContentViewCore, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
access$1900 (ContentViewCore, int, float, float): void 0%   (0/1)0%   (0/6)0%   (0/1)
access$2400 (ContentViewCore): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
access$2500 (ContentViewCore): void 0%   (0/1)0%   (0/3)0%   (0/1)
access$2600 (ContentViewCore): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
access$2700 (ContentViewCore): SelectionHandleController 0%   (0/1)0%   (0/3)0%   (0/1)
access$2800 (ContentViewCore): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
access$2900 (ContentViewCore): InsertionHandleController 0%   (0/1)0%   (0/3)0%   (0/1)
access$3000 (ContentViewCore): AccessibilityManager 0%   (0/1)0%   (0/3)0%   (0/1)
access$302 (ContentViewCore, boolean): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
access$900 (ContentViewCore): void 0%   (0/1)0%   (0/3)0%   (0/1)
allowTextHandleFadeIn (): boolean 0%   (0/1)0%   (0/18)0%   (0/4)
attachExternalVideoSurface (int, Surface): void 0%   (0/1)0%   (0/10)0%   (0/3)
canGoBack (): boolean 0%   (0/1)0%   (0/12)0%   (0/1)
canGoForward (): boolean 0%   (0/1)0%   (0/12)0%   (0/1)
canGoToOffset (int): boolean 0%   (0/1)0%   (0/13)0%   (0/1)
clearHistory (): void 0%   (0/1)0%   (0/8)0%   (0/2)
clearSslPreferences (): void 0%   (0/1)0%   (0/5)0%   (0/2)
computeHorizontalScrollExtent (): int 0%   (0/1)0%   (0/4)0%   (0/1)
computeHorizontalScrollRange (): int 0%   (0/1)0%   (0/4)0%   (0/1)
computeVerticalScrollExtent (): int 0%   (0/1)0%   (0/4)0%   (0/1)
computeVerticalScrollRange (): int 0%   (0/1)0%   (0/4)0%   (0/1)
confirmTouchEvent (int): void 0%   (0/1)0%   (0/5)0%   (0/2)
consumePendingRendererFrame (): boolean 0%   (0/1)0%   (0/8)0%   (0/3)
continuePendingReload (): void 0%   (0/1)0%   (0/8)0%   (0/2)
createGenericTouchGesture (int, int, int, int): GenericTouchGesture 0%   (0/1)0%   (0/9)0%   (0/1)
detachExternalVideoSurface (int): void 0%   (0/1)0%   (0/9)0%   (0/3)
dispatchKeyEventPreIme (KeyEvent): boolean 0%   (0/1)0%   (0/28)0%   (0/6)
evaluateJavaScriptEvenIfNotYetNavigated (String): void 0%   (0/1)0%   (0/10)0%   (0/3)
exitFullscreen (): void 0%   (0/1)0%   (0/5)0%   (0/2)
getAccessibilityNodeProvider (): AccessibilityNodeProvider 0%   (0/1)0%   (0/9)0%   (0/3)
getBackgroundColor (): int 0%   (0/1)0%   (0/10)0%   (0/3)
getBitmap (): Bitmap 0%   (0/1)0%   (0/7)0%   (0/1)
getBitmap (int, int): Bitmap 0%   (0/1)0%   (0/57)0%   (0/10)
getBrowserAccessibilityManager (): BrowserAccessibilityManager 0%   (0/1)0%   (0/3)0%   (0/1)
getContentHeightCss (): float 0%   (0/1)0%   (0/4)0%   (0/1)
getContentSettings (): ContentSettings 0%   (0/1)0%   (0/3)0%   (0/1)
getContentVideoViewClient (): ContentVideoViewClient 0%   (0/1)0%   (0/4)0%   (0/1)
getContentViewGestureHandler (): ContentViewGestureHandler 0%   (0/1)0%   (0/3)0%   (0/1)
getContentWidthCss (): float 0%   (0/1)0%   (0/4)0%   (0/1)
getDownloadDelegate (): ContentViewDownloadDelegate 0%   (0/1)0%   (0/3)0%   (0/1)
getNativeScrollXForTest (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getNativeScrollYForTest (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getOriginalUrlForActiveNavigationEntry (): String 0%   (0/1)0%   (0/5)0%   (0/1)
getScaledPerformanceOptimizedBitmap (int, int): Pair 0%   (0/1)0%   (0/28)0%   (0/4)
getUseDesktopUserAgent (): boolean 0%   (0/1)0%   (0/10)0%   (0/3)
goToNavigationIndex (int): void 0%   (0/1)0%   (0/9)0%   (0/2)
isCrashed (): boolean 0%   (0/1)0%   (0/10)0%   (0/2)
isDeviceAccessibilityScriptInjectionEnabled (): boolean 0%   (0/1)0%   (0/66)0%   (0/18)
isInjectingAccessibilityScript (): boolean 0%   (0/1)0%   (0/4)0%   (0/1)
isReady (): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
needsReload (): boolean 0%   (0/1)0%   (0/12)0%   (0/1)
notifyExternalSurface (int, boolean, float, float, float, float): void 0%   (0/1)0%   (0/22)0%   (0/3)
onAccessibilityStateChanged (boolean): void 0%   (0/1)0%   (0/4)0%   (0/2)
onActivityResume (): void 0%   (0/1)0%   (0/10)0%   (0/3)
onAnimate (long): boolean 0%   (0/1)0%   (0/11)0%   (0/2)
onConfigurationChanged (Configuration): void 0%   (0/1)0%   (0/34)0%   (0/9)
onGenericMotionEvent (MotionEvent): boolean 0%   (0/1)0%   (0/52)0%   (0/9)
onHoverEvent (MotionEvent): boolean 0%   (0/1)0%   (0/34)0%   (0/8)
onInitializeAccessibilityEvent (AccessibilityEvent): void 0%   (0/1)0%   (0/48)0%   (0/11)
onInitializeAccessibilityNodeInfo (AccessibilityNodeInfo): void 0%   (0/1)0%   (0/5)0%   (0/2)
onKeyUp (int, KeyEvent): boolean 0%   (0/1)0%   (0/19)0%   (0/4)
onNativeContentViewCoreDestroyed (int): void 0%   (0/1)0%   (0/14)0%   (0/3)
onOverdrawBottomHeightChanged (int): void 0%   (0/1)0%   (0/16)0%   (0/5)
onTabCrash (): void 0%   (0/1)0%   (0/19)0%   (0/4)
onVisibilityChanged (View, int): void 0%   (0/1)0%   (0/6)0%   (0/3)
performAccessibilityAction (int, Bundle): boolean 0%   (0/1)0%   (0/13)0%   (0/3)
scrollBy (int, int): void 0%   (0/1)0%   (0/16)0%   (0/3)
scrollFocusedEditableNodeIntoView (): void 0%   (0/1)0%   (0/14)0%   (0/5)
scrollTo (int, int): void 0%   (0/1)0%   (0/55)0%   (0/11)
selectPopupMenuItems (int []): void 0%   (0/1)0%   (0/9)0%   (0/3)
sendOrientationChangeEvent (): void 0%   (0/1)0%   (0/43)0%   (0/13)
sendTouchEvent (long, int, TouchPoint []): boolean 0%   (0/1)0%   (0/13)0%   (0/3)
setBrowserAccessibilityManager (BrowserAccessibilityManager): void 0%   (0/1)0%   (0/4)0%   (0/2)
setDownloadDelegate (ContentViewDownloadDelegate): void 0%   (0/1)0%   (0/4)0%   (0/2)
setNeedsAnimate (): void 0%   (0/1)0%   (0/10)0%   (0/4)
setUseDesktopUserAgent (boolean, boolean): void 0%   (0/1)0%   (0/10)0%   (0/3)
setViewportSizeOffset (int, int): void 0%   (0/1)0%   (0/22)0%   (0/5)
showDisambiguationPopup (Rect, Bitmap): void 0%   (0/1)0%   (0/11)0%   (0/4)
showPastePopup (int, int): void 0%   (0/1)0%   (0/16)0%   (0/5)
showSelectPopup (String [], int [], boolean, int []): void 0%   (0/1)0%   (0/7)0%   (0/2)
stopCurrentAccessibilityNotifications (): void 0%   (0/1)0%   (0/4)0%   (0/2)
stopLoading (): void 0%   (0/1)0%   (0/8)0%   (0/2)
supportsAccessibilityAction (int): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
updateTopControlsState (boolean, boolean, boolean): void 0%   (0/1)0%   (0/8)0%   (0/2)
zoomByDelta (float): boolean 0%   (0/1)0%   (0/36)0%   (0/9)
zoomIn (): boolean 0%   (0/1)0%   (0/9)0%   (0/3)
zoomOut (): boolean 0%   (0/1)0%   (0/9)0%   (0/3)
zoomReset (): boolean 0%   (0/1)0%   (0/15)0%   (0/2)
scheduleTextHandleFadeIn (): void 100% (1/1)23%  (7/30)17%  (1/6)
animateIfNecessary (long): void 100% (1/1)27%  (4/15)50%  (2/4)
unregisterAccessibilityContentObserver (): void 100% (1/1)29%  (4/14)40%  (2/5)
updateAfterSizeChanged (): void 100% (1/1)33%  (15/45)34%  (4.8/14)
undoScrollFocusedEditableNodeIntoViewIfNeeded (boolean): void 100% (1/1)37%  (7/19)47%  (2.4/5)
hasHardwareAcceleration (Activity): boolean 100% (1/1)37%  (13/35)36%  (4/11)
checkIsAlive (): void 100% (1/1)44%  (4/9)67%  (2/3)
awakenScrollBars (int, boolean): boolean 100% (1/1)50%  (6/12)67%  (2/3)
temporarilyHideTextHandles (): void 100% (1/1)53%  (9/17)67%  (4/6)
setNativeAccessibilityState (boolean): void 100% (1/1)54%  (7/13)69%  (2.8/4)
dispatchKeyEvent (KeyEvent): boolean 100% (1/1)55%  (12/22)50%  (2/4)
setContentViewClient (ContentViewClient): void 100% (1/1)55%  (6/11)75%  (3/4)
sendGesture (int, long, int, int, boolean, Bundle): boolean 100% (1/1)60%  (143/238)58%  (25/43)
updateGestureStateListener (int, Bundle): void 100% (1/1)61%  (19/31)45%  (5/11)
setAccessibilityState (boolean): void 100% (1/1)62%  (13/21)67%  (6/9)
<static initializer> 100% (1/1)75%  (6/8)75%  (0.8/1)
resetVSyncNotification (): void 100% (1/1)76%  (13/17)88%  (4.4/5)
hasHardwareAcceleration (Context): boolean 100% (1/1)78%  (7/9)67%  (2/3)
getTitle (): String 100% (1/1)80%  (8/10)50%  (1/2)
getUrl (): String 100% (1/1)80%  (8/10)50%  (1/2)
isShowingInterstitialPage (): boolean 100% (1/1)80%  (8/10)80%  (0.8/1)
onRenderProcessSwap (int, int): void 100% (1/1)87%  (26/30)96%  (6.7/7)
onAttachedToWindow (): void 100% (1/1)87%  (27/31)96%  (6.7/7)
canZoomOut (): boolean 100% (1/1)88%  (14/16)94%  (1.9/2)
getSelectedText (): String 100% (1/1)88%  (7/8)87%  (0.9/1)
isSelectionEditable (): boolean 100% (1/1)88%  (7/8)87%  (0.9/1)
onDetachedFromWindow (): void 100% (1/1)88%  (29/33)97%  (8.7/9)
onSelectionBoundsChanged (Rect, int, Rect, int, boolean): void 100% (1/1)88%  (131/149)91%  (32/35)
setVSyncNotificationEnabled (boolean): void 100% (1/1)88%  (60/68)94%  (12.2/13)
processImeBatchStateAck (boolean): void 100% (1/1)89%  (8/9)92%  (2.8/3)
showSelectActionBar (): void 100% (1/1)90%  (44/49)92%  (11/12)
showInterstitialPage (String, InterstitialPageDelegateAndroid): void 100% (1/1)92%  (11/12)92%  (2.8/3)
initialize (ViewGroup, ContentViewCore$InternalAccessDelegate, int, WindowAnd... 100% (1/1)94%  (84/89)95%  (18/19)
handleTapOrPress (long, float, float, int, boolean): void 100% (1/1)96%  (93/97)95%  (18/19)
onSizeChanged (int, int, int, int): void 100% (1/1)96%  (24/25)98%  (6.9/7)
loadUrl (LoadUrlParams): void 100% (1/1)96%  (26/27)92%  (2.8/3)
updateFrameInfo (float, float, float, float, float, float, float, float, floa... 100% (1/1)96%  (193/200)94%  (28.3/30)
ContentViewCore (Context): void 100% (1/1)100% (94/94)100% (24/24)
access$000 (ContentViewCore): int 100% (1/1)100% (3/3)100% (1/1)
access$100 (ContentViewCore, int, long, long): void 100% (1/1)100% (6/6)100% (1/1)
access$1100 (ContentViewCore): void 100% (1/1)100% (3/3)100% (1/1)
access$1200 (ContentViewCore): void 100% (1/1)100% (3/3)100% (1/1)
access$1700 (ContentViewCore, int, float, float, float, float): void 100% (1/1)100% (8/8)100% (1/1)
access$1800 (ContentViewCore): void 100% (1/1)100% (3/3)100% (1/1)
access$200 (ContentViewCore, long): void 100% (1/1)100% (4/4)100% (1/1)
access$2000 (ContentViewCore): ImeAdapter 100% (1/1)100% (3/3)100% (1/1)
access$2100 (ContentViewCore): boolean 100% (1/1)100% (3/3)100% (1/1)
access$2202 (ContentViewCore, ActionMode): ActionMode 100% (1/1)100% (5/5)100% (1/1)
access$2300 (ContentViewCore): boolean 100% (1/1)100% (3/3)100% (1/1)
access$300 (ContentViewCore): boolean 100% (1/1)100% (3/3)100% (1/1)
access$400 (ContentViewCore, int, long): void 100% (1/1)100% (5/5)100% (1/1)
access$500 (ContentViewCore): ViewGroup 100% (1/1)100% (3/3)100% (1/1)
access$600 (ContentViewCore): RenderCoordinates 100% (1/1)100% (3/3)100% (1/1)
access$700 (ContentViewCore): void 100% (1/1)100% (3/3)100% (1/1)
access$800 (ContentViewCore, boolean): void 100% (1/1)100% (4/4)100% (1/1)
addJavascriptInterface (Object, String): void 100% (1/1)100% (6/6)100% (2/2)
addPossiblyUnsafeJavascriptInterface (Object, String, Class): void 100% (1/1)100% (21/21)100% (4/4)
addToNavigationHistory (Object, int, String, String, String, String, Bitmap):... 100% (1/1)100% (15/15)100% (3/3)
canZoomIn (): boolean 100% (1/1)100% (16/16)100% (2/2)
cancelPendingReload (): void 100% (1/1)100% (8/8)100% (2/2)
computeHorizontalScrollOffset (): int 100% (1/1)100% (4/4)100% (1/1)
computeVerticalScrollOffset (): int 100% (1/1)100% (4/4)100% (1/1)
createImeAdapter (Context): ImeAdapter 100% (1/1)100% (12/12)100% (1/1)
createRect (int, int, int, int): Rect 100% (1/1)100% (8/8)100% (1/1)
destroy (): void 100% (1/1)100% (33/33)100% (11/11)
didUIStealScroll (float, float): boolean 100% (1/1)100% (12/12)100% (1/1)
evaluateJavaScript (String, ContentViewCore$JavaScriptCallback): void 100% (1/1)100% (10/10)100% (3/3)
getContainerView (): ViewGroup 100% (1/1)100% (3/3)100% (1/1)
getContentViewClient (): ContentViewClient 100% (1/1)100% (11/11)100% (3/3)
getContext (): Context 100% (1/1)100% (3/3)100% (1/1)
getDirectedNavigationHistory (boolean, int): NavigationHistory 100% (1/1)100% (13/13)100% (3/3)
getEditableForTest (): Editable 100% (1/1)100% (4/4)100% (1/1)
getImeAdapterForTest (): ImeAdapter 100% (1/1)100% (3/3)100% (1/1)
getInputConnectionForTest (): AdapterInputConnection 100% (1/1)100% (3/3)100% (1/1)
getInsertionHandleController (): InsertionHandleController 100% (1/1)100% (17/17)100% (4/4)
getInsertionHandleControllerForTest (): InsertionHandleController 100% (1/1)100% (3/3)100% (1/1)
getNativeContentViewCore (): int 100% (1/1)100% (3/3)100% (1/1)
getNavigationHistory (): NavigationHistory 100% (1/1)100% (15/15)100% (4/4)
getOverdrawBottomHeightPix (): int 100% (1/1)100% (3/3)100% (1/1)
getPhysicalBackingHeightPix (): int 100% (1/1)100% (3/3)100% (1/1)
getPhysicalBackingWidthPix (): int 100% (1/1)100% (3/3)100% (1/1)
getRenderCoordinates (): RenderCoordinates 100% (1/1)100% (3/3)100% (1/1)
getScale (): float 100% (1/1)100% (4/4)100% (1/1)
getSelectionHandleController (): SelectionHandleController 100% (1/1)100% (17/17)100% (4/4)
getSelectionHandleControllerForTest (): SelectionHandleController 100% (1/1)100% (3/3)100% (1/1)
getVSyncListener (VSyncManager$Provider): VSyncManager$Listener 100% (1/1)100% (36/36)100% (9/9)
getViewAndroidDelegate (): ViewAndroidDelegate 100% (1/1)100% (5/5)100% (1/1)
getViewportHeightPix (): int 100% (1/1)100% (3/3)100% (1/1)
getViewportSizeOffsetHeightPix (): int 100% (1/1)100% (3/3)100% (1/1)
getViewportSizeOffsetWidthPix (): int 100% (1/1)100% (3/3)100% (1/1)
getViewportWidthPix (): int 100% (1/1)100% (3/3)100% (1/1)
goBack (): void 100% (1/1)100% (8/8)100% (2/2)
goForward (): void 100% (1/1)100% (8/8)100% (2/2)
goToOffset (int): void 100% (1/1)100% (9/9)100% (2/2)
hasFixedPageScale (): boolean 100% (1/1)100% (4/4)100% (1/1)
hasFocus (): boolean 100% (1/1)100% (4/4)100% (1/1)
hasTouchEventHandlers (boolean): void 100% (1/1)100% (5/5)100% (2/2)
hideHandles (): void 100% (1/1)100% (13/13)100% (5/5)
hidePopupDialog (): void 100% (1/1)100% (7/7)100% (4/4)
hideSelectActionBar (): void 100% (1/1)100% (10/10)100% (4/4)
initPopupZoomer (Context): void 100% (1/1)100% (23/23)100% (5/5)
initializeContainerView (ContentViewCore$InternalAccessDelegate, int): void 100% (1/1)100% (52/52)100% (12/12)
invokeZoomPicker (): void 100% (1/1)100% (4/4)100% (2/2)
isAlive (): boolean 100% (1/1)100% (7/7)100% (1/1)
isInsertionHandleShowing (): boolean 100% (1/1)100% (11/11)100% (1/1)
isSelectActionBarShowing (): boolean 100% (1/1)100% (7/7)100% (1/1)
isSelectionHandleShowing (): boolean 100% (1/1)100% (11/11)100% (1/1)
isVSyncNotificationEnabled (): boolean 100% (1/1)100% (10/10)100% (1/1)
offerGestureToEmbedder (int): boolean 100% (1/1)100% (9/9)100% (3/3)
onActivityPause (): void 100% (1/1)100% (9/9)100% (5/5)
onBackgroundColorChanged (int): void 100% (1/1)100% (5/5)100% (2/2)
onCheckIsTextEditor (): boolean 100% (1/1)100% (4/4)100% (1/1)
onCreateInputConnection (EditorInfo): InputConnection 100% (1/1)100% (20/20)100% (4/4)
onEvaluateJavaScriptResult (String, ContentViewCore$JavaScriptCallback): void 100% (1/1)100% (4/4)100% (2/2)
onFocusChanged (boolean): void 100% (1/1)100% (15/15)100% (3/3)
onHide (): void 100% (1/1)100% (10/10)100% (4/4)
onPhysicalBackingSizeChanged (int, int): void 100% (1/1)100% (23/23)100% (6/6)
onSelectionChanged (String): void 100% (1/1)100% (4/4)100% (2/2)
onShow (): void 100% (1/1)100% (10/10)100% (3/3)
onTouchEvent (MotionEvent): boolean 100% (1/1)100% (8/8)100% (2/2)
onWebContentsConnected (): void 100% (1/1)100% (18/18)100% (3/3)
onWebContentsSwapped (): void 100% (1/1)100% (14/14)100% (3/3)
reload (): void 100% (1/1)100% (11/11)100% (3/3)
removeJavascriptInterface (String): void 100% (1/1)100% (14/14)100% (4/4)
resetGestureDetectors (): void 100% (1/1)100% (4/4)100% (2/2)
setAdapterInputConnectionFactory (ImeAdapter$AdapterInputConnectionFactory): ... 100% (1/1)100% (4/4)100% (2/2)
setGestureStateListener (ContentViewCore$GestureStateListener): void 100% (1/1)100% (4/4)100% (2/2)
setInjectedAccessibility (boolean): void 100% (1/1)100% (8/8)100% (3/3)
setTitle (String): void 100% (1/1)100% (5/5)100% (2/2)
setUpdateFrameInfoListener (ContentViewCore$UpdateFrameInfoListener): void 100% (1/1)100% (4/4)100% (2/2)
setZoomControlsDelegate (ContentViewCore$ZoomControlsDelegate): void 100% (1/1)100% (4/4)100% (2/2)
showImeIfNeeded (): void 100% (1/1)100% (8/8)100% (2/2)
startContentIntent (String): void 100% (1/1)100% (7/7)100% (2/2)
unhandledFlingStartEvent (): void 100% (1/1)100% (7/7)100% (3/3)
updateDoubleTapDragSupport (boolean): void 100% (1/1)100% (5/5)100% (2/2)
updateHandleScreenPositions (): void 100% (1/1)100% (34/34)100% (6/6)
updateImeAdapter (int, int, String, int, int, int, int, boolean): void 100% (1/1)100% (36/36)100% (8/8)
updateMultiTouchZoomSupport (boolean): void 100% (1/1)100% (5/5)100% (2/2)
updateTextHandlesForGesture (int): void 100% (1/1)100% (6/6)100% (4/4)
     
class ContentViewCore$2100% (1/1)100% (5/5)66%  (107/163)74%  (19.3/26)
setAnchorViewPosition (View, float, float, float, float): void 100% (1/1)58%  (75/129)67%  (13.4/20)
<static initializer> 100% (1/1)75%  (6/8)75%  (0.8/1)
ContentViewCore$2 (ContentViewCore): void 100% (1/1)100% (6/6)100% (1/1)
acquireAnchorView (): View 100% (1/1)100% (14/14)100% (3/3)
releaseAnchorView (View): void 100% (1/1)100% (6/6)100% (2/2)
     
class ContentViewCore$1100% (1/1)100% (3/3)83%  (39/47)75%  (9/12)
onVSync (long): void 100% (1/1)71%  (20/28)62%  (5/8)
ContentViewCore$1 (ContentViewCore): void 100% (1/1)100% (6/6)100% (1/1)
updateVSync (long, long): void 100% (1/1)100% (13/13)100% (3/3)
     
class ContentViewCore$5100% (1/1)75%  (3/4)89%  (8/9)75%  (3/4)
invokeZoomPicker (): void 0%   (0/1)0%   (0/1)0%   (0/1)
ContentViewCore$5 (ContentViewCore): void 100% (1/1)100% (6/6)100% (1/1)
dismissZoomPicker (): void 100% (1/1)100% (1/1)100% (1/1)
updateZoomControls (): void 100% (1/1)100% (1/1)100% (1/1)
     
class ContentViewCore$3100% (1/1)83%  (5/6)90%  (38/42)83%  (10/12)
onSetFieldValue (): void 0%   (0/1)0%   (0/4)0%   (0/2)
ContentViewCore$3 (ContentViewCore): void 100% (1/1)100% (6/6)100% (1/1)
getAttachedView (): View 100% (1/1)100% (4/4)100% (1/1)
getNewShowKeyboardReceiver (): ResultReceiver 100% (1/1)100% (8/8)100% (1/1)
onDismissInput (): void 100% (1/1)100% (6/6)100% (2/2)
onImeEvent (boolean): void 100% (1/1)100% (14/14)100% (5/5)
     
class ContentViewCore$11100% (1/1)100% (3/3)94%  (47/50)96%  (6.7/7)
selectBetweenCoordinates (int, int, int, int): void 100% (1/1)91%  (32/35)90%  (2.7/3)
ContentViewCore$11 (ContentViewCore, View): void 100% (1/1)100% (7/7)100% (1/1)
showHandles (int, int): void 100% (1/1)100% (8/8)100% (3/3)
     
class ContentViewCore$4100% (1/1)100% (2/2)100% (14/14)100% (4/4)
ContentViewCore$4 (ContentViewCore, ContentViewCore): void 100% (1/1)100% (7/7)100% (1/1)
didStartLoading (String): void 100% (1/1)100% (7/7)100% (3/3)

1// Copyright 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.ContentResolver;
9import android.content.Context;
10import android.content.pm.ActivityInfo;
11import android.content.pm.PackageManager;
12import android.content.res.Configuration;
13import android.database.ContentObserver;
14import android.graphics.Bitmap;
15import android.graphics.Canvas;
16import android.graphics.Color;
17import android.graphics.Rect;
18import android.graphics.RectF;
19import android.net.Uri;
20import android.os.Build;
21import android.os.Bundle;
22import android.os.Handler;
23import android.os.ResultReceiver;
24import android.provider.Settings;
25import android.provider.Settings.Secure;
26import android.text.Editable;
27import android.util.Log;
28import android.util.Pair;
29import android.view.ActionMode;
30import android.view.InputDevice;
31import android.view.KeyEvent;
32import android.view.MotionEvent;
33import android.view.Surface;
34import android.view.View;
35import android.view.ViewGroup;
36import android.view.Window;
37import android.view.WindowManager;
38import android.view.accessibility.AccessibilityEvent;
39import android.view.accessibility.AccessibilityManager;
40import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
41import android.view.accessibility.AccessibilityNodeInfo;
42import android.view.accessibility.AccessibilityNodeProvider;
43import android.view.inputmethod.EditorInfo;
44import android.view.inputmethod.InputConnection;
45import android.view.inputmethod.InputMethodManager;
46import android.widget.AbsoluteLayout;
47import android.widget.FrameLayout;
48 
49import com.google.common.annotations.VisibleForTesting;
50 
51import org.chromium.base.CalledByNative;
52import org.chromium.base.JNINamespace;
53import org.chromium.base.WeakContext;
54import org.chromium.content.R;
55import org.chromium.content.browser.ContentViewGestureHandler.MotionEventDelegate;
56import org.chromium.content.browser.accessibility.AccessibilityInjector;
57import org.chromium.content.browser.accessibility.BrowserAccessibilityManager;
58import org.chromium.content.browser.input.AdapterInputConnection;
59import org.chromium.content.browser.input.HandleView;
60import org.chromium.content.browser.input.ImeAdapter;
61import org.chromium.content.browser.input.InputMethodManagerWrapper;
62import org.chromium.content.browser.input.ImeAdapter.AdapterInputConnectionFactory;
63import org.chromium.content.browser.input.InsertionHandleController;
64import org.chromium.content.browser.input.SelectPopupDialog;
65import org.chromium.content.browser.input.SelectionHandleController;
66import org.chromium.content.common.TraceEvent;
67import org.chromium.ui.ViewAndroid;
68import org.chromium.ui.ViewAndroidDelegate;
69import org.chromium.ui.WindowAndroid;
70import org.chromium.ui.gfx.DeviceDisplayInfo;
71 
72import java.lang.annotation.Annotation;
73import java.lang.reflect.Field;
74import java.util.Arrays;
75import java.util.HashMap;
76import java.util.HashSet;
77import java.util.Map;
78 
79/**
80 * Provides a Java-side 'wrapper' around a WebContent (native) instance.
81 * Contains all the major functionality necessary to manage the lifecycle of a ContentView without
82 * being tied to the view system.
83 */
84@JNINamespace("content")
85    public class ContentViewCore implements MotionEventDelegate,
86                                            NavigationClient,
87                                            AccessibilityStateChangeListener {
88    /**
89     * Indicates that input events are batched together and delivered just before vsync.
90     */
91    public static final int INPUT_EVENTS_DELIVERED_AT_VSYNC = 1;
92 
93    /**
94     * Opposite of INPUT_EVENTS_DELIVERED_AT_VSYNC.
95     */
96    public static final int INPUT_EVENTS_DELIVERED_IMMEDIATELY = 0;
97 
98    private static final String TAG = "ContentViewCore";
99 
100    // Used to avoid enabling zooming in / out if resulting zooming will
101    // produce little visible difference.
102    private static final float ZOOM_CONTROLS_EPSILON = 0.007f;
103 
104    // Used to represent gestures for long press and long tap.
105    private static final int IS_LONG_PRESS = 1;
106    private static final int IS_LONG_TAP = 2;
107 
108    // Length of the delay (in ms) before fading in handles after the last page movement.
109    private static final int TEXT_HANDLE_FADE_IN_DELAY = 300;
110 
111    // If the embedder adds a JavaScript interface object that contains an indirect reference to
112    // the ContentViewCore, then storing a strong ref to the interface object on the native
113    // side would prevent garbage collection of the ContentViewCore (as that strong ref would
114    // create a new GC root).
115    // For that reason, we store only a weak reference to the interface object on the
116    // native side. However we still need a strong reference on the Java side to
117    // prevent garbage collection if the embedder doesn't maintain their own ref to the
118    // interface object - the Java side ref won't create a new GC root.
119    // This map stores those refernces. We put into the map on addJavaScriptInterface()
120    // and remove from it in removeJavaScriptInterface().
121    private final Map<String, Object> mJavaScriptInterfaces = new HashMap<String, Object>();
122 
123    // Additionally, we keep track of all Java bound JS objects that are in use on the
124    // current page to ensure that they are not garbage collected until the page is
125    // navigated. This includes interface objects that have been removed
126    // via the removeJavaScriptInterface API and transient objects returned from methods
127    // on the interface object. Note we use HashSet rather than Set as the native side
128    // expects HashSet (no bindings for interfaces).
129    private final HashSet<Object> mRetainedJavaScriptObjects = new HashSet<Object>();
130 
131    /**
132     * Interface that consumers of {@link ContentViewCore} must implement to allow the proper
133     * dispatching of view methods through the containing view.
134     *
135     * <p>
136     * All methods with the "super_" prefix should be routed to the parent of the
137     * implementing container view.
138     */
139    @SuppressWarnings("javadoc")
140    public interface InternalAccessDelegate {
141        /**
142         * @see View#drawChild(Canvas, View, long)
143         */
144        boolean drawChild(Canvas canvas, View child, long drawingTime);
145 
146        /**
147         * @see View#onKeyUp(keyCode, KeyEvent)
148         */
149        boolean super_onKeyUp(int keyCode, KeyEvent event);
150 
151        /**
152         * @see View#dispatchKeyEventPreIme(KeyEvent)
153         */
154        boolean super_dispatchKeyEventPreIme(KeyEvent event);
155 
156        /**
157         * @see View#dispatchKeyEvent(KeyEvent)
158         */
159        boolean super_dispatchKeyEvent(KeyEvent event);
160 
161        /**
162         * @see View#onGenericMotionEvent(MotionEvent)
163         */
164        boolean super_onGenericMotionEvent(MotionEvent event);
165 
166        /**
167         * @see View#onConfigurationChanged(Configuration)
168         */
169        void super_onConfigurationChanged(Configuration newConfig);
170 
171        /**
172         * @see View#awakenScrollBars()
173         */
174        boolean awakenScrollBars();
175 
176        /**
177         * @see View#awakenScrollBars(int, boolean)
178         */
179        boolean super_awakenScrollBars(int startDelay, boolean invalidate);
180    }
181 
182    /**
183     * An interface that allows the embedder to be notified when the pinch gesture starts and
184     * stops.
185     */
186    public interface GestureStateListener {
187        /**
188         * Called when the pinch gesture starts.
189         */
190        void onPinchGestureStart();
191 
192        /**
193         * Called when the pinch gesture ends.
194         */
195        void onPinchGestureEnd();
196 
197        /**
198         * Called when the fling gesture is sent.
199         */
200        void onFlingStartGesture(int vx, int vy);
201 
202        /**
203         * Called when the fling cancel gesture is sent.
204         */
205        void onFlingCancelGesture();
206 
207        /**
208         * Called when a fling event was not handled by the renderer.
209         */
210        void onUnhandledFlingStartEvent();
211    }
212 
213    /**
214     * An interface for controlling visibility and state of embedder-provided zoom controls.
215     */
216    public interface ZoomControlsDelegate {
217        /**
218         * Called when it's reasonable to show zoom controls.
219         */
220        void invokeZoomPicker();
221 
222        /**
223         * Called when zoom controls need to be hidden (e.g. when the view hides).
224         */
225        void dismissZoomPicker();
226 
227        /**
228         * Called when page scale has been changed, so the controls can update their state.
229         */
230        void updateZoomControls();
231    }
232 
233    /**
234     * An interface that allows the embedder to be notified of changes to the parameters of the
235     * currently displayed contents.
236     * These notifications are consistent with respect to the UI thread (the size is the size of
237     * the contents currently displayed on screen).
238     */
239    public interface UpdateFrameInfoListener {
240        /**
241         * Called each time any of the parameters are changed.
242         *
243         * @param widthCss The content width in logical (CSS) pixels.
244         * @param heightCss The content height in logical (CSS) pixels.
245         * @param pageScaleFactor The page scale.
246         */
247        void onFrameInfoUpdated(float widthCss, float heightCss, float pageScaleFactor);
248    }
249 
250    private VSyncManager.Provider mVSyncProvider;
251    private VSyncManager.Listener mVSyncListener;
252    private int mVSyncSubscriberCount;
253    private boolean mVSyncListenerRegistered;
254 
255    // To avoid IPC delay we use input events to directly trigger a vsync signal in the renderer.
256    // When we do this, we also need to avoid sending the real vsync signal for the current
257    // frame to avoid double-ticking. This flag is used to inhibit the next vsync notification.
258    private boolean mDidSignalVSyncUsingInputEvent;
259 
260    public VSyncManager.Listener getVSyncListener(VSyncManager.Provider vsyncProvider) {
261        if (mVSyncProvider != null && mVSyncListenerRegistered) {
262            mVSyncProvider.unregisterVSyncListener(mVSyncListener);
263            mVSyncListenerRegistered = false;
264        }
265 
266        mVSyncProvider = vsyncProvider;
267        mVSyncListener = new VSyncManager.Listener() {
268            @Override
269            public void updateVSync(long tickTimeMicros, long intervalMicros) {
270                if (mNativeContentViewCore != 0) {
271                    nativeUpdateVSyncParameters(mNativeContentViewCore, tickTimeMicros,
272                            intervalMicros);
273                }
274            }
275 
276            @Override
277            public void onVSync(long frameTimeMicros) {
278                animateIfNecessary(frameTimeMicros);
279 
280                if (mDidSignalVSyncUsingInputEvent) {
281                    TraceEvent.instant("ContentViewCore::onVSync ignored");
282                    mDidSignalVSyncUsingInputEvent = false;
283                    return;
284                }
285                if (mNativeContentViewCore != 0) {
286                    nativeOnVSync(mNativeContentViewCore, frameTimeMicros);
287                }
288            }
289        };
290 
291        if (mVSyncSubscriberCount > 0) {
292            // setVSyncNotificationEnabled(true) is called before getVSyncListener.
293            vsyncProvider.registerVSyncListener(mVSyncListener);
294            mVSyncListenerRegistered = true;
295        }
296 
297        return mVSyncListener;
298    }
299 
300    @CalledByNative
301    void setVSyncNotificationEnabled(boolean enabled) {
302        if (!isVSyncNotificationEnabled() && enabled) {
303            mDidSignalVSyncUsingInputEvent = false;
304        }
305        if (mVSyncProvider != null) {
306            if (!mVSyncListenerRegistered && enabled) {
307                mVSyncProvider.registerVSyncListener(mVSyncListener);
308                mVSyncListenerRegistered = true;
309            } else if (mVSyncSubscriberCount == 1 && !enabled) {
310                assert mVSyncListenerRegistered;
311                mVSyncProvider.unregisterVSyncListener(mVSyncListener);
312                mVSyncListenerRegistered = false;
313            }
314        }
315        mVSyncSubscriberCount += enabled ? 1 : -1;
316        assert mVSyncSubscriberCount >= 0;
317    }
318 
319    @CalledByNative
320    private void resetVSyncNotification() {
321        while (isVSyncNotificationEnabled()) setVSyncNotificationEnabled(false);
322        mVSyncSubscriberCount = 0;
323        mVSyncListenerRegistered = false;
324        mNeedAnimate = false;
325    }
326 
327    private boolean isVSyncNotificationEnabled() {
328        return mVSyncProvider != null && mVSyncListenerRegistered;
329    }
330 
331    @CalledByNative
332    private void setNeedsAnimate() {
333        if (!mNeedAnimate) {
334            mNeedAnimate = true;
335            setVSyncNotificationEnabled(true);
336        }
337    }
338 
339    private final Context mContext;
340    private ViewGroup mContainerView;
341    private InternalAccessDelegate mContainerViewInternals;
342    private WebContentsObserverAndroid mWebContentsObserver;
343 
344    private ContentViewClient mContentViewClient;
345 
346    private ContentSettings mContentSettings;
347 
348    // Native pointer to C++ ContentViewCoreImpl object which will be set by nativeInit().
349    private int mNativeContentViewCore = 0;
350 
351    private boolean mAttachedToWindow = false;
352 
353    // Pid of the renderer process backing this ContentViewCore.
354    private int mPid = 0;
355 
356    private ContentViewGestureHandler mContentViewGestureHandler;
357    private GestureStateListener mGestureStateListener;
358    private UpdateFrameInfoListener mUpdateFrameInfoListener;
359    private ZoomManager mZoomManager;
360    private ZoomControlsDelegate mZoomControlsDelegate;
361 
362    private PopupZoomer mPopupZoomer;
363 
364    private Runnable mFakeMouseMoveRunnable = null;
365 
366    // Only valid when focused on a text / password field.
367    private ImeAdapter mImeAdapter;
368    private ImeAdapter.AdapterInputConnectionFactory mAdapterInputConnectionFactory;
369    private AdapterInputConnection mInputConnection;
370 
371    private SelectionHandleController mSelectionHandleController;
372    private InsertionHandleController mInsertionHandleController;
373 
374    private Runnable mDeferredHandleFadeInRunnable;
375 
376    // Size of the viewport in physical pixels as set from onSizeChanged.
377    private int mViewportWidthPix;
378    private int mViewportHeightPix;
379    private int mPhysicalBackingWidthPix;
380    private int mPhysicalBackingHeightPix;
381    private int mOverdrawBottomHeightPix;
382    private int mViewportSizeOffsetWidthPix;
383    private int mViewportSizeOffsetHeightPix;
384 
385    // Cached copy of all positions and scales as reported by the renderer.
386    private final RenderCoordinates mRenderCoordinates;
387 
388    private final RenderCoordinates.NormalizedPoint mStartHandlePoint;
389    private final RenderCoordinates.NormalizedPoint mEndHandlePoint;
390    private final RenderCoordinates.NormalizedPoint mInsertionHandlePoint;
391 
392    // Tracks whether a selection is currently active.  When applied to selected text, indicates
393    // whether the last selected text is still highlighted.
394    private boolean mHasSelection;
395    private String mLastSelectedText;
396    private boolean mSelectionEditable;
397    private ActionMode mActionMode;
398    private boolean mUnselectAllOnActionModeDismiss;
399 
400    // Delegate that will handle GET downloads, and be notified of completion of POST downloads.
401    private ContentViewDownloadDelegate mDownloadDelegate;
402 
403    // The AccessibilityInjector that handles loading Accessibility scripts into the web page.
404    private AccessibilityInjector mAccessibilityInjector;
405 
406    // Handles native accessibility, i.e. without any script injection.
407    private BrowserAccessibilityManager mBrowserAccessibilityManager;
408 
409    // System accessibility service.
410    private final AccessibilityManager mAccessibilityManager;
411 
412    // Allows us to dynamically respond when the accessibility script injection flag changes.
413    private ContentObserver mAccessibilityScriptInjectionObserver;
414 
415    // Temporary notification to tell onSizeChanged to focus a form element,
416    // because the OSK was just brought up.
417    private boolean mUnfocusOnNextSizeChanged = false;
418    private final Rect mFocusPreOSKViewportRect = new Rect();
419 
420    private boolean mNeedUpdateOrientationChanged;
421 
422    // Used to keep track of whether we should try to undo the last zoom-to-textfield operation.
423    private boolean mScrolledAndZoomedFocusedEditableNode = false;
424 
425    // Whether we use hardware-accelerated drawing.
426    private boolean mHardwareAccelerated = false;
427 
428    // Whether we received a new frame since consumePendingRendererFrame() was last called.
429    private boolean mPendingRendererFrame = false;
430 
431    // Whether we should animate at the next vsync tick.
432    private boolean mNeedAnimate = false;
433 
434    private ViewAndroid mViewAndroid;
435 
436 
437    /**
438     * Constructs a new ContentViewCore. Embedders must call initialize() after constructing
439     * a ContentViewCore and before using it.
440     *
441     * @param context The context used to create this.
442     */
443    public ContentViewCore(Context context) {
444        mContext = context;
445 
446        WeakContext.initializeWeakContext(context);
447        HeapStatsLogger.init(mContext.getApplicationContext());
448        mAdapterInputConnectionFactory = new AdapterInputConnectionFactory();
449 
450        mRenderCoordinates = new RenderCoordinates();
451        mRenderCoordinates.setDeviceScaleFactor(
452                getContext().getResources().getDisplayMetrics().density);
453        mStartHandlePoint = mRenderCoordinates.createNormalizedPoint();
454        mEndHandlePoint = mRenderCoordinates.createNormalizedPoint();
455        mInsertionHandlePoint = mRenderCoordinates.createNormalizedPoint();
456        mAccessibilityManager = (AccessibilityManager)
457                getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
458    }
459 
460    /**
461     * @return The context used for creating this ContentViewCore.
462     */
463    @CalledByNative
464    public Context getContext() {
465        return mContext;
466    }
467 
468    /**
469     * @return The ViewGroup that all view actions of this ContentViewCore should interact with.
470     */
471    public ViewGroup getContainerView() {
472        return mContainerView;
473    }
474 
475    /**
476     * Specifies how much smaller the WebKit layout size should be relative to the size of this
477     * view.
478     * @param offsetXPix The X amount in pixels to shrink the viewport by.
479     * @param offsetYPix The Y amount in pixels to shrink the viewport by.
480     */
481    public void setViewportSizeOffset(int offsetXPix, int offsetYPix) {
482        if (offsetXPix != mViewportSizeOffsetWidthPix ||
483                offsetYPix != mViewportSizeOffsetHeightPix) {
484            mViewportSizeOffsetWidthPix = offsetXPix;
485            mViewportSizeOffsetHeightPix = offsetYPix;
486            if (mNativeContentViewCore != 0) nativeWasResized(mNativeContentViewCore);
487        }
488    }
489 
490    /**
491     * Returns a delegate that can be used to add and remove views from the ContainerView.
492     *
493     * NOTE: Use with care, as not all ContentViewCore users setup their ContainerView in the same
494     * way. In particular, the Android WebView has limitations on what implementation details can
495     * be provided via a child view, as they are visible in the API and could introduce
496     * compatibility breaks with existing applications. If in doubt, contact the
497     * android_webview/OWNERS
498     *
499     * @return A ViewAndroidDelegate that can be used to add and remove views.
500     */
501    @VisibleForTesting
502    public ViewAndroidDelegate getViewAndroidDelegate() {
503        return new ViewAndroidDelegate() {
504            @Override
505            public View acquireAnchorView() {
506                View anchorView = new View(getContext());
507                mContainerView.addView(anchorView);
508                return anchorView;
509            }
510 
511            @Override
512            @SuppressWarnings("deprecation")  // AbsoluteLayout.LayoutParams
513            public void setAnchorViewPosition(
514                    View view, float x, float y, float width, float height) {
515                assert(view.getParent() == mContainerView);
516 
517                float scale = (float) DeviceDisplayInfo.create(getContext()).getDIPScale();
518 
519                // The anchor view should not go outside the bounds of the ContainerView.
520                int leftMargin = Math.round(x * scale);
521                int topMargin = Math.round(mRenderCoordinates.getContentOffsetYPix() + y * scale);
522                // ContentViewCore currently only supports these two container view types.
523                if (mContainerView instanceof FrameLayout) {
524                    int scaledWidth = Math.round(width * scale);
525                    if (scaledWidth + leftMargin > mContainerView.getWidth()) {
526                        scaledWidth = mContainerView.getWidth() - leftMargin;
527                    }
528                    FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
529                        scaledWidth, Math.round(height * scale));
530                    lp.leftMargin = leftMargin;
531                    lp.topMargin = topMargin;
532                    view.setLayoutParams(lp);
533                } else if (mContainerView instanceof AbsoluteLayout) {
534                    // This fixes the offset due to a difference in
535                    // scrolling model of WebView vs. Chrome.
536                    // TODO(sgurun) fix this to use mContainerView.getScroll[X/Y]()
537                    // as it naturally accounts for scroll differences between
538                    // these models.
539                    leftMargin += mRenderCoordinates.getScrollXPixInt();
540                    topMargin += mRenderCoordinates.getScrollYPixInt();
541                    android.widget.AbsoluteLayout.LayoutParams lp =
542                            new android.widget.AbsoluteLayout.LayoutParams((int)width,
543                                    (int)(height * scale), leftMargin, topMargin);
544                    view.setLayoutParams(lp);
545                } else {
546                    Log.e(TAG, "Unknown layout " + mContainerView.getClass().getName());
547                }
548            }
549 
550            @Override
551            public void releaseAnchorView(View anchorView) {
552                mContainerView.removeView(anchorView);
553            }
554        };
555    }
556 
557    @VisibleForTesting
558    public ImeAdapter getImeAdapterForTest() {
559        return mImeAdapter;
560    }
561 
562    @VisibleForTesting
563    public void setAdapterInputConnectionFactory(AdapterInputConnectionFactory factory) {
564        mAdapterInputConnectionFactory = factory;
565    }
566 
567    @VisibleForTesting
568    public AdapterInputConnection getInputConnectionForTest() {
569        return mInputConnection;
570    }
571 
572    private ImeAdapter createImeAdapter(Context context) {
573        return new ImeAdapter(new InputMethodManagerWrapper(context),
574                new ImeAdapter.ImeAdapterDelegate() {
575                    @Override
576                    public void onImeEvent(boolean isFinish) {
577                        getContentViewClient().onImeEvent();
578                        if (!isFinish) {
579                            hideHandles();
580                            undoScrollFocusedEditableNodeIntoViewIfNeeded(false);
581                        }
582                    }
583 
584                    @Override
585                    public void onSetFieldValue() {
586                        scrollFocusedEditableNodeIntoView();
587                    }
588 
589                    @Override
590                    public void onDismissInput() {
591                        getContentViewClient().onImeStateChangeRequested(false);
592                    }
593 
594                    @Override
595                    public View getAttachedView() {
596                        return mContainerView;
597                    }
598 
599                    @Override
600                    public ResultReceiver getNewShowKeyboardReceiver() {
601                        return new ResultReceiver(new Handler()) {
602                            @Override
603                            public void onReceiveResult(int resultCode, Bundle resultData) {
604                                getContentViewClient().onImeStateChangeRequested(
605                                        resultCode == InputMethodManager.RESULT_SHOWN ||
606                                        resultCode == InputMethodManager.RESULT_UNCHANGED_SHOWN);
607                                if (resultCode == InputMethodManager.RESULT_SHOWN) {
608                                    // If OSK is newly shown, delay the form focus until
609                                    // the onSizeChanged (in order to adjust relative to the
610                                    // new size).
611                                    getContainerView().getWindowVisibleDisplayFrame(
612                                            mFocusPreOSKViewportRect);
613                                } else if (resultCode ==
614                                        InputMethodManager.RESULT_UNCHANGED_SHOWN) {
615                                    // If the OSK was already there, focus the form immediately.
616                                    scrollFocusedEditableNodeIntoView();
617                                } else {
618                                    undoScrollFocusedEditableNodeIntoViewIfNeeded(false);
619                                }
620                            }
621                        };
622                    }
623                }
624        );
625    }
626 
627    /**
628     * Returns true if the given Activity has hardware acceleration enabled
629     * in its manifest, or in its foreground window.
630     *
631     * TODO(husky): Remove when initialize() is refactored (see TODO there)
632     * TODO(dtrainor) This is still used by other classes.  Make sure to pull some version of this
633     * out before removing it.
634     */
635    public static boolean hasHardwareAcceleration(Activity activity) {
636        // Has HW acceleration been enabled manually in the current window?
637        Window window = activity.getWindow();
638        if (window != null) {
639            if ((window.getAttributes().flags
640                    & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0) {
641                return true;
642            }
643        }
644 
645        // Has HW acceleration been enabled in the manifest?
646        try {
647            ActivityInfo info = activity.getPackageManager().getActivityInfo(
648                    activity.getComponentName(), 0);
649            if ((info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
650                return true;
651            }
652        } catch (PackageManager.NameNotFoundException e) {
653            Log.e("Chrome", "getActivityInfo(self) should not fail");
654        }
655 
656        return false;
657    }
658 
659    /**
660     * Returns true if the given Context is a HW-accelerated Activity.
661     *
662     * TODO(husky): Remove when initialize() is refactored (see TODO there)
663     */
664    private static boolean hasHardwareAcceleration(Context context) {
665        if (context instanceof Activity) {
666            return hasHardwareAcceleration((Activity) context);
667        }
668        return false;
669    }
670 
671    /**
672     *
673     * @param containerView The view that will act as a container for all views created by this.
674     * @param internalDispatcher Handles dispatching all hidden or super methods to the
675     *                           containerView.
676     * @param nativeWebContents A pointer to the native web contents.
677     * @param windowAndroid An instance of the WindowAndroid.
678     */
679    // Perform important post-construction set up of the ContentViewCore.
680    // We do not require the containing view in the constructor to allow embedders to create a
681    // ContentViewCore without having fully created its containing view. The containing view
682    // is a vital component of the ContentViewCore, so embedders must exercise caution in what
683    // they do with the ContentViewCore before calling initialize().
684    // We supply the nativeWebContents pointer here rather than in the constructor to allow us
685    // to set the private browsing mode at a later point for the WebView implementation.
686    // Note that the caller remains the owner of the nativeWebContents and is responsible for
687    // deleting it after destroying the ContentViewCore.
688    public void initialize(ViewGroup containerView, InternalAccessDelegate internalDispatcher,
689            int nativeWebContents, WindowAndroid windowAndroid,
690            int inputEventDeliveryMode) {
691        // Check whether to use hardware acceleration. This is a bit hacky, and
692        // only works if the Context is actually an Activity (as it is in the
693        // Chrome application).
694        //
695        // What we're doing here is checking whether the app has *requested*
696        // hardware acceleration by setting the appropriate flags. This does not
697        // necessarily mean we're going to *get* hardware acceleration -- that's
698        // up to the Android framework.
699        //
700        // TODO(husky): Once the native code has been updated so that the
701        // HW acceleration flag can be set dynamically (Grace is doing this),
702        // move this check into onAttachedToWindow(), where we can test for
703        // HW support directly.
704        mHardwareAccelerated = hasHardwareAcceleration(mContext);
705 
706        mContainerView = containerView;
707 
708        int windowNativePointer = windowAndroid != null ? windowAndroid.getNativePointer() : 0;
709 
710        int viewAndroidNativePointer = 0;
711        if (windowNativePointer != 0) {
712            mViewAndroid = new ViewAndroid(windowAndroid, getViewAndroidDelegate());
713            viewAndroidNativePointer = mViewAndroid.getNativePointer();
714        }
715 
716        mNativeContentViewCore = nativeInit(mHardwareAccelerated,
717                nativeWebContents, viewAndroidNativePointer, windowNativePointer);
718        mContentSettings = new ContentSettings(this, mNativeContentViewCore);
719        initializeContainerView(internalDispatcher, inputEventDeliveryMode);
720 
721        mAccessibilityInjector = AccessibilityInjector.newInstance(this);
722 
723        String contentDescription = "Web View";
724        if (R.string.accessibility_content_view == 0) {
725            Log.w(TAG, "Setting contentDescription to 'Web View' as no value was specified.");
726        } else {
727            contentDescription = mContext.getResources().getString(
728                    R.string.accessibility_content_view);
729        }
730        mContainerView.setContentDescription(contentDescription);
731        mWebContentsObserver = new WebContentsObserverAndroid(this) {
732            @Override
733            public void didStartLoading(String url) {
734                hidePopupDialog();
735                resetGestureDetectors();
736            }
737        };
738 
739        mPid = nativeGetCurrentRenderProcessId(mNativeContentViewCore);
740    }
741 
742    @CalledByNative
743    void onNativeContentViewCoreDestroyed(int nativeContentViewCore) {
744        assert nativeContentViewCore == mNativeContentViewCore;
745        mNativeContentViewCore = 0;
746    }
747 
748    /**
749     * Initializes the View that will contain all Views created by the ContentViewCore.
750     *
751     * @param internalDispatcher Handles dispatching all hidden or super methods to the
752     *                           containerView.
753     */
754    private void initializeContainerView(InternalAccessDelegate internalDispatcher,
755            int inputEventDeliveryMode) {
756        TraceEvent.begin();
757        mContainerViewInternals = internalDispatcher;
758 
759        mContainerView.setWillNotDraw(false);
760        mContainerView.setClickable(true);
761 
762        mZoomManager = new ZoomManager(mContext, this);
763        mContentViewGestureHandler = new ContentViewGestureHandler(mContext, this, mZoomManager,
764                inputEventDeliveryMode);
765        mZoomControlsDelegate = new ZoomControlsDelegate() {
766            @Override
767            public void invokeZoomPicker() {}
768            @Override
769            public void dismissZoomPicker() {}
770            @Override
771            public void updateZoomControls() {}
772        };
773 
774        mRenderCoordinates.reset();
775 
776        initPopupZoomer(mContext);
777        mImeAdapter = createImeAdapter(mContext);
778        TraceEvent.end();
779    }
780 
781    private void initPopupZoomer(Context context){
782        mPopupZoomer = new PopupZoomer(context);
783        mPopupZoomer.setOnVisibilityChangedListener(new PopupZoomer.OnVisibilityChangedListener() {
784            @Override
785            public void onPopupZoomerShown(final PopupZoomer zoomer) {
786                mContainerView.post(new Runnable() {
787                    @Override
788                    public void run() {
789                        if (mContainerView.indexOfChild(zoomer) == -1) {
790                            mContainerView.addView(zoomer);
791                        } else {
792                            assert false : "PopupZoomer should never be shown without being hidden";
793                        }
794                    }
795                });
796            }
797 
798            @Override
799            public void onPopupZoomerHidden(final PopupZoomer zoomer) {
800                mContainerView.post(new Runnable() {
801                    @Override
802                    public void run() {
803                        if (mContainerView.indexOfChild(zoomer) != -1) {
804                            mContainerView.removeView(zoomer);
805                            mContainerView.invalidate();
806                        } else {
807                            assert false : "PopupZoomer should never be hidden without being shown";
808                        }
809                    }
810                });
811            }
812        });
813        // TODO(yongsheng): LONG_TAP is not enabled in PopupZoomer. So need to dispatch a LONG_TAP
814        // gesture if a user completes a tap on PopupZoomer UI after a LONG_PRESS gesture.
815        PopupZoomer.OnTapListener listener = new PopupZoomer.OnTapListener() {
816            @Override
817            public boolean onSingleTap(View v, MotionEvent e) {
818                mContainerView.requestFocus();
819                if (mNativeContentViewCore != 0) {
820                    nativeSingleTap(mNativeContentViewCore, e.getEventTime(),
821                            e.getX(), e.getY(), true);
822                }
823                return true;
824            }
825 
826            @Override
827            public boolean onLongPress(View v, MotionEvent e) {
828                if (mNativeContentViewCore != 0) {
829                    nativeLongPress(mNativeContentViewCore, e.getEventTime(),
830                            e.getX(), e.getY(), true);
831                }
832                return true;
833            }
834        };
835        mPopupZoomer.setOnTapListener(listener);
836    }
837 
838    /**
839     * Destroy the internal state of the ContentView. This method may only be
840     * called after the ContentView has been removed from the view system. No
841     * other methods may be called on this ContentView after this method has
842     * been called.
843     */
844    public void destroy() {
845        if (mNativeContentViewCore != 0) {
846            nativeOnJavaContentViewCoreDestroyed(mNativeContentViewCore);
847        }
848        resetVSyncNotification();
849        mVSyncProvider = null;
850        if (mViewAndroid != null) mViewAndroid.destroy();
851        mNativeContentViewCore = 0;
852        mContentSettings = null;
853        mJavaScriptInterfaces.clear();
854        mRetainedJavaScriptObjects.clear();
855        unregisterAccessibilityContentObserver();
856    }
857 
858    private void unregisterAccessibilityContentObserver() {
859        if (mAccessibilityScriptInjectionObserver == null) {
860            return;
861        }
862        getContext().getContentResolver().unregisterContentObserver(
863                mAccessibilityScriptInjectionObserver);
864        mAccessibilityScriptInjectionObserver = null;
865    }
866 
867    /**
868     * Returns true initially, false after destroy() has been called.
869     * It is illegal to call any other public method after destroy().
870     */
871    public boolean isAlive() {
872        return mNativeContentViewCore != 0;
873    }
874 
875    /**
876     * This is only useful for passing over JNI to native code that requires ContentViewCore*.
877     * @return native ContentViewCore pointer.
878     */
879    @CalledByNative
880    public int getNativeContentViewCore() {
881        return mNativeContentViewCore;
882    }
883 
884    /**
885     * For internal use. Throws IllegalStateException if mNativeContentView is 0.
886     * Use this to ensure we get a useful Java stack trace, rather than a native
887     * crash dump, from use-after-destroy bugs in Java code.
888     */
889    void checkIsAlive() throws IllegalStateException {
890        if (!isAlive()) {
891            throw new IllegalStateException("ContentView used after destroy() was called");
892        }
893    }
894 
895    public void setContentViewClient(ContentViewClient client) {
896        if (client == null) {
897            throw new IllegalArgumentException("The client can't be null.");
898        }
899        mContentViewClient = client;
900    }
901 
902    ContentViewClient getContentViewClient() {
903        if (mContentViewClient == null) {
904            // We use the Null Object pattern to avoid having to perform a null check in this class.
905            // We create it lazily because most of the time a client will be set almost immediately
906            // after ContentView is created.
907            mContentViewClient = new ContentViewClient();
908            // We don't set the native ContentViewClient pointer here on purpose. The native
909            // implementation doesn't mind a null delegate and using one is better than passing a
910            // Null Object, since we cut down on the number of JNI calls.
911        }
912        return mContentViewClient;
913    }
914 
915    public int getBackgroundColor() {
916        if (mNativeContentViewCore != 0) {
917            return nativeGetBackgroundColor(mNativeContentViewCore);
918        }
919        return Color.WHITE;
920    }
921 
922    @CalledByNative
923    private void onBackgroundColorChanged(int color) {
924        getContentViewClient().onBackgroundColorChanged(color);
925    }
926 
927    /**
928     * Load url without fixing up the url string. Consumers of ContentView are responsible for
929     * ensuring the URL passed in is properly formatted (i.e. the scheme has been added if left
930     * off during user input).
931     *
932     * @param params Parameters for this load.
933     */
934    public void loadUrl(LoadUrlParams params) {
935        if (mNativeContentViewCore == 0) return;
936 
937        nativeLoadUrl(mNativeContentViewCore,
938                params.mUrl,
939                params.mLoadUrlType,
940                params.mTransitionType,
941                params.mUaOverrideOption,
942                params.getExtraHeadersString(),
943                params.mPostData,
944                params.mBaseUrlForDataUrl,
945                params.mVirtualUrlForDataUrl,
946                params.mCanLoadLocalResources);
947    }
948 
949    /**
950     * Stops loading the current web contents.
951     */
952    public void stopLoading() {
953        if (mNativeContentViewCore != 0) nativeStopLoading(mNativeContentViewCore);
954    }
955 
956    /**
957     * Get the URL of the current page.
958     *
959     * @return The URL of the current page.
960     */
961    public String getUrl() {
962        if (mNativeContentViewCore != 0) return nativeGetURL(mNativeContentViewCore);
963        return null;
964    }
965 
966    /**
967     * Get the title of the current page.
968     *
969     * @return The title of the current page.
970     */
971    public String getTitle() {
972        if (mNativeContentViewCore != 0) return nativeGetTitle(mNativeContentViewCore);
973        return null;
974    }
975 
976    /**
977     * Shows an interstitial page driven by the passed in delegate.
978     *
979     * @param url The URL being blocked by the interstitial.
980     * @param delegate The delegate handling the interstitial.
981     */
982    @VisibleForTesting
983    public void showInterstitialPage(
984            String url, InterstitialPageDelegateAndroid delegate) {
985        if (mNativeContentViewCore == 0) return;
986        nativeShowInterstitialPage(mNativeContentViewCore, url, delegate.getNative());
987    }
988 
989    /**
990     * @return Whether the page is currently showing an interstitial, such as a bad HTTPS page.
991     */
992    public boolean isShowingInterstitialPage() {
993        return mNativeContentViewCore == 0 ?
994                false : nativeIsShowingInterstitialPage(mNativeContentViewCore);
995    }
996 
997    /**
998     * Mark any new frames that have arrived since this function was last called as non-pending.
999     *
1000     * @return Whether there was a pending frame from the renderer.
1001     */
1002    public boolean consumePendingRendererFrame() {
1003        boolean hadPendingFrame = mPendingRendererFrame;
1004        mPendingRendererFrame = false;
1005        return hadPendingFrame;
1006    }
1007 
1008    /**
1009     * @return Viewport width in physical pixels as set from onSizeChanged.
1010     */
1011    @CalledByNative
1012    public int getViewportWidthPix() { return mViewportWidthPix; }
1013 
1014    /**
1015     * @return Viewport height in physical pixels as set from onSizeChanged.
1016     */
1017    @CalledByNative
1018    public int getViewportHeightPix() { return mViewportHeightPix; }
1019 
1020    /**
1021     * @return Width of underlying physical surface.
1022     */
1023    @CalledByNative
1024    public int getPhysicalBackingWidthPix() { return mPhysicalBackingWidthPix; }
1025 
1026    /**
1027     * @return Height of underlying physical surface.
1028     */
1029    @CalledByNative
1030    public int getPhysicalBackingHeightPix() { return mPhysicalBackingHeightPix; }
1031 
1032    /**
1033     * @return Amount the output surface extends past the bottom of the window viewport.
1034     */
1035    @CalledByNative
1036    public int getOverdrawBottomHeightPix() { return mOverdrawBottomHeightPix; }
1037 
1038    /**
1039     * @return The amount to shrink the viewport relative to {@link #getViewportWidthPix()}.
1040     */
1041    @CalledByNative
1042    public int getViewportSizeOffsetWidthPix() { return mViewportSizeOffsetWidthPix; }
1043 
1044    /**
1045     * @return The amount to shrink the viewport relative to {@link #getViewportHeightPix()}.
1046     */
1047    @CalledByNative
1048    public int getViewportSizeOffsetHeightPix() { return mViewportSizeOffsetHeightPix; }
1049 
1050    /**
1051     * @see android.webkit.WebView#getContentHeight()
1052     */
1053    public float getContentHeightCss() {
1054        return mRenderCoordinates.getContentHeightCss();
1055    }
1056 
1057    /**
1058     * @see android.webkit.WebView#getContentWidth()
1059     */
1060    public float getContentWidthCss() {
1061        return mRenderCoordinates.getContentWidthCss();
1062    }
1063 
1064    public Bitmap getBitmap() {
1065        return getBitmap(getViewportWidthPix(), getViewportHeightPix());
1066    }
1067 
1068    public Bitmap getBitmap(int width, int height) {
1069        if (width == 0 || height == 0
1070                || getViewportWidthPix() == 0 || getViewportHeightPix() == 0) {
1071            return null;
1072        }
1073 
1074        Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
1075 
1076        if (mNativeContentViewCore != 0 &&
1077                nativePopulateBitmapFromCompositor(mNativeContentViewCore, b)) {
1078            // If we successfully grabbed a bitmap, check if we have to draw the Android overlay
1079            // components as well.
1080            if (mContainerView.getChildCount() > 0) {
1081                Canvas c = new Canvas(b);
1082                c.scale(width / (float) getViewportWidthPix(),
1083                        height / (float) getViewportHeightPix());
1084                mContainerView.draw(c);
1085            }
1086            return b;
1087        }
1088 
1089        return null;
1090    }
1091 
1092    /**
1093     * Generates a bitmap of the content that is performance optimized based on capture time.
1094     *
1095     * <p>
1096     * To have a consistent capture time across devices, we will scale down the captured bitmap
1097     * where necessary to reduce the time to generate the bitmap.
1098     *
1099     * @param width The width of the content to be captured.
1100     * @param height The height of the content to be captured.
1101     * @return A pair of the generated bitmap, and the scale that needs to be applied to return the
1102     *         bitmap to it's original size (i.e. if the bitmap is scaled down 50%, this
1103     *         will be 2).
1104     */
1105    public Pair<Bitmap, Float> getScaledPerformanceOptimizedBitmap(int width, int height) {
1106        float scale = 1f;
1107        // On tablets, always scale down to MDPI for performance reasons.
1108        if (DeviceUtils.isTablet(getContext())) {
1109            scale = getContext().getResources().getDisplayMetrics().density;
1110        }
1111        return Pair.create(
1112                getBitmap((int) (width / scale), (int) (height / scale)),
1113                scale);
1114    }
1115 
1116    /**
1117     * @return Whether the current WebContents has a previous navigation entry.
1118     */
1119    public boolean canGoBack() {
1120        return mNativeContentViewCore != 0 && nativeCanGoBack(mNativeContentViewCore);
1121    }
1122 
1123    /**
1124     * @return Whether the current WebContents has a navigation entry after the current one.
1125     */
1126    public boolean canGoForward() {
1127        return mNativeContentViewCore != 0 && nativeCanGoForward(mNativeContentViewCore);
1128    }
1129 
1130    /**
1131     * @param offset The offset into the navigation history.
1132     * @return Whether we can move in history by given offset
1133     */
1134    public boolean canGoToOffset(int offset) {
1135        return mNativeContentViewCore != 0 && nativeCanGoToOffset(mNativeContentViewCore, offset);
1136    }
1137 
1138    /**
1139     * Navigates to the specified offset from the "current entry". Does nothing if the offset is out
1140     * of bounds.
1141     * @param offset The offset into the navigation history.
1142     */
1143    public void goToOffset(int offset) {
1144        if (mNativeContentViewCore != 0) nativeGoToOffset(mNativeContentViewCore, offset);
1145    }
1146 
1147    @Override
1148    public void goToNavigationIndex(int index) {
1149        if (mNativeContentViewCore != 0) nativeGoToNavigationIndex(mNativeContentViewCore, index);
1150    }
1151 
1152    /**
1153     * Goes to the navigation entry before the current one.
1154     */
1155    public void goBack() {
1156        if (mNativeContentViewCore != 0) nativeGoBack(mNativeContentViewCore);
1157    }
1158 
1159    /**
1160     * Goes to the navigation entry following the current one.
1161     */
1162    public void goForward() {
1163        if (mNativeContentViewCore != 0) nativeGoForward(mNativeContentViewCore);
1164    }
1165 
1166    /**
1167     * Reload the current page.
1168     */
1169    public void reload() {
1170        mAccessibilityInjector.addOrRemoveAccessibilityApisIfNecessary();
1171        if (mNativeContentViewCore != 0) nativeReload(mNativeContentViewCore);
1172    }
1173 
1174    /**
1175     * Cancel the pending reload.
1176     */
1177    public void cancelPendingReload() {
1178        if (mNativeContentViewCore != 0) nativeCancelPendingReload(mNativeContentViewCore);
1179    }
1180 
1181    /**
1182     * Continue the pending reload.
1183     */
1184    public void continuePendingReload() {
1185        if (mNativeContentViewCore != 0) nativeContinuePendingReload(mNativeContentViewCore);
1186    }
1187 
1188    /**
1189     * Clears the ContentViewCore's page history in both the backwards and
1190     * forwards directions.
1191     */
1192    public void clearHistory() {
1193        if (mNativeContentViewCore != 0) nativeClearHistory(mNativeContentViewCore);
1194    }
1195 
1196    /**
1197     * @return The selected text (empty if no text selected).
1198     */
1199    public String getSelectedText() {
1200        return mHasSelection ? mLastSelectedText : "";
1201    }
1202 
1203    /**
1204     * @return Whether the current selection is editable (false if no text selected).
1205     */
1206    public boolean isSelectionEditable() {
1207        return mHasSelection ? mSelectionEditable : false;
1208    }
1209 
1210    // End FrameLayout overrides.
1211 
1212    /**
1213     * @see View#onTouchEvent(MotionEvent)
1214     */
1215    public boolean onTouchEvent(MotionEvent event) {
1216        undoScrollFocusedEditableNodeIntoViewIfNeeded(false);
1217        return mContentViewGestureHandler.onTouchEvent(event);
1218    }
1219 
1220    /**
1221     * @return ContentViewGestureHandler for all MotionEvent and gesture related calls.
1222     */
1223    ContentViewGestureHandler getContentViewGestureHandler() {
1224        return mContentViewGestureHandler;
1225    }
1226 
1227    @Override
1228    public boolean sendTouchEvent(long timeMs, int action, TouchPoint[] pts) {
1229        if (mNativeContentViewCore != 0) {
1230            return nativeSendTouchEvent(mNativeContentViewCore, timeMs, action, pts);
1231        }
1232        return false;
1233    }
1234 
1235    @SuppressWarnings("unused")
1236    @CalledByNative
1237    private void hasTouchEventHandlers(boolean hasTouchHandlers) {
1238        mContentViewGestureHandler.hasTouchEventHandlers(hasTouchHandlers);
1239    }
1240 
1241    @SuppressWarnings("unused")
1242    @CalledByNative
1243    private void confirmTouchEvent(int ackResult) {
1244        mContentViewGestureHandler.confirmTouchEvent(ackResult);
1245    }
1246 
1247    @SuppressWarnings("unused")
1248    @CalledByNative
1249    private void unhandledFlingStartEvent() {
1250        if (mGestureStateListener != null) {
1251            mGestureStateListener.onUnhandledFlingStartEvent();
1252        }
1253    }
1254 
1255    @Override
1256    public boolean sendGesture(int type, long timeMs, int x, int y, boolean lastInputEventForVSync,
1257                               Bundle b) {
1258        if (offerGestureToEmbedder(type)) return false;
1259        if (mNativeContentViewCore == 0) return false;
1260        updateTextHandlesForGesture(type);
1261        updateGestureStateListener(type, b);
1262        if (lastInputEventForVSync && isVSyncNotificationEnabled()) {
1263            assert type == ContentViewGestureHandler.GESTURE_SCROLL_BY ||
1264                    type == ContentViewGestureHandler.GESTURE_PINCH_BY;
1265            mDidSignalVSyncUsingInputEvent = true;
1266        }
1267        switch (type) {
1268            case ContentViewGestureHandler.GESTURE_SHOW_PRESSED_STATE:
1269                nativeShowPressState(mNativeContentViewCore, timeMs, x, y);
1270                return true;
1271            case ContentViewGestureHandler.GESTURE_SHOW_PRESS_CANCEL:
1272                nativeShowPressCancel(mNativeContentViewCore, timeMs, x, y);
1273                return true;
1274            case ContentViewGestureHandler.GESTURE_DOUBLE_TAP:
1275                nativeDoubleTap(mNativeContentViewCore, timeMs, x, y);
1276                return true;
1277            case ContentViewGestureHandler.GESTURE_SINGLE_TAP_UP:
1278                nativeSingleTap(mNativeContentViewCore, timeMs, x, y, false);
1279                return true;
1280            case ContentViewGestureHandler.GESTURE_SINGLE_TAP_CONFIRMED:
1281                handleTapOrPress(timeMs, x, y, 0,
1282                        b.getBoolean(ContentViewGestureHandler.SHOW_PRESS, false));
1283                return true;
1284            case ContentViewGestureHandler.GESTURE_SINGLE_TAP_UNCONFIRMED:
1285                nativeSingleTapUnconfirmed(mNativeContentViewCore, timeMs, x, y);
1286                return true;
1287            case ContentViewGestureHandler.GESTURE_LONG_PRESS:
1288                handleTapOrPress(timeMs, x, y, IS_LONG_PRESS, false);
1289                return true;
1290            case ContentViewGestureHandler.GESTURE_LONG_TAP:
1291                handleTapOrPress(timeMs, x, y, IS_LONG_TAP, false);
1292                return true;
1293            case ContentViewGestureHandler.GESTURE_SCROLL_START:
1294                nativeScrollBegin(mNativeContentViewCore, timeMs, x, y);
1295                return true;
1296            case ContentViewGestureHandler.GESTURE_SCROLL_BY: {
1297                int dx = b.getInt(ContentViewGestureHandler.DISTANCE_X);
1298                int dy = b.getInt(ContentViewGestureHandler.DISTANCE_Y);
1299                nativeScrollBy(mNativeContentViewCore, timeMs, x, y, dx, dy,
1300                        lastInputEventForVSync);
1301                return true;
1302            }
1303            case ContentViewGestureHandler.GESTURE_SCROLL_END:
1304                nativeScrollEnd(mNativeContentViewCore, timeMs);
1305                return true;
1306            case ContentViewGestureHandler.GESTURE_FLING_START:
1307                nativeFlingStart(mNativeContentViewCore, timeMs, x, y,
1308                        b.getInt(ContentViewGestureHandler.VELOCITY_X, 0),
1309                        b.getInt(ContentViewGestureHandler.VELOCITY_Y, 0));
1310                return true;
1311            case ContentViewGestureHandler.GESTURE_FLING_CANCEL:
1312                nativeFlingCancel(mNativeContentViewCore, timeMs);
1313                return true;
1314            case ContentViewGestureHandler.GESTURE_PINCH_BEGIN:
1315                nativePinchBegin(mNativeContentViewCore, timeMs, x, y);
1316                return true;
1317            case ContentViewGestureHandler.GESTURE_PINCH_BY:
1318                nativePinchBy(mNativeContentViewCore, timeMs, x, y,
1319                        b.getFloat(ContentViewGestureHandler.DELTA, 0),
1320                        lastInputEventForVSync);
1321                return true;
1322            case ContentViewGestureHandler.GESTURE_PINCH_END:
1323                nativePinchEnd(mNativeContentViewCore, timeMs);
1324                return true;
1325            default:
1326                return false;
1327        }
1328    }
1329 
1330    public void setGestureStateListener(GestureStateListener pinchGestureStateListener) {
1331        mGestureStateListener = pinchGestureStateListener;
1332    }
1333 
1334    void updateGestureStateListener(int gestureType, Bundle b) {
1335        if (mGestureStateListener == null) return;
1336 
1337        switch (gestureType) {
1338            case ContentViewGestureHandler.GESTURE_PINCH_BEGIN:
1339                mGestureStateListener.onPinchGestureStart();
1340                break;
1341            case ContentViewGestureHandler.GESTURE_PINCH_END:
1342                mGestureStateListener.onPinchGestureEnd();
1343                break;
1344            case ContentViewGestureHandler.GESTURE_FLING_START:
1345                mGestureStateListener.onFlingStartGesture(
1346                        b.getInt(ContentViewGestureHandler.VELOCITY_X, 0),
1347                        b.getInt(ContentViewGestureHandler.VELOCITY_Y, 0));
1348                break;
1349            case ContentViewGestureHandler.GESTURE_FLING_CANCEL:
1350                mGestureStateListener.onFlingCancelGesture();
1351                break;
1352            default:
1353                break;
1354        }
1355    }
1356 
1357    public interface JavaScriptCallback {
1358        void handleJavaScriptResult(String jsonResult);
1359    }
1360 
1361    /**
1362     * Injects the passed Javascript code in the current page and evaluates it.
1363     * If a result is required, pass in a callback.
1364     * Used in automation tests.
1365     *
1366     * @param script The Javascript to execute.
1367     * @param callback The callback to be fired off when a result is ready. The script's
1368     *                 result will be json encoded and passed as the parameter, and the call
1369     *                 will be made on the main thread.
1370     *                 If no result is required, pass null.
1371     * @throws IllegalStateException If the ContentView has been destroyed.
1372     */
1373    public void evaluateJavaScript(
1374            String script, JavaScriptCallback callback) throws IllegalStateException {
1375        checkIsAlive();
1376        nativeEvaluateJavaScript(mNativeContentViewCore, script, callback, false);
1377    }
1378 
1379    /**
1380     * Injects the passed Javascript code in the current page and evaluates it.
1381     * If there is no page existing, a new one will be created.
1382     *
1383     * @param script The Javascript to execute.
1384     * @throws IllegalStateException If the ContentView has been destroyed.
1385     */
1386    public void evaluateJavaScriptEvenIfNotYetNavigated(String script)
1387            throws IllegalStateException {
1388        checkIsAlive();
1389        nativeEvaluateJavaScript(mNativeContentViewCore, script, null, true);
1390    }
1391 
1392    /**
1393     * This method should be called when the containing activity is paused.
1394     */
1395    public void onActivityPause() {
1396        TraceEvent.begin();
1397        hidePopupDialog();
1398        nativeOnHide(mNativeContentViewCore);
1399        TraceEvent.end();
1400    }
1401 
1402    /**
1403     * This method should be called when the containing activity is resumed.
1404     */
1405    public void onActivityResume() {
1406        nativeOnShow(mNativeContentViewCore);
1407        setAccessibilityState(mAccessibilityManager.isEnabled());
1408    }
1409 
1410    /**
1411     * To be called when the ContentView is shown.
1412     */
1413    public void onShow() {
1414        nativeOnShow(mNativeContentViewCore);
1415        setAccessibilityState(mAccessibilityManager.isEnabled());
1416    }
1417 
1418    /**
1419     * To be called when the ContentView is hidden.
1420     */
1421    public void onHide() {
1422        hidePopupDialog();
1423        setInjectedAccessibility(false);
1424        nativeOnHide(mNativeContentViewCore);
1425    }
1426 
1427    /**
1428     * Return the ContentSettings object used to retrieve the settings for this
1429     * ContentViewCore. For modifications, ChromeNativePreferences is to be used.
1430     * @return A ContentSettings object that can be used to retrieve this
1431     *         ContentViewCore's settings.
1432     */
1433    public ContentSettings getContentSettings() {
1434        return mContentSettings;
1435    }
1436 
1437    @Override
1438    public boolean didUIStealScroll(float x, float y) {
1439        return getContentViewClient().shouldOverrideScroll(
1440                x, y, computeHorizontalScrollOffset(), computeVerticalScrollOffset());
1441    }
1442 
1443    @Override
1444    public boolean hasFixedPageScale() {
1445        return mRenderCoordinates.hasFixedPageScale();
1446    }
1447 
1448    private void hidePopupDialog() {
1449        SelectPopupDialog.hide(this);
1450        hideHandles();
1451        hideSelectActionBar();
1452    }
1453 
1454    void hideSelectActionBar() {
1455        if (mActionMode != null) {
1456            mActionMode.finish();
1457            mActionMode = null;
1458        }
1459    }
1460 
1461    public boolean isSelectActionBarShowing() {
1462        return mActionMode != null;
1463    }
1464 
1465    private void resetGestureDetectors() {
1466        mContentViewGestureHandler.resetGestureHandlers();
1467    }
1468 
1469    /**
1470     * @see View#onAttachedToWindow()
1471     */
1472    @SuppressWarnings("javadoc")
1473    public void onAttachedToWindow() {
1474        mAttachedToWindow = true;
1475        if (mNativeContentViewCore != 0) {
1476            assert mPid == nativeGetCurrentRenderProcessId(mNativeContentViewCore);
1477            ChildProcessLauncher.bindAsHighPriority(mPid);
1478            // Normally the initial binding is removed in onRenderProcessSwap(), but it is possible
1479            // to construct WebContents and spawn the renderer before passing it to ContentViewCore.
1480            // In this case there will be no onRenderProcessSwap() call and the initial binding will
1481            // be removed here.
1482            ChildProcessLauncher.removeInitialBinding(mPid);
1483        }
1484        setAccessibilityState(mAccessibilityManager.isEnabled());
1485    }
1486 
1487    /**
1488     * @see View#onDetachedFromWindow()
1489     */
1490    @SuppressWarnings("javadoc")
1491    public void onDetachedFromWindow() {
1492        mAttachedToWindow = false;
1493        if (mNativeContentViewCore != 0) {
1494            assert mPid == nativeGetCurrentRenderProcessId(mNativeContentViewCore);
1495            ChildProcessLauncher.unbindAsHighPriority(mPid);
1496        }
1497        setInjectedAccessibility(false);
1498        hidePopupDialog();
1499        mZoomControlsDelegate.dismissZoomPicker();
1500        unregisterAccessibilityContentObserver();
1501    }
1502 
1503    /**
1504     * @see View#onVisibilityChanged(android.view.View, int)
1505     */
1506    public void onVisibilityChanged(View changedView, int visibility) {
1507        if (visibility != View.VISIBLE) {
1508            mZoomControlsDelegate.dismissZoomPicker();
1509        }
1510    }
1511 
1512    /**
1513     * @see View#onCreateInputConnection(EditorInfo)
1514     */
1515    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
1516        if (!mImeAdapter.hasTextInputType()) {
1517            // Although onCheckIsTextEditor will return false in this case, the EditorInfo
1518            // is still used by the InputMethodService. Need to make sure the IME doesn't
1519            // enter fullscreen mode.
1520            outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN;
1521        }
1522        mInputConnection =
1523                mAdapterInputConnectionFactory.get(mContainerView, mImeAdapter, outAttrs);
1524        return mInputConnection;
1525    }
1526 
1527    public Editable getEditableForTest() {
1528        return mInputConnection.getEditable();
1529    }
1530 
1531    /**
1532     * @see View#onCheckIsTextEditor()
1533     */
1534    public boolean onCheckIsTextEditor() {
1535        return mImeAdapter.hasTextInputType();
1536    }
1537 
1538    /**
1539     * @see View#onConfigurationChanged(Configuration)
1540     */
1541    @SuppressWarnings("javadoc")
1542    public void onConfigurationChanged(Configuration newConfig) {
1543        TraceEvent.begin();
1544 
1545        if (newConfig.keyboard != Configuration.KEYBOARD_NOKEYS) {
1546            mImeAdapter.attach(nativeGetNativeImeAdapter(mNativeContentViewCore),
1547                    ImeAdapter.getTextInputTypeNone(),
1548                    AdapterInputConnection.INVALID_SELECTION,
1549                    AdapterInputConnection.INVALID_SELECTION);
1550            InputMethodManager manager = (InputMethodManager)
1551                    getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
1552            manager.restartInput(mContainerView);
1553        }
1554        mContainerViewInternals.super_onConfigurationChanged(newConfig);
1555        mNeedUpdateOrientationChanged = true;
1556        TraceEvent.end();
1557    }
1558 
1559    /**
1560     * @see View#onSizeChanged(int, int, int, int)
1561     */
1562    @SuppressWarnings("javadoc")
1563    public void onSizeChanged(int wPix, int hPix, int owPix, int ohPix) {
1564        if (getViewportWidthPix() == wPix && getViewportHeightPix() == hPix) return;
1565 
1566        mViewportWidthPix = wPix;
1567        mViewportHeightPix = hPix;
1568        if (mNativeContentViewCore != 0) {
1569            nativeWasResized(mNativeContentViewCore);
1570        }
1571 
1572        updateAfterSizeChanged();
1573    }
1574 
1575    /**
1576     * Called when the underlying surface the compositor draws to changes size.
1577     * This may be larger than the viewport size.
1578     */
1579    public void onPhysicalBackingSizeChanged(int wPix, int hPix) {
1580        if (mPhysicalBackingWidthPix == wPix && mPhysicalBackingHeightPix == hPix) return;
1581 
1582        mPhysicalBackingWidthPix = wPix;
1583        mPhysicalBackingHeightPix = hPix;
1584 
1585        if (mNativeContentViewCore != 0) {
1586            nativeWasResized(mNativeContentViewCore);
1587        }
1588    }
1589 
1590    /**
1591     * Called when the amount the surface is overdrawing off the bottom has changed.
1592     * @param overdrawHeightPix The overdraw height.
1593     */
1594    public void onOverdrawBottomHeightChanged(int overdrawHeightPix) {
1595        if (mOverdrawBottomHeightPix == overdrawHeightPix) return;
1596 
1597        mOverdrawBottomHeightPix = overdrawHeightPix;
1598 
1599        if (mNativeContentViewCore != 0) {
1600            nativeWasResized(mNativeContentViewCore);
1601        }
1602    }
1603 
1604    private void updateAfterSizeChanged() {
1605        mPopupZoomer.hide(false);
1606 
1607        // Execute a delayed form focus operation because the OSK was brought
1608        // up earlier.
1609        if (!mFocusPreOSKViewportRect.isEmpty()) {
1610            Rect rect = new Rect();
1611            getContainerView().getWindowVisibleDisplayFrame(rect);
1612            if (!rect.equals(mFocusPreOSKViewportRect)) {
1613                scrollFocusedEditableNodeIntoView();
1614                mFocusPreOSKViewportRect.setEmpty();
1615            }
1616        } else if (mUnfocusOnNextSizeChanged) {
1617            undoScrollFocusedEditableNodeIntoViewIfNeeded(true);
1618            mUnfocusOnNextSizeChanged = false;
1619        }
1620 
1621        if (mNeedUpdateOrientationChanged) {
1622            sendOrientationChangeEvent();
1623            mNeedUpdateOrientationChanged = false;
1624        }
1625    }
1626 
1627    private void scrollFocusedEditableNodeIntoView() {
1628        if (mNativeContentViewCore != 0) {
1629            Runnable scrollTask = new Runnable() {
1630                @Override
1631                public void run() {
1632                    if (mNativeContentViewCore != 0) {
1633                        nativeScrollFocusedEditableNodeIntoView(mNativeContentViewCore);
1634                    }
1635                }
1636            };
1637 
1638            scrollTask.run();
1639 
1640            // The native side keeps track of whether the zoom and scroll actually occurred. It is
1641            // more efficient to do it this way and sometimes fire an unnecessary message rather
1642            // than synchronize with the renderer and always have an additional message.
1643            mScrolledAndZoomedFocusedEditableNode = true;
1644        }
1645    }
1646 
1647    private void undoScrollFocusedEditableNodeIntoViewIfNeeded(boolean backButtonPressed) {
1648        // The only call to this function that matters is the first call after the
1649        // scrollFocusedEditableNodeIntoView function call.
1650        // If the first call to this function is a result of a back button press we want to undo the
1651        // preceding scroll. If the call is a result of some other action we don't want to perform
1652        // an undo.
1653        // All subsequent calls are ignored since only the scroll function sets
1654        // mScrolledAndZoomedFocusedEditableNode to true.
1655        if (mScrolledAndZoomedFocusedEditableNode && backButtonPressed &&
1656                mNativeContentViewCore != 0) {
1657            Runnable scrollTask = new Runnable() {
1658                @Override
1659                public void run() {
1660                    if (mNativeContentViewCore != 0) {
1661                        nativeUndoScrollFocusedEditableNodeIntoView(mNativeContentViewCore);
1662                    }
1663                }
1664            };
1665 
1666            scrollTask.run();
1667        }
1668        mScrolledAndZoomedFocusedEditableNode = false;
1669    }
1670 
1671    public void onFocusChanged(boolean gainFocus) {
1672        if (!gainFocus) getContentViewClient().onImeStateChangeRequested(false);
1673        if (mNativeContentViewCore != 0) nativeSetFocus(mNativeContentViewCore, gainFocus);
1674    }
1675 
1676    /**
1677     * @see View#onKeyUp(int, KeyEvent)
1678     */
1679    public boolean onKeyUp(int keyCode, KeyEvent event) {
1680        if (mPopupZoomer.isShowing() && keyCode == KeyEvent.KEYCODE_BACK) {
1681            mPopupZoomer.hide(true);
1682            return true;
1683        }
1684        return mContainerViewInternals.super_onKeyUp(keyCode, event);
1685    }
1686 
1687    /**
1688     * @see View#dispatchKeyEventPreIme(KeyEvent)
1689     */
1690    public boolean dispatchKeyEventPreIme(KeyEvent event) {
1691        try {
1692            TraceEvent.begin();
1693            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && mImeAdapter.isActive()) {
1694                mUnfocusOnNextSizeChanged = true;
1695            } else {
1696                undoScrollFocusedEditableNodeIntoViewIfNeeded(false);
1697            }
1698            return mContainerViewInternals.super_dispatchKeyEventPreIme(event);
1699        } finally {
1700            TraceEvent.end();
1701        }
1702    }
1703 
1704    /**
1705     * @see View#dispatchKeyEvent(KeyEvent)
1706     */
1707    public boolean dispatchKeyEvent(KeyEvent event) {
1708        if (getContentViewClient().shouldOverrideKeyEvent(event)) {
1709            return mContainerViewInternals.super_dispatchKeyEvent(event);
1710        }
1711 
1712        if (mImeAdapter.dispatchKeyEvent(event)) return true;
1713 
1714        return mContainerViewInternals.super_dispatchKeyEvent(event);
1715    }
1716 
1717    /**
1718     * @see View#onHoverEvent(MotionEvent)
1719     * Mouse move events are sent on hover enter, hover move and hover exit.
1720     * They are sent on hover exit because sometimes it acts as both a hover
1721     * move and hover exit.
1722     */
1723    public boolean onHoverEvent(MotionEvent event) {
1724        TraceEvent.begin("onHoverEvent");
1725        mContainerView.removeCallbacks(mFakeMouseMoveRunnable);
1726        if (mBrowserAccessibilityManager != null) {
1727            return mBrowserAccessibilityManager.onHoverEvent(event);
1728        }
1729        if (mNativeContentViewCore != 0) {
1730            nativeSendMouseMoveEvent(mNativeContentViewCore, event.getEventTime(),
1731                    event.getX(), event.getY());
1732        }
1733        TraceEvent.end("onHoverEvent");
1734        return true;
1735    }
1736 
1737    /**
1738     * @see View#onGenericMotionEvent(MotionEvent)
1739     */
1740    public boolean onGenericMotionEvent(MotionEvent event) {
1741        if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
1742            switch (event.getAction()) {
1743                case MotionEvent.ACTION_SCROLL:
1744                    nativeSendMouseWheelEvent(mNativeContentViewCore, event.getEventTime(),
1745                            event.getX(), event.getY(),
1746                            event.getAxisValue(MotionEvent.AXIS_VSCROLL));
1747 
1748                    mContainerView.removeCallbacks(mFakeMouseMoveRunnable);
1749                    // Send a delayed onMouseMove event so that we end
1750                    // up hovering over the right position after the scroll.
1751                    final MotionEvent eventFakeMouseMove = MotionEvent.obtain(event);
1752                    mFakeMouseMoveRunnable = new Runnable() {
1753                          @Override
1754                          public void run() {
1755                              onHoverEvent(eventFakeMouseMove);
1756                          }
1757                    };
1758                    mContainerView.postDelayed(mFakeMouseMoveRunnable, 250);
1759                    return true;
1760            }
1761        }
1762        return mContainerViewInternals.super_onGenericMotionEvent(event);
1763    }
1764 
1765    /**
1766     * @see View#scrollBy(int, int)
1767     * Currently the ContentView scrolling happens in the native side. In
1768     * the Java view system, it is always pinned at (0, 0). scrollBy() and scrollTo()
1769     * are overridden, so that View's mScrollX and mScrollY will be unchanged at
1770     * (0, 0). This is critical for drawing ContentView correctly.
1771     */
1772    public void scrollBy(int xPix, int yPix) {
1773        if (mNativeContentViewCore != 0) {
1774            nativeScrollBy(mNativeContentViewCore,
1775                    System.currentTimeMillis(), 0, 0, xPix, yPix, false);
1776        }
1777    }
1778 
1779    /**
1780     * @see View#scrollTo(int, int)
1781     */
1782    public void scrollTo(int xPix, int yPix) {
1783        if (mNativeContentViewCore == 0) return;
1784        final float xCurrentPix = mRenderCoordinates.getScrollXPix();
1785        final float yCurrentPix = mRenderCoordinates.getScrollYPix();
1786        final float dxPix = xPix - xCurrentPix;
1787        final float dyPix = yPix - yCurrentPix;
1788        if (dxPix != 0 || dyPix != 0) {
1789            long time = System.currentTimeMillis();
1790            nativeScrollBegin(mNativeContentViewCore, time, xCurrentPix, yCurrentPix);
1791            nativeScrollBy(mNativeContentViewCore,
1792                    time, xCurrentPix, yCurrentPix, dxPix, dyPix, false);
1793            nativeScrollEnd(mNativeContentViewCore, time);
1794        }
1795    }
1796 
1797    // NOTE: this can go away once ContentView.getScrollX() reports correct values.
1798    //       see: b/6029133
1799    public int getNativeScrollXForTest() {
1800        return mRenderCoordinates.getScrollXPixInt();
1801    }
1802 
1803    // NOTE: this can go away once ContentView.getScrollY() reports correct values.
1804    //       see: b/6029133
1805    public int getNativeScrollYForTest() {
1806        return mRenderCoordinates.getScrollYPixInt();
1807    }
1808 
1809    /**
1810     * @see View#computeHorizontalScrollExtent()
1811     */
1812    @SuppressWarnings("javadoc")
1813    public int computeHorizontalScrollExtent() {
1814        return mRenderCoordinates.getLastFrameViewportWidthPixInt();
1815    }
1816 
1817    /**
1818     * @see View#computeHorizontalScrollOffset()
1819     */
1820    @SuppressWarnings("javadoc")
1821    public int computeHorizontalScrollOffset() {
1822        return mRenderCoordinates.getScrollXPixInt();
1823    }
1824 
1825    /**
1826     * @see View#computeHorizontalScrollRange()
1827     */
1828    @SuppressWarnings("javadoc")
1829    public int computeHorizontalScrollRange() {
1830        return mRenderCoordinates.getContentWidthPixInt();
1831    }
1832 
1833    /**
1834     * @see View#computeVerticalScrollExtent()
1835     */
1836    @SuppressWarnings("javadoc")
1837    public int computeVerticalScrollExtent() {
1838        return mRenderCoordinates.getLastFrameViewportHeightPixInt();
1839    }
1840 
1841    /**
1842     * @see View#computeVerticalScrollOffset()
1843     */
1844    @SuppressWarnings("javadoc")
1845    public int computeVerticalScrollOffset() {
1846        return mRenderCoordinates.getScrollYPixInt();
1847    }
1848 
1849    /**
1850     * @see View#computeVerticalScrollRange()
1851     */
1852    @SuppressWarnings("javadoc")
1853    public int computeVerticalScrollRange() {
1854        return mRenderCoordinates.getContentHeightPixInt();
1855    }
1856 
1857    // End FrameLayout overrides.
1858 
1859    /**
1860     * @see View#awakenScrollBars(int, boolean)
1861     */
1862    @SuppressWarnings("javadoc")
1863    public boolean awakenScrollBars(int startDelay, boolean invalidate) {
1864        // For the default implementation of ContentView which draws the scrollBars on the native
1865        // side, calling this function may get us into a bad state where we keep drawing the
1866        // scrollBars, so disable it by always returning false.
1867        if (mContainerView.getScrollBarStyle() == View.SCROLLBARS_INSIDE_OVERLAY) {
1868            return false;
1869        } else {
1870            return mContainerViewInternals.super_awakenScrollBars(startDelay, invalidate);
1871        }
1872    }
1873 
1874    @SuppressWarnings("unused")
1875    @CalledByNative
1876    private void onTabCrash() {
1877        assert mPid != 0;
1878        getContentViewClient().onRendererCrash(ChildProcessLauncher.isOomProtected(mPid));
1879        mPid = 0;
1880    }
1881 
1882    private void handleTapOrPress(
1883            long timeMs, float xPix, float yPix, int isLongPressOrTap, boolean showPress) {
1884        if (mContainerView.isFocusable() && mContainerView.isFocusableInTouchMode()
1885                && !mContainerView.isFocused())  {
1886            mContainerView.requestFocus();
1887        }
1888 
1889        if (!mPopupZoomer.isShowing()) mPopupZoomer.setLastTouch(xPix, yPix);
1890 
1891        if (isLongPressOrTap == IS_LONG_PRESS) {
1892            getInsertionHandleController().allowAutomaticShowing();
1893            getSelectionHandleController().allowAutomaticShowing();
1894            if (mNativeContentViewCore != 0) {
1895                nativeLongPress(mNativeContentViewCore, timeMs, xPix, yPix, false);
1896            }
1897        } else if (isLongPressOrTap == IS_LONG_TAP) {
1898            getInsertionHandleController().allowAutomaticShowing();
1899            getSelectionHandleController().allowAutomaticShowing();
1900            if (mNativeContentViewCore != 0) {
1901                nativeLongTap(mNativeContentViewCore, timeMs, xPix, yPix, false);
1902            }
1903        } else {
1904            if (!showPress && mNativeContentViewCore != 0) {
1905                nativeShowPressState(mNativeContentViewCore, timeMs, xPix, yPix);
1906            }
1907            if (mSelectionEditable) getInsertionHandleController().allowAutomaticShowing();
1908            if (mNativeContentViewCore != 0) {
1909                nativeSingleTap(mNativeContentViewCore, timeMs, xPix, yPix, false);
1910            }
1911        }
1912    }
1913 
1914    public void setZoomControlsDelegate(ZoomControlsDelegate zoomControlsDelegate) {
1915        mZoomControlsDelegate = zoomControlsDelegate;
1916    }
1917 
1918    public void updateMultiTouchZoomSupport(boolean supportsMultiTouchZoom) {
1919        mZoomManager.updateMultiTouchSupport(supportsMultiTouchZoom);
1920    }
1921 
1922    public void updateDoubleTapDragSupport(boolean supportsDoubleTapDrag) {
1923        mContentViewGestureHandler.updateDoubleTapDragSupport(supportsDoubleTapDrag);
1924    }
1925 
1926    public void selectPopupMenuItems(int[] indices) {
1927        if (mNativeContentViewCore != 0) {
1928            nativeSelectPopupMenuItems(mNativeContentViewCore, indices);
1929        }
1930    }
1931 
1932    /**
1933     * Get the screen orientation from the OS and push it to WebKit.
1934     *
1935     * TODO(husky): Add a hook for mock orientations.
1936     *
1937     * TODO(husky): Currently each new tab starts with an orientation of 0 until you actually
1938     * rotate the device. This is wrong if you actually started in landscape mode. To fix this, we
1939     * need to push the correct orientation, but only after WebKit's Frame object has been fully
1940     * initialized. Need to find a good time to do that. onPageFinished() would probably work but
1941     * it isn't implemented yet.
1942     */
1943    private void sendOrientationChangeEvent() {
1944        if (mNativeContentViewCore == 0) return;
1945 
1946        WindowManager windowManager =
1947                (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
1948        switch (windowManager.getDefaultDisplay().getRotation()) {
1949            case Surface.ROTATION_90:
1950                nativeSendOrientationChangeEvent(mNativeContentViewCore, 90);
1951                break;
1952            case Surface.ROTATION_180:
1953                nativeSendOrientationChangeEvent(mNativeContentViewCore, 180);
1954                break;
1955            case Surface.ROTATION_270:
1956                nativeSendOrientationChangeEvent(mNativeContentViewCore, -90);
1957                break;
1958            case Surface.ROTATION_0:
1959                nativeSendOrientationChangeEvent(mNativeContentViewCore, 0);
1960                break;
1961            default:
1962                Log.w(TAG, "Unknown rotation!");
1963                break;
1964        }
1965    }
1966 
1967    /**
1968     * Register the delegate to be used when content can not be handled by
1969     * the rendering engine, and should be downloaded instead. This will replace
1970     * the current delegate, if any.
1971     * @param delegate An implementation of ContentViewDownloadDelegate.
1972     */
1973    public void setDownloadDelegate(ContentViewDownloadDelegate delegate) {
1974        mDownloadDelegate = delegate;
1975    }
1976 
1977    // Called by DownloadController.
1978    ContentViewDownloadDelegate getDownloadDelegate() {
1979        return mDownloadDelegate;
1980    }
1981 
1982    private SelectionHandleController getSelectionHandleController() {
1983        if (mSelectionHandleController == null) {
1984            mSelectionHandleController = new SelectionHandleController(getContainerView()) {
1985                @Override
1986                public void selectBetweenCoordinates(int x1, int y1, int x2, int y2) {
1987                    if (mNativeContentViewCore != 0 && !(x1 == x2 && y1 == y2)) {
1988                        nativeSelectBetweenCoordinates(mNativeContentViewCore,
1989                                x1, y1 - mRenderCoordinates.getContentOffsetYPix(),
1990                                x2, y2 - mRenderCoordinates.getContentOffsetYPix());
1991                    }
1992                }
1993 
1994                @Override
1995                public void showHandles(int startDir, int endDir) {
1996                    super.showHandles(startDir, endDir);
1997                    showSelectActionBar();
1998                }
1999 
2000            };
2001 
2002            mSelectionHandleController.hideAndDisallowAutomaticShowing();
2003        }
2004 
2005        return mSelectionHandleController;
2006    }
2007 
2008    private InsertionHandleController getInsertionHandleController() {
2009        if (mInsertionHandleController == null) {
2010            mInsertionHandleController = new InsertionHandleController(getContainerView()) {
2011                private static final int AVERAGE_LINE_HEIGHT = 14;
2012 
2013                @Override
2014                public void setCursorPosition(int x, int y) {
2015                    if (mNativeContentViewCore != 0) {
2016                        nativeMoveCaret(mNativeContentViewCore,
2017                                x, y - mRenderCoordinates.getContentOffsetYPix());
2018                    }
2019                }
2020 
2021                @Override
2022                public void paste() {
2023                    mImeAdapter.paste();
2024                    hideHandles();
2025                }
2026 
2027                @Override
2028                public int getLineHeight() {
2029                    return (int) Math.ceil(
2030                            mRenderCoordinates.fromLocalCssToPix(AVERAGE_LINE_HEIGHT));
2031                }
2032 
2033                @Override
2034                public void showHandle() {
2035                    super.showHandle();
2036                }
2037            };
2038 
2039            mInsertionHandleController.hideAndDisallowAutomaticShowing();
2040        }
2041 
2042        return mInsertionHandleController;
2043    }
2044 
2045    @VisibleForTesting
2046    public InsertionHandleController getInsertionHandleControllerForTest() {
2047        return mInsertionHandleController;
2048    }
2049 
2050    @VisibleForTesting
2051    public SelectionHandleController getSelectionHandleControllerForTest() {
2052        return mSelectionHandleController;
2053    }
2054 
2055    private void updateHandleScreenPositions() {
2056        if (isSelectionHandleShowing()) {
2057            mSelectionHandleController.setStartHandlePosition(
2058                    mStartHandlePoint.getXPix(), mStartHandlePoint.getYPix());
2059            mSelectionHandleController.setEndHandlePosition(
2060                    mEndHandlePoint.getXPix(), mEndHandlePoint.getYPix());
2061        }
2062 
2063        if (isInsertionHandleShowing()) {
2064            mInsertionHandleController.setHandlePosition(
2065                    mInsertionHandlePoint.getXPix(), mInsertionHandlePoint.getYPix());
2066        }
2067    }
2068 
2069    private void hideHandles() {
2070        if (mSelectionHandleController != null) {
2071            mSelectionHandleController.hideAndDisallowAutomaticShowing();
2072        }
2073        if (mInsertionHandleController != null) {
2074            mInsertionHandleController.hideAndDisallowAutomaticShowing();
2075        }
2076    }
2077 
2078    private void showSelectActionBar() {
2079        if (mActionMode != null) {
2080            mActionMode.invalidate();
2081            return;
2082        }
2083 
2084        // Start a new action mode with a SelectActionModeCallback.
2085        SelectActionModeCallback.ActionHandler actionHandler =
2086                new SelectActionModeCallback.ActionHandler() {
2087            @Override
2088            public boolean selectAll() {
2089                return mImeAdapter.selectAll();
2090            }
2091 
2092            @Override
2093            public boolean cut() {
2094                return mImeAdapter.cut();
2095            }
2096 
2097            @Override
2098            public boolean copy() {
2099                return mImeAdapter.copy();
2100            }
2101 
2102            @Override
2103            public boolean paste() {
2104                return mImeAdapter.paste();
2105            }
2106 
2107            @Override
2108            public boolean isSelectionEditable() {
2109                return mSelectionEditable;
2110            }
2111 
2112            @Override
2113            public String getSelectedText() {
2114                return ContentViewCore.this.getSelectedText();
2115            }
2116 
2117            @Override
2118            public void onDestroyActionMode() {
2119                mActionMode = null;
2120                if (mUnselectAllOnActionModeDismiss) mImeAdapter.unselect();
2121                getContentViewClient().onContextualActionBarHidden();
2122            }
2123        };
2124        mActionMode = null;
2125        // On ICS, startActionMode throws an NPE when getParent() is null.
2126        if (mContainerView.getParent() != null) {
2127            mActionMode = mContainerView.startActionMode(
2128                    getContentViewClient().getSelectActionModeCallback(getContext(), actionHandler,
2129                            nativeIsIncognito(mNativeContentViewCore)));
2130        }
2131        mUnselectAllOnActionModeDismiss = true;
2132        if (mActionMode == null) {
2133            // There is no ActionMode, so remove the selection.
2134            mImeAdapter.unselect();
2135        } else {
2136            getContentViewClient().onContextualActionBarShown();
2137        }
2138    }
2139 
2140    public boolean getUseDesktopUserAgent() {
2141        if (mNativeContentViewCore != 0) {
2142            return nativeGetUseDesktopUserAgent(mNativeContentViewCore);
2143        }
2144        return false;
2145    }
2146 
2147    /**
2148     * Set whether or not we're using a desktop user agent for the currently loaded page.
2149     * @param override If true, use a desktop user agent.  Use a mobile one otherwise.
2150     * @param reloadOnChange Reload the page if the UA has changed.
2151     */
2152    public void setUseDesktopUserAgent(boolean override, boolean reloadOnChange) {
2153        if (mNativeContentViewCore != 0) {
2154            nativeSetUseDesktopUserAgent(mNativeContentViewCore, override, reloadOnChange);
2155        }
2156    }
2157 
2158    public void clearSslPreferences() {
2159        nativeClearSslPreferences(mNativeContentViewCore);
2160    }
2161 
2162    /**
2163     * @return Whether the native ContentView has crashed.
2164     */
2165    public boolean isCrashed() {
2166        if (mNativeContentViewCore == 0) return false;
2167        return nativeCrashed(mNativeContentViewCore);
2168    }
2169 
2170    private boolean isSelectionHandleShowing() {
2171        return mSelectionHandleController != null && mSelectionHandleController.isShowing();
2172    }
2173 
2174    private boolean isInsertionHandleShowing() {
2175        return mInsertionHandleController != null && mInsertionHandleController.isShowing();
2176    }
2177 
2178    private void updateTextHandlesForGesture(int type) {
2179        switch(type) {
2180            case ContentViewGestureHandler.GESTURE_DOUBLE_TAP:
2181            case ContentViewGestureHandler.GESTURE_SCROLL_START:
2182            case ContentViewGestureHandler.GESTURE_FLING_START:
2183            case ContentViewGestureHandler.GESTURE_PINCH_BEGIN:
2184                temporarilyHideTextHandles();
2185                break;
2186 
2187            default:
2188                break;
2189        }
2190    }
2191 
2192    // Makes the insertion/selection handles invisible. They will fade back in shortly after the
2193    // last call to scheduleTextHandleFadeIn (or temporarilyHideTextHandles).
2194    private void temporarilyHideTextHandles() {
2195        if (isSelectionHandleShowing()) {
2196            mSelectionHandleController.setHandleVisibility(HandleView.INVISIBLE);
2197        }
2198        if (isInsertionHandleShowing()) {
2199            mInsertionHandleController.setHandleVisibility(HandleView.INVISIBLE);
2200        }
2201        scheduleTextHandleFadeIn();
2202    }
2203 
2204    private boolean allowTextHandleFadeIn() {
2205        if (mContentViewGestureHandler.isNativeScrolling() ||
2206                mContentViewGestureHandler.isNativePinching()) {
2207            return false;
2208        }
2209 
2210        if (mPopupZoomer.isShowing()) return false;
2211 
2212        return true;
2213    }
2214 
2215    // Cancels any pending fade in and schedules a new one.
2216    private void scheduleTextHandleFadeIn() {
2217        if (!isInsertionHandleShowing() && !isSelectionHandleShowing()) return;
2218 
2219        if (mDeferredHandleFadeInRunnable == null) {
2220            mDeferredHandleFadeInRunnable = new Runnable() {
2221                @Override
2222                public void run() {
2223                    if (!allowTextHandleFadeIn()) {
2224                        // Delay fade in until it is allowed.
2225                        scheduleTextHandleFadeIn();
2226                    } else {
2227                        if (isSelectionHandleShowing()) {
2228                            mSelectionHandleController.beginHandleFadeIn();
2229                        }
2230                        if (isInsertionHandleShowing()) {
2231                            mInsertionHandleController.beginHandleFadeIn();
2232                        }
2233                    }
2234                }
2235            };
2236        }
2237 
2238        mContainerView.removeCallbacks(mDeferredHandleFadeInRunnable);
2239        mContainerView.postDelayed(mDeferredHandleFadeInRunnable, TEXT_HANDLE_FADE_IN_DELAY);
2240    }
2241 
2242    /**
2243     * Shows the IME if the focused widget could accept text input.
2244     */
2245    public void showImeIfNeeded() {
2246        if (mNativeContentViewCore != 0) nativeShowImeIfNeeded(mNativeContentViewCore);
2247    }
2248 
2249    public void setUpdateFrameInfoListener(UpdateFrameInfoListener updateFrameInfoListener) {
2250        mUpdateFrameInfoListener = updateFrameInfoListener;
2251    }
2252 
2253    @SuppressWarnings("unused")
2254    @CalledByNative
2255    private void updateFrameInfo(
2256            float scrollOffsetX, float scrollOffsetY,
2257            float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor,
2258            float contentWidth, float contentHeight,
2259            float viewportWidth, float viewportHeight,
2260            float controlsOffsetYCss, float contentOffsetYCss,
2261            float overdrawBottomHeightCss) {
2262        TraceEvent.instant("ContentViewCore:updateFrameInfo");
2263        // Adjust contentWidth/Height to be always at least as big as
2264        // the actual viewport (as set by onSizeChanged).
2265        contentWidth = Math.max(contentWidth,
2266                mRenderCoordinates.fromPixToLocalCss(mViewportWidthPix));
2267        contentHeight = Math.max(contentHeight,
2268                mRenderCoordinates.fromPixToLocalCss(mViewportHeightPix));
2269 
2270        final float contentOffsetYPix = mRenderCoordinates.fromDipToPix(contentOffsetYCss);
2271 
2272        final boolean contentSizeChanged =
2273                contentWidth != mRenderCoordinates.getContentWidthCss()
2274                || contentHeight != mRenderCoordinates.getContentHeightCss();
2275        final boolean scaleLimitsChanged =
2276                minPageScaleFactor != mRenderCoordinates.getMinPageScaleFactor()
2277                || maxPageScaleFactor != mRenderCoordinates.getMaxPageScaleFactor();
2278        final boolean pageScaleChanged =
2279                pageScaleFactor != mRenderCoordinates.getPageScaleFactor();
2280        final boolean scrollChanged =
2281                pageScaleChanged
2282                || scrollOffsetX != mRenderCoordinates.getScrollX()
2283                || scrollOffsetY != mRenderCoordinates.getScrollY();
2284        final boolean contentOffsetChanged =
2285                contentOffsetYPix != mRenderCoordinates.getContentOffsetYPix();
2286 
2287        final boolean needHidePopupZoomer = contentSizeChanged || scrollChanged;
2288        final boolean needUpdateZoomControls = scaleLimitsChanged || scrollChanged;
2289        final boolean needTemporarilyHideHandles = scrollChanged;
2290 
2291        if (needHidePopupZoomer) mPopupZoomer.hide(true);
2292 
2293        if (pageScaleChanged) {
2294            // This function should be called back from native as soon
2295            // as the scroll is applied to the backbuffer.  We should only
2296            // update mNativeScrollX/Y here for consistency.
2297            getContentViewClient().onScaleChanged(
2298                    mRenderCoordinates.getPageScaleFactor(), pageScaleFactor);
2299        }
2300 
2301        mRenderCoordinates.updateFrameInfo(
2302                scrollOffsetX, scrollOffsetY,
2303                contentWidth, contentHeight,
2304                viewportWidth, viewportHeight,
2305                pageScaleFactor, minPageScaleFactor, maxPageScaleFactor,
2306                contentOffsetYPix);
2307 
2308        if ((contentSizeChanged || pageScaleChanged) && mUpdateFrameInfoListener != null) {
2309            mUpdateFrameInfoListener.onFrameInfoUpdated(
2310                    contentWidth, contentHeight, pageScaleFactor);
2311        }
2312 
2313        if (needTemporarilyHideHandles) temporarilyHideTextHandles();
2314        if (needUpdateZoomControls) mZoomControlsDelegate.updateZoomControls();
2315        if (contentOffsetChanged) updateHandleScreenPositions();
2316 
2317        // Update offsets for fullscreen.
2318        final float deviceScale = mRenderCoordinates.getDeviceScaleFactor();
2319        final float controlsOffsetPix = controlsOffsetYCss * deviceScale;
2320        final float overdrawBottomHeightPix = overdrawBottomHeightCss * deviceScale;
2321        getContentViewClient().onOffsetsForFullscreenChanged(
2322                controlsOffsetPix, contentOffsetYPix, overdrawBottomHeightPix);
2323 
2324        mPendingRendererFrame = true;
2325        if (mBrowserAccessibilityManager != null) {
2326            mBrowserAccessibilityManager.notifyFrameInfoInitialized();
2327        }
2328 
2329        // Update geometry for external video surface.
2330        getContentViewClient().onGeometryChanged(-1, null);
2331    }
2332 
2333    @SuppressWarnings("unused")
2334    @CalledByNative
2335    private void updateImeAdapter(int nativeImeAdapterAndroid, int textInputType,
2336            String text, int selectionStart, int selectionEnd,
2337            int compositionStart, int compositionEnd, boolean showImeIfNeeded) {
2338        TraceEvent.begin();
2339        mSelectionEditable = (textInputType != ImeAdapter.getTextInputTypeNone());
2340 
2341        if (mActionMode != null) mActionMode.invalidate();
2342 
2343        mImeAdapter.attachAndShowIfNeeded(nativeImeAdapterAndroid, textInputType,
2344                selectionStart, selectionEnd, showImeIfNeeded);
2345 
2346        if (mInputConnection != null) {
2347            mInputConnection.setEditableText(text, selectionStart, selectionEnd,
2348                    compositionStart, compositionEnd);
2349        }
2350        TraceEvent.end();
2351    }
2352 
2353    @SuppressWarnings("unused")
2354    @CalledByNative
2355    private void processImeBatchStateAck(boolean isBegin) {
2356        if (mInputConnection == null) return;
2357        mInputConnection.setIgnoreTextInputStateUpdates(isBegin);
2358    }
2359 
2360    @SuppressWarnings("unused")
2361    @CalledByNative
2362    private void setTitle(String title) {
2363        getContentViewClient().onUpdateTitle(title);
2364    }
2365 
2366    /**
2367     * Called (from native) when the <select> popup needs to be shown.
2368     * @param items           Items to show.
2369     * @param enabled         POPUP_ITEM_TYPEs for items.
2370     * @param multiple        Whether the popup menu should support multi-select.
2371     * @param selectedIndices Indices of selected items.
2372     */
2373    @SuppressWarnings("unused")
2374    @CalledByNative
2375    private void showSelectPopup(String[] items, int[] enabled, boolean multiple,
2376            int[] selectedIndices) {
2377        SelectPopupDialog.show(this, items, enabled, multiple, selectedIndices);
2378    }
2379 
2380    @SuppressWarnings("unused")
2381    @CalledByNative
2382    private void showDisambiguationPopup(Rect targetRect, Bitmap zoomedBitmap) {
2383        mPopupZoomer.setBitmap(zoomedBitmap);
2384        mPopupZoomer.show(targetRect);
2385        temporarilyHideTextHandles();
2386    }
2387 
2388    @SuppressWarnings("unused")
2389    @CalledByNative
2390    private GenericTouchGesture createGenericTouchGesture(int startX,
2391            int startY, int deltaX, int deltaY) {
2392        return new GenericTouchGesture(this, startX, startY, deltaX, deltaY);
2393    }
2394 
2395    @SuppressWarnings("unused")
2396    @CalledByNative
2397    private void onSelectionChanged(String text) {
2398        mLastSelectedText = text;
2399    }
2400 
2401    @SuppressWarnings("unused")
2402    @CalledByNative
2403    private void onSelectionBoundsChanged(Rect anchorRectDip, int anchorDir, Rect focusRectDip,
2404            int focusDir, boolean isAnchorFirst) {
2405        // All coordinates are in DIP.
2406        int x1 = anchorRectDip.left;
2407        int y1 = anchorRectDip.bottom;
2408        int x2 = focusRectDip.left;
2409        int y2 = focusRectDip.bottom;
2410 
2411        if (x1 != x2 || y1 != y2 ||
2412                (mSelectionHandleController != null && mSelectionHandleController.isDragging())) {
2413            if (mInsertionHandleController != null) {
2414                mInsertionHandleController.hide();
2415            }
2416            if (isAnchorFirst) {
2417                mStartHandlePoint.setLocalDip(x1, y1);
2418                mEndHandlePoint.setLocalDip(x2, y2);
2419            } else {
2420                mStartHandlePoint.setLocalDip(x2, y2);
2421                mEndHandlePoint.setLocalDip(x1, y1);
2422            }
2423 
2424            getSelectionHandleController().onSelectionChanged(anchorDir, focusDir);
2425            updateHandleScreenPositions();
2426            mHasSelection = true;
2427        } else {
2428            mUnselectAllOnActionModeDismiss = false;
2429            hideSelectActionBar();
2430            if (x1 != 0 && y1 != 0 && mSelectionEditable) {
2431                // Selection is a caret, and a text field is focused.
2432                if (mSelectionHandleController != null) {
2433                    mSelectionHandleController.hide();
2434                }
2435                mInsertionHandlePoint.setLocalDip(x1, y1);
2436 
2437                getInsertionHandleController().onCursorPositionChanged();
2438                updateHandleScreenPositions();
2439                InputMethodManager manager = (InputMethodManager)
2440                        getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
2441                if (manager.isWatchingCursor(mContainerView)) {
2442                    final int xPix = (int) mInsertionHandlePoint.getXPix();
2443                    final int yPix = (int) mInsertionHandlePoint.getYPix();
2444                    manager.updateCursor(mContainerView, xPix, yPix, xPix, yPix);
2445                }
2446            } else {
2447                // Deselection
2448                if (mSelectionHandleController != null) {
2449                    mSelectionHandleController.hideAndDisallowAutomaticShowing();
2450                }
2451                if (mInsertionHandleController != null) {
2452                    mInsertionHandleController.hideAndDisallowAutomaticShowing();
2453                }
2454            }
2455            mHasSelection = false;
2456        }
2457    }
2458 
2459    @SuppressWarnings("unused")
2460    @CalledByNative
2461    private static void onEvaluateJavaScriptResult(
2462            String jsonResult, JavaScriptCallback callback) {
2463        callback.handleJavaScriptResult(jsonResult);
2464    }
2465 
2466    @SuppressWarnings("unused")
2467    @CalledByNative
2468    private void showPastePopup(int xDip, int yDip) {
2469        mInsertionHandlePoint.setLocalDip(xDip, yDip);
2470        getInsertionHandleController().showHandle();
2471        updateHandleScreenPositions();
2472        getInsertionHandleController().showHandleWithPastePopup();
2473    }
2474 
2475    @SuppressWarnings("unused")
2476    @CalledByNative
2477    private void onRenderProcessSwap(int oldPid, int newPid) {
2478        assert mPid == oldPid || mPid == newPid;
2479        if (mAttachedToWindow && oldPid != newPid) {
2480            ChildProcessLauncher.unbindAsHighPriority(oldPid);
2481            ChildProcessLauncher.bindAsHighPriority(newPid);
2482        }
2483 
2484        // We want to remove the initial binding even if the ContentView is not attached, so that
2485        // renderers for ContentViews loading in background do not retain the high priority.
2486        ChildProcessLauncher.removeInitialBinding(newPid);
2487        mPid = newPid;
2488    }
2489 
2490    @SuppressWarnings("unused")
2491    @CalledByNative
2492    private void onWebContentsConnected() {
2493        if (mImeAdapter != null &&
2494                !mImeAdapter.isNativeImeAdapterAttached() && mNativeContentViewCore != 0) {
2495            mImeAdapter.attach(nativeGetNativeImeAdapter(mNativeContentViewCore));
2496        }
2497    }
2498 
2499    @SuppressWarnings("unused")
2500    @CalledByNative
2501    private void onWebContentsSwapped() {
2502        if (mImeAdapter != null && mNativeContentViewCore != 0) {
2503            mImeAdapter.attach(nativeGetNativeImeAdapter(mNativeContentViewCore));
2504        }
2505    }
2506 
2507    /**
2508     * @return Whether a reload happens when this ContentView is activated.
2509     */
2510    public boolean needsReload() {
2511        return mNativeContentViewCore != 0 && nativeNeedsReload(mNativeContentViewCore);
2512    }
2513 
2514    /**
2515     * @see View#hasFocus()
2516     */
2517    @CalledByNative
2518    public boolean hasFocus() {
2519        return mContainerView.hasFocus();
2520    }
2521 
2522    /**
2523     * Checks whether the ContentViewCore can be zoomed in.
2524     *
2525     * @return True if the ContentViewCore can be zoomed in.
2526     */
2527    // This method uses the term 'zoom' for legacy reasons, but relates
2528    // to what chrome calls the 'page scale factor'.
2529    public boolean canZoomIn() {
2530        final float zoomInExtent = mRenderCoordinates.getMaxPageScaleFactor()
2531                - mRenderCoordinates.getPageScaleFactor();
2532        return zoomInExtent > ZOOM_CONTROLS_EPSILON;
2533    }
2534 
2535    /**
2536     * Checks whether the ContentViewCore can be zoomed out.
2537     *
2538     * @return True if the ContentViewCore can be zoomed out.
2539     */
2540    // This method uses the term 'zoom' for legacy reasons, but relates
2541    // to what chrome calls the 'page scale factor'.
2542    public boolean canZoomOut() {
2543        final float zoomOutExtent = mRenderCoordinates.getPageScaleFactor()
2544                - mRenderCoordinates.getMinPageScaleFactor();
2545        return zoomOutExtent > ZOOM_CONTROLS_EPSILON;
2546    }
2547 
2548    /**
2549     * Zooms in the ContentViewCore by 25% (or less if that would result in
2550     * zooming in more than possible).
2551     *
2552     * @return True if there was a zoom change, false otherwise.
2553     */
2554    // This method uses the term 'zoom' for legacy reasons, but relates
2555    // to what chrome calls the 'page scale factor'.
2556    public boolean zoomIn() {
2557        if (!canZoomIn()) {
2558            return false;
2559        }
2560        return zoomByDelta(1.25f);
2561    }
2562 
2563    /**
2564     * Zooms out the ContentViewCore by 20% (or less if that would result in
2565     * zooming out more than possible).
2566     *
2567     * @return True if there was a zoom change, false otherwise.
2568     */
2569    // This method uses the term 'zoom' for legacy reasons, but relates
2570    // to what chrome calls the 'page scale factor'.
2571    public boolean zoomOut() {
2572        if (!canZoomOut()) {
2573            return false;
2574        }
2575        return zoomByDelta(0.8f);
2576    }
2577 
2578    /**
2579     * Resets the zoom factor of the ContentViewCore.
2580     *
2581     * @return True if there was a zoom change, false otherwise.
2582     */
2583    // This method uses the term 'zoom' for legacy reasons, but relates
2584    // to what chrome calls the 'page scale factor'.
2585    public boolean zoomReset() {
2586        // The page scale factor is initialized to mNativeMinimumScale when
2587        // the page finishes loading. Thus sets it back to mNativeMinimumScale.
2588        if (!canZoomOut()) return false;
2589        return zoomByDelta(
2590                mRenderCoordinates.getMinPageScaleFactor()
2591                        / mRenderCoordinates.getPageScaleFactor());
2592    }
2593 
2594    private boolean zoomByDelta(float delta) {
2595        if (mNativeContentViewCore == 0) {
2596            return false;
2597        }
2598 
2599        long timeMs = System.currentTimeMillis();
2600        int xPix = getViewportWidthPix() / 2;
2601        int yPix = getViewportHeightPix() / 2;
2602 
2603        getContentViewGestureHandler().pinchBegin(timeMs, xPix, yPix);
2604        getContentViewGestureHandler().pinchBy(timeMs, xPix, yPix, delta);
2605        getContentViewGestureHandler().pinchEnd(timeMs);
2606 
2607        return true;
2608    }
2609 
2610    /**
2611     * Invokes the graphical zoom picker widget for this ContentView.
2612     */
2613    @Override
2614    public void invokeZoomPicker() {
2615        mZoomControlsDelegate.invokeZoomPicker();
2616    }
2617 
2618    /**
2619     * This will mimic {@link #addPossiblyUnsafeJavascriptInterface(Object, String, Class)}
2620     * and automatically pass in {@link JavascriptInterface} as the required annotation.
2621     *
2622     * @param object The Java object to inject into the ContentViewCore's JavaScript context.  Null
2623     *               values are ignored.
2624     * @param name   The name used to expose the instance in JavaScript.
2625     */
2626    public void addJavascriptInterface(Object object, String name) {
2627        addPossiblyUnsafeJavascriptInterface(object, name, JavascriptInterface.class);
2628    }
2629 
2630    /**
2631     * This method injects the supplied Java object into the ContentViewCore.
2632     * The object is injected into the JavaScript context of the main frame,
2633     * using the supplied name. This allows the Java object to be accessed from
2634     * JavaScript. Note that that injected objects will not appear in
2635     * JavaScript until the page is next (re)loaded. For example:
2636     * <pre> view.addJavascriptInterface(new Object(), "injectedObject");
2637     * view.loadData("<!DOCTYPE html><title></title>", "text/html", null);
2638     * view.loadUrl("javascript:alert(injectedObject.toString())");</pre>
2639     * <p><strong>IMPORTANT:</strong>
2640     * <ul>
2641     * <li> addJavascriptInterface() can be used to allow JavaScript to control
2642     * the host application. This is a powerful feature, but also presents a
2643     * security risk. Use of this method in a ContentViewCore containing
2644     * untrusted content could allow an attacker to manipulate the host
2645     * application in unintended ways, executing Java code with the permissions
2646     * of the host application. Use extreme care when using this method in a
2647     * ContentViewCore which could contain untrusted content. Particular care
2648     * should be taken to avoid unintentional access to inherited methods, such
2649     * as {@link Object#getClass()}. To prevent access to inherited methods,
2650     * pass an annotation for {@code requiredAnnotation}.  This will ensure
2651     * that only methods with {@code requiredAnnotation} are exposed to the
2652     * Javascript layer.  {@code requiredAnnotation} will be passed to all
2653     * subsequently injected Java objects if any methods return an object.  This
2654     * means the same restrictions (or lack thereof) will apply.  Alternatively,
2655     * {@link #addJavascriptInterface(Object, String)} can be called, which
2656     * automatically uses the {@link JavascriptInterface} annotation.
2657     * <li> JavaScript interacts with Java objects on a private, background
2658     * thread of the ContentViewCore. Care is therefore required to maintain
2659     * thread safety.</li>
2660     * </ul></p>
2661     *
2662     * @param object             The Java object to inject into the
2663     *                           ContentViewCore's JavaScript context. Null
2664     *                           values are ignored.
2665     * @param name               The name used to expose the instance in
2666     *                           JavaScript.
2667     * @param requiredAnnotation Restrict exposed methods to ones with this
2668     *                           annotation.  If {@code null} all methods are
2669     *                           exposed.
2670     *
2671     */
2672    public void addPossiblyUnsafeJavascriptInterface(Object object, String name,
2673            Class<? extends Annotation> requiredAnnotation) {
2674        if (mNativeContentViewCore != 0 && object != null) {
2675            mJavaScriptInterfaces.put(name, object);
2676            nativeAddJavascriptInterface(mNativeContentViewCore, object, name, requiredAnnotation,
2677                    mRetainedJavaScriptObjects);
2678        }
2679    }
2680 
2681    /**
2682     * Removes a previously added JavaScript interface with the given name.
2683     *
2684     * @param name The name of the interface to remove.
2685     */
2686    public void removeJavascriptInterface(String name) {
2687        mJavaScriptInterfaces.remove(name);
2688        if (mNativeContentViewCore != 0) {
2689            nativeRemoveJavascriptInterface(mNativeContentViewCore, name);
2690        }
2691    }
2692 
2693    /**
2694     * Return the current scale of the ContentView.
2695     * @return The current page scale factor.
2696     */
2697    public float getScale() {
2698        return mRenderCoordinates.getPageScaleFactor();
2699    }
2700 
2701    /**
2702     * If the view is ready to draw contents to the screen. In hardware mode,
2703     * the initialization of the surface texture may not occur until after the
2704     * view has been added to the layout. This method will return {@code true}
2705     * once the texture is actually ready.
2706     */
2707    public boolean isReady() {
2708        return nativeIsRenderWidgetHostViewReady(mNativeContentViewCore);
2709    }
2710 
2711    @CalledByNative
2712    private void startContentIntent(String contentUrl) {
2713        getContentViewClient().onStartContentIntent(getContext(), contentUrl);
2714    }
2715 
2716    @Override
2717    public void onAccessibilityStateChanged(boolean enabled) {
2718        setAccessibilityState(enabled);
2719    }
2720 
2721    /**
2722     * Determines whether or not this ContentViewCore can handle this accessibility action.
2723     * @param action The action to perform.
2724     * @return Whether or not this action is supported.
2725     */
2726    public boolean supportsAccessibilityAction(int action) {
2727        return mAccessibilityInjector.supportsAccessibilityAction(action);
2728    }
2729 
2730    /**
2731     * Attempts to perform an accessibility action on the web content.  If the accessibility action
2732     * cannot be processed, it returns {@code null}, allowing the caller to know to call the
2733     * super {@link View#performAccessibilityAction(int, Bundle)} method and use that return value.
2734     * Otherwise the return value from this method should be used.
2735     * @param action The action to perform.
2736     * @param arguments Optional action arguments.
2737     * @return Whether the action was performed or {@code null} if the call should be delegated to
2738     *         the super {@link View} class.
2739     */
2740    public boolean performAccessibilityAction(int action, Bundle arguments) {
2741        if (mAccessibilityInjector.supportsAccessibilityAction(action)) {
2742            return mAccessibilityInjector.performAccessibilityAction(action, arguments);
2743        }
2744 
2745        return false;
2746    }
2747 
2748    /**
2749     * Set the BrowserAccessibilityManager, used for native accessibility
2750     * (not script injection). This is only set when system accessibility
2751     * has been enabled.
2752     * @param manager The new BrowserAccessibilityManager.
2753     */
2754    public void setBrowserAccessibilityManager(BrowserAccessibilityManager manager) {
2755        mBrowserAccessibilityManager = manager;
2756    }
2757 
2758    /**
2759     * Get the BrowserAccessibilityManager, used for native accessibility
2760     * (not script injection). This will return null when system accessibility
2761     * is not enabled.
2762     * @return This view's BrowserAccessibilityManager.
2763     */
2764    public BrowserAccessibilityManager getBrowserAccessibilityManager() {
2765        return mBrowserAccessibilityManager;
2766    }
2767 
2768    /**
2769     * If native accessibility (not script injection) is enabled, and if this is
2770     * running on JellyBean or later, returns an AccessibilityNodeProvider that
2771     * implements native accessibility for this view. Returns null otherwise.
2772     * @return The AccessibilityNodeProvider, if available, or null otherwise.
2773     */
2774    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
2775        if (mBrowserAccessibilityManager != null) {
2776            return mBrowserAccessibilityManager.getAccessibilityNodeProvider();
2777        } else {
2778            return null;
2779        }
2780    }
2781 
2782    /**
2783     * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
2784     */
2785    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
2786        // Note: this is only used by the script-injecting accessibility code.
2787        mAccessibilityInjector.onInitializeAccessibilityNodeInfo(info);
2788    }
2789 
2790    /**
2791     * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
2792     */
2793    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
2794        // Note: this is only used by the script-injecting accessibility code.
2795        event.setClassName(this.getClass().getName());
2796 
2797        // Identify where the top-left of the screen currently points to.
2798        event.setScrollX(mRenderCoordinates.getScrollXPixInt());
2799        event.setScrollY(mRenderCoordinates.getScrollYPixInt());
2800 
2801        // The maximum scroll values are determined by taking the content dimensions and
2802        // subtracting off the actual dimensions of the ChromeView.
2803        int maxScrollXPix = Math.max(0, mRenderCoordinates.getMaxHorizontalScrollPixInt());
2804        int maxScrollYPix = Math.max(0, mRenderCoordinates.getMaxVerticalScrollPixInt());
2805        event.setScrollable(maxScrollXPix > 0 || maxScrollYPix > 0);
2806 
2807        // Setting the maximum scroll values requires API level 15 or higher.
2808        final int SDK_VERSION_REQUIRED_TO_SET_SCROLL = 15;
2809        if (Build.VERSION.SDK_INT >= SDK_VERSION_REQUIRED_TO_SET_SCROLL) {
2810            event.setMaxScrollX(maxScrollXPix);
2811            event.setMaxScrollY(maxScrollYPix);
2812        }
2813    }
2814 
2815    /**
2816     * Returns whether accessibility script injection is enabled on the device
2817     */
2818    public boolean isDeviceAccessibilityScriptInjectionEnabled() {
2819        try {
2820            if (!mContentSettings.getJavaScriptEnabled()) {
2821                return false;
2822            }
2823 
2824            int result = getContext().checkCallingOrSelfPermission(
2825                    android.Manifest.permission.INTERNET);
2826            if (result != PackageManager.PERMISSION_GRANTED) {
2827                return false;
2828            }
2829 
2830            Field field = Settings.Secure.class.getField("ACCESSIBILITY_SCRIPT_INJECTION");
2831            field.setAccessible(true);
2832            String accessibilityScriptInjection = (String) field.get(null);
2833            ContentResolver contentResolver = getContext().getContentResolver();
2834 
2835            if (mAccessibilityScriptInjectionObserver == null) {
2836                ContentObserver contentObserver = new ContentObserver(new Handler()) {
2837                    public void onChange(boolean selfChange, Uri uri) {
2838                        setAccessibilityState(mAccessibilityManager.isEnabled());
2839                    }
2840                };
2841                contentResolver.registerContentObserver(
2842                    Settings.Secure.getUriFor(accessibilityScriptInjection),
2843                    false,
2844                    contentObserver);
2845                mAccessibilityScriptInjectionObserver = contentObserver;
2846            }
2847 
2848            return Settings.Secure.getInt(contentResolver, accessibilityScriptInjection, 0) == 1;
2849        } catch (NoSuchFieldException e) {
2850        } catch (IllegalAccessException e) {
2851        }
2852        return false;
2853    }
2854 
2855    /**
2856     * Returns whether or not accessibility injection is being used.
2857     */
2858    public boolean isInjectingAccessibilityScript() {
2859        return mAccessibilityInjector.accessibilityIsAvailable();
2860    }
2861 
2862    /**
2863     * Turns browser accessibility on or off.
2864     * If |state| is |false|, this turns off both native and injected accessibility.
2865     * Otherwise, if accessibility script injection is enabled, this will enable the injected
2866     * accessibility scripts, and if it is disabled this will enable the native accessibility.
2867     */
2868    public void setAccessibilityState(boolean state) {
2869        boolean injectedAccessibility = false;
2870        boolean nativeAccessibility = false;
2871        if (state) {
2872            if (isDeviceAccessibilityScriptInjectionEnabled()) {
2873                injectedAccessibility = true;
2874            } else {
2875                nativeAccessibility = true;
2876            }
2877        }
2878        setInjectedAccessibility(injectedAccessibility);
2879        setNativeAccessibilityState(nativeAccessibility);
2880    }
2881 
2882    /**
2883     * Enable or disable native accessibility features.
2884     */
2885    public void setNativeAccessibilityState(boolean enabled) {
2886        if (mNativeContentViewCore == 0) return;
2887        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
2888            nativeSetAccessibilityEnabled(mNativeContentViewCore, enabled);
2889        }
2890    }
2891 
2892    /**
2893     * Enable or disable injected accessibility features
2894     */
2895    public void setInjectedAccessibility(boolean enabled) {
2896        mAccessibilityInjector.addOrRemoveAccessibilityApisIfNecessary();
2897        mAccessibilityInjector.setScriptEnabled(enabled);
2898    }
2899 
2900    /**
2901     * Stop any TTS notifications that are currently going on.
2902     */
2903    public void stopCurrentAccessibilityNotifications() {
2904        mAccessibilityInjector.onPageLostFocus();
2905    }
2906 
2907    /**
2908     * Inform WebKit that Fullscreen mode has been exited by the user.
2909     */
2910    public void exitFullscreen() {
2911        nativeExitFullscreen(mNativeContentViewCore);
2912    }
2913 
2914    /**
2915     * Changes whether hiding the top controls is enabled.
2916     *
2917     * @param enableHiding Whether hiding the top controls should be enabled or not.
2918     * @param enableShowing Whether showing the top controls should be enabled or not.
2919     * @param animate Whether the transition should be animated or not.
2920     */
2921    public void updateTopControlsState(boolean enableHiding, boolean enableShowing,
2922            boolean animate) {
2923        nativeUpdateTopControlsState(mNativeContentViewCore, enableHiding, enableShowing, animate);
2924    }
2925 
2926    /**
2927     * Callback factory method for nativeGetNavigationHistory().
2928     */
2929    @CalledByNative
2930    private void addToNavigationHistory(Object history, int index, String url, String virtualUrl,
2931            String originalUrl, String title, Bitmap favicon) {
2932        NavigationEntry entry = new NavigationEntry(
2933                index, url, virtualUrl, originalUrl, title, favicon);
2934        ((NavigationHistory) history).addEntry(entry);
2935    }
2936 
2937    /**
2938     * Get a copy of the navigation history of the view.
2939     */
2940    public NavigationHistory getNavigationHistory() {
2941        NavigationHistory history = new NavigationHistory();
2942        int currentIndex = nativeGetNavigationHistory(mNativeContentViewCore, history);
2943        history.setCurrentEntryIndex(currentIndex);
2944        return history;
2945    }
2946 
2947    @Override
2948    public NavigationHistory getDirectedNavigationHistory(boolean isForward, int itemLimit) {
2949        NavigationHistory history = new NavigationHistory();
2950        nativeGetDirectedNavigationHistory(mNativeContentViewCore, history, isForward, itemLimit);
2951        return history;
2952    }
2953 
2954    /**
2955     * @return The original request URL for the current navigation entry, or null if there is no
2956     *         current entry.
2957     */
2958    public String getOriginalUrlForActiveNavigationEntry() {
2959        return nativeGetOriginalUrlForActiveNavigationEntry(mNativeContentViewCore);
2960    }
2961 
2962    /**
2963     * @return The cached copy of render positions and scales.
2964     */
2965    public RenderCoordinates getRenderCoordinates() {
2966        return mRenderCoordinates;
2967    }
2968 
2969    @CalledByNative
2970    private static Rect createRect(int x, int y, int right, int bottom) {
2971        return new Rect(x, y, right, bottom);
2972    }
2973 
2974    public void attachExternalVideoSurface(int playerId, Surface surface) {
2975        if (mNativeContentViewCore != 0) {
2976            nativeAttachExternalVideoSurface(mNativeContentViewCore, playerId, surface);
2977        }
2978    }
2979 
2980    public void detachExternalVideoSurface(int playerId) {
2981        if (mNativeContentViewCore != 0) {
2982            nativeDetachExternalVideoSurface(mNativeContentViewCore, playerId);
2983        }
2984    }
2985 
2986    private boolean onAnimate(long frameTimeMicros) {
2987        if (mNativeContentViewCore == 0) return false;
2988        return nativeOnAnimate(mNativeContentViewCore, frameTimeMicros);
2989    }
2990 
2991    private void animateIfNecessary(long frameTimeMicros) {
2992        if (mNeedAnimate) {
2993            mNeedAnimate = onAnimate(frameTimeMicros);
2994            if (!mNeedAnimate) setVSyncNotificationEnabled(false);
2995        }
2996    }
2997 
2998    @CalledByNative
2999    private void notifyExternalSurface(
3000            int playerId, boolean isRequest, float x, float y, float width, float height) {
3001        if (isRequest) getContentViewClient().onExternalVideoSurfaceRequested(playerId);
3002        getContentViewClient().onGeometryChanged(playerId, new RectF(x, y, x + width, y + height));
3003    }
3004 
3005    /**
3006     * Offer a subset of gesture events to the embedding View,
3007     * primarily for WebView compatibility.
3008     *
3009     * @param type The type of the event.
3010     *
3011     * @return true if the embedder handled the event.
3012     */
3013    private boolean offerGestureToEmbedder(int type) {
3014        if (type == ContentViewGestureHandler.GESTURE_LONG_PRESS) {
3015            return mContainerView.performLongClick();
3016        }
3017        return false;
3018    }
3019 
3020    private native int nativeInit(boolean hardwareAccelerated, int webContentsPtr,
3021            int viewAndroidPtr, int windowAndroidPtr);
3022 
3023    @CalledByNative
3024    private ContentVideoViewClient getContentVideoViewClient() {
3025        return mContentViewClient.getContentVideoViewClient();
3026    }
3027 
3028    private native void nativeOnJavaContentViewCoreDestroyed(int nativeContentViewCoreImpl);
3029 
3030    private native void nativeLoadUrl(
3031            int nativeContentViewCoreImpl,
3032            String url,
3033            int loadUrlType,
3034            int transitionType,
3035            int uaOverrideOption,
3036            String extraHeaders,
3037            byte[] postData,
3038            String baseUrlForDataUrl,
3039            String virtualUrlForDataUrl,
3040            boolean canLoadLocalResources);
3041 
3042    private native String nativeGetURL(int nativeContentViewCoreImpl);
3043 
3044    private native String nativeGetTitle(int nativeContentViewCoreImpl);
3045 
3046    private native void nativeShowInterstitialPage(
3047            int nativeContentViewCoreImpl, String url, int nativeInterstitialPageDelegateAndroid);
3048    private native boolean nativeIsShowingInterstitialPage(int nativeContentViewCoreImpl);
3049 
3050    private native boolean nativeIsIncognito(int nativeContentViewCoreImpl);
3051 
3052    // Returns true if the native side crashed so that java side can draw a sad tab.
3053    private native boolean nativeCrashed(int nativeContentViewCoreImpl);
3054 
3055    private native void nativeSetFocus(int nativeContentViewCoreImpl, boolean focused);
3056 
3057    private native void nativeSendOrientationChangeEvent(
3058            int nativeContentViewCoreImpl, int orientation);
3059 
3060    // All touch events (including flings, scrolls etc) accept coordinates in physical pixels.
3061    private native boolean nativeSendTouchEvent(
3062            int nativeContentViewCoreImpl, long timeMs, int action, TouchPoint[] pts);
3063 
3064    private native int nativeSendMouseMoveEvent(
3065            int nativeContentViewCoreImpl, long timeMs, float x, float y);
3066 
3067    private native int nativeSendMouseWheelEvent(
3068            int nativeContentViewCoreImpl, long timeMs, float x, float y, float verticalAxis);
3069 
3070    private native void nativeScrollBegin(
3071            int nativeContentViewCoreImpl, long timeMs, float x, float y);
3072 
3073    private native void nativeScrollEnd(int nativeContentViewCoreImpl, long timeMs);
3074 
3075    private native void nativeScrollBy(
3076            int nativeContentViewCoreImpl, long timeMs, float x, float y,
3077            float deltaX, float deltaY, boolean lastInputEventForVSync);
3078 
3079    private native void nativeFlingStart(
3080            int nativeContentViewCoreImpl, long timeMs, float x, float y, float vx, float vy);
3081 
3082    private native void nativeFlingCancel(int nativeContentViewCoreImpl, long timeMs);
3083 
3084    private native void nativeSingleTap(
3085            int nativeContentViewCoreImpl, long timeMs, float x, float y, boolean linkPreviewTap);
3086 
3087    private native void nativeSingleTapUnconfirmed(
3088            int nativeContentViewCoreImpl, long timeMs, float x, float y);
3089 
3090    private native void nativeShowPressState(
3091            int nativeContentViewCoreImpl, long timeMs, float x, float y);
3092 
3093    private native void nativeShowPressCancel(
3094            int nativeContentViewCoreImpl, long timeMs, float x, float y);
3095 
3096    private native void nativeDoubleTap(
3097            int nativeContentViewCoreImpl, long timeMs, float x, float y);
3098 
3099    private native void nativeLongPress(
3100            int nativeContentViewCoreImpl, long timeMs, float x, float y, boolean linkPreviewTap);
3101 
3102    private native void nativeLongTap(
3103            int nativeContentViewCoreImpl, long timeMs, float x, float y, boolean linkPreviewTap);
3104 
3105    private native void nativePinchBegin(
3106            int nativeContentViewCoreImpl, long timeMs, float x, float y);
3107 
3108    private native void nativePinchEnd(int nativeContentViewCoreImpl, long timeMs);
3109 
3110    private native void nativePinchBy(int nativeContentViewCoreImpl, long timeMs,
3111            float anchorX, float anchorY, float deltaScale, boolean lastInputEventForVSync);
3112 
3113    private native void nativeSelectBetweenCoordinates(
3114            int nativeContentViewCoreImpl, float x1, float y1, float x2, float y2);
3115 
3116    private native void nativeMoveCaret(int nativeContentViewCoreImpl, float x, float y);
3117 
3118    private native boolean nativeCanGoBack(int nativeContentViewCoreImpl);
3119    private native boolean nativeCanGoForward(int nativeContentViewCoreImpl);
3120    private native boolean nativeCanGoToOffset(int nativeContentViewCoreImpl, int offset);
3121    private native void nativeGoBack(int nativeContentViewCoreImpl);
3122    private native void nativeGoForward(int nativeContentViewCoreImpl);
3123    private native void nativeGoToOffset(int nativeContentViewCoreImpl, int offset);
3124    private native void nativeGoToNavigationIndex(int nativeContentViewCoreImpl, int index);
3125 
3126    private native void nativeStopLoading(int nativeContentViewCoreImpl);
3127 
3128    private native void nativeReload(int nativeContentViewCoreImpl);
3129 
3130    private native void nativeCancelPendingReload(int nativeContentViewCoreImpl);
3131 
3132    private native void nativeContinuePendingReload(int nativeContentViewCoreImpl);
3133 
3134    private native void nativeSelectPopupMenuItems(int nativeContentViewCoreImpl, int[] indices);
3135 
3136    private native void nativeScrollFocusedEditableNodeIntoView(int nativeContentViewCoreImpl);
3137    private native void nativeUndoScrollFocusedEditableNodeIntoView(int nativeContentViewCoreImpl);
3138    private native boolean nativeNeedsReload(int nativeContentViewCoreImpl);
3139 
3140    private native void nativeClearHistory(int nativeContentViewCoreImpl);
3141 
3142    private native void nativeEvaluateJavaScript(int nativeContentViewCoreImpl,
3143            String script, JavaScriptCallback callback, boolean startRenderer);
3144 
3145    private native int nativeGetNativeImeAdapter(int nativeContentViewCoreImpl);
3146 
3147    private native int nativeGetCurrentRenderProcessId(int nativeContentViewCoreImpl);
3148 
3149    private native int nativeGetBackgroundColor(int nativeContentViewCoreImpl);
3150 
3151    private native void nativeOnShow(int nativeContentViewCoreImpl);
3152    private native void nativeOnHide(int nativeContentViewCoreImpl);
3153 
3154    private native void nativeSetUseDesktopUserAgent(int nativeContentViewCoreImpl,
3155            boolean enabled, boolean reloadOnChange);
3156    private native boolean nativeGetUseDesktopUserAgent(int nativeContentViewCoreImpl);
3157 
3158    private native void nativeClearSslPreferences(int nativeContentViewCoreImpl);
3159 
3160    private native void nativeAddJavascriptInterface(int nativeContentViewCoreImpl, Object object,
3161            String name, Class requiredAnnotation, HashSet<Object> retainedObjectSet);
3162 
3163    private native void nativeRemoveJavascriptInterface(int nativeContentViewCoreImpl, String name);
3164 
3165    private native int nativeGetNavigationHistory(int nativeContentViewCoreImpl, Object context);
3166    private native void nativeGetDirectedNavigationHistory(int nativeContentViewCoreImpl,
3167            Object context, boolean isForward, int maxEntries);
3168    private native String nativeGetOriginalUrlForActiveNavigationEntry(
3169            int nativeContentViewCoreImpl);
3170 
3171    private native void nativeUpdateVSyncParameters(int nativeContentViewCoreImpl,
3172            long timebaseMicros, long intervalMicros);
3173 
3174    private native void nativeOnVSync(int nativeContentViewCoreImpl, long frameTimeMicros);
3175 
3176    private native boolean nativeOnAnimate(int nativeContentViewCoreImpl, long frameTimeMicros);
3177 
3178    private native boolean nativePopulateBitmapFromCompositor(int nativeContentViewCoreImpl,
3179            Bitmap bitmap);
3180 
3181    private native void nativeWasResized(int nativeContentViewCoreImpl);
3182 
3183    private native boolean nativeIsRenderWidgetHostViewReady(int nativeContentViewCoreImpl);
3184 
3185    private native void nativeExitFullscreen(int nativeContentViewCoreImpl);
3186    private native void nativeUpdateTopControlsState(int nativeContentViewCoreImpl,
3187            boolean enableHiding, boolean enableShowing, boolean animate);
3188 
3189    private native void nativeShowImeIfNeeded(int nativeContentViewCoreImpl);
3190 
3191    private native void nativeAttachExternalVideoSurface(
3192            int nativeContentViewCoreImpl, int playerId, Surface surface);
3193 
3194    private native void nativeDetachExternalVideoSurface(
3195            int nativeContentViewCoreImpl, int playerId);
3196 
3197    private native void nativeSetAccessibilityEnabled(
3198            int nativeContentViewCoreImpl, boolean enabled);
3199}

[all classes][org.chromium.content.browser]
EMMA 2.0.5312 (C) Vladimir Roubtsov