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