ContentViewCore.java revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
1a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org// Copyright 2012 The Chromium Authors. All rights reserved. 2a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org// Use of this source code is governed by a BSD-style license that can be 3a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org// found in the LICENSE file. 4a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org 5a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgpackage org.chromium.content.browser; 6a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org 7a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport android.app.Activity; 8a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport android.app.SearchManager; 9a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport android.content.ContentResolver; 10a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport android.content.Context; 11a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport android.content.Intent; 12a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport android.content.pm.ActivityInfo; 13a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport android.content.pm.PackageManager; 14a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport android.content.res.Configuration; 157e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.orgimport android.database.ContentObserver; 167e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.orgimport android.graphics.Bitmap; 17a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport android.graphics.Canvas; 1874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgimport android.graphics.Color; 19a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport android.graphics.Rect; 207e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.orgimport android.graphics.RectF; 217e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.orgimport android.net.Uri; 227e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.orgimport android.os.Build; 237e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.orgimport android.os.Bundle; 247e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.orgimport android.os.Handler; 257e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.orgimport android.os.ResultReceiver; 26a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport android.provider.Browser; 27a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport android.provider.Settings; 28a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport android.provider.Settings.Secure; 2901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.orgimport android.text.Editable; 3001d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.orgimport android.text.TextUtils; 317e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.orgimport android.util.Log; 3201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.orgimport android.util.Pair; 3374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgimport android.view.ActionMode; 3474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgimport android.view.HapticFeedbackConstants; 3574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgimport android.view.InputDevice; 36a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport android.view.KeyEvent; 37c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.orgimport android.view.MotionEvent; 3872cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.orgimport android.view.Surface; 3972cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.orgimport android.view.View; 4072cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.orgimport android.view.ViewGroup; 4172cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.orgimport android.view.Window; 4272cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.orgimport android.view.WindowManager; 4372cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.orgimport android.view.accessibility.AccessibilityEvent; 4472cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.orgimport android.view.accessibility.AccessibilityManager; 45c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.orgimport android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener; 46c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.orgimport android.view.accessibility.AccessibilityNodeInfo; 47c4af4cf7814bb773d838aefa476c196e5f1bc360asapersson@webrtc.orgimport android.view.accessibility.AccessibilityNodeProvider; 4872cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.orgimport android.view.inputmethod.EditorInfo; 4972cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.orgimport android.view.inputmethod.InputConnection; 5072cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.orgimport android.view.inputmethod.InputMethodManager; 51a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport android.widget.AbsoluteLayout; 52a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport android.widget.FrameLayout; 53a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org 5474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgimport com.google.common.annotations.VisibleForTesting; 5574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org 5674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgimport org.chromium.base.CalledByNative; 5774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgimport org.chromium.base.JNINamespace; 5874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgimport org.chromium.base.WeakContext; 5974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgimport org.chromium.content.R; 60a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport org.chromium.content.browser.ContentViewGestureHandler.MotionEventDelegate; 6101d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.orgimport org.chromium.content.browser.accessibility.AccessibilityInjector; 6201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.orgimport org.chromium.content.browser.accessibility.BrowserAccessibilityManager; 63a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport org.chromium.content.browser.input.AdapterInputConnection; 6401d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.orgimport org.chromium.content.browser.input.HandleView; 65a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport org.chromium.content.browser.input.ImeAdapter; 66a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport org.chromium.content.browser.input.ImeAdapter.AdapterInputConnectionFactory; 67a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport org.chromium.content.browser.input.InputMethodManagerWrapper; 6874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgimport org.chromium.content.browser.input.InsertionHandleController; 6974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgimport org.chromium.content.browser.input.SelectPopupDialog; 7074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgimport org.chromium.content.browser.input.SelectionHandleController; 7174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgimport org.chromium.content.common.TraceEvent; 7274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgimport org.chromium.ui.ViewAndroid; 7374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgimport org.chromium.ui.ViewAndroidDelegate; 7474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgimport org.chromium.ui.WindowAndroid; 7574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.orgimport org.chromium.ui.gfx.DeviceDisplayInfo; 7674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org 77a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport java.lang.annotation.Annotation; 78a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport java.lang.reflect.Field; 79a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport java.util.HashMap; 80a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport java.util.HashSet; 81a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.orgimport java.util.Map; 8201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org 8301d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org/** 84a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org * Provides a Java-side 'wrapper' around a WebContent (native) instance. 85a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org * Contains all the major functionality necessary to manage the lifecycle of a ContentView without 86a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org * being tied to the view system. 8701d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org */ 88a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org@JNINamespace("content") 8901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org public class ContentViewCore implements MotionEventDelegate, 9074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org NavigationClient, 9174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org AccessibilityStateChangeListener { 9201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org /** 9301d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org * Indicates that input events are batched together and delivered just before vsync. 9401d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org */ 9501d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org public static final int INPUT_EVENTS_DELIVERED_AT_VSYNC = 1; 9601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org 9701d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org /** 9801d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org * Opposite of INPUT_EVENTS_DELIVERED_AT_VSYNC. 9901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org */ 10001d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org public static final int INPUT_EVENTS_DELIVERED_IMMEDIATELY = 0; 10101d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org 10201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org private static final String TAG = "ContentViewCore"; 10301d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org 10401d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org // Used to avoid enabling zooming in / out if resulting zooming will 10501d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org // produce little visible difference. 10601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org private static final float ZOOM_CONTROLS_EPSILON = 0.007f; 10701d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org 10801d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org // Used to represent gestures for long press and long tap. 10901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org private static final int IS_LONG_PRESS = 1; 1104a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org private static final int IS_LONG_TAP = 2; 1114a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org 1124a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org // Length of the delay (in ms) before fading in handles after the last page movement. 11301d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org private static final int TEXT_HANDLE_FADE_IN_DELAY = 300; 11401d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org 11501d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org // If the embedder adds a JavaScript interface object that contains an indirect reference to 11601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org // the ContentViewCore, then storing a strong ref to the interface object on the native 1174a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org // side would prevent garbage collection of the ContentViewCore (as that strong ref would 1184a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org // create a new GC root). 1194a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org // For that reason, we store only a weak reference to the interface object on the 1204a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org // native side. However we still need a strong reference on the Java side to 1214a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org // prevent garbage collection if the embedder doesn't maintain their own ref to the 1224a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org // interface object - the Java side ref won't create a new GC root. 1234a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org // This map stores those refernces. We put into the map on addJavaScriptInterface() 1244a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org // and remove from it in removeJavaScriptInterface(). 1254a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org private final Map<String, Object> mJavaScriptInterfaces = new HashMap<String, Object>(); 12674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org 12774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org // Additionally, we keep track of all Java bound JS objects that are in use on the 12874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org // current page to ensure that they are not garbage collected until the page is 12974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org // navigated. This includes interface objects that have been removed 13074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org // via the removeJavaScriptInterface API and transient objects returned from methods 13174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org // on the interface object. Note we use HashSet rather than Set as the native side 132a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org // expects HashSet (no bindings for interfaces). 133a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org private final HashSet<Object> mRetainedJavaScriptObjects = new HashSet<Object>(); 134a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org 135a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org /** 136a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org * Interface that consumers of {@link ContentViewCore} must implement to allow the proper 137a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org * dispatching of view methods through the containing view. 138a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org * 13901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org * <p> 14001d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org * All methods with the "super_" prefix should be routed to the parent of the 14101d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org * implementing container view. 14201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org */ 14374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org @SuppressWarnings("javadoc") 144903e746cc9a73da17bfa3f6110293582fa6ee3bestefan@webrtc.org public interface InternalAccessDelegate { 14501d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org /** 14674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * @see View#drawChild(Canvas, View, long) 14774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org */ 14874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org boolean drawChild(Canvas canvas, View child, long drawingTime); 14974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org 15074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org /** 15174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * @see View#onKeyUp(keyCode, KeyEvent) 15274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org */ 15374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org boolean super_onKeyUp(int keyCode, KeyEvent event); 15474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org 15574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org /** 15601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org * @see View#dispatchKeyEventPreIme(KeyEvent) 15701d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org */ 15874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org boolean super_dispatchKeyEventPreIme(KeyEvent event); 159903e746cc9a73da17bfa3f6110293582fa6ee3bestefan@webrtc.org 16001d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org /** 16101d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org * @see View#dispatchKeyEvent(KeyEvent) 16201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org */ 16301d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org boolean super_dispatchKeyEvent(KeyEvent event); 164a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org 165a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org /** 16601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org * @see View#onGenericMotionEvent(MotionEvent) 16701d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org */ 16874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org boolean super_onGenericMotionEvent(MotionEvent event); 16974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org 17074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org /** 17174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * @see View#onConfigurationChanged(Configuration) 17274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org */ 17374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org void super_onConfigurationChanged(Configuration newConfig); 17474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org 17574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org /** 17674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * @see View#awakenScrollBars() 17774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org */ 17874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org boolean awakenScrollBars(); 17974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org 18074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org /** 18174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * @see View#awakenScrollBars(int, boolean) 18274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org */ 18374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org boolean super_awakenScrollBars(int startDelay, boolean invalidate); 18474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org } 18574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org 18674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org /** 18774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * An interface that allows the embedder to be notified when the pinch gesture starts and 18874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * stops. 18974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org */ 19074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org public interface GestureStateListener { 19174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org /** 19274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * Called when the pinch gesture starts. 19374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org */ 19474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org void onPinchGestureStart(); 19574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org 19674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org /** 19774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * Called when the pinch gesture ends. 19874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org */ 199a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org void onPinchGestureEnd(); 200a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org 20174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org /** 20274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * Called when the fling gesture is sent. 20374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org */ 20474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org void onFlingStartGesture(int vx, int vy); 20574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org 20674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org /** 20774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * Called when the fling cancel gesture is sent. 20874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org */ 20974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org void onFlingCancelGesture(); 21074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org 21174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org /** 21274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * Called when a fling event was not handled by the renderer. 21374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org */ 21474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org void onUnhandledFlingStartEvent(); 21574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org } 21674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org 21774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org /** 21874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * An interface for controlling visibility and state of embedder-provided zoom controls. 21974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org */ 22074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org public interface ZoomControlsDelegate { 22174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org /** 22274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * Called when it's reasonable to show zoom controls. 22374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org */ 22474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org void invokeZoomPicker(); 22574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org 22674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org /** 22774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * Called when zoom controls need to be hidden (e.g. when the view hides). 22874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org */ 22974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org void dismissZoomPicker(); 23074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org 23174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org /** 23274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * Called when page scale has been changed, so the controls can update their state. 23374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org */ 23474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org void updateZoomControls(); 23574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org } 23674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org 23774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org /** 23874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * An interface that allows the embedder to be notified of changes to the parameters of the 23974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * currently displayed contents. 24074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * These notifications are consistent with respect to the UI thread (the size is the size of 24174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * the contents currently displayed on screen). 24274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org */ 24374257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org public interface UpdateFrameInfoListener { 24474257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org /** 24574257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * Called each time any of the parameters are changed. 24674257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * 24774257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org * @param pageScaleFactor The page scale. 24874257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org */ 24974257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org void onFrameInfoUpdated(float pageScaleFactor); 25074257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org } 25174257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org 25274257108b4a17f3aeff1756b1f5bf45f971b6caeasapersson@webrtc.org private VSyncManager.Provider mVSyncProvider; 253a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org private VSyncManager.Listener mVSyncListener; 254fec6b6e5999edec8c90efae54357f1aae6a4c7ddsolenberg@webrtc.org private int mVSyncSubscriberCount; 255a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org private boolean mVSyncListenerRegistered; 256a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org 25701d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org // To avoid IPC delay we use input events to directly trigger a vsync signal in the renderer. 258a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org // When we do this, we also need to avoid sending the real vsync signal for the current 25901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org // frame to avoid double-ticking. This flag is used to inhibit the next vsync notification. 260a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org private boolean mDidSignalVSyncUsingInputEvent; 26101d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org 26201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org public VSyncManager.Listener getVSyncListener(VSyncManager.Provider vsyncProvider) { 263a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org if (mVSyncProvider != null && mVSyncListenerRegistered) { 26401d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org mVSyncProvider.unregisterVSyncListener(mVSyncListener); 265a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org mVSyncListenerRegistered = false; 26601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org } 267a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org 268a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org mVSyncProvider = vsyncProvider; 269a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org mVSyncListener = new VSyncManager.Listener() { 270a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org @Override 271a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org public void updateVSync(long tickTimeMicros, long intervalMicros) { 272a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org if (mNativeContentViewCore != 0) { 27301d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org nativeUpdateVSyncParameters(mNativeContentViewCore, tickTimeMicros, 27401d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org intervalMicros); 27501d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org } 27601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org } 27701d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org 27801d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org @Override 279a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org public void onVSync(long frameTimeMicros) { 280a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org animateIfNecessary(frameTimeMicros); 281a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org 28201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org if (mDidSignalVSyncUsingInputEvent) { 2835041831648212bfd5b68e91e1ff39e2b420f679easapersson@webrtc.org TraceEvent.instant("ContentViewCore::onVSync ignored"); 2845041831648212bfd5b68e91e1ff39e2b420f679easapersson@webrtc.org mDidSignalVSyncUsingInputEvent = false; 28501d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org return; 28601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org } 28701d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org if (mNativeContentViewCore != 0) { 28801d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org nativeOnVSync(mNativeContentViewCore, frameTimeMicros); 28901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org } 290a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org } 291a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org }; 2923dc7ff30185a2d7a597acb69183fca73bd1004d8asapersson@webrtc.org 29301d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org if (mVSyncSubscriberCount > 0) { 29401d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org // addVSyncSubscriber() is called before getVSyncListener. 29501d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org vsyncProvider.registerVSyncListener(mVSyncListener); 2963dc7ff30185a2d7a597acb69183fca73bd1004d8asapersson@webrtc.org mVSyncListenerRegistered = true; 2973dc7ff30185a2d7a597acb69183fca73bd1004d8asapersson@webrtc.org } 29872cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org 29901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org return mVSyncListener; 30072cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org } 30101d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org 30201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org @CalledByNative 30372cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org void addVSyncSubscriber() { 30401d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org if (!isVSyncNotificationEnabled()) { 30572cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org mDidSignalVSyncUsingInputEvent = false; 30601d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org } 30772cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org if (mVSyncProvider != null && !mVSyncListenerRegistered) { 30872cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org mVSyncProvider.registerVSyncListener(mVSyncListener); 30901d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org mVSyncListenerRegistered = true; 31001d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org } 31101d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org mVSyncSubscriberCount++; 31201d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org } 31301d06c859328f3fb8c8521eede87063b05583208asapersson@webrtc.org 31472cc32a68bcb9b2aa32f751dc6d120716d220a10asapersson@webrtc.org @CalledByNative 3154a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org void removeVSyncSubscriber() { 3164a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org if (mVSyncProvider != null && mVSyncSubscriberCount == 1) { 3174a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org assert mVSyncListenerRegistered; 3184a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org mVSyncProvider.unregisterVSyncListener(mVSyncListener); 3194a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org mVSyncListenerRegistered = false; 3204a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org } 3214a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org mVSyncSubscriberCount--; 3224a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org assert mVSyncSubscriberCount >= 0; 3234a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org } 3244a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org 3254a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org @CalledByNative 3264a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org private void resetVSyncNotification() { 3274a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org while (isVSyncNotificationEnabled()) removeVSyncSubscriber(); 3284a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org mVSyncSubscriberCount = 0; 3294a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org mVSyncListenerRegistered = false; 3304a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org mNeedAnimate = false; 3314a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org } 3324a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org 3334a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org private boolean isVSyncNotificationEnabled() { 3344a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org return mVSyncProvider != null && mVSyncListenerRegistered; 3354a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org } 3364a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org 3374a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org @CalledByNative 3384a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org private void setNeedsAnimate() { 3394a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org if (!mNeedAnimate) { 3404a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org mNeedAnimate = true; 3414a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org addVSyncSubscriber(); 3424a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org } 3434a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org } 3444a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org 3454a1556017653ef7702585897b071872e83bd95b9asapersson@webrtc.org private final Context mContext; 3467e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private ViewGroup mContainerView; 3477e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private InternalAccessDelegate mContainerViewInternals; 3487e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private WebContentsObserverAndroid mWebContentsObserver; 3497e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 3507e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private ContentViewClient mContentViewClient; 3517e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 3527e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private ContentSettings mContentSettings; 3537e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 3546aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org // Native pointer to C++ ContentViewCoreImpl object which will be set by nativeInit(). 3556aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org private int mNativeContentViewCore = 0; 3566aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org 3577e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private boolean mAttachedToWindow = false; 3587e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 3597e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // Pid of the renderer process backing this ContentViewCore. 3607e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private int mPid = 0; 3617e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 3627e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private ContentViewGestureHandler mContentViewGestureHandler; 3637e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private GestureStateListener mGestureStateListener; 3647e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private ZoomManager mZoomManager; 3657e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private ZoomControlsDelegate mZoomControlsDelegate; 3667e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 3677e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private PopupZoomer mPopupZoomer; 3687e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 3697e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private Runnable mFakeMouseMoveRunnable = null; 3707e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 3717e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // Only valid when focused on a text / password field. 3727e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private ImeAdapter mImeAdapter; 3737e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private ImeAdapter.AdapterInputConnectionFactory mAdapterInputConnectionFactory; 3747e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private AdapterInputConnection mInputConnection; 3757e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 3767e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private SelectionHandleController mSelectionHandleController; 3777e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private InsertionHandleController mInsertionHandleController; 3787e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 3797e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private Runnable mDeferredHandleFadeInRunnable; 3807e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 3817e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // Size of the viewport in physical pixels as set from onSizeChanged. 3827e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private int mViewportWidthPix; 3837e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private int mViewportHeightPix; 3847e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private int mPhysicalBackingWidthPix; 3857e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private int mPhysicalBackingHeightPix; 3867e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private int mOverdrawBottomHeightPix; 3877e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private int mViewportSizeOffsetWidthPix; 3887e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private int mViewportSizeOffsetHeightPix; 3897e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 3907e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // Cached copy of all positions and scales as reported by the renderer. 3917e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private final RenderCoordinates mRenderCoordinates; 3927e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 3937e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private final RenderCoordinates.NormalizedPoint mStartHandlePoint; 3947e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private final RenderCoordinates.NormalizedPoint mEndHandlePoint; 3957e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private final RenderCoordinates.NormalizedPoint mInsertionHandlePoint; 3967e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 3977e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // Tracks whether a selection is currently active. When applied to selected text, indicates 3987e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // whether the last selected text is still highlighted. 3997e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private boolean mHasSelection; 4007e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private String mLastSelectedText; 4017e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private boolean mSelectionEditable; 4027e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private ActionMode mActionMode; 4037e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private boolean mUnselectAllOnActionModeDismiss; 4047e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4057e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // Delegate that will handle GET downloads, and be notified of completion of POST downloads. 4067e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private ContentViewDownloadDelegate mDownloadDelegate; 4077e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4087e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // The AccessibilityInjector that handles loading Accessibility scripts into the web page. 4097e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private AccessibilityInjector mAccessibilityInjector; 4107e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4117e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // Whether native accessibility, i.e. without any script injection, is allowed. 4127e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private boolean mNativeAccessibilityAllowed; 4137e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4147e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // Whether native accessibility, i.e. without any script injection, has been enabled. 4157e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private boolean mNativeAccessibilityEnabled; 4167e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4177e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // Handles native accessibility, i.e. without any script injection. 4187e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private BrowserAccessibilityManager mBrowserAccessibilityManager; 4197e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4207e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // System accessibility service. 4217e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private final AccessibilityManager mAccessibilityManager; 4227e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4237e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // Allows us to dynamically respond when the accessibility script injection flag changes. 4247e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private ContentObserver mAccessibilityScriptInjectionObserver; 4257e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4267e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // Temporary notification to tell onSizeChanged to focus a form element, 4277e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // because the OSK was just brought up. 4287e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private boolean mUnfocusOnNextSizeChanged = false; 4297e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private final Rect mFocusPreOSKViewportRect = new Rect(); 4307e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4317e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private boolean mNeedUpdateOrientationChanged; 4327e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4337e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // Used to keep track of whether we should try to undo the last zoom-to-textfield operation. 4347e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private boolean mScrolledAndZoomedFocusedEditableNode = false; 4357e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4367e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // Whether we use hardware-accelerated drawing. 4377e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private boolean mHardwareAccelerated = false; 4387e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4397e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // Whether we received a new frame since consumePendingRendererFrame() was last called. 4407e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private boolean mPendingRendererFrame = false; 4417e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4427e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // Whether we should animate at the next vsync tick. 4437e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private boolean mNeedAnimate = false; 4447e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4457e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private ViewAndroid mViewAndroid; 4467e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4477e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4487e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org /** 4497e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * Constructs a new ContentViewCore. Embedders must call initialize() after constructing 4507e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * a ContentViewCore and before using it. 4517e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * 4527e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * @param context The context used to create this. 4537e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org */ 4547e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org public ContentViewCore(Context context) { 4557e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org mContext = context; 4567e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4577e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org WeakContext.initializeWeakContext(context); 4587e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org HeapStatsLogger.init(mContext.getApplicationContext()); 4597e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org mAdapterInputConnectionFactory = new AdapterInputConnectionFactory(); 4607e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4617e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org mRenderCoordinates = new RenderCoordinates(); 4627e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org mRenderCoordinates.setDeviceScaleFactor( 4637e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org getContext().getResources().getDisplayMetrics().density); 4647e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org mStartHandlePoint = mRenderCoordinates.createNormalizedPoint(); 4657e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org mEndHandlePoint = mRenderCoordinates.createNormalizedPoint(); 4667e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org mInsertionHandlePoint = mRenderCoordinates.createNormalizedPoint(); 4677e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org mAccessibilityManager = (AccessibilityManager) 4687e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); 4697e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org } 4707e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4717e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org /** 4727e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * @return The context used for creating this ContentViewCore. 4737e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org */ 4747e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org @CalledByNative 4757e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org public Context getContext() { 4767e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org return mContext; 4777e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org } 4787e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4797e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org /** 4807e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * @return The ViewGroup that all view actions of this ContentViewCore should interact with. 4817e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org */ 4827e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org public ViewGroup getContainerView() { 4837e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org return mContainerView; 4847e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org } 4857e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 4867e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org /** 4877e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * Specifies how much smaller the WebKit layout size should be relative to the size of this 4887e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * view. 4897e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * @param offsetXPix The X amount in pixels to shrink the viewport by. 4907e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * @param offsetYPix The Y amount in pixels to shrink the viewport by. 4917e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org */ 4927e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org public void setViewportSizeOffset(int offsetXPix, int offsetYPix) { 4937e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org if (offsetXPix != mViewportSizeOffsetWidthPix || 4947e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org offsetYPix != mViewportSizeOffsetHeightPix) { 4957e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org mViewportSizeOffsetWidthPix = offsetXPix; 4967e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org mViewportSizeOffsetHeightPix = offsetYPix; 4977e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org if (mNativeContentViewCore != 0) nativeWasResized(mNativeContentViewCore); 4987e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org } 4997e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org } 5007e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 5017e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org /** 5027e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * Returns a delegate that can be used to add and remove views from the ContainerView. 5037e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * 5047e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * NOTE: Use with care, as not all ContentViewCore users setup their ContainerView in the same 5057e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * way. In particular, the Android WebView has limitations on what implementation details can 5067e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * be provided via a child view, as they are visible in the API and could introduce 5077e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * compatibility breaks with existing applications. If in doubt, contact the 5087e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * android_webview/OWNERS 5097e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org * 5104a1b3e3a69d349b0d3e91f607f24e02d8b975688mflodman@webrtc.org * @return A ViewAndroidDelegate that can be used to add and remove views. 5117e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org */ 5127e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org @VisibleForTesting 5137e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org public ViewAndroidDelegate getViewAndroidDelegate() { 5147e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org return new ViewAndroidDelegate() { 5157e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org @Override 5167e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org public View acquireAnchorView() { 5177e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org View anchorView = new View(getContext()); 5187e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org mContainerView.addView(anchorView); 5197e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org return anchorView; 5207e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org } 5217e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 5227e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org @Override 5237e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org @SuppressWarnings("deprecation") // AbsoluteLayout.LayoutParams 5247e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org public void setAnchorViewPosition( 5257e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org View view, float x, float y, float width, float height) { 5267e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org assert(view.getParent() == mContainerView); 5277e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 5287e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org float scale = (float) DeviceDisplayInfo.create(getContext()).getDIPScale(); 5297e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 5307e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // The anchor view should not go outside the bounds of the ContainerView. 5317e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org int leftMargin = Math.round(x * scale); 5324a1b3e3a69d349b0d3e91f607f24e02d8b975688mflodman@webrtc.org int topMargin = Math.round(mRenderCoordinates.getContentOffsetYPix() + y * scale); 5337e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org int scaledWidth = Math.round(width * scale); 5347e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // ContentViewCore currently only supports these two container view types. 535f147639fcf3f45fdf764480834a483eb88b1cf2astefan@webrtc.org if (mContainerView instanceof FrameLayout) { 536f147639fcf3f45fdf764480834a483eb88b1cf2astefan@webrtc.org if (scaledWidth + leftMargin > mContainerView.getWidth()) { 537f147639fcf3f45fdf764480834a483eb88b1cf2astefan@webrtc.org scaledWidth = mContainerView.getWidth() - leftMargin; 538f147639fcf3f45fdf764480834a483eb88b1cf2astefan@webrtc.org } 5397e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( 5407e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org scaledWidth, Math.round(height * scale)); 5417e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org lp.leftMargin = leftMargin; 5427e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org lp.topMargin = topMargin; 5437e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org view.setLayoutParams(lp); 5447e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org } else if (mContainerView instanceof AbsoluteLayout) { 5457e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // This fixes the offset due to a difference in 5467e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // scrolling model of WebView vs. Chrome. 5477e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // TODO(sgurun) fix this to use mContainerView.getScroll[X/Y]() 5487e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // as it naturally accounts for scroll differences between 5497e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org // these models. 5507e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org leftMargin += mRenderCoordinates.getScrollXPixInt(); 5517e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org topMargin += mRenderCoordinates.getScrollYPixInt(); 5527e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 5537e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org android.widget.AbsoluteLayout.LayoutParams lp = 5547e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org new android.widget.AbsoluteLayout.LayoutParams( 5557e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org scaledWidth, (int)(height * scale), leftMargin, topMargin); 5567e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org view.setLayoutParams(lp); 5577e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org } else { 5587e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org Log.e(TAG, "Unknown layout " + mContainerView.getClass().getName()); 5597e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org } 5607e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org } 5617e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 5624a1b3e3a69d349b0d3e91f607f24e02d8b975688mflodman@webrtc.org @Override 5637e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org public void releaseAnchorView(View anchorView) { 5647e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org mContainerView.removeView(anchorView); 5657e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org } 5667e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org }; 5677e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org } 5687e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 5697e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org @VisibleForTesting 5707e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org public ImeAdapter getImeAdapterForTest() { 5717e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org return mImeAdapter; 5727e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org } 5737e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 5747e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org @VisibleForTesting 5757e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org public void setAdapterInputConnectionFactory(AdapterInputConnectionFactory factory) { 5767e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org mAdapterInputConnectionFactory = factory; 5777e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org } 5787e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 5797e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org @VisibleForTesting 5807e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org public AdapterInputConnection getInputConnectionForTest() { 5817e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org return mInputConnection; 5827e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org } 5837e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org 5847e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org private ImeAdapter createImeAdapter(Context context) { 5857e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org return new ImeAdapter(new InputMethodManagerWrapper(context), 5867e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org new ImeAdapter.ImeAdapterDelegate() { 5877e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org @Override 5887e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org public void onImeEvent(boolean isFinish) { 5897e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org getContentViewClient().onImeEvent(); 5907e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org if (!isFinish) { 5917e87822cf6f75bb60c3d47cfb7d76c98b0ad6d6astefan@webrtc.org hideHandles(); 592a2d942a1e99a150f42f23ef2d6342c91a756dbb0asapersson@webrtc.org undoScrollFocusedEditableNodeIntoViewIfNeeded(false); 593 } 594 } 595 596 @Override 597 public void onSetFieldValue() { 598 scrollFocusedEditableNodeIntoView(); 599 } 600 601 @Override 602 public void onDismissInput() { 603 getContentViewClient().onImeStateChangeRequested(false); 604 } 605 606 @Override 607 public View getAttachedView() { 608 return mContainerView; 609 } 610 611 @Override 612 public ResultReceiver getNewShowKeyboardReceiver() { 613 return new ResultReceiver(new Handler()) { 614 @Override 615 public void onReceiveResult(int resultCode, Bundle resultData) { 616 getContentViewClient().onImeStateChangeRequested( 617 resultCode == InputMethodManager.RESULT_SHOWN || 618 resultCode == InputMethodManager.RESULT_UNCHANGED_SHOWN); 619 if (resultCode == InputMethodManager.RESULT_SHOWN) { 620 // If OSK is newly shown, delay the form focus until 621 // the onSizeChanged (in order to adjust relative to the 622 // new size). 623 // TODO(jdduke): We should not assume that onSizeChanged will 624 // always be called, crbug.com/294908. 625 getContainerView().getWindowVisibleDisplayFrame( 626 mFocusPreOSKViewportRect); 627 } else if (resultCode == 628 InputMethodManager.RESULT_UNCHANGED_SHOWN) { 629 // If the OSK was already there, focus the form immediately. 630 scrollFocusedEditableNodeIntoView(); 631 } else { 632 undoScrollFocusedEditableNodeIntoViewIfNeeded(false); 633 } 634 } 635 }; 636 } 637 } 638 ); 639 } 640 641 /** 642 * Returns true if the given Activity has hardware acceleration enabled 643 * in its manifest, or in its foreground window. 644 * 645 * TODO(husky): Remove when initialize() is refactored (see TODO there) 646 * TODO(dtrainor) This is still used by other classes. Make sure to pull some version of this 647 * out before removing it. 648 */ 649 public static boolean hasHardwareAcceleration(Activity activity) { 650 // Has HW acceleration been enabled manually in the current window? 651 Window window = activity.getWindow(); 652 if (window != null) { 653 if ((window.getAttributes().flags 654 & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0) { 655 return true; 656 } 657 } 658 659 // Has HW acceleration been enabled in the manifest? 660 try { 661 ActivityInfo info = activity.getPackageManager().getActivityInfo( 662 activity.getComponentName(), 0); 663 if ((info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) { 664 return true; 665 } 666 } catch (PackageManager.NameNotFoundException e) { 667 Log.e("Chrome", "getActivityInfo(self) should not fail"); 668 } 669 670 return false; 671 } 672 673 /** 674 * Returns true if the given Context is a HW-accelerated Activity. 675 * 676 * TODO(husky): Remove when initialize() is refactored (see TODO there) 677 */ 678 private static boolean hasHardwareAcceleration(Context context) { 679 if (context instanceof Activity) { 680 return hasHardwareAcceleration((Activity) context); 681 } 682 return false; 683 } 684 685 /** 686 * 687 * @param containerView The view that will act as a container for all views created by this. 688 * @param internalDispatcher Handles dispatching all hidden or super methods to the 689 * containerView. 690 * @param nativeWebContents A pointer to the native web contents. 691 * @param windowAndroid An instance of the WindowAndroid. 692 */ 693 // Perform important post-construction set up of the ContentViewCore. 694 // We do not require the containing view in the constructor to allow embedders to create a 695 // ContentViewCore without having fully created its containing view. The containing view 696 // is a vital component of the ContentViewCore, so embedders must exercise caution in what 697 // they do with the ContentViewCore before calling initialize(). 698 // We supply the nativeWebContents pointer here rather than in the constructor to allow us 699 // to set the private browsing mode at a later point for the WebView implementation. 700 // Note that the caller remains the owner of the nativeWebContents and is responsible for 701 // deleting it after destroying the ContentViewCore. 702 public void initialize(ViewGroup containerView, InternalAccessDelegate internalDispatcher, 703 int nativeWebContents, WindowAndroid windowAndroid, 704 int inputEventDeliveryMode) { 705 // Check whether to use hardware acceleration. This is a bit hacky, and 706 // only works if the Context is actually an Activity (as it is in the 707 // Chrome application). 708 // 709 // What we're doing here is checking whether the app has *requested* 710 // hardware acceleration by setting the appropriate flags. This does not 711 // necessarily mean we're going to *get* hardware acceleration -- that's 712 // up to the Android framework. 713 // 714 // TODO(husky): Once the native code has been updated so that the 715 // HW acceleration flag can be set dynamically (Grace is doing this), 716 // move this check into onAttachedToWindow(), where we can test for 717 // HW support directly. 718 mHardwareAccelerated = hasHardwareAcceleration(mContext); 719 720 mContainerView = containerView; 721 722 int windowNativePointer = windowAndroid != null ? windowAndroid.getNativePointer() : 0; 723 724 int viewAndroidNativePointer = 0; 725 if (windowNativePointer != 0) { 726 mViewAndroid = new ViewAndroid(windowAndroid, getViewAndroidDelegate()); 727 viewAndroidNativePointer = mViewAndroid.getNativePointer(); 728 } 729 730 mNativeContentViewCore = nativeInit(mHardwareAccelerated, 731 nativeWebContents, viewAndroidNativePointer, windowNativePointer); 732 mContentSettings = new ContentSettings(this, mNativeContentViewCore); 733 initializeContainerView(internalDispatcher, inputEventDeliveryMode); 734 735 mAccessibilityInjector = AccessibilityInjector.newInstance(this); 736 737 String contentDescription = "Web View"; 738 if (R.string.accessibility_content_view == 0) { 739 Log.w(TAG, "Setting contentDescription to 'Web View' as no value was specified."); 740 } else { 741 contentDescription = mContext.getResources().getString( 742 R.string.accessibility_content_view); 743 } 744 mContainerView.setContentDescription(contentDescription); 745 mWebContentsObserver = new WebContentsObserverAndroid(this) { 746 @Override 747 public void didStartLoading(String url) { 748 hidePopupDialog(); 749 resetGestureDetectors(); 750 } 751 }; 752 753 mPid = nativeGetCurrentRenderProcessId(mNativeContentViewCore); 754 } 755 756 @CalledByNative 757 void onNativeContentViewCoreDestroyed(int nativeContentViewCore) { 758 assert nativeContentViewCore == mNativeContentViewCore; 759 mNativeContentViewCore = 0; 760 } 761 762 /** 763 * Initializes the View that will contain all Views created by the ContentViewCore. 764 * 765 * @param internalDispatcher Handles dispatching all hidden or super methods to the 766 * containerView. 767 */ 768 private void initializeContainerView(InternalAccessDelegate internalDispatcher, 769 int inputEventDeliveryMode) { 770 TraceEvent.begin(); 771 mContainerViewInternals = internalDispatcher; 772 773 mContainerView.setWillNotDraw(false); 774 mContainerView.setClickable(true); 775 776 mZoomManager = new ZoomManager(mContext, this); 777 mContentViewGestureHandler = new ContentViewGestureHandler(mContext, this, mZoomManager, 778 inputEventDeliveryMode); 779 mZoomControlsDelegate = new ZoomControlsDelegate() { 780 @Override 781 public void invokeZoomPicker() {} 782 @Override 783 public void dismissZoomPicker() {} 784 @Override 785 public void updateZoomControls() {} 786 }; 787 788 mRenderCoordinates.reset(); 789 790 initPopupZoomer(mContext); 791 mImeAdapter = createImeAdapter(mContext); 792 TraceEvent.end(); 793 } 794 795 private void initPopupZoomer(Context context){ 796 mPopupZoomer = new PopupZoomer(context); 797 mPopupZoomer.setOnVisibilityChangedListener(new PopupZoomer.OnVisibilityChangedListener() { 798 @Override 799 public void onPopupZoomerShown(final PopupZoomer zoomer) { 800 mContainerView.post(new Runnable() { 801 @Override 802 public void run() { 803 if (mContainerView.indexOfChild(zoomer) == -1) { 804 mContainerView.addView(zoomer); 805 } else { 806 assert false : "PopupZoomer should never be shown without being hidden"; 807 } 808 } 809 }); 810 } 811 812 @Override 813 public void onPopupZoomerHidden(final PopupZoomer zoomer) { 814 mContainerView.post(new Runnable() { 815 @Override 816 public void run() { 817 if (mContainerView.indexOfChild(zoomer) != -1) { 818 mContainerView.removeView(zoomer); 819 mContainerView.invalidate(); 820 } else { 821 assert false : "PopupZoomer should never be hidden without being shown"; 822 } 823 } 824 }); 825 } 826 }); 827 // TODO(yongsheng): LONG_TAP is not enabled in PopupZoomer. So need to dispatch a LONG_TAP 828 // gesture if a user completes a tap on PopupZoomer UI after a LONG_PRESS gesture. 829 PopupZoomer.OnTapListener listener = new PopupZoomer.OnTapListener() { 830 @Override 831 public boolean onSingleTap(View v, MotionEvent e) { 832 mContainerView.requestFocus(); 833 if (mNativeContentViewCore != 0) { 834 nativeSingleTap(mNativeContentViewCore, e.getEventTime(), 835 e.getX(), e.getY(), true); 836 } 837 return true; 838 } 839 840 @Override 841 public boolean onLongPress(View v, MotionEvent e) { 842 if (mNativeContentViewCore != 0) { 843 nativeLongPress(mNativeContentViewCore, e.getEventTime(), 844 e.getX(), e.getY(), true); 845 } 846 return true; 847 } 848 }; 849 mPopupZoomer.setOnTapListener(listener); 850 } 851 852 /** 853 * Destroy the internal state of the ContentView. This method may only be 854 * called after the ContentView has been removed from the view system. No 855 * other methods may be called on this ContentView after this method has 856 * been called. 857 */ 858 public void destroy() { 859 if (mNativeContentViewCore != 0) { 860 nativeOnJavaContentViewCoreDestroyed(mNativeContentViewCore); 861 } 862 resetVSyncNotification(); 863 mVSyncProvider = null; 864 if (mViewAndroid != null) mViewAndroid.destroy(); 865 mNativeContentViewCore = 0; 866 mContentSettings = null; 867 mJavaScriptInterfaces.clear(); 868 mRetainedJavaScriptObjects.clear(); 869 unregisterAccessibilityContentObserver(); 870 } 871 872 private void unregisterAccessibilityContentObserver() { 873 if (mAccessibilityScriptInjectionObserver == null) { 874 return; 875 } 876 getContext().getContentResolver().unregisterContentObserver( 877 mAccessibilityScriptInjectionObserver); 878 mAccessibilityScriptInjectionObserver = null; 879 } 880 881 /** 882 * Returns true initially, false after destroy() has been called. 883 * It is illegal to call any other public method after destroy(). 884 */ 885 public boolean isAlive() { 886 return mNativeContentViewCore != 0; 887 } 888 889 /** 890 * This is only useful for passing over JNI to native code that requires ContentViewCore*. 891 * @return native ContentViewCore pointer. 892 */ 893 @CalledByNative 894 public int getNativeContentViewCore() { 895 return mNativeContentViewCore; 896 } 897 898 /** 899 * For internal use. Throws IllegalStateException if mNativeContentView is 0. 900 * Use this to ensure we get a useful Java stack trace, rather than a native 901 * crash dump, from use-after-destroy bugs in Java code. 902 */ 903 void checkIsAlive() throws IllegalStateException { 904 if (!isAlive()) { 905 throw new IllegalStateException("ContentView used after destroy() was called"); 906 } 907 } 908 909 public void setContentViewClient(ContentViewClient client) { 910 if (client == null) { 911 throw new IllegalArgumentException("The client can't be null."); 912 } 913 mContentViewClient = client; 914 } 915 916 ContentViewClient getContentViewClient() { 917 if (mContentViewClient == null) { 918 // We use the Null Object pattern to avoid having to perform a null check in this class. 919 // We create it lazily because most of the time a client will be set almost immediately 920 // after ContentView is created. 921 mContentViewClient = new ContentViewClient(); 922 // We don't set the native ContentViewClient pointer here on purpose. The native 923 // implementation doesn't mind a null delegate and using one is better than passing a 924 // Null Object, since we cut down on the number of JNI calls. 925 } 926 return mContentViewClient; 927 } 928 929 public int getBackgroundColor() { 930 if (mNativeContentViewCore != 0) { 931 return nativeGetBackgroundColor(mNativeContentViewCore); 932 } 933 return Color.WHITE; 934 } 935 936 @CalledByNative 937 private void onBackgroundColorChanged(int color) { 938 getContentViewClient().onBackgroundColorChanged(color); 939 } 940 941 /** 942 * Load url without fixing up the url string. Consumers of ContentView are responsible for 943 * ensuring the URL passed in is properly formatted (i.e. the scheme has been added if left 944 * off during user input). 945 * 946 * @param params Parameters for this load. 947 */ 948 public void loadUrl(LoadUrlParams params) { 949 if (mNativeContentViewCore == 0) return; 950 951 nativeLoadUrl(mNativeContentViewCore, 952 params.mUrl, 953 params.mLoadUrlType, 954 params.mTransitionType, 955 params.mUaOverrideOption, 956 params.getExtraHeadersString(), 957 params.mPostData, 958 params.mBaseUrlForDataUrl, 959 params.mVirtualUrlForDataUrl, 960 params.mCanLoadLocalResources); 961 } 962 963 /** 964 * Stops loading the current web contents. 965 */ 966 public void stopLoading() { 967 if (mNativeContentViewCore != 0) nativeStopLoading(mNativeContentViewCore); 968 } 969 970 /** 971 * Get the URL of the current page. 972 * 973 * @return The URL of the current page. 974 */ 975 public String getUrl() { 976 if (mNativeContentViewCore != 0) return nativeGetURL(mNativeContentViewCore); 977 return null; 978 } 979 980 /** 981 * Get the title of the current page. 982 * 983 * @return The title of the current page. 984 */ 985 public String getTitle() { 986 if (mNativeContentViewCore != 0) return nativeGetTitle(mNativeContentViewCore); 987 return null; 988 } 989 990 /** 991 * Shows an interstitial page driven by the passed in delegate. 992 * 993 * @param url The URL being blocked by the interstitial. 994 * @param delegate The delegate handling the interstitial. 995 */ 996 @VisibleForTesting 997 public void showInterstitialPage( 998 String url, InterstitialPageDelegateAndroid delegate) { 999 if (mNativeContentViewCore == 0) return; 1000 nativeShowInterstitialPage(mNativeContentViewCore, url, delegate.getNative()); 1001 } 1002 1003 /** 1004 * @return Whether the page is currently showing an interstitial, such as a bad HTTPS page. 1005 */ 1006 public boolean isShowingInterstitialPage() { 1007 return mNativeContentViewCore == 0 ? 1008 false : nativeIsShowingInterstitialPage(mNativeContentViewCore); 1009 } 1010 1011 /** 1012 * Mark any new frames that have arrived since this function was last called as non-pending. 1013 * 1014 * @return Whether there was a pending frame from the renderer. 1015 */ 1016 public boolean consumePendingRendererFrame() { 1017 boolean hadPendingFrame = mPendingRendererFrame; 1018 mPendingRendererFrame = false; 1019 return hadPendingFrame; 1020 } 1021 1022 /** 1023 * @return Viewport width in physical pixels as set from onSizeChanged. 1024 */ 1025 @CalledByNative 1026 public int getViewportWidthPix() { return mViewportWidthPix; } 1027 1028 /** 1029 * @return Viewport height in physical pixels as set from onSizeChanged. 1030 */ 1031 @CalledByNative 1032 public int getViewportHeightPix() { return mViewportHeightPix; } 1033 1034 /** 1035 * @return Width of underlying physical surface. 1036 */ 1037 @CalledByNative 1038 public int getPhysicalBackingWidthPix() { return mPhysicalBackingWidthPix; } 1039 1040 /** 1041 * @return Height of underlying physical surface. 1042 */ 1043 @CalledByNative 1044 public int getPhysicalBackingHeightPix() { return mPhysicalBackingHeightPix; } 1045 1046 /** 1047 * @return Amount the output surface extends past the bottom of the window viewport. 1048 */ 1049 @CalledByNative 1050 public int getOverdrawBottomHeightPix() { return mOverdrawBottomHeightPix; } 1051 1052 /** 1053 * @return The amount to shrink the viewport relative to {@link #getViewportWidthPix()}. 1054 */ 1055 @CalledByNative 1056 public int getViewportSizeOffsetWidthPix() { return mViewportSizeOffsetWidthPix; } 1057 1058 /** 1059 * @return The amount to shrink the viewport relative to {@link #getViewportHeightPix()}. 1060 */ 1061 @CalledByNative 1062 public int getViewportSizeOffsetHeightPix() { return mViewportSizeOffsetHeightPix; } 1063 1064 /** 1065 * @see android.webkit.WebView#getContentHeight() 1066 */ 1067 public float getContentHeightCss() { 1068 return mRenderCoordinates.getContentHeightCss(); 1069 } 1070 1071 /** 1072 * @see android.webkit.WebView#getContentWidth() 1073 */ 1074 public float getContentWidthCss() { 1075 return mRenderCoordinates.getContentWidthCss(); 1076 } 1077 1078 public Bitmap getBitmap() { 1079 return getBitmap(getViewportWidthPix(), getViewportHeightPix()); 1080 } 1081 1082 public Bitmap getBitmap(int width, int height) { 1083 if (width == 0 || height == 0 1084 || getViewportWidthPix() == 0 || getViewportHeightPix() == 0) { 1085 return null; 1086 } 1087 1088 Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 1089 1090 if (mNativeContentViewCore != 0 && 1091 nativePopulateBitmapFromCompositor(mNativeContentViewCore, b)) { 1092 // If we successfully grabbed a bitmap, check if we have to draw the Android overlay 1093 // components as well. 1094 if (mContainerView.getChildCount() > 0) { 1095 Canvas c = new Canvas(b); 1096 c.scale(width / (float) getViewportWidthPix(), 1097 height / (float) getViewportHeightPix()); 1098 mContainerView.draw(c); 1099 } 1100 return b; 1101 } 1102 1103 return null; 1104 } 1105 1106 /** 1107 * Generates a bitmap of the content that is performance optimized based on capture time. 1108 * 1109 * <p> 1110 * To have a consistent capture time across devices, we will scale down the captured bitmap 1111 * where necessary to reduce the time to generate the bitmap. 1112 * 1113 * @param width The width of the content to be captured. 1114 * @param height The height of the content to be captured. 1115 * @return A pair of the generated bitmap, and the scale that needs to be applied to return the 1116 * bitmap to it's original size (i.e. if the bitmap is scaled down 50%, this 1117 * will be 2). 1118 */ 1119 public Pair<Bitmap, Float> getScaledPerformanceOptimizedBitmap(int width, int height) { 1120 float scale = 1f; 1121 // On tablets, always scale down to MDPI for performance reasons. 1122 if (DeviceUtils.isTablet(getContext())) { 1123 scale = getContext().getResources().getDisplayMetrics().density; 1124 } 1125 return Pair.create( 1126 getBitmap((int) (width / scale), (int) (height / scale)), 1127 scale); 1128 } 1129 1130 /** 1131 * @return Whether the current WebContents has a previous navigation entry. 1132 */ 1133 public boolean canGoBack() { 1134 return mNativeContentViewCore != 0 && nativeCanGoBack(mNativeContentViewCore); 1135 } 1136 1137 /** 1138 * @return Whether the current WebContents has a navigation entry after the current one. 1139 */ 1140 public boolean canGoForward() { 1141 return mNativeContentViewCore != 0 && nativeCanGoForward(mNativeContentViewCore); 1142 } 1143 1144 /** 1145 * @param offset The offset into the navigation history. 1146 * @return Whether we can move in history by given offset 1147 */ 1148 public boolean canGoToOffset(int offset) { 1149 return mNativeContentViewCore != 0 && nativeCanGoToOffset(mNativeContentViewCore, offset); 1150 } 1151 1152 /** 1153 * Navigates to the specified offset from the "current entry". Does nothing if the offset is out 1154 * of bounds. 1155 * @param offset The offset into the navigation history. 1156 */ 1157 public void goToOffset(int offset) { 1158 if (mNativeContentViewCore != 0) nativeGoToOffset(mNativeContentViewCore, offset); 1159 } 1160 1161 @Override 1162 public void goToNavigationIndex(int index) { 1163 if (mNativeContentViewCore != 0) nativeGoToNavigationIndex(mNativeContentViewCore, index); 1164 } 1165 1166 /** 1167 * Goes to the navigation entry before the current one. 1168 */ 1169 public void goBack() { 1170 if (mNativeContentViewCore != 0) nativeGoBack(mNativeContentViewCore); 1171 } 1172 1173 /** 1174 * Goes to the navigation entry following the current one. 1175 */ 1176 public void goForward() { 1177 if (mNativeContentViewCore != 0) nativeGoForward(mNativeContentViewCore); 1178 } 1179 1180 /** 1181 * Reload the current page. 1182 */ 1183 public void reload() { 1184 mAccessibilityInjector.addOrRemoveAccessibilityApisIfNecessary(); 1185 if (mNativeContentViewCore != 0) nativeReload(mNativeContentViewCore); 1186 } 1187 1188 /** 1189 * Cancel the pending reload. 1190 */ 1191 public void cancelPendingReload() { 1192 if (mNativeContentViewCore != 0) nativeCancelPendingReload(mNativeContentViewCore); 1193 } 1194 1195 /** 1196 * Continue the pending reload. 1197 */ 1198 public void continuePendingReload() { 1199 if (mNativeContentViewCore != 0) nativeContinuePendingReload(mNativeContentViewCore); 1200 } 1201 1202 /** 1203 * Clears the ContentViewCore's page history in both the backwards and 1204 * forwards directions. 1205 */ 1206 public void clearHistory() { 1207 if (mNativeContentViewCore != 0) nativeClearHistory(mNativeContentViewCore); 1208 } 1209 1210 /** 1211 * @return The selected text (empty if no text selected). 1212 */ 1213 public String getSelectedText() { 1214 return mHasSelection ? mLastSelectedText : ""; 1215 } 1216 1217 /** 1218 * @return Whether the current selection is editable (false if no text selected). 1219 */ 1220 public boolean isSelectionEditable() { 1221 return mHasSelection ? mSelectionEditable : false; 1222 } 1223 1224 // End FrameLayout overrides. 1225 1226 /** 1227 * @see View#onTouchEvent(MotionEvent) 1228 */ 1229 public boolean onTouchEvent(MotionEvent event) { 1230 undoScrollFocusedEditableNodeIntoViewIfNeeded(false); 1231 return mContentViewGestureHandler.onTouchEvent(event); 1232 } 1233 1234 /** 1235 * @return ContentViewGestureHandler for all MotionEvent and gesture related calls. 1236 */ 1237 ContentViewGestureHandler getContentViewGestureHandler() { 1238 return mContentViewGestureHandler; 1239 } 1240 1241 @Override 1242 public boolean sendTouchEvent(long timeMs, int action, TouchPoint[] pts) { 1243 if (mNativeContentViewCore != 0) { 1244 return nativeSendTouchEvent(mNativeContentViewCore, timeMs, action, pts); 1245 } 1246 return false; 1247 } 1248 1249 @SuppressWarnings("unused") 1250 @CalledByNative 1251 private void hasTouchEventHandlers(boolean hasTouchHandlers) { 1252 mContentViewGestureHandler.hasTouchEventHandlers(hasTouchHandlers); 1253 } 1254 1255 @SuppressWarnings("unused") 1256 @CalledByNative 1257 private void confirmTouchEvent(int ackResult) { 1258 mContentViewGestureHandler.confirmTouchEvent(ackResult); 1259 } 1260 1261 @SuppressWarnings("unused") 1262 @CalledByNative 1263 private void unhandledFlingStartEvent() { 1264 if (mGestureStateListener != null) { 1265 mGestureStateListener.onUnhandledFlingStartEvent(); 1266 } 1267 } 1268 1269 @Override 1270 public boolean sendGesture(int type, long timeMs, int x, int y, Bundle b) { 1271 if (offerGestureToEmbedder(type)) return false; 1272 if (mNativeContentViewCore == 0) return false; 1273 updateTextHandlesForGesture(type); 1274 updateGestureStateListener(type, b); 1275 switch (type) { 1276 case ContentViewGestureHandler.GESTURE_SHOW_PRESSED_STATE: 1277 nativeShowPressState(mNativeContentViewCore, timeMs, x, y); 1278 return true; 1279 case ContentViewGestureHandler.GESTURE_SHOW_PRESS_CANCEL: 1280 nativeShowPressCancel(mNativeContentViewCore, timeMs, x, y); 1281 return true; 1282 case ContentViewGestureHandler.GESTURE_DOUBLE_TAP: 1283 nativeDoubleTap(mNativeContentViewCore, timeMs, x, y); 1284 return true; 1285 case ContentViewGestureHandler.GESTURE_SINGLE_TAP_UP: 1286 nativeSingleTap(mNativeContentViewCore, timeMs, x, y, false); 1287 return true; 1288 case ContentViewGestureHandler.GESTURE_SINGLE_TAP_CONFIRMED: 1289 handleTapOrPress(timeMs, x, y, 0, 1290 b.getBoolean(ContentViewGestureHandler.SHOW_PRESS, false)); 1291 return true; 1292 case ContentViewGestureHandler.GESTURE_SINGLE_TAP_UNCONFIRMED: 1293 nativeSingleTapUnconfirmed(mNativeContentViewCore, timeMs, x, y); 1294 return true; 1295 case ContentViewGestureHandler.GESTURE_LONG_PRESS: 1296 handleTapOrPress(timeMs, x, y, IS_LONG_PRESS, false); 1297 return true; 1298 case ContentViewGestureHandler.GESTURE_LONG_TAP: 1299 handleTapOrPress(timeMs, x, y, IS_LONG_TAP, false); 1300 return true; 1301 case ContentViewGestureHandler.GESTURE_SCROLL_START: 1302 nativeScrollBegin(mNativeContentViewCore, timeMs, x, y); 1303 return true; 1304 case ContentViewGestureHandler.GESTURE_SCROLL_BY: { 1305 int dx = b.getInt(ContentViewGestureHandler.DISTANCE_X); 1306 int dy = b.getInt(ContentViewGestureHandler.DISTANCE_Y); 1307 nativeScrollBy(mNativeContentViewCore, timeMs, x, y, dx, dy); 1308 return true; 1309 } 1310 case ContentViewGestureHandler.GESTURE_SCROLL_END: 1311 nativeScrollEnd(mNativeContentViewCore, timeMs); 1312 return true; 1313 case ContentViewGestureHandler.GESTURE_FLING_START: 1314 nativeFlingStart(mNativeContentViewCore, timeMs, x, y, 1315 b.getInt(ContentViewGestureHandler.VELOCITY_X, 0), 1316 b.getInt(ContentViewGestureHandler.VELOCITY_Y, 0)); 1317 return true; 1318 case ContentViewGestureHandler.GESTURE_FLING_CANCEL: 1319 nativeFlingCancel(mNativeContentViewCore, timeMs); 1320 return true; 1321 case ContentViewGestureHandler.GESTURE_PINCH_BEGIN: 1322 nativePinchBegin(mNativeContentViewCore, timeMs, x, y); 1323 return true; 1324 case ContentViewGestureHandler.GESTURE_PINCH_BY: 1325 nativePinchBy(mNativeContentViewCore, timeMs, x, y, 1326 b.getFloat(ContentViewGestureHandler.DELTA, 0)); 1327 return true; 1328 case ContentViewGestureHandler.GESTURE_PINCH_END: 1329 nativePinchEnd(mNativeContentViewCore, timeMs); 1330 return true; 1331 default: 1332 return false; 1333 } 1334 } 1335 1336 @Override 1337 public void onSentLastGestureForVSync(long eventTimeMs) { 1338 if (isVSyncNotificationEnabled()) { 1339 mDidSignalVSyncUsingInputEvent = true; 1340 } 1341 if (mNativeContentViewCore != 0) { 1342 nativeOnVSync(mNativeContentViewCore, eventTimeMs * 1000); 1343 } 1344 } 1345 1346 public void setGestureStateListener(GestureStateListener pinchGestureStateListener) { 1347 mGestureStateListener = pinchGestureStateListener; 1348 } 1349 1350 void updateGestureStateListener(int gestureType, Bundle b) { 1351 if (mGestureStateListener == null) return; 1352 1353 switch (gestureType) { 1354 case ContentViewGestureHandler.GESTURE_PINCH_BEGIN: 1355 mGestureStateListener.onPinchGestureStart(); 1356 break; 1357 case ContentViewGestureHandler.GESTURE_PINCH_END: 1358 mGestureStateListener.onPinchGestureEnd(); 1359 break; 1360 case ContentViewGestureHandler.GESTURE_FLING_START: 1361 mGestureStateListener.onFlingStartGesture( 1362 b.getInt(ContentViewGestureHandler.VELOCITY_X, 0), 1363 b.getInt(ContentViewGestureHandler.VELOCITY_Y, 0)); 1364 break; 1365 case ContentViewGestureHandler.GESTURE_FLING_CANCEL: 1366 mGestureStateListener.onFlingCancelGesture(); 1367 break; 1368 default: 1369 break; 1370 } 1371 } 1372 1373 public interface JavaScriptCallback { 1374 void handleJavaScriptResult(String jsonResult); 1375 } 1376 1377 /** 1378 * Injects the passed Javascript code in the current page and evaluates it. 1379 * If a result is required, pass in a callback. 1380 * Used in automation tests. 1381 * 1382 * @param script The Javascript to execute. 1383 * @param callback The callback to be fired off when a result is ready. The script's 1384 * result will be json encoded and passed as the parameter, and the call 1385 * will be made on the main thread. 1386 * If no result is required, pass null. 1387 */ 1388 public void evaluateJavaScript(String script, JavaScriptCallback callback) { 1389 if (mNativeContentViewCore == 0) return; 1390 nativeEvaluateJavaScript(mNativeContentViewCore, script, callback, false); 1391 } 1392 1393 /** 1394 * Injects the passed Javascript code in the current page and evaluates it. 1395 * If there is no page existing, a new one will be created. 1396 * 1397 * @param script The Javascript to execute. 1398 */ 1399 public void evaluateJavaScriptEvenIfNotYetNavigated(String script) { 1400 if (mNativeContentViewCore == 0) return; 1401 nativeEvaluateJavaScript(mNativeContentViewCore, script, null, true); 1402 } 1403 1404 /** 1405 * This method should be called when the containing activity is paused. 1406 */ 1407 public void onActivityPause() { 1408 TraceEvent.begin(); 1409 hidePopupDialog(); 1410 nativeOnHide(mNativeContentViewCore); 1411 TraceEvent.end(); 1412 } 1413 1414 /** 1415 * This method should be called when the containing activity is resumed. 1416 */ 1417 public void onActivityResume() { 1418 nativeOnShow(mNativeContentViewCore); 1419 setAccessibilityState(mAccessibilityManager.isEnabled()); 1420 } 1421 1422 /** 1423 * To be called when the ContentView is shown. 1424 */ 1425 public void onShow() { 1426 nativeOnShow(mNativeContentViewCore); 1427 setAccessibilityState(mAccessibilityManager.isEnabled()); 1428 } 1429 1430 /** 1431 * To be called when the ContentView is hidden. 1432 */ 1433 public void onHide() { 1434 hidePopupDialog(); 1435 setInjectedAccessibility(false); 1436 nativeOnHide(mNativeContentViewCore); 1437 } 1438 1439 /** 1440 * Return the ContentSettings object used to retrieve the settings for this 1441 * ContentViewCore. For modifications, ChromeNativePreferences is to be used. 1442 * @return A ContentSettings object that can be used to retrieve this 1443 * ContentViewCore's settings. 1444 */ 1445 public ContentSettings getContentSettings() { 1446 return mContentSettings; 1447 } 1448 1449 @Override 1450 public boolean didUIStealScroll(float x, float y) { 1451 return getContentViewClient().shouldOverrideScroll( 1452 x, y, computeHorizontalScrollOffset(), computeVerticalScrollOffset()); 1453 } 1454 1455 @Override 1456 public boolean hasFixedPageScale() { 1457 return mRenderCoordinates.hasFixedPageScale(); 1458 } 1459 1460 private void hidePopupDialog() { 1461 SelectPopupDialog.hide(this); 1462 hideHandles(); 1463 hideSelectActionBar(); 1464 } 1465 1466 void hideSelectActionBar() { 1467 if (mActionMode != null) { 1468 mActionMode.finish(); 1469 mActionMode = null; 1470 } 1471 } 1472 1473 public boolean isSelectActionBarShowing() { 1474 return mActionMode != null; 1475 } 1476 1477 private void resetGestureDetectors() { 1478 mContentViewGestureHandler.resetGestureHandlers(); 1479 } 1480 1481 /** 1482 * @see View#onAttachedToWindow() 1483 */ 1484 @SuppressWarnings("javadoc") 1485 public void onAttachedToWindow() { 1486 mAttachedToWindow = true; 1487 if (mNativeContentViewCore != 0) { 1488 assert mPid == nativeGetCurrentRenderProcessId(mNativeContentViewCore); 1489 ChildProcessLauncher.getBindingManager().bindAsHighPriority(mPid); 1490 // Normally the initial binding is removed in onRenderProcessSwap(), but it is possible 1491 // to construct WebContents and spawn the renderer before passing it to ContentViewCore. 1492 // In this case there will be no onRenderProcessSwap() call and the initial binding will 1493 // be removed here. 1494 ChildProcessLauncher.getBindingManager().removeInitialBinding(mPid); 1495 } 1496 setAccessibilityState(mAccessibilityManager.isEnabled()); 1497 } 1498 1499 /** 1500 * @see View#onDetachedFromWindow() 1501 */ 1502 @SuppressWarnings("javadoc") 1503 public void onDetachedFromWindow() { 1504 mAttachedToWindow = false; 1505 if (mNativeContentViewCore != 0) { 1506 assert mPid == nativeGetCurrentRenderProcessId(mNativeContentViewCore); 1507 ChildProcessLauncher.getBindingManager().unbindAsHighPriority(mPid); 1508 } 1509 setInjectedAccessibility(false); 1510 hidePopupDialog(); 1511 mZoomControlsDelegate.dismissZoomPicker(); 1512 unregisterAccessibilityContentObserver(); 1513 } 1514 1515 /** 1516 * @see View#onVisibilityChanged(android.view.View, int) 1517 */ 1518 public void onVisibilityChanged(View changedView, int visibility) { 1519 if (visibility != View.VISIBLE) { 1520 mZoomControlsDelegate.dismissZoomPicker(); 1521 } 1522 } 1523 1524 /** 1525 * @see View#onCreateInputConnection(EditorInfo) 1526 */ 1527 public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 1528 if (!mImeAdapter.hasTextInputType()) { 1529 // Although onCheckIsTextEditor will return false in this case, the EditorInfo 1530 // is still used by the InputMethodService. Need to make sure the IME doesn't 1531 // enter fullscreen mode. 1532 outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN; 1533 } 1534 mInputConnection = 1535 mAdapterInputConnectionFactory.get(mContainerView, mImeAdapter, outAttrs); 1536 return mInputConnection; 1537 } 1538 1539 public Editable getEditableForTest() { 1540 return mInputConnection.getEditable(); 1541 } 1542 1543 /** 1544 * @see View#onCheckIsTextEditor() 1545 */ 1546 public boolean onCheckIsTextEditor() { 1547 return mImeAdapter.hasTextInputType(); 1548 } 1549 1550 /** 1551 * @see View#onConfigurationChanged(Configuration) 1552 */ 1553 @SuppressWarnings("javadoc") 1554 public void onConfigurationChanged(Configuration newConfig) { 1555 TraceEvent.begin(); 1556 1557 if (newConfig.keyboard != Configuration.KEYBOARD_NOKEYS) { 1558 mImeAdapter.attach(nativeGetNativeImeAdapter(mNativeContentViewCore), 1559 ImeAdapter.getTextInputTypeNone(), 1560 AdapterInputConnection.INVALID_SELECTION, 1561 AdapterInputConnection.INVALID_SELECTION); 1562 InputMethodManager manager = (InputMethodManager) 1563 getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 1564 manager.restartInput(mContainerView); 1565 } 1566 mContainerViewInternals.super_onConfigurationChanged(newConfig); 1567 mNeedUpdateOrientationChanged = true; 1568 TraceEvent.end(); 1569 } 1570 1571 /** 1572 * @see View#onSizeChanged(int, int, int, int) 1573 */ 1574 @SuppressWarnings("javadoc") 1575 public void onSizeChanged(int wPix, int hPix, int owPix, int ohPix) { 1576 if (getViewportWidthPix() == wPix && getViewportHeightPix() == hPix) return; 1577 1578 mViewportWidthPix = wPix; 1579 mViewportHeightPix = hPix; 1580 if (mNativeContentViewCore != 0) { 1581 nativeWasResized(mNativeContentViewCore); 1582 } 1583 1584 updateAfterSizeChanged(); 1585 } 1586 1587 /** 1588 * Called when the underlying surface the compositor draws to changes size. 1589 * This may be larger than the viewport size. 1590 */ 1591 public void onPhysicalBackingSizeChanged(int wPix, int hPix) { 1592 if (mPhysicalBackingWidthPix == wPix && mPhysicalBackingHeightPix == hPix) return; 1593 1594 mPhysicalBackingWidthPix = wPix; 1595 mPhysicalBackingHeightPix = hPix; 1596 1597 if (mNativeContentViewCore != 0) { 1598 nativeWasResized(mNativeContentViewCore); 1599 } 1600 } 1601 1602 /** 1603 * Called when the amount the surface is overdrawing off the bottom has changed. 1604 * @param overdrawHeightPix The overdraw height. 1605 */ 1606 public void onOverdrawBottomHeightChanged(int overdrawHeightPix) { 1607 if (mOverdrawBottomHeightPix == overdrawHeightPix) return; 1608 1609 mOverdrawBottomHeightPix = overdrawHeightPix; 1610 1611 if (mNativeContentViewCore != 0) { 1612 nativeWasResized(mNativeContentViewCore); 1613 } 1614 } 1615 1616 private void updateAfterSizeChanged() { 1617 mPopupZoomer.hide(false); 1618 1619 // Execute a delayed form focus operation because the OSK was brought 1620 // up earlier. 1621 if (!mFocusPreOSKViewportRect.isEmpty()) { 1622 Rect rect = new Rect(); 1623 getContainerView().getWindowVisibleDisplayFrame(rect); 1624 if (!rect.equals(mFocusPreOSKViewportRect)) { 1625 // Only assume the OSK triggered the onSizeChanged if width was preserved. 1626 if (rect.width() == mFocusPreOSKViewportRect.width()) { 1627 scrollFocusedEditableNodeIntoView(); 1628 } 1629 mFocusPreOSKViewportRect.setEmpty(); 1630 } 1631 } else if (mUnfocusOnNextSizeChanged) { 1632 undoScrollFocusedEditableNodeIntoViewIfNeeded(true); 1633 mUnfocusOnNextSizeChanged = false; 1634 } 1635 1636 if (mNeedUpdateOrientationChanged) { 1637 sendOrientationChangeEvent(); 1638 mNeedUpdateOrientationChanged = false; 1639 } 1640 } 1641 1642 private void scrollFocusedEditableNodeIntoView() { 1643 if (mNativeContentViewCore != 0) { 1644 Runnable scrollTask = new Runnable() { 1645 @Override 1646 public void run() { 1647 if (mNativeContentViewCore != 0) { 1648 nativeScrollFocusedEditableNodeIntoView(mNativeContentViewCore); 1649 } 1650 } 1651 }; 1652 1653 scrollTask.run(); 1654 1655 // The native side keeps track of whether the zoom and scroll actually occurred. It is 1656 // more efficient to do it this way and sometimes fire an unnecessary message rather 1657 // than synchronize with the renderer and always have an additional message. 1658 mScrolledAndZoomedFocusedEditableNode = true; 1659 } 1660 } 1661 1662 private void undoScrollFocusedEditableNodeIntoViewIfNeeded(boolean backButtonPressed) { 1663 // The only call to this function that matters is the first call after the 1664 // scrollFocusedEditableNodeIntoView function call. 1665 // If the first call to this function is a result of a back button press we want to undo the 1666 // preceding scroll. If the call is a result of some other action we don't want to perform 1667 // an undo. 1668 // All subsequent calls are ignored since only the scroll function sets 1669 // mScrolledAndZoomedFocusedEditableNode to true. 1670 if (mScrolledAndZoomedFocusedEditableNode && backButtonPressed && 1671 mNativeContentViewCore != 0) { 1672 Runnable scrollTask = new Runnable() { 1673 @Override 1674 public void run() { 1675 if (mNativeContentViewCore != 0) { 1676 nativeUndoScrollFocusedEditableNodeIntoView(mNativeContentViewCore); 1677 } 1678 } 1679 }; 1680 1681 scrollTask.run(); 1682 } 1683 mScrolledAndZoomedFocusedEditableNode = false; 1684 } 1685 1686 /** 1687 * @see View#onWindowFocusChanged(boolean) 1688 */ 1689 public void onWindowFocusChanged(boolean hasWindowFocus) { 1690 if (!hasWindowFocus) { 1691 mContentViewGestureHandler.onWindowFocusLost(); 1692 } 1693 } 1694 1695 public void onFocusChanged(boolean gainFocus) { 1696 if (!gainFocus) getContentViewClient().onImeStateChangeRequested(false); 1697 if (mNativeContentViewCore != 0) nativeSetFocus(mNativeContentViewCore, gainFocus); 1698 } 1699 1700 /** 1701 * @see View#onKeyUp(int, KeyEvent) 1702 */ 1703 public boolean onKeyUp(int keyCode, KeyEvent event) { 1704 if (mPopupZoomer.isShowing() && keyCode == KeyEvent.KEYCODE_BACK) { 1705 mPopupZoomer.hide(true); 1706 return true; 1707 } 1708 return mContainerViewInternals.super_onKeyUp(keyCode, event); 1709 } 1710 1711 /** 1712 * @see View#dispatchKeyEventPreIme(KeyEvent) 1713 */ 1714 public boolean dispatchKeyEventPreIme(KeyEvent event) { 1715 try { 1716 TraceEvent.begin(); 1717 if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && mImeAdapter.isActive()) { 1718 mUnfocusOnNextSizeChanged = true; 1719 } else { 1720 undoScrollFocusedEditableNodeIntoViewIfNeeded(false); 1721 } 1722 return mContainerViewInternals.super_dispatchKeyEventPreIme(event); 1723 } finally { 1724 TraceEvent.end(); 1725 } 1726 } 1727 1728 /** 1729 * @see View#dispatchKeyEvent(KeyEvent) 1730 */ 1731 public boolean dispatchKeyEvent(KeyEvent event) { 1732 if (getContentViewClient().shouldOverrideKeyEvent(event)) { 1733 return mContainerViewInternals.super_dispatchKeyEvent(event); 1734 } 1735 1736 if (mImeAdapter.dispatchKeyEvent(event)) return true; 1737 1738 return mContainerViewInternals.super_dispatchKeyEvent(event); 1739 } 1740 1741 /** 1742 * @see View#onHoverEvent(MotionEvent) 1743 * Mouse move events are sent on hover enter, hover move and hover exit. 1744 * They are sent on hover exit because sometimes it acts as both a hover 1745 * move and hover exit. 1746 */ 1747 public boolean onHoverEvent(MotionEvent event) { 1748 TraceEvent.begin("onHoverEvent"); 1749 mContainerView.removeCallbacks(mFakeMouseMoveRunnable); 1750 if (mBrowserAccessibilityManager != null) { 1751 return mBrowserAccessibilityManager.onHoverEvent(event); 1752 } 1753 if (mNativeContentViewCore != 0) { 1754 nativeSendMouseMoveEvent(mNativeContentViewCore, event.getEventTime(), 1755 event.getX(), event.getY()); 1756 } 1757 TraceEvent.end("onHoverEvent"); 1758 return true; 1759 } 1760 1761 /** 1762 * @see View#onGenericMotionEvent(MotionEvent) 1763 */ 1764 public boolean onGenericMotionEvent(MotionEvent event) { 1765 if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { 1766 switch (event.getAction()) { 1767 case MotionEvent.ACTION_SCROLL: 1768 nativeSendMouseWheelEvent(mNativeContentViewCore, event.getEventTime(), 1769 event.getX(), event.getY(), 1770 event.getAxisValue(MotionEvent.AXIS_VSCROLL)); 1771 1772 mContainerView.removeCallbacks(mFakeMouseMoveRunnable); 1773 // Send a delayed onMouseMove event so that we end 1774 // up hovering over the right position after the scroll. 1775 final MotionEvent eventFakeMouseMove = MotionEvent.obtain(event); 1776 mFakeMouseMoveRunnable = new Runnable() { 1777 @Override 1778 public void run() { 1779 onHoverEvent(eventFakeMouseMove); 1780 } 1781 }; 1782 mContainerView.postDelayed(mFakeMouseMoveRunnable, 250); 1783 return true; 1784 } 1785 } 1786 return mContainerViewInternals.super_onGenericMotionEvent(event); 1787 } 1788 1789 /** 1790 * @see View#scrollBy(int, int) 1791 * Currently the ContentView scrolling happens in the native side. In 1792 * the Java view system, it is always pinned at (0, 0). scrollBy() and scrollTo() 1793 * are overridden, so that View's mScrollX and mScrollY will be unchanged at 1794 * (0, 0). This is critical for drawing ContentView correctly. 1795 */ 1796 public void scrollBy(int xPix, int yPix) { 1797 if (mNativeContentViewCore != 0) { 1798 nativeScrollBy(mNativeContentViewCore, 1799 System.currentTimeMillis(), 0, 0, xPix, yPix); 1800 } 1801 } 1802 1803 /** 1804 * @see View#scrollTo(int, int) 1805 */ 1806 public void scrollTo(int xPix, int yPix) { 1807 if (mNativeContentViewCore == 0) return; 1808 final float xCurrentPix = mRenderCoordinates.getScrollXPix(); 1809 final float yCurrentPix = mRenderCoordinates.getScrollYPix(); 1810 final float dxPix = xPix - xCurrentPix; 1811 final float dyPix = yPix - yCurrentPix; 1812 if (dxPix != 0 || dyPix != 0) { 1813 long time = System.currentTimeMillis(); 1814 nativeScrollBegin(mNativeContentViewCore, time, xCurrentPix, yCurrentPix); 1815 nativeScrollBy(mNativeContentViewCore, 1816 time, xCurrentPix, yCurrentPix, dxPix, dyPix); 1817 nativeScrollEnd(mNativeContentViewCore, time); 1818 } 1819 } 1820 1821 // NOTE: this can go away once ContentView.getScrollX() reports correct values. 1822 // see: b/6029133 1823 public int getNativeScrollXForTest() { 1824 return mRenderCoordinates.getScrollXPixInt(); 1825 } 1826 1827 // NOTE: this can go away once ContentView.getScrollY() reports correct values. 1828 // see: b/6029133 1829 public int getNativeScrollYForTest() { 1830 return mRenderCoordinates.getScrollYPixInt(); 1831 } 1832 1833 /** 1834 * @see View#computeHorizontalScrollExtent() 1835 */ 1836 @SuppressWarnings("javadoc") 1837 public int computeHorizontalScrollExtent() { 1838 return mRenderCoordinates.getLastFrameViewportWidthPixInt(); 1839 } 1840 1841 /** 1842 * @see View#computeHorizontalScrollOffset() 1843 */ 1844 @SuppressWarnings("javadoc") 1845 public int computeHorizontalScrollOffset() { 1846 return mRenderCoordinates.getScrollXPixInt(); 1847 } 1848 1849 /** 1850 * @see View#computeHorizontalScrollRange() 1851 */ 1852 @SuppressWarnings("javadoc") 1853 public int computeHorizontalScrollRange() { 1854 return mRenderCoordinates.getContentWidthPixInt(); 1855 } 1856 1857 /** 1858 * @see View#computeVerticalScrollExtent() 1859 */ 1860 @SuppressWarnings("javadoc") 1861 public int computeVerticalScrollExtent() { 1862 return mRenderCoordinates.getLastFrameViewportHeightPixInt(); 1863 } 1864 1865 /** 1866 * @see View#computeVerticalScrollOffset() 1867 */ 1868 @SuppressWarnings("javadoc") 1869 public int computeVerticalScrollOffset() { 1870 return mRenderCoordinates.getScrollYPixInt(); 1871 } 1872 1873 /** 1874 * @see View#computeVerticalScrollRange() 1875 */ 1876 @SuppressWarnings("javadoc") 1877 public int computeVerticalScrollRange() { 1878 return mRenderCoordinates.getContentHeightPixInt(); 1879 } 1880 1881 // End FrameLayout overrides. 1882 1883 /** 1884 * @see View#awakenScrollBars(int, boolean) 1885 */ 1886 @SuppressWarnings("javadoc") 1887 public boolean awakenScrollBars(int startDelay, boolean invalidate) { 1888 // For the default implementation of ContentView which draws the scrollBars on the native 1889 // side, calling this function may get us into a bad state where we keep drawing the 1890 // scrollBars, so disable it by always returning false. 1891 if (mContainerView.getScrollBarStyle() == View.SCROLLBARS_INSIDE_OVERLAY) { 1892 return false; 1893 } else { 1894 return mContainerViewInternals.super_awakenScrollBars(startDelay, invalidate); 1895 } 1896 } 1897 1898 /** 1899 * Called by native side when the corresponding renderer crashes. Note that if a renderer is 1900 * shared between tabs, this might be called multiple times while the tab is crashed. This is 1901 * because the tabs sharing a renderer also share RenderProcessHost. When one of those tabs 1902 * reloads and a new renderer is created for the shared RenderProcessHost, all tabs are notified 1903 * in onRenderProcessSwap(), not only the one that reloads. If this renderer dies, all the other 1904 * dead tabs are notified again. 1905 * @param alreadyCrashed true iff this tab is already in crashed state but the shared renderer 1906 * resurrected and died again since the last time this was called. 1907 */ 1908 @SuppressWarnings("unused") 1909 @CalledByNative 1910 private void onTabCrash(boolean alreadyCrashed) { 1911 assert mPid != 0; 1912 if (!alreadyCrashed) { 1913 getContentViewClient().onRendererCrash( 1914 ChildProcessLauncher.getBindingManager().isOomProtected(mPid)); 1915 } 1916 mPid = 0; 1917 } 1918 1919 private void handleTapOrPress( 1920 long timeMs, float xPix, float yPix, int isLongPressOrTap, boolean showPress) { 1921 if (mContainerView.isFocusable() && mContainerView.isFocusableInTouchMode() 1922 && !mContainerView.isFocused()) { 1923 mContainerView.requestFocus(); 1924 } 1925 1926 if (!mPopupZoomer.isShowing()) mPopupZoomer.setLastTouch(xPix, yPix); 1927 1928 if (isLongPressOrTap == IS_LONG_PRESS) { 1929 getInsertionHandleController().allowAutomaticShowing(); 1930 getSelectionHandleController().allowAutomaticShowing(); 1931 if (mNativeContentViewCore != 0) { 1932 nativeLongPress(mNativeContentViewCore, timeMs, xPix, yPix, false); 1933 } 1934 } else if (isLongPressOrTap == IS_LONG_TAP) { 1935 getInsertionHandleController().allowAutomaticShowing(); 1936 getSelectionHandleController().allowAutomaticShowing(); 1937 if (mNativeContentViewCore != 0) { 1938 nativeLongTap(mNativeContentViewCore, timeMs, xPix, yPix, false); 1939 } 1940 } else { 1941 if (!showPress && mNativeContentViewCore != 0) { 1942 nativeShowPressState(mNativeContentViewCore, timeMs, xPix, yPix); 1943 } 1944 if (mSelectionEditable) getInsertionHandleController().allowAutomaticShowing(); 1945 if (mNativeContentViewCore != 0) { 1946 nativeSingleTap(mNativeContentViewCore, timeMs, xPix, yPix, false); 1947 } 1948 } 1949 } 1950 1951 public void setZoomControlsDelegate(ZoomControlsDelegate zoomControlsDelegate) { 1952 mZoomControlsDelegate = zoomControlsDelegate; 1953 } 1954 1955 public void updateMultiTouchZoomSupport(boolean supportsMultiTouchZoom) { 1956 mZoomManager.updateMultiTouchSupport(supportsMultiTouchZoom); 1957 } 1958 1959 public void updateDoubleTapDragSupport(boolean supportsDoubleTapDrag) { 1960 mContentViewGestureHandler.updateDoubleTapDragSupport(supportsDoubleTapDrag); 1961 } 1962 1963 public void selectPopupMenuItems(int[] indices) { 1964 if (mNativeContentViewCore != 0) { 1965 nativeSelectPopupMenuItems(mNativeContentViewCore, indices); 1966 } 1967 } 1968 1969 /** 1970 * Get the screen orientation from the OS and push it to WebKit. 1971 * 1972 * TODO(husky): Add a hook for mock orientations. 1973 * 1974 * TODO(husky): Currently each new tab starts with an orientation of 0 until you actually 1975 * rotate the device. This is wrong if you actually started in landscape mode. To fix this, we 1976 * need to push the correct orientation, but only after WebKit's Frame object has been fully 1977 * initialized. Need to find a good time to do that. onPageFinished() would probably work but 1978 * it isn't implemented yet. 1979 */ 1980 private void sendOrientationChangeEvent() { 1981 if (mNativeContentViewCore == 0) return; 1982 1983 WindowManager windowManager = 1984 (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); 1985 switch (windowManager.getDefaultDisplay().getRotation()) { 1986 case Surface.ROTATION_90: 1987 nativeSendOrientationChangeEvent(mNativeContentViewCore, 90); 1988 break; 1989 case Surface.ROTATION_180: 1990 nativeSendOrientationChangeEvent(mNativeContentViewCore, 180); 1991 break; 1992 case Surface.ROTATION_270: 1993 nativeSendOrientationChangeEvent(mNativeContentViewCore, -90); 1994 break; 1995 case Surface.ROTATION_0: 1996 nativeSendOrientationChangeEvent(mNativeContentViewCore, 0); 1997 break; 1998 default: 1999 Log.w(TAG, "Unknown rotation!"); 2000 break; 2001 } 2002 } 2003 2004 /** 2005 * Register the delegate to be used when content can not be handled by 2006 * the rendering engine, and should be downloaded instead. This will replace 2007 * the current delegate, if any. 2008 * @param delegate An implementation of ContentViewDownloadDelegate. 2009 */ 2010 public void setDownloadDelegate(ContentViewDownloadDelegate delegate) { 2011 mDownloadDelegate = delegate; 2012 } 2013 2014 // Called by DownloadController. 2015 ContentViewDownloadDelegate getDownloadDelegate() { 2016 return mDownloadDelegate; 2017 } 2018 2019 private SelectionHandleController getSelectionHandleController() { 2020 if (mSelectionHandleController == null) { 2021 mSelectionHandleController = new SelectionHandleController(getContainerView()) { 2022 @Override 2023 public void selectBetweenCoordinates(int x1, int y1, int x2, int y2) { 2024 if (mNativeContentViewCore != 0 && !(x1 == x2 && y1 == y2)) { 2025 nativeSelectBetweenCoordinates(mNativeContentViewCore, 2026 x1, y1 - mRenderCoordinates.getContentOffsetYPix(), 2027 x2, y2 - mRenderCoordinates.getContentOffsetYPix()); 2028 } 2029 } 2030 2031 @Override 2032 public void showHandles(int startDir, int endDir) { 2033 super.showHandles(startDir, endDir); 2034 showSelectActionBar(); 2035 } 2036 2037 }; 2038 2039 mSelectionHandleController.hideAndDisallowAutomaticShowing(); 2040 } 2041 2042 return mSelectionHandleController; 2043 } 2044 2045 private InsertionHandleController getInsertionHandleController() { 2046 if (mInsertionHandleController == null) { 2047 mInsertionHandleController = new InsertionHandleController(getContainerView()) { 2048 private static final int AVERAGE_LINE_HEIGHT = 14; 2049 2050 @Override 2051 public void setCursorPosition(int x, int y) { 2052 if (mNativeContentViewCore != 0) { 2053 nativeMoveCaret(mNativeContentViewCore, 2054 x, y - mRenderCoordinates.getContentOffsetYPix()); 2055 } 2056 } 2057 2058 @Override 2059 public void paste() { 2060 mImeAdapter.paste(); 2061 hideHandles(); 2062 } 2063 2064 @Override 2065 public int getLineHeight() { 2066 return (int) Math.ceil( 2067 mRenderCoordinates.fromLocalCssToPix(AVERAGE_LINE_HEIGHT)); 2068 } 2069 2070 @Override 2071 public void showHandle() { 2072 super.showHandle(); 2073 } 2074 }; 2075 2076 mInsertionHandleController.hideAndDisallowAutomaticShowing(); 2077 } 2078 2079 return mInsertionHandleController; 2080 } 2081 2082 @VisibleForTesting 2083 public InsertionHandleController getInsertionHandleControllerForTest() { 2084 return mInsertionHandleController; 2085 } 2086 2087 @VisibleForTesting 2088 public SelectionHandleController getSelectionHandleControllerForTest() { 2089 return mSelectionHandleController; 2090 } 2091 2092 private void updateHandleScreenPositions() { 2093 if (isSelectionHandleShowing()) { 2094 mSelectionHandleController.setStartHandlePosition( 2095 mStartHandlePoint.getXPix(), mStartHandlePoint.getYPix()); 2096 mSelectionHandleController.setEndHandlePosition( 2097 mEndHandlePoint.getXPix(), mEndHandlePoint.getYPix()); 2098 } 2099 2100 if (isInsertionHandleShowing()) { 2101 mInsertionHandleController.setHandlePosition( 2102 mInsertionHandlePoint.getXPix(), mInsertionHandlePoint.getYPix()); 2103 } 2104 } 2105 2106 private void hideHandles() { 2107 if (mSelectionHandleController != null) { 2108 mSelectionHandleController.hideAndDisallowAutomaticShowing(); 2109 } 2110 if (mInsertionHandleController != null) { 2111 mInsertionHandleController.hideAndDisallowAutomaticShowing(); 2112 } 2113 } 2114 2115 private void showSelectActionBar() { 2116 if (mActionMode != null) { 2117 mActionMode.invalidate(); 2118 return; 2119 } 2120 2121 // Start a new action mode with a SelectActionModeCallback. 2122 SelectActionModeCallback.ActionHandler actionHandler = 2123 new SelectActionModeCallback.ActionHandler() { 2124 @Override 2125 public void selectAll() { 2126 mImeAdapter.selectAll(); 2127 } 2128 2129 @Override 2130 public void cut() { 2131 mImeAdapter.cut(); 2132 } 2133 2134 @Override 2135 public void copy() { 2136 mImeAdapter.copy(); 2137 } 2138 2139 @Override 2140 public void paste() { 2141 mImeAdapter.paste(); 2142 } 2143 2144 @Override 2145 public void share() { 2146 final String query = getSelectedText(); 2147 if (TextUtils.isEmpty(query)) return; 2148 2149 Intent send = new Intent(Intent.ACTION_SEND); 2150 send.setType("text/plain"); 2151 send.putExtra(Intent.EXTRA_TEXT, query); 2152 try { 2153 Intent i = Intent.createChooser(send, getContext().getString( 2154 R.string.actionbar_share)); 2155 i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2156 getContext().startActivity(i); 2157 } catch (android.content.ActivityNotFoundException ex) { 2158 // If no app handles it, do nothing. 2159 } 2160 } 2161 2162 @Override 2163 public void search() { 2164 final String query = getSelectedText(); 2165 if (TextUtils.isEmpty(query)) return; 2166 2167 // See if ContentViewClient wants to override 2168 if (getContentViewClient().doesPerformWebSearch()) { 2169 getContentViewClient().performWebSearch(query); 2170 return; 2171 } 2172 2173 Intent i = new Intent(Intent.ACTION_WEB_SEARCH); 2174 i.putExtra(SearchManager.EXTRA_NEW_SEARCH, true); 2175 i.putExtra(SearchManager.QUERY, query); 2176 i.putExtra(Browser.EXTRA_APPLICATION_ID, getContext().getPackageName()); 2177 if (!(getContext() instanceof Activity)) { 2178 i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2179 } 2180 try { 2181 getContext().startActivity(i); 2182 } catch (android.content.ActivityNotFoundException ex) { 2183 // If no app handles it, do nothing. 2184 } 2185 } 2186 2187 @Override 2188 public boolean isSelectionEditable() { 2189 return mSelectionEditable; 2190 } 2191 2192 @Override 2193 public void onDestroyActionMode() { 2194 mActionMode = null; 2195 if (mUnselectAllOnActionModeDismiss) mImeAdapter.unselect(); 2196 getContentViewClient().onContextualActionBarHidden(); 2197 } 2198 2199 @Override 2200 public boolean isShareAvailable() { 2201 Intent intent = new Intent(Intent.ACTION_SEND); 2202 intent.setType("text/plain"); 2203 return getContext().getPackageManager().queryIntentActivities(intent, 2204 PackageManager.MATCH_DEFAULT_ONLY).size() > 0; 2205 } 2206 2207 @Override 2208 public boolean isWebSearchAvailable() { 2209 if (getContentViewClient().doesPerformWebSearch()) return true; 2210 Intent intent = new Intent(Intent.ACTION_WEB_SEARCH); 2211 intent.putExtra(SearchManager.EXTRA_NEW_SEARCH, true); 2212 return getContext().getPackageManager().queryIntentActivities(intent, 2213 PackageManager.MATCH_DEFAULT_ONLY).size() > 0; 2214 } 2215 }; 2216 mActionMode = null; 2217 // On ICS, startActionMode throws an NPE when getParent() is null. 2218 if (mContainerView.getParent() != null) { 2219 mActionMode = mContainerView.startActionMode( 2220 getContentViewClient().getSelectActionModeCallback(getContext(), actionHandler, 2221 nativeIsIncognito(mNativeContentViewCore))); 2222 } 2223 mUnselectAllOnActionModeDismiss = true; 2224 if (mActionMode == null) { 2225 // There is no ActionMode, so remove the selection. 2226 mImeAdapter.unselect(); 2227 } else { 2228 getContentViewClient().onContextualActionBarShown(); 2229 } 2230 } 2231 2232 public boolean getUseDesktopUserAgent() { 2233 if (mNativeContentViewCore != 0) { 2234 return nativeGetUseDesktopUserAgent(mNativeContentViewCore); 2235 } 2236 return false; 2237 } 2238 2239 /** 2240 * Set whether or not we're using a desktop user agent for the currently loaded page. 2241 * @param override If true, use a desktop user agent. Use a mobile one otherwise. 2242 * @param reloadOnChange Reload the page if the UA has changed. 2243 */ 2244 public void setUseDesktopUserAgent(boolean override, boolean reloadOnChange) { 2245 if (mNativeContentViewCore != 0) { 2246 nativeSetUseDesktopUserAgent(mNativeContentViewCore, override, reloadOnChange); 2247 } 2248 } 2249 2250 public void clearSslPreferences() { 2251 nativeClearSslPreferences(mNativeContentViewCore); 2252 } 2253 2254 /** 2255 * @return Whether the native ContentView has crashed. 2256 */ 2257 public boolean isCrashed() { 2258 if (mNativeContentViewCore == 0) return false; 2259 return nativeCrashed(mNativeContentViewCore); 2260 } 2261 2262 private boolean isSelectionHandleShowing() { 2263 return mSelectionHandleController != null && mSelectionHandleController.isShowing(); 2264 } 2265 2266 private boolean isInsertionHandleShowing() { 2267 return mInsertionHandleController != null && mInsertionHandleController.isShowing(); 2268 } 2269 2270 private void updateTextHandlesForGesture(int type) { 2271 switch(type) { 2272 case ContentViewGestureHandler.GESTURE_DOUBLE_TAP: 2273 case ContentViewGestureHandler.GESTURE_SCROLL_START: 2274 case ContentViewGestureHandler.GESTURE_FLING_START: 2275 case ContentViewGestureHandler.GESTURE_PINCH_BEGIN: 2276 temporarilyHideTextHandles(); 2277 break; 2278 2279 default: 2280 break; 2281 } 2282 } 2283 2284 // Makes the insertion/selection handles invisible. They will fade back in shortly after the 2285 // last call to scheduleTextHandleFadeIn (or temporarilyHideTextHandles). 2286 private void temporarilyHideTextHandles() { 2287 if (isSelectionHandleShowing()) { 2288 mSelectionHandleController.setHandleVisibility(HandleView.INVISIBLE); 2289 } 2290 if (isInsertionHandleShowing()) { 2291 mInsertionHandleController.setHandleVisibility(HandleView.INVISIBLE); 2292 } 2293 scheduleTextHandleFadeIn(); 2294 } 2295 2296 private boolean allowTextHandleFadeIn() { 2297 if (mContentViewGestureHandler.isNativeScrolling() || 2298 mContentViewGestureHandler.isNativePinching()) { 2299 return false; 2300 } 2301 2302 if (mPopupZoomer.isShowing()) return false; 2303 2304 return true; 2305 } 2306 2307 // Cancels any pending fade in and schedules a new one. 2308 private void scheduleTextHandleFadeIn() { 2309 if (!isInsertionHandleShowing() && !isSelectionHandleShowing()) return; 2310 2311 if (mDeferredHandleFadeInRunnable == null) { 2312 mDeferredHandleFadeInRunnable = new Runnable() { 2313 @Override 2314 public void run() { 2315 if (!allowTextHandleFadeIn()) { 2316 // Delay fade in until it is allowed. 2317 scheduleTextHandleFadeIn(); 2318 } else { 2319 if (isSelectionHandleShowing()) { 2320 mSelectionHandleController.beginHandleFadeIn(); 2321 } 2322 if (isInsertionHandleShowing()) { 2323 mInsertionHandleController.beginHandleFadeIn(); 2324 } 2325 } 2326 } 2327 }; 2328 } 2329 2330 mContainerView.removeCallbacks(mDeferredHandleFadeInRunnable); 2331 mContainerView.postDelayed(mDeferredHandleFadeInRunnable, TEXT_HANDLE_FADE_IN_DELAY); 2332 } 2333 2334 /** 2335 * Shows the IME if the focused widget could accept text input. 2336 */ 2337 public void showImeIfNeeded() { 2338 if (mNativeContentViewCore != 0) nativeShowImeIfNeeded(mNativeContentViewCore); 2339 } 2340 2341 @SuppressWarnings("unused") 2342 @CalledByNative 2343 private void updateFrameInfo( 2344 float scrollOffsetX, float scrollOffsetY, 2345 float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor, 2346 float contentWidth, float contentHeight, 2347 float viewportWidth, float viewportHeight, 2348 float controlsOffsetYCss, float contentOffsetYCss, 2349 float overdrawBottomHeightCss) { 2350 TraceEvent.instant("ContentViewCore:updateFrameInfo"); 2351 // Adjust contentWidth/Height to be always at least as big as 2352 // the actual viewport (as set by onSizeChanged). 2353 contentWidth = Math.max(contentWidth, 2354 mRenderCoordinates.fromPixToLocalCss(mViewportWidthPix)); 2355 contentHeight = Math.max(contentHeight, 2356 mRenderCoordinates.fromPixToLocalCss(mViewportHeightPix)); 2357 2358 final float contentOffsetYPix = mRenderCoordinates.fromDipToPix(contentOffsetYCss); 2359 2360 final boolean contentSizeChanged = 2361 contentWidth != mRenderCoordinates.getContentWidthCss() 2362 || contentHeight != mRenderCoordinates.getContentHeightCss(); 2363 final boolean scaleLimitsChanged = 2364 minPageScaleFactor != mRenderCoordinates.getMinPageScaleFactor() 2365 || maxPageScaleFactor != mRenderCoordinates.getMaxPageScaleFactor(); 2366 final boolean pageScaleChanged = 2367 pageScaleFactor != mRenderCoordinates.getPageScaleFactor(); 2368 final boolean scrollChanged = 2369 pageScaleChanged 2370 || scrollOffsetX != mRenderCoordinates.getScrollX() 2371 || scrollOffsetY != mRenderCoordinates.getScrollY(); 2372 final boolean contentOffsetChanged = 2373 contentOffsetYPix != mRenderCoordinates.getContentOffsetYPix(); 2374 2375 final boolean needHidePopupZoomer = contentSizeChanged || scrollChanged; 2376 final boolean needUpdateZoomControls = scaleLimitsChanged || scrollChanged; 2377 final boolean needTemporarilyHideHandles = scrollChanged; 2378 2379 if (needHidePopupZoomer) mPopupZoomer.hide(true); 2380 2381 if (pageScaleChanged) { 2382 // This function should be called back from native as soon 2383 // as the scroll is applied to the backbuffer. We should only 2384 // update mNativeScrollX/Y here for consistency. 2385 getContentViewClient().onScaleChanged( 2386 mRenderCoordinates.getPageScaleFactor(), pageScaleFactor); 2387 } 2388 2389 mRenderCoordinates.updateFrameInfo( 2390 scrollOffsetX, scrollOffsetY, 2391 contentWidth, contentHeight, 2392 viewportWidth, viewportHeight, 2393 pageScaleFactor, minPageScaleFactor, maxPageScaleFactor, 2394 contentOffsetYPix); 2395 2396 if (needTemporarilyHideHandles) temporarilyHideTextHandles(); 2397 if (needUpdateZoomControls) mZoomControlsDelegate.updateZoomControls(); 2398 if (contentOffsetChanged) updateHandleScreenPositions(); 2399 2400 // Update offsets for fullscreen. 2401 final float deviceScale = mRenderCoordinates.getDeviceScaleFactor(); 2402 final float controlsOffsetPix = controlsOffsetYCss * deviceScale; 2403 final float overdrawBottomHeightPix = overdrawBottomHeightCss * deviceScale; 2404 getContentViewClient().onOffsetsForFullscreenChanged( 2405 controlsOffsetPix, contentOffsetYPix, overdrawBottomHeightPix); 2406 2407 mPendingRendererFrame = true; 2408 if (mBrowserAccessibilityManager != null) { 2409 mBrowserAccessibilityManager.notifyFrameInfoInitialized(); 2410 } 2411 2412 // Update geometry for external video surface. 2413 getContentViewClient().onGeometryChanged(-1, null); 2414 } 2415 2416 @SuppressWarnings("unused") 2417 @CalledByNative 2418 private void updateImeAdapter(int nativeImeAdapterAndroid, int textInputType, 2419 String text, int selectionStart, int selectionEnd, 2420 int compositionStart, int compositionEnd, boolean showImeIfNeeded) { 2421 TraceEvent.begin(); 2422 mSelectionEditable = (textInputType != ImeAdapter.getTextInputTypeNone()); 2423 2424 if (mActionMode != null) mActionMode.invalidate(); 2425 2426 mImeAdapter.attachAndShowIfNeeded(nativeImeAdapterAndroid, textInputType, 2427 selectionStart, selectionEnd, showImeIfNeeded); 2428 2429 if (mInputConnection != null) { 2430 mInputConnection.setEditableText(text, selectionStart, selectionEnd, 2431 compositionStart, compositionEnd); 2432 } 2433 TraceEvent.end(); 2434 } 2435 2436 @SuppressWarnings("unused") 2437 @CalledByNative 2438 private void processImeBatchStateAck(boolean isBegin) { 2439 if (mInputConnection == null) return; 2440 mInputConnection.setIgnoreTextInputStateUpdates(isBegin); 2441 } 2442 2443 @SuppressWarnings("unused") 2444 @CalledByNative 2445 private void setTitle(String title) { 2446 getContentViewClient().onUpdateTitle(title); 2447 } 2448 2449 /** 2450 * Called (from native) when the <select> popup needs to be shown. 2451 * @param items Items to show. 2452 * @param enabled POPUP_ITEM_TYPEs for items. 2453 * @param multiple Whether the popup menu should support multi-select. 2454 * @param selectedIndices Indices of selected items. 2455 */ 2456 @SuppressWarnings("unused") 2457 @CalledByNative 2458 private void showSelectPopup(String[] items, int[] enabled, boolean multiple, 2459 int[] selectedIndices) { 2460 SelectPopupDialog.show(this, items, enabled, multiple, selectedIndices); 2461 } 2462 2463 @SuppressWarnings("unused") 2464 @CalledByNative 2465 private void showDisambiguationPopup(Rect targetRect, Bitmap zoomedBitmap) { 2466 mPopupZoomer.setBitmap(zoomedBitmap); 2467 mPopupZoomer.show(targetRect); 2468 temporarilyHideTextHandles(); 2469 } 2470 2471 @SuppressWarnings("unused") 2472 @CalledByNative 2473 private GenericTouchGesture createOnePointTouchGesture(int startX, 2474 int startY, int deltaX, int deltaY) { 2475 return new GenericTouchGesture(this, startX, startY, deltaX, deltaY); 2476 } 2477 2478 @SuppressWarnings("unused") 2479 @CalledByNative 2480 private GenericTouchGesture createTwoPointTouchGesture( 2481 int startX0, int startY0, int deltaX0, int deltaY0, 2482 int startX1, int startY1, int deltaX1, int deltaY1) { 2483 return new GenericTouchGesture(this, startX0, startY0, deltaX0, deltaY0, 2484 startX1, startY1, deltaX1, deltaY1); 2485 } 2486 2487 @SuppressWarnings("unused") 2488 @CalledByNative 2489 private void onSelectionChanged(String text) { 2490 mLastSelectedText = text; 2491 } 2492 2493 @SuppressWarnings("unused") 2494 @CalledByNative 2495 private void onSelectionBoundsChanged(Rect anchorRectDip, int anchorDir, Rect focusRectDip, 2496 int focusDir, boolean isAnchorFirst) { 2497 // All coordinates are in DIP. 2498 int x1 = anchorRectDip.left; 2499 int y1 = anchorRectDip.bottom; 2500 int x2 = focusRectDip.left; 2501 int y2 = focusRectDip.bottom; 2502 2503 if (x1 != x2 || y1 != y2 || 2504 (mSelectionHandleController != null && mSelectionHandleController.isDragging())) { 2505 if (mInsertionHandleController != null) { 2506 mInsertionHandleController.hide(); 2507 } 2508 if (isAnchorFirst) { 2509 mStartHandlePoint.setLocalDip(x1, y1); 2510 mEndHandlePoint.setLocalDip(x2, y2); 2511 } else { 2512 mStartHandlePoint.setLocalDip(x2, y2); 2513 mEndHandlePoint.setLocalDip(x1, y1); 2514 } 2515 2516 if (!getSelectionHandleController().isShowing()) { 2517 // TODO(cjhopman): Remove this when there is a better signal that long press caused 2518 // a selection. See http://crbug.com/150151. 2519 mContainerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); 2520 } 2521 2522 getSelectionHandleController().onSelectionChanged(anchorDir, focusDir); 2523 updateHandleScreenPositions(); 2524 mHasSelection = true; 2525 } else { 2526 mUnselectAllOnActionModeDismiss = false; 2527 hideSelectActionBar(); 2528 if (x1 != 0 && y1 != 0 && mSelectionEditable) { 2529 // Selection is a caret, and a text field is focused. 2530 if (mSelectionHandleController != null) { 2531 mSelectionHandleController.hide(); 2532 } 2533 mInsertionHandlePoint.setLocalDip(x1, y1); 2534 2535 getInsertionHandleController().onCursorPositionChanged(); 2536 updateHandleScreenPositions(); 2537 InputMethodManager manager = (InputMethodManager) 2538 getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 2539 if (manager.isWatchingCursor(mContainerView)) { 2540 final int xPix = (int) mInsertionHandlePoint.getXPix(); 2541 final int yPix = (int) mInsertionHandlePoint.getYPix(); 2542 manager.updateCursor(mContainerView, xPix, yPix, xPix, yPix); 2543 } 2544 } else { 2545 // Deselection 2546 if (mSelectionHandleController != null) { 2547 mSelectionHandleController.hideAndDisallowAutomaticShowing(); 2548 } 2549 if (mInsertionHandleController != null) { 2550 mInsertionHandleController.hideAndDisallowAutomaticShowing(); 2551 } 2552 } 2553 mHasSelection = false; 2554 } 2555 } 2556 2557 @SuppressWarnings("unused") 2558 @CalledByNative 2559 private static void onEvaluateJavaScriptResult( 2560 String jsonResult, JavaScriptCallback callback) { 2561 callback.handleJavaScriptResult(jsonResult); 2562 } 2563 2564 @SuppressWarnings("unused") 2565 @CalledByNative 2566 private void showPastePopup(int xDip, int yDip) { 2567 mInsertionHandlePoint.setLocalDip(xDip, yDip); 2568 getInsertionHandleController().showHandle(); 2569 updateHandleScreenPositions(); 2570 getInsertionHandleController().showHandleWithPastePopup(); 2571 } 2572 2573 @SuppressWarnings("unused") 2574 @CalledByNative 2575 private void onRenderProcessSwap(int oldPid, int newPid) { 2576 assert mPid == oldPid || mPid == newPid; 2577 if (mAttachedToWindow && oldPid != newPid) { 2578 ChildProcessLauncher.getBindingManager().unbindAsHighPriority(oldPid); 2579 ChildProcessLauncher.getBindingManager().bindAsHighPriority(newPid); 2580 } 2581 2582 // We want to remove the initial binding even if the ContentView is not attached, so that 2583 // renderers for ContentViews loading in background do not retain the high priority. 2584 ChildProcessLauncher.getBindingManager().removeInitialBinding(newPid); 2585 mPid = newPid; 2586 } 2587 2588 @SuppressWarnings("unused") 2589 @CalledByNative 2590 private void onWebContentsConnected() { 2591 if (mImeAdapter != null && 2592 !mImeAdapter.isNativeImeAdapterAttached() && mNativeContentViewCore != 0) { 2593 mImeAdapter.attach(nativeGetNativeImeAdapter(mNativeContentViewCore)); 2594 } 2595 } 2596 2597 @SuppressWarnings("unused") 2598 @CalledByNative 2599 private void onWebContentsSwapped() { 2600 if (mImeAdapter != null && mNativeContentViewCore != 0) { 2601 mImeAdapter.attach(nativeGetNativeImeAdapter(mNativeContentViewCore)); 2602 } 2603 } 2604 2605 /** 2606 * @return Whether a reload happens when this ContentView is activated. 2607 */ 2608 public boolean needsReload() { 2609 return mNativeContentViewCore != 0 && nativeNeedsReload(mNativeContentViewCore); 2610 } 2611 2612 /** 2613 * @see View#hasFocus() 2614 */ 2615 @CalledByNative 2616 public boolean hasFocus() { 2617 return mContainerView.hasFocus(); 2618 } 2619 2620 /** 2621 * Checks whether the ContentViewCore can be zoomed in. 2622 * 2623 * @return True if the ContentViewCore can be zoomed in. 2624 */ 2625 // This method uses the term 'zoom' for legacy reasons, but relates 2626 // to what chrome calls the 'page scale factor'. 2627 public boolean canZoomIn() { 2628 final float zoomInExtent = mRenderCoordinates.getMaxPageScaleFactor() 2629 - mRenderCoordinates.getPageScaleFactor(); 2630 return zoomInExtent > ZOOM_CONTROLS_EPSILON; 2631 } 2632 2633 /** 2634 * Checks whether the ContentViewCore can be zoomed out. 2635 * 2636 * @return True if the ContentViewCore can be zoomed out. 2637 */ 2638 // This method uses the term 'zoom' for legacy reasons, but relates 2639 // to what chrome calls the 'page scale factor'. 2640 public boolean canZoomOut() { 2641 final float zoomOutExtent = mRenderCoordinates.getPageScaleFactor() 2642 - mRenderCoordinates.getMinPageScaleFactor(); 2643 return zoomOutExtent > ZOOM_CONTROLS_EPSILON; 2644 } 2645 2646 /** 2647 * Zooms in the ContentViewCore by 25% (or less if that would result in 2648 * zooming in more than possible). 2649 * 2650 * @return True if there was a zoom change, false otherwise. 2651 */ 2652 // This method uses the term 'zoom' for legacy reasons, but relates 2653 // to what chrome calls the 'page scale factor'. 2654 public boolean zoomIn() { 2655 if (!canZoomIn()) { 2656 return false; 2657 } 2658 return zoomByDelta(1.25f); 2659 } 2660 2661 /** 2662 * Zooms out the ContentViewCore by 20% (or less if that would result in 2663 * zooming out more than possible). 2664 * 2665 * @return True if there was a zoom change, false otherwise. 2666 */ 2667 // This method uses the term 'zoom' for legacy reasons, but relates 2668 // to what chrome calls the 'page scale factor'. 2669 public boolean zoomOut() { 2670 if (!canZoomOut()) { 2671 return false; 2672 } 2673 return zoomByDelta(0.8f); 2674 } 2675 2676 /** 2677 * Resets the zoom factor of the ContentViewCore. 2678 * 2679 * @return True if there was a zoom change, false otherwise. 2680 */ 2681 // This method uses the term 'zoom' for legacy reasons, but relates 2682 // to what chrome calls the 'page scale factor'. 2683 public boolean zoomReset() { 2684 // The page scale factor is initialized to mNativeMinimumScale when 2685 // the page finishes loading. Thus sets it back to mNativeMinimumScale. 2686 if (!canZoomOut()) return false; 2687 return zoomByDelta( 2688 mRenderCoordinates.getMinPageScaleFactor() 2689 / mRenderCoordinates.getPageScaleFactor()); 2690 } 2691 2692 private boolean zoomByDelta(float delta) { 2693 if (mNativeContentViewCore == 0) { 2694 return false; 2695 } 2696 2697 long timeMs = System.currentTimeMillis(); 2698 int xPix = getViewportWidthPix() / 2; 2699 int yPix = getViewportHeightPix() / 2; 2700 2701 getContentViewGestureHandler().pinchBegin(timeMs, xPix, yPix); 2702 getContentViewGestureHandler().pinchBy(timeMs, xPix, yPix, delta); 2703 getContentViewGestureHandler().pinchEnd(timeMs); 2704 2705 return true; 2706 } 2707 2708 /** 2709 * Invokes the graphical zoom picker widget for this ContentView. 2710 */ 2711 @Override 2712 public void invokeZoomPicker() { 2713 mZoomControlsDelegate.invokeZoomPicker(); 2714 } 2715 2716 /** 2717 * This will mimic {@link #addPossiblyUnsafeJavascriptInterface(Object, String, Class)} 2718 * and automatically pass in {@link JavascriptInterface} as the required annotation. 2719 * 2720 * @param object The Java object to inject into the ContentViewCore's JavaScript context. Null 2721 * values are ignored. 2722 * @param name The name used to expose the instance in JavaScript. 2723 */ 2724 public void addJavascriptInterface(Object object, String name) { 2725 addPossiblyUnsafeJavascriptInterface(object, name, JavascriptInterface.class); 2726 } 2727 2728 /** 2729 * This method injects the supplied Java object into the ContentViewCore. 2730 * The object is injected into the JavaScript context of the main frame, 2731 * using the supplied name. This allows the Java object to be accessed from 2732 * JavaScript. Note that that injected objects will not appear in 2733 * JavaScript until the page is next (re)loaded. For example: 2734 * <pre> view.addJavascriptInterface(new Object(), "injectedObject"); 2735 * view.loadData("<!DOCTYPE html><title></title>", "text/html", null); 2736 * view.loadUrl("javascript:alert(injectedObject.toString())");</pre> 2737 * <p><strong>IMPORTANT:</strong> 2738 * <ul> 2739 * <li> addJavascriptInterface() can be used to allow JavaScript to control 2740 * the host application. This is a powerful feature, but also presents a 2741 * security risk. Use of this method in a ContentViewCore containing 2742 * untrusted content could allow an attacker to manipulate the host 2743 * application in unintended ways, executing Java code with the permissions 2744 * of the host application. Use extreme care when using this method in a 2745 * ContentViewCore which could contain untrusted content. Particular care 2746 * should be taken to avoid unintentional access to inherited methods, such 2747 * as {@link Object#getClass()}. To prevent access to inherited methods, 2748 * pass an annotation for {@code requiredAnnotation}. This will ensure 2749 * that only methods with {@code requiredAnnotation} are exposed to the 2750 * Javascript layer. {@code requiredAnnotation} will be passed to all 2751 * subsequently injected Java objects if any methods return an object. This 2752 * means the same restrictions (or lack thereof) will apply. Alternatively, 2753 * {@link #addJavascriptInterface(Object, String)} can be called, which 2754 * automatically uses the {@link JavascriptInterface} annotation. 2755 * <li> JavaScript interacts with Java objects on a private, background 2756 * thread of the ContentViewCore. Care is therefore required to maintain 2757 * thread safety.</li> 2758 * </ul></p> 2759 * 2760 * @param object The Java object to inject into the 2761 * ContentViewCore's JavaScript context. Null 2762 * values are ignored. 2763 * @param name The name used to expose the instance in 2764 * JavaScript. 2765 * @param requiredAnnotation Restrict exposed methods to ones with this 2766 * annotation. If {@code null} all methods are 2767 * exposed. 2768 * 2769 */ 2770 public void addPossiblyUnsafeJavascriptInterface(Object object, String name, 2771 Class<? extends Annotation> requiredAnnotation) { 2772 if (mNativeContentViewCore != 0 && object != null) { 2773 mJavaScriptInterfaces.put(name, object); 2774 nativeAddJavascriptInterface(mNativeContentViewCore, object, name, requiredAnnotation, 2775 mRetainedJavaScriptObjects); 2776 } 2777 } 2778 2779 /** 2780 * Removes a previously added JavaScript interface with the given name. 2781 * 2782 * @param name The name of the interface to remove. 2783 */ 2784 public void removeJavascriptInterface(String name) { 2785 mJavaScriptInterfaces.remove(name); 2786 if (mNativeContentViewCore != 0) { 2787 nativeRemoveJavascriptInterface(mNativeContentViewCore, name); 2788 } 2789 } 2790 2791 /** 2792 * Return the current scale of the ContentView. 2793 * @return The current page scale factor. 2794 */ 2795 public float getScale() { 2796 return mRenderCoordinates.getPageScaleFactor(); 2797 } 2798 2799 /** 2800 * If the view is ready to draw contents to the screen. In hardware mode, 2801 * the initialization of the surface texture may not occur until after the 2802 * view has been added to the layout. This method will return {@code true} 2803 * once the texture is actually ready. 2804 */ 2805 public boolean isReady() { 2806 return nativeIsRenderWidgetHostViewReady(mNativeContentViewCore); 2807 } 2808 2809 @CalledByNative 2810 private void startContentIntent(String contentUrl) { 2811 getContentViewClient().onStartContentIntent(getContext(), contentUrl); 2812 } 2813 2814 @Override 2815 public void onAccessibilityStateChanged(boolean enabled) { 2816 setAccessibilityState(enabled); 2817 } 2818 2819 /** 2820 * Determines whether or not this ContentViewCore can handle this accessibility action. 2821 * @param action The action to perform. 2822 * @return Whether or not this action is supported. 2823 */ 2824 public boolean supportsAccessibilityAction(int action) { 2825 return mAccessibilityInjector.supportsAccessibilityAction(action); 2826 } 2827 2828 /** 2829 * Attempts to perform an accessibility action on the web content. If the accessibility action 2830 * cannot be processed, it returns {@code null}, allowing the caller to know to call the 2831 * super {@link View#performAccessibilityAction(int, Bundle)} method and use that return value. 2832 * Otherwise the return value from this method should be used. 2833 * @param action The action to perform. 2834 * @param arguments Optional action arguments. 2835 * @return Whether the action was performed or {@code null} if the call should be delegated to 2836 * the super {@link View} class. 2837 */ 2838 public boolean performAccessibilityAction(int action, Bundle arguments) { 2839 if (mAccessibilityInjector.supportsAccessibilityAction(action)) { 2840 return mAccessibilityInjector.performAccessibilityAction(action, arguments); 2841 } 2842 2843 return false; 2844 } 2845 2846 /** 2847 * Set the BrowserAccessibilityManager, used for native accessibility 2848 * (not script injection). This is only set when system accessibility 2849 * has been enabled. 2850 * @param manager The new BrowserAccessibilityManager. 2851 */ 2852 public void setBrowserAccessibilityManager(BrowserAccessibilityManager manager) { 2853 mBrowserAccessibilityManager = manager; 2854 } 2855 2856 /** 2857 * Get the BrowserAccessibilityManager, used for native accessibility 2858 * (not script injection). This will return null when system accessibility 2859 * is not enabled. 2860 * @return This view's BrowserAccessibilityManager. 2861 */ 2862 public BrowserAccessibilityManager getBrowserAccessibilityManager() { 2863 return mBrowserAccessibilityManager; 2864 } 2865 2866 /** 2867 * If native accessibility (not script injection) is enabled, and if this is 2868 * running on JellyBean or later, returns an AccessibilityNodeProvider that 2869 * implements native accessibility for this view. Returns null otherwise. 2870 * Lazily initializes native accessibility here if it's allowed. 2871 * @return The AccessibilityNodeProvider, if available, or null otherwise. 2872 */ 2873 public AccessibilityNodeProvider getAccessibilityNodeProvider() { 2874 if (mBrowserAccessibilityManager != null) { 2875 return mBrowserAccessibilityManager.getAccessibilityNodeProvider(); 2876 } 2877 2878 if (mNativeAccessibilityAllowed && 2879 !mNativeAccessibilityEnabled && 2880 mNativeContentViewCore != 0 && 2881 Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 2882 mNativeAccessibilityEnabled = true; 2883 nativeSetAccessibilityEnabled(mNativeContentViewCore, true); 2884 } 2885 2886 return null; 2887 } 2888 2889 /** 2890 * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 2891 */ 2892 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 2893 // Note: this is only used by the script-injecting accessibility code. 2894 mAccessibilityInjector.onInitializeAccessibilityNodeInfo(info); 2895 } 2896 2897 /** 2898 * @see View#onInitializeAccessibilityEvent(AccessibilityEvent) 2899 */ 2900 public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 2901 // Note: this is only used by the script-injecting accessibility code. 2902 event.setClassName(this.getClass().getName()); 2903 2904 // Identify where the top-left of the screen currently points to. 2905 event.setScrollX(mRenderCoordinates.getScrollXPixInt()); 2906 event.setScrollY(mRenderCoordinates.getScrollYPixInt()); 2907 2908 // The maximum scroll values are determined by taking the content dimensions and 2909 // subtracting off the actual dimensions of the ChromeView. 2910 int maxScrollXPix = Math.max(0, mRenderCoordinates.getMaxHorizontalScrollPixInt()); 2911 int maxScrollYPix = Math.max(0, mRenderCoordinates.getMaxVerticalScrollPixInt()); 2912 event.setScrollable(maxScrollXPix > 0 || maxScrollYPix > 0); 2913 2914 // Setting the maximum scroll values requires API level 15 or higher. 2915 final int SDK_VERSION_REQUIRED_TO_SET_SCROLL = 15; 2916 if (Build.VERSION.SDK_INT >= SDK_VERSION_REQUIRED_TO_SET_SCROLL) { 2917 event.setMaxScrollX(maxScrollXPix); 2918 event.setMaxScrollY(maxScrollYPix); 2919 } 2920 } 2921 2922 /** 2923 * Returns whether accessibility script injection is enabled on the device 2924 */ 2925 public boolean isDeviceAccessibilityScriptInjectionEnabled() { 2926 try { 2927 if (!mContentSettings.getJavaScriptEnabled()) { 2928 return false; 2929 } 2930 2931 int result = getContext().checkCallingOrSelfPermission( 2932 android.Manifest.permission.INTERNET); 2933 if (result != PackageManager.PERMISSION_GRANTED) { 2934 return false; 2935 } 2936 2937 Field field = Settings.Secure.class.getField("ACCESSIBILITY_SCRIPT_INJECTION"); 2938 field.setAccessible(true); 2939 String accessibilityScriptInjection = (String) field.get(null); 2940 ContentResolver contentResolver = getContext().getContentResolver(); 2941 2942 if (mAccessibilityScriptInjectionObserver == null) { 2943 ContentObserver contentObserver = new ContentObserver(new Handler()) { 2944 public void onChange(boolean selfChange, Uri uri) { 2945 setAccessibilityState(mAccessibilityManager.isEnabled()); 2946 } 2947 }; 2948 contentResolver.registerContentObserver( 2949 Settings.Secure.getUriFor(accessibilityScriptInjection), 2950 false, 2951 contentObserver); 2952 mAccessibilityScriptInjectionObserver = contentObserver; 2953 } 2954 2955 return Settings.Secure.getInt(contentResolver, accessibilityScriptInjection, 0) == 1; 2956 } catch (NoSuchFieldException e) { 2957 } catch (IllegalAccessException e) { 2958 } 2959 return false; 2960 } 2961 2962 /** 2963 * Returns whether or not accessibility injection is being used. 2964 */ 2965 public boolean isInjectingAccessibilityScript() { 2966 return mAccessibilityInjector.accessibilityIsAvailable(); 2967 } 2968 2969 /** 2970 * Turns browser accessibility on or off. 2971 * If |state| is |false|, this turns off both native and injected accessibility. 2972 * Otherwise, if accessibility script injection is enabled, this will enable the injected 2973 * accessibility scripts. Native accessibility is enabled on demand. 2974 */ 2975 public void setAccessibilityState(boolean state) { 2976 if (!state) { 2977 setInjectedAccessibility(false); 2978 return; 2979 } 2980 2981 if (isDeviceAccessibilityScriptInjectionEnabled()) { 2982 setInjectedAccessibility(true); 2983 return; 2984 } 2985 2986 mNativeAccessibilityAllowed = true; 2987 } 2988 2989 /** 2990 * Enable or disable injected accessibility features 2991 */ 2992 public void setInjectedAccessibility(boolean enabled) { 2993 mAccessibilityInjector.addOrRemoveAccessibilityApisIfNecessary(); 2994 mAccessibilityInjector.setScriptEnabled(enabled); 2995 } 2996 2997 /** 2998 * Stop any TTS notifications that are currently going on. 2999 */ 3000 public void stopCurrentAccessibilityNotifications() { 3001 mAccessibilityInjector.onPageLostFocus(); 3002 } 3003 3004 /** 3005 * Inform WebKit that Fullscreen mode has been exited by the user. 3006 */ 3007 public void exitFullscreen() { 3008 nativeExitFullscreen(mNativeContentViewCore); 3009 } 3010 3011 /** 3012 * Changes whether hiding the top controls is enabled. 3013 * 3014 * @param enableHiding Whether hiding the top controls should be enabled or not. 3015 * @param enableShowing Whether showing the top controls should be enabled or not. 3016 * @param animate Whether the transition should be animated or not. 3017 */ 3018 public void updateTopControlsState(boolean enableHiding, boolean enableShowing, 3019 boolean animate) { 3020 nativeUpdateTopControlsState(mNativeContentViewCore, enableHiding, enableShowing, animate); 3021 } 3022 3023 /** 3024 * Callback factory method for nativeGetNavigationHistory(). 3025 */ 3026 @CalledByNative 3027 private void addToNavigationHistory(Object history, int index, String url, String virtualUrl, 3028 String originalUrl, String title, Bitmap favicon) { 3029 NavigationEntry entry = new NavigationEntry( 3030 index, url, virtualUrl, originalUrl, title, favicon); 3031 ((NavigationHistory) history).addEntry(entry); 3032 } 3033 3034 /** 3035 * Get a copy of the navigation history of the view. 3036 */ 3037 public NavigationHistory getNavigationHistory() { 3038 NavigationHistory history = new NavigationHistory(); 3039 int currentIndex = nativeGetNavigationHistory(mNativeContentViewCore, history); 3040 history.setCurrentEntryIndex(currentIndex); 3041 return history; 3042 } 3043 3044 @Override 3045 public NavigationHistory getDirectedNavigationHistory(boolean isForward, int itemLimit) { 3046 NavigationHistory history = new NavigationHistory(); 3047 nativeGetDirectedNavigationHistory(mNativeContentViewCore, history, isForward, itemLimit); 3048 return history; 3049 } 3050 3051 /** 3052 * @return The original request URL for the current navigation entry, or null if there is no 3053 * current entry. 3054 */ 3055 public String getOriginalUrlForActiveNavigationEntry() { 3056 return nativeGetOriginalUrlForActiveNavigationEntry(mNativeContentViewCore); 3057 } 3058 3059 /** 3060 * @return The cached copy of render positions and scales. 3061 */ 3062 public RenderCoordinates getRenderCoordinates() { 3063 return mRenderCoordinates; 3064 } 3065 3066 @CalledByNative 3067 private static Rect createRect(int x, int y, int right, int bottom) { 3068 return new Rect(x, y, right, bottom); 3069 } 3070 3071 public void attachExternalVideoSurface(int playerId, Surface surface) { 3072 if (mNativeContentViewCore != 0) { 3073 nativeAttachExternalVideoSurface(mNativeContentViewCore, playerId, surface); 3074 } 3075 } 3076 3077 public void detachExternalVideoSurface(int playerId) { 3078 if (mNativeContentViewCore != 0) { 3079 nativeDetachExternalVideoSurface(mNativeContentViewCore, playerId); 3080 } 3081 } 3082 3083 private boolean onAnimate(long frameTimeMicros) { 3084 if (mNativeContentViewCore == 0) return false; 3085 return nativeOnAnimate(mNativeContentViewCore, frameTimeMicros); 3086 } 3087 3088 private void animateIfNecessary(long frameTimeMicros) { 3089 if (mNeedAnimate) { 3090 mNeedAnimate = onAnimate(frameTimeMicros); 3091 if (!mNeedAnimate) removeVSyncSubscriber(); 3092 } 3093 } 3094 3095 @CalledByNative 3096 private void notifyExternalSurface( 3097 int playerId, boolean isRequest, float x, float y, float width, float height) { 3098 if (isRequest) getContentViewClient().onExternalVideoSurfaceRequested(playerId); 3099 getContentViewClient().onGeometryChanged(playerId, new RectF(x, y, x + width, y + height)); 3100 } 3101 3102 /** 3103 * Offer a subset of gesture events to the embedding View, 3104 * primarily for WebView compatibility. 3105 * 3106 * @param type The type of the event. 3107 * 3108 * @return true if the embedder handled the event. 3109 */ 3110 private boolean offerGestureToEmbedder(int type) { 3111 if (type == ContentViewGestureHandler.GESTURE_LONG_PRESS) { 3112 return mContainerView.performLongClick(); 3113 } 3114 return false; 3115 } 3116 3117 private native int nativeInit(boolean hardwareAccelerated, int webContentsPtr, 3118 int viewAndroidPtr, int windowAndroidPtr); 3119 3120 @CalledByNative 3121 private ContentVideoViewClient getContentVideoViewClient() { 3122 return mContentViewClient.getContentVideoViewClient(); 3123 } 3124 3125 private native void nativeOnJavaContentViewCoreDestroyed(int nativeContentViewCoreImpl); 3126 3127 private native void nativeLoadUrl( 3128 int nativeContentViewCoreImpl, 3129 String url, 3130 int loadUrlType, 3131 int transitionType, 3132 int uaOverrideOption, 3133 String extraHeaders, 3134 byte[] postData, 3135 String baseUrlForDataUrl, 3136 String virtualUrlForDataUrl, 3137 boolean canLoadLocalResources); 3138 3139 private native String nativeGetURL(int nativeContentViewCoreImpl); 3140 3141 private native String nativeGetTitle(int nativeContentViewCoreImpl); 3142 3143 private native void nativeShowInterstitialPage( 3144 int nativeContentViewCoreImpl, String url, int nativeInterstitialPageDelegateAndroid); 3145 private native boolean nativeIsShowingInterstitialPage(int nativeContentViewCoreImpl); 3146 3147 private native boolean nativeIsIncognito(int nativeContentViewCoreImpl); 3148 3149 // Returns true if the native side crashed so that java side can draw a sad tab. 3150 private native boolean nativeCrashed(int nativeContentViewCoreImpl); 3151 3152 private native void nativeSetFocus(int nativeContentViewCoreImpl, boolean focused); 3153 3154 private native void nativeSendOrientationChangeEvent( 3155 int nativeContentViewCoreImpl, int orientation); 3156 3157 // All touch events (including flings, scrolls etc) accept coordinates in physical pixels. 3158 private native boolean nativeSendTouchEvent( 3159 int nativeContentViewCoreImpl, long timeMs, int action, TouchPoint[] pts); 3160 3161 private native int nativeSendMouseMoveEvent( 3162 int nativeContentViewCoreImpl, long timeMs, float x, float y); 3163 3164 private native int nativeSendMouseWheelEvent( 3165 int nativeContentViewCoreImpl, long timeMs, float x, float y, float verticalAxis); 3166 3167 private native void nativeScrollBegin( 3168 int nativeContentViewCoreImpl, long timeMs, float x, float y); 3169 3170 private native void nativeScrollEnd(int nativeContentViewCoreImpl, long timeMs); 3171 3172 private native void nativeScrollBy( 3173 int nativeContentViewCoreImpl, long timeMs, float x, float y, 3174 float deltaX, float deltaY); 3175 3176 private native void nativeFlingStart( 3177 int nativeContentViewCoreImpl, long timeMs, float x, float y, float vx, float vy); 3178 3179 private native void nativeFlingCancel(int nativeContentViewCoreImpl, long timeMs); 3180 3181 private native void nativeSingleTap( 3182 int nativeContentViewCoreImpl, long timeMs, float x, float y, boolean linkPreviewTap); 3183 3184 private native void nativeSingleTapUnconfirmed( 3185 int nativeContentViewCoreImpl, long timeMs, float x, float y); 3186 3187 private native void nativeShowPressState( 3188 int nativeContentViewCoreImpl, long timeMs, float x, float y); 3189 3190 private native void nativeShowPressCancel( 3191 int nativeContentViewCoreImpl, long timeMs, float x, float y); 3192 3193 private native void nativeDoubleTap( 3194 int nativeContentViewCoreImpl, long timeMs, float x, float y); 3195 3196 private native void nativeLongPress( 3197 int nativeContentViewCoreImpl, long timeMs, float x, float y, boolean linkPreviewTap); 3198 3199 private native void nativeLongTap( 3200 int nativeContentViewCoreImpl, long timeMs, float x, float y, boolean linkPreviewTap); 3201 3202 private native void nativePinchBegin( 3203 int nativeContentViewCoreImpl, long timeMs, float x, float y); 3204 3205 private native void nativePinchEnd(int nativeContentViewCoreImpl, long timeMs); 3206 3207 private native void nativePinchBy(int nativeContentViewCoreImpl, long timeMs, 3208 float anchorX, float anchorY, float deltaScale); 3209 3210 private native void nativeSelectBetweenCoordinates( 3211 int nativeContentViewCoreImpl, float x1, float y1, float x2, float y2); 3212 3213 private native void nativeMoveCaret(int nativeContentViewCoreImpl, float x, float y); 3214 3215 private native boolean nativeCanGoBack(int nativeContentViewCoreImpl); 3216 private native boolean nativeCanGoForward(int nativeContentViewCoreImpl); 3217 private native boolean nativeCanGoToOffset(int nativeContentViewCoreImpl, int offset); 3218 private native void nativeGoBack(int nativeContentViewCoreImpl); 3219 private native void nativeGoForward(int nativeContentViewCoreImpl); 3220 private native void nativeGoToOffset(int nativeContentViewCoreImpl, int offset); 3221 private native void nativeGoToNavigationIndex(int nativeContentViewCoreImpl, int index); 3222 3223 private native void nativeStopLoading(int nativeContentViewCoreImpl); 3224 3225 private native void nativeReload(int nativeContentViewCoreImpl); 3226 3227 private native void nativeCancelPendingReload(int nativeContentViewCoreImpl); 3228 3229 private native void nativeContinuePendingReload(int nativeContentViewCoreImpl); 3230 3231 private native void nativeSelectPopupMenuItems(int nativeContentViewCoreImpl, int[] indices); 3232 3233 private native void nativeScrollFocusedEditableNodeIntoView(int nativeContentViewCoreImpl); 3234 private native void nativeUndoScrollFocusedEditableNodeIntoView(int nativeContentViewCoreImpl); 3235 private native boolean nativeNeedsReload(int nativeContentViewCoreImpl); 3236 3237 private native void nativeClearHistory(int nativeContentViewCoreImpl); 3238 3239 private native void nativeEvaluateJavaScript(int nativeContentViewCoreImpl, 3240 String script, JavaScriptCallback callback, boolean startRenderer); 3241 3242 private native int nativeGetNativeImeAdapter(int nativeContentViewCoreImpl); 3243 3244 private native int nativeGetCurrentRenderProcessId(int nativeContentViewCoreImpl); 3245 3246 private native int nativeGetBackgroundColor(int nativeContentViewCoreImpl); 3247 3248 private native void nativeOnShow(int nativeContentViewCoreImpl); 3249 private native void nativeOnHide(int nativeContentViewCoreImpl); 3250 3251 private native void nativeSetUseDesktopUserAgent(int nativeContentViewCoreImpl, 3252 boolean enabled, boolean reloadOnChange); 3253 private native boolean nativeGetUseDesktopUserAgent(int nativeContentViewCoreImpl); 3254 3255 private native void nativeClearSslPreferences(int nativeContentViewCoreImpl); 3256 3257 private native void nativeAddJavascriptInterface(int nativeContentViewCoreImpl, Object object, 3258 String name, Class requiredAnnotation, HashSet<Object> retainedObjectSet); 3259 3260 private native void nativeRemoveJavascriptInterface(int nativeContentViewCoreImpl, String name); 3261 3262 private native int nativeGetNavigationHistory(int nativeContentViewCoreImpl, Object context); 3263 private native void nativeGetDirectedNavigationHistory(int nativeContentViewCoreImpl, 3264 Object context, boolean isForward, int maxEntries); 3265 private native String nativeGetOriginalUrlForActiveNavigationEntry( 3266 int nativeContentViewCoreImpl); 3267 3268 private native void nativeUpdateVSyncParameters(int nativeContentViewCoreImpl, 3269 long timebaseMicros, long intervalMicros); 3270 3271 private native void nativeOnVSync(int nativeContentViewCoreImpl, long frameTimeMicros); 3272 3273 private native boolean nativeOnAnimate(int nativeContentViewCoreImpl, long frameTimeMicros); 3274 3275 private native boolean nativePopulateBitmapFromCompositor(int nativeContentViewCoreImpl, 3276 Bitmap bitmap); 3277 3278 private native void nativeWasResized(int nativeContentViewCoreImpl); 3279 3280 private native boolean nativeIsRenderWidgetHostViewReady(int nativeContentViewCoreImpl); 3281 3282 private native void nativeExitFullscreen(int nativeContentViewCoreImpl); 3283 private native void nativeUpdateTopControlsState(int nativeContentViewCoreImpl, 3284 boolean enableHiding, boolean enableShowing, boolean animate); 3285 3286 private native void nativeShowImeIfNeeded(int nativeContentViewCoreImpl); 3287 3288 private native void nativeAttachExternalVideoSurface( 3289 int nativeContentViewCoreImpl, int playerId, Surface surface); 3290 3291 private native void nativeDetachExternalVideoSurface( 3292 int nativeContentViewCoreImpl, int playerId); 3293 3294 private native void nativeSetAccessibilityEnabled( 3295 int nativeContentViewCoreImpl, boolean enabled); 3296} 3297