| Index: content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
|
| diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
|
| deleted file mode 100644
|
| index ec600bcf0724103c93a4fdf1c3555a1ac2e6ca5c..0000000000000000000000000000000000000000
|
| --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
|
| +++ /dev/null
|
| @@ -1,3452 +0,0 @@
|
| -// Copyright 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -package org.chromium.content.browser;
|
| -
|
| -import android.app.Activity;
|
| -import android.app.SearchManager;
|
| -import android.content.ContentResolver;
|
| -import android.content.Context;
|
| -import android.content.Intent;
|
| -import android.content.pm.ActivityInfo;
|
| -import android.content.pm.PackageManager;
|
| -import android.content.res.Configuration;
|
| -import android.database.ContentObserver;
|
| -import android.graphics.Bitmap;
|
| -import android.graphics.Canvas;
|
| -import android.graphics.Color;
|
| -import android.graphics.Rect;
|
| -import android.graphics.RectF;
|
| -import android.net.Uri;
|
| -import android.os.Build;
|
| -import android.os.Bundle;
|
| -import android.os.Handler;
|
| -import android.os.ResultReceiver;
|
| -import android.provider.Browser;
|
| -import android.provider.Settings;
|
| -import android.text.Editable;
|
| -import android.text.TextUtils;
|
| -import android.util.Log;
|
| -import android.util.Pair;
|
| -import android.view.ActionMode;
|
| -import android.view.HapticFeedbackConstants;
|
| -import android.view.InputDevice;
|
| -import android.view.KeyEvent;
|
| -import android.view.MotionEvent;
|
| -import android.view.Surface;
|
| -import android.view.View;
|
| -import android.view.ViewGroup;
|
| -import android.view.Window;
|
| -import android.view.WindowManager;
|
| -import android.view.accessibility.AccessibilityEvent;
|
| -import android.view.accessibility.AccessibilityManager;
|
| -import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
|
| -import android.view.accessibility.AccessibilityNodeInfo;
|
| -import android.view.accessibility.AccessibilityNodeProvider;
|
| -import android.view.inputmethod.EditorInfo;
|
| -import android.view.inputmethod.InputConnection;
|
| -import android.view.inputmethod.InputMethodManager;
|
| -import android.widget.AbsoluteLayout;
|
| -import android.widget.FrameLayout;
|
| -
|
| -import com.google.common.annotations.VisibleForTesting;
|
| -
|
| -import org.chromium.base.CalledByNative;
|
| -import org.chromium.base.CommandLine;
|
| -import org.chromium.base.JNINamespace;
|
| -import org.chromium.base.TraceEvent;
|
| -import org.chromium.base.WeakContext;
|
| -import org.chromium.content.R;
|
| -import org.chromium.content.browser.ContentViewGestureHandler.MotionEventDelegate;
|
| -import org.chromium.content.browser.accessibility.AccessibilityInjector;
|
| -import org.chromium.content.browser.accessibility.BrowserAccessibilityManager;
|
| -import org.chromium.content.browser.input.AdapterInputConnection;
|
| -import org.chromium.content.browser.input.HandleView;
|
| -import org.chromium.content.browser.input.ImeAdapter;
|
| -import org.chromium.content.browser.input.ImeAdapter.AdapterInputConnectionFactory;
|
| -import org.chromium.content.browser.input.InputMethodManagerWrapper;
|
| -import org.chromium.content.browser.input.InsertionHandleController;
|
| -import org.chromium.content.browser.input.SelectPopupDialog;
|
| -import org.chromium.content.browser.input.SelectPopupItem;
|
| -import org.chromium.content.browser.input.SelectionHandleController;
|
| -import org.chromium.content.common.ContentSwitches;
|
| -import org.chromium.ui.base.ViewAndroid;
|
| -import org.chromium.ui.base.ViewAndroidDelegate;
|
| -import org.chromium.ui.base.WindowAndroid;
|
| -import org.chromium.ui.gfx.DeviceDisplayInfo;
|
| -
|
| -import java.lang.annotation.Annotation;
|
| -import java.lang.reflect.Field;
|
| -import java.util.ArrayList;
|
| -import java.util.HashMap;
|
| -import java.util.HashSet;
|
| -import java.util.List;
|
| -import java.util.Map;
|
| -
|
| -/**
|
| - * Provides a Java-side 'wrapper' around a WebContent (native) instance.
|
| - * Contains all the major functionality necessary to manage the lifecycle of a ContentView without
|
| - * being tied to the view system.
|
| - */
|
| -@JNINamespace("content")
|
| -public class ContentViewCore
|
| - implements MotionEventDelegate, NavigationClient, AccessibilityStateChangeListener {
|
| -
|
| - private static final String TAG = "ContentViewCore";
|
| -
|
| - // Used to avoid enabling zooming in / out if resulting zooming will
|
| - // produce little visible difference.
|
| - private static final float ZOOM_CONTROLS_EPSILON = 0.007f;
|
| -
|
| - // Used to represent gestures for long press and long tap.
|
| - private static final int IS_LONG_PRESS = 1;
|
| - private static final int IS_LONG_TAP = 2;
|
| -
|
| - // Length of the delay (in ms) before fading in handles after the last page movement.
|
| - private static final int TEXT_HANDLE_FADE_IN_DELAY = 300;
|
| -
|
| - // If the embedder adds a JavaScript interface object that contains an indirect reference to
|
| - // the ContentViewCore, then storing a strong ref to the interface object on the native
|
| - // side would prevent garbage collection of the ContentViewCore (as that strong ref would
|
| - // create a new GC root).
|
| - // For that reason, we store only a weak reference to the interface object on the
|
| - // native side. However we still need a strong reference on the Java side to
|
| - // prevent garbage collection if the embedder doesn't maintain their own ref to the
|
| - // interface object - the Java side ref won't create a new GC root.
|
| - // This map stores those refernces. We put into the map on addJavaScriptInterface()
|
| - // and remove from it in removeJavaScriptInterface().
|
| - private final Map<String, Object> mJavaScriptInterfaces = new HashMap<String, Object>();
|
| -
|
| - // Additionally, we keep track of all Java bound JS objects that are in use on the
|
| - // current page to ensure that they are not garbage collected until the page is
|
| - // navigated. This includes interface objects that have been removed
|
| - // via the removeJavaScriptInterface API and transient objects returned from methods
|
| - // on the interface object. Note we use HashSet rather than Set as the native side
|
| - // expects HashSet (no bindings for interfaces).
|
| - private final HashSet<Object> mRetainedJavaScriptObjects = new HashSet<Object>();
|
| -
|
| - /**
|
| - * Interface that consumers of {@link ContentViewCore} must implement to allow the proper
|
| - * dispatching of view methods through the containing view.
|
| - *
|
| - * <p>
|
| - * All methods with the "super_" prefix should be routed to the parent of the
|
| - * implementing container view.
|
| - */
|
| - @SuppressWarnings("javadoc")
|
| - public interface InternalAccessDelegate {
|
| - /**
|
| - * @see View#drawChild(Canvas, View, long)
|
| - */
|
| - boolean drawChild(Canvas canvas, View child, long drawingTime);
|
| -
|
| - /**
|
| - * @see View#onKeyUp(keyCode, KeyEvent)
|
| - */
|
| - boolean super_onKeyUp(int keyCode, KeyEvent event);
|
| -
|
| - /**
|
| - * @see View#dispatchKeyEventPreIme(KeyEvent)
|
| - */
|
| - boolean super_dispatchKeyEventPreIme(KeyEvent event);
|
| -
|
| - /**
|
| - * @see View#dispatchKeyEvent(KeyEvent)
|
| - */
|
| - boolean super_dispatchKeyEvent(KeyEvent event);
|
| -
|
| - /**
|
| - * @see View#onGenericMotionEvent(MotionEvent)
|
| - */
|
| - boolean super_onGenericMotionEvent(MotionEvent event);
|
| -
|
| - /**
|
| - * @see View#onConfigurationChanged(Configuration)
|
| - */
|
| - void super_onConfigurationChanged(Configuration newConfig);
|
| -
|
| - /**
|
| - * @see View#onScrollChanged(int, int, int, int)
|
| - */
|
| - void onScrollChanged(int lPix, int tPix, int oldlPix, int oldtPix);
|
| -
|
| - /**
|
| - * @see View#awakenScrollBars()
|
| - */
|
| - boolean awakenScrollBars();
|
| -
|
| - /**
|
| - * @see View#awakenScrollBars(int, boolean)
|
| - */
|
| - boolean super_awakenScrollBars(int startDelay, boolean invalidate);
|
| - }
|
| -
|
| - /**
|
| - * An interface that allows the embedder to be notified of events and state changes related to
|
| - * gesture processing.
|
| - */
|
| - public interface GestureStateListener {
|
| - /**
|
| - * Called when the pinch gesture starts.
|
| - */
|
| - void onPinchGestureStart();
|
| -
|
| - /**
|
| - * Called when the pinch gesture ends.
|
| - */
|
| - void onPinchGestureEnd();
|
| -
|
| - /**
|
| - * Called when the fling gesture is sent.
|
| - */
|
| - void onFlingStartGesture(int vx, int vy);
|
| -
|
| - /**
|
| - * Called when the fling cancel gesture is sent.
|
| - */
|
| - void onFlingCancelGesture();
|
| -
|
| - /**
|
| - * Called when a fling event was not handled by the renderer.
|
| - */
|
| - void onUnhandledFlingStartEvent();
|
| -
|
| - /**
|
| - * Called to indicate that a scroll update gesture had been consumed by the page.
|
| - * This callback is called whenever any layer is scrolled (like a frame or div). It is
|
| - * not called when a JS touch handler consumes the event (preventDefault), it is not called
|
| - * for JS-initiated scrolling.
|
| - */
|
| - void onScrollUpdateGestureConsumed();
|
| - }
|
| -
|
| - /**
|
| - * An interface for controlling visibility and state of embedder-provided zoom controls.
|
| - */
|
| - public interface ZoomControlsDelegate {
|
| - /**
|
| - * Called when it's reasonable to show zoom controls.
|
| - */
|
| - void invokeZoomPicker();
|
| -
|
| - /**
|
| - * Called when zoom controls need to be hidden (e.g. when the view hides).
|
| - */
|
| - void dismissZoomPicker();
|
| -
|
| - /**
|
| - * Called when page scale has been changed, so the controls can update their state.
|
| - */
|
| - void updateZoomControls();
|
| - }
|
| -
|
| - /**
|
| - * An interface that allows the embedder to be notified of changes to the parameters of the
|
| - * currently displayed contents.
|
| - * These notifications are consistent with respect to the UI thread (the size is the size of
|
| - * the contents currently displayed on screen).
|
| - */
|
| - public interface UpdateFrameInfoListener {
|
| - /**
|
| - * Called each time any of the parameters are changed.
|
| - *
|
| - * @param pageScaleFactor The page scale.
|
| - */
|
| - void onFrameInfoUpdated(float pageScaleFactor);
|
| - }
|
| -
|
| - /**
|
| - * An interface that allows the embedder to be notified when the results of
|
| - * extractSmartClipData are available.
|
| - */
|
| - public interface SmartClipDataListener {
|
| - public void onSmartClipDataExtracted(String result);
|
| - }
|
| -
|
| - private VSyncManager.Provider mVSyncProvider;
|
| - private VSyncManager.Listener mVSyncListener;
|
| - private int mVSyncSubscriberCount;
|
| - private boolean mVSyncListenerRegistered;
|
| -
|
| - // To avoid IPC delay we use input events to directly trigger a vsync signal in the renderer.
|
| - // When we do this, we also need to avoid sending the real vsync signal for the current
|
| - // frame to avoid double-ticking. This flag is used to inhibit the next vsync notification.
|
| - private boolean mDidSignalVSyncUsingInputEvent;
|
| -
|
| - public VSyncManager.Listener getVSyncListener(VSyncManager.Provider vsyncProvider) {
|
| - if (mVSyncProvider != null && mVSyncListenerRegistered) {
|
| - mVSyncProvider.unregisterVSyncListener(mVSyncListener);
|
| - mVSyncListenerRegistered = false;
|
| - }
|
| -
|
| - mVSyncProvider = vsyncProvider;
|
| - mVSyncListener = new VSyncManager.Listener() {
|
| - @Override
|
| - public void updateVSync(long tickTimeMicros, long intervalMicros) {
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeUpdateVSyncParameters(mNativeContentViewCore, tickTimeMicros,
|
| - intervalMicros);
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public void onVSync(long frameTimeMicros) {
|
| - animateIfNecessary(frameTimeMicros);
|
| -
|
| - if (mRequestedVSyncForInput) {
|
| - mRequestedVSyncForInput = false;
|
| - removeVSyncSubscriber();
|
| - }
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeOnVSync(mNativeContentViewCore, frameTimeMicros);
|
| - }
|
| - }
|
| - };
|
| -
|
| - if (mVSyncSubscriberCount > 0) {
|
| - // addVSyncSubscriber() is called before getVSyncListener.
|
| - vsyncProvider.registerVSyncListener(mVSyncListener);
|
| - mVSyncListenerRegistered = true;
|
| - }
|
| -
|
| - return mVSyncListener;
|
| - }
|
| -
|
| - @CalledByNative
|
| - void addVSyncSubscriber() {
|
| - if (!isVSyncNotificationEnabled()) {
|
| - mDidSignalVSyncUsingInputEvent = false;
|
| - }
|
| - if (mVSyncProvider != null && !mVSyncListenerRegistered) {
|
| - mVSyncProvider.registerVSyncListener(mVSyncListener);
|
| - mVSyncListenerRegistered = true;
|
| - }
|
| - mVSyncSubscriberCount++;
|
| - }
|
| -
|
| - @CalledByNative
|
| - void removeVSyncSubscriber() {
|
| - if (mVSyncProvider != null && mVSyncSubscriberCount == 1) {
|
| - assert mVSyncListenerRegistered;
|
| - mVSyncProvider.unregisterVSyncListener(mVSyncListener);
|
| - mVSyncListenerRegistered = false;
|
| - }
|
| - mVSyncSubscriberCount--;
|
| - assert mVSyncSubscriberCount >= 0;
|
| - }
|
| -
|
| - @CalledByNative
|
| - private void resetVSyncNotification() {
|
| - while (isVSyncNotificationEnabled()) removeVSyncSubscriber();
|
| - mVSyncSubscriberCount = 0;
|
| - mVSyncListenerRegistered = false;
|
| - mNeedAnimate = false;
|
| - }
|
| -
|
| - private boolean isVSyncNotificationEnabled() {
|
| - return mVSyncProvider != null && mVSyncListenerRegistered;
|
| - }
|
| -
|
| - @CalledByNative
|
| - private void setNeedsAnimate() {
|
| - if (!mNeedAnimate) {
|
| - mNeedAnimate = true;
|
| - addVSyncSubscriber();
|
| - }
|
| - }
|
| -
|
| - private final Context mContext;
|
| - private ViewGroup mContainerView;
|
| - private InternalAccessDelegate mContainerViewInternals;
|
| - private WebContents mWebContents;
|
| - private WebContentsObserverAndroid mWebContentsObserver;
|
| -
|
| - private ContentViewClient mContentViewClient;
|
| -
|
| - private ContentSettings mContentSettings;
|
| -
|
| - // Native pointer to C++ ContentViewCoreImpl object which will be set by nativeInit().
|
| - private long mNativeContentViewCore = 0;
|
| -
|
| - private boolean mInForeground = false;
|
| -
|
| - private ContentViewGestureHandler mContentViewGestureHandler;
|
| - private GestureStateListener mGestureStateListener;
|
| - private ZoomManager mZoomManager;
|
| - private ZoomControlsDelegate mZoomControlsDelegate;
|
| -
|
| - private PopupZoomer mPopupZoomer;
|
| -
|
| - private Runnable mFakeMouseMoveRunnable = null;
|
| -
|
| - // Only valid when focused on a text / password field.
|
| - private ImeAdapter mImeAdapter;
|
| - private ImeAdapter.AdapterInputConnectionFactory mAdapterInputConnectionFactory;
|
| - private AdapterInputConnection mInputConnection;
|
| -
|
| - private SelectionHandleController mSelectionHandleController;
|
| - private InsertionHandleController mInsertionHandleController;
|
| -
|
| - private Runnable mDeferredHandleFadeInRunnable;
|
| -
|
| - private PositionObserver mPositionObserver;
|
| - private PositionObserver.Listener mPositionListener;
|
| -
|
| - // Size of the viewport in physical pixels as set from onSizeChanged.
|
| - private int mViewportWidthPix;
|
| - private int mViewportHeightPix;
|
| - private int mPhysicalBackingWidthPix;
|
| - private int mPhysicalBackingHeightPix;
|
| - private int mOverdrawBottomHeightPix;
|
| - private int mViewportSizeOffsetWidthPix;
|
| - private int mViewportSizeOffsetHeightPix;
|
| - private int mLocationInWindowX;
|
| - private int mLocationInWindowY;
|
| -
|
| - // Cached copy of all positions and scales as reported by the renderer.
|
| - private final RenderCoordinates mRenderCoordinates;
|
| -
|
| - private final RenderCoordinates.NormalizedPoint mStartHandlePoint;
|
| - private final RenderCoordinates.NormalizedPoint mEndHandlePoint;
|
| - private final RenderCoordinates.NormalizedPoint mInsertionHandlePoint;
|
| -
|
| - // Tracks whether a selection is currently active. When applied to selected text, indicates
|
| - // whether the last selected text is still highlighted.
|
| - private boolean mHasSelection;
|
| - private String mLastSelectedText;
|
| - private boolean mSelectionEditable;
|
| - private ActionMode mActionMode;
|
| - private boolean mUnselectAllOnActionModeDismiss;
|
| -
|
| - // Delegate that will handle GET downloads, and be notified of completion of POST downloads.
|
| - private ContentViewDownloadDelegate mDownloadDelegate;
|
| -
|
| - // The AccessibilityInjector that handles loading Accessibility scripts into the web page.
|
| - private AccessibilityInjector mAccessibilityInjector;
|
| -
|
| - // Whether native accessibility, i.e. without any script injection, is allowed.
|
| - private boolean mNativeAccessibilityAllowed;
|
| -
|
| - // Whether native accessibility, i.e. without any script injection, has been enabled.
|
| - private boolean mNativeAccessibilityEnabled;
|
| -
|
| - // Handles native accessibility, i.e. without any script injection.
|
| - private BrowserAccessibilityManager mBrowserAccessibilityManager;
|
| -
|
| - // System accessibility service.
|
| - private final AccessibilityManager mAccessibilityManager;
|
| -
|
| - // Allows us to dynamically respond when the accessibility script injection flag changes.
|
| - private ContentObserver mAccessibilityScriptInjectionObserver;
|
| -
|
| - // Temporary notification to tell onSizeChanged to focus a form element,
|
| - // because the OSK was just brought up.
|
| - private boolean mUnfocusOnNextSizeChanged = false;
|
| - private final Rect mFocusPreOSKViewportRect = new Rect();
|
| -
|
| - // Used to keep track of whether we should try to undo the last zoom-to-textfield operation.
|
| - private boolean mScrolledAndZoomedFocusedEditableNode = false;
|
| -
|
| - // Whether we use hardware-accelerated drawing.
|
| - private boolean mHardwareAccelerated = false;
|
| -
|
| - // Whether we received a new frame since consumePendingRendererFrame() was last called.
|
| - private boolean mPendingRendererFrame = false;
|
| -
|
| - // Whether we should animate at the next vsync tick.
|
| - private boolean mNeedAnimate = false;
|
| -
|
| - // Whether we requested a proactive vsync event in response to touch input.
|
| - // This reduces the latency of responding to input by ensuring the renderer
|
| - // is sent a BeginFrame for every touch event we receive. Otherwise the
|
| - // renderer's SetNeedsBeginFrame message would get serviced at the next
|
| - // vsync.
|
| - private boolean mRequestedVSyncForInput = false;
|
| -
|
| - private ViewAndroid mViewAndroid;
|
| -
|
| - private SmartClipDataListener mSmartClipDataListener = null;
|
| -
|
| - /** ActionAfterDoubleTap defined in tools/metrics/histograms/histograms.xml. */
|
| - public static class UMAActionAfterDoubleTap {
|
| - public static final int NAVIGATE_BACK = 0;
|
| - public static final int NAVIGATE_STOP = 1;
|
| - public static final int NO_ACTION = 2;
|
| - public static final int COUNT = 3;
|
| - }
|
| -
|
| - /** TapDelayType defined in tools/metrics/histograms/histograms.xml. */
|
| - public static class UMASingleTapType {
|
| - public static final int DELAYED_TAP = 0;
|
| - public static final int UNDELAYED_TAP = 1;
|
| - public static final int COUNT = 2;
|
| - }
|
| -
|
| - /**
|
| - * Constructs a new ContentViewCore. Embedders must call initialize() after constructing
|
| - * a ContentViewCore and before using it.
|
| - *
|
| - * @param context The context used to create this.
|
| - */
|
| - public ContentViewCore(Context context) {
|
| - mContext = context;
|
| -
|
| - WeakContext.initializeWeakContext(context);
|
| - HeapStatsLogger.init(mContext.getApplicationContext());
|
| - mAdapterInputConnectionFactory = new AdapterInputConnectionFactory();
|
| -
|
| - mRenderCoordinates = new RenderCoordinates();
|
| - mRenderCoordinates.setDeviceScaleFactor(
|
| - getContext().getResources().getDisplayMetrics().density);
|
| - mStartHandlePoint = mRenderCoordinates.createNormalizedPoint();
|
| - mEndHandlePoint = mRenderCoordinates.createNormalizedPoint();
|
| - mInsertionHandlePoint = mRenderCoordinates.createNormalizedPoint();
|
| - mAccessibilityManager = (AccessibilityManager)
|
| - getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
|
| - }
|
| -
|
| - /**
|
| - * @return The context used for creating this ContentViewCore.
|
| - */
|
| - @CalledByNative
|
| - public Context getContext() {
|
| - return mContext;
|
| - }
|
| -
|
| - /**
|
| - * @return The ViewGroup that all view actions of this ContentViewCore should interact with.
|
| - */
|
| - public ViewGroup getContainerView() {
|
| - return mContainerView;
|
| - }
|
| -
|
| - /**
|
| - * @return The WebContents currently being rendered.
|
| - */
|
| - public WebContents getWebContents() {
|
| - return mWebContents;
|
| - }
|
| -
|
| - /**
|
| - * Specifies how much smaller the WebKit layout size should be relative to the size of this
|
| - * view.
|
| - * @param offsetXPix The X amount in pixels to shrink the viewport by.
|
| - * @param offsetYPix The Y amount in pixels to shrink the viewport by.
|
| - */
|
| - public void setViewportSizeOffset(int offsetXPix, int offsetYPix) {
|
| - if (offsetXPix != mViewportSizeOffsetWidthPix ||
|
| - offsetYPix != mViewportSizeOffsetHeightPix) {
|
| - mViewportSizeOffsetWidthPix = offsetXPix;
|
| - mViewportSizeOffsetHeightPix = offsetYPix;
|
| - if (mNativeContentViewCore != 0) nativeWasResized(mNativeContentViewCore);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Returns a delegate that can be used to add and remove views from the ContainerView.
|
| - *
|
| - * NOTE: Use with care, as not all ContentViewCore users setup their ContainerView in the same
|
| - * way. In particular, the Android WebView has limitations on what implementation details can
|
| - * be provided via a child view, as they are visible in the API and could introduce
|
| - * compatibility breaks with existing applications. If in doubt, contact the
|
| - * android_webview/OWNERS
|
| - *
|
| - * @return A ViewAndroidDelegate that can be used to add and remove views.
|
| - */
|
| - @VisibleForTesting
|
| - public ViewAndroidDelegate getViewAndroidDelegate() {
|
| - return new ViewAndroidDelegate() {
|
| - @Override
|
| - public View acquireAnchorView() {
|
| - View anchorView = new View(getContext());
|
| - mContainerView.addView(anchorView);
|
| - return anchorView;
|
| - }
|
| -
|
| - @Override
|
| - @SuppressWarnings("deprecation") // AbsoluteLayout.LayoutParams
|
| - public void setAnchorViewPosition(
|
| - View view, float x, float y, float width, float height) {
|
| - assert view.getParent() == mContainerView;
|
| -
|
| - float scale = (float) DeviceDisplayInfo.create(getContext()).getDIPScale();
|
| -
|
| - // The anchor view should not go outside the bounds of the ContainerView.
|
| - int leftMargin = Math.round(x * scale);
|
| - int topMargin = Math.round(mRenderCoordinates.getContentOffsetYPix() + y * scale);
|
| - int scaledWidth = Math.round(width * scale);
|
| - // ContentViewCore currently only supports these two container view types.
|
| - if (mContainerView instanceof FrameLayout) {
|
| - if (scaledWidth + leftMargin > mContainerView.getWidth()) {
|
| - scaledWidth = mContainerView.getWidth() - leftMargin;
|
| - }
|
| - FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
|
| - scaledWidth, Math.round(height * scale));
|
| - lp.leftMargin = leftMargin;
|
| - lp.topMargin = topMargin;
|
| - view.setLayoutParams(lp);
|
| - } else if (mContainerView instanceof AbsoluteLayout) {
|
| - // This fixes the offset due to a difference in
|
| - // scrolling model of WebView vs. Chrome.
|
| - // TODO(sgurun) fix this to use mContainerView.getScroll[X/Y]()
|
| - // as it naturally accounts for scroll differences between
|
| - // these models.
|
| - leftMargin += mRenderCoordinates.getScrollXPixInt();
|
| - topMargin += mRenderCoordinates.getScrollYPixInt();
|
| -
|
| - android.widget.AbsoluteLayout.LayoutParams lp =
|
| - new android.widget.AbsoluteLayout.LayoutParams(
|
| - scaledWidth, (int) (height * scale), leftMargin, topMargin);
|
| - view.setLayoutParams(lp);
|
| - } else {
|
| - Log.e(TAG, "Unknown layout " + mContainerView.getClass().getName());
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public void releaseAnchorView(View anchorView) {
|
| - mContainerView.removeView(anchorView);
|
| - }
|
| - };
|
| - }
|
| -
|
| - @VisibleForTesting
|
| - public ImeAdapter getImeAdapterForTest() {
|
| - return mImeAdapter;
|
| - }
|
| -
|
| - @VisibleForTesting
|
| - public void setAdapterInputConnectionFactory(AdapterInputConnectionFactory factory) {
|
| - mAdapterInputConnectionFactory = factory;
|
| - }
|
| -
|
| - @VisibleForTesting
|
| - public AdapterInputConnection getInputConnectionForTest() {
|
| - return mInputConnection;
|
| - }
|
| -
|
| - private ImeAdapter createImeAdapter(Context context) {
|
| - return new ImeAdapter(new InputMethodManagerWrapper(context),
|
| - new ImeAdapter.ImeAdapterDelegate() {
|
| - @Override
|
| - public void onImeEvent(boolean isFinish) {
|
| - getContentViewClient().onImeEvent();
|
| - if (!isFinish) {
|
| - hideHandles();
|
| - undoScrollFocusedEditableNodeIntoViewIfNeeded(false);
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public void onSetFieldValue() {
|
| - scrollFocusedEditableNodeIntoView();
|
| - }
|
| -
|
| - @Override
|
| - public void onDismissInput() {
|
| - getContentViewClient().onImeStateChangeRequested(false);
|
| - }
|
| -
|
| - @Override
|
| - public View getAttachedView() {
|
| - return mContainerView;
|
| - }
|
| -
|
| - @Override
|
| - public ResultReceiver getNewShowKeyboardReceiver() {
|
| - return new ResultReceiver(new Handler()) {
|
| - @Override
|
| - public void onReceiveResult(int resultCode, Bundle resultData) {
|
| - getContentViewClient().onImeStateChangeRequested(
|
| - resultCode == InputMethodManager.RESULT_SHOWN ||
|
| - resultCode == InputMethodManager.RESULT_UNCHANGED_SHOWN);
|
| - if (resultCode == InputMethodManager.RESULT_SHOWN) {
|
| - // If OSK is newly shown, delay the form focus until
|
| - // the onSizeChanged (in order to adjust relative to the
|
| - // new size).
|
| - // TODO(jdduke): We should not assume that onSizeChanged will
|
| - // always be called, crbug.com/294908.
|
| - getContainerView().getWindowVisibleDisplayFrame(
|
| - mFocusPreOSKViewportRect);
|
| - } else if (resultCode ==
|
| - InputMethodManager.RESULT_UNCHANGED_SHOWN) {
|
| - // If the OSK was already there, focus the form immediately.
|
| - scrollFocusedEditableNodeIntoView();
|
| - } else {
|
| - undoScrollFocusedEditableNodeIntoViewIfNeeded(false);
|
| - }
|
| - }
|
| - };
|
| - }
|
| - }
|
| - );
|
| - }
|
| -
|
| - /**
|
| - * Returns true if the given Activity has hardware acceleration enabled
|
| - * in its manifest, or in its foreground window.
|
| - *
|
| - * TODO(husky): Remove when initialize() is refactored (see TODO there)
|
| - * TODO(dtrainor) This is still used by other classes. Make sure to pull some version of this
|
| - * out before removing it.
|
| - */
|
| - public static boolean hasHardwareAcceleration(Activity activity) {
|
| - // Has HW acceleration been enabled manually in the current window?
|
| - Window window = activity.getWindow();
|
| - if (window != null) {
|
| - if ((window.getAttributes().flags
|
| - & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0) {
|
| - return true;
|
| - }
|
| - }
|
| -
|
| - // Has HW acceleration been enabled in the manifest?
|
| - try {
|
| - ActivityInfo info = activity.getPackageManager().getActivityInfo(
|
| - activity.getComponentName(), 0);
|
| - if ((info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
|
| - return true;
|
| - }
|
| - } catch (PackageManager.NameNotFoundException e) {
|
| - Log.e("Chrome", "getActivityInfo(self) should not fail");
|
| - }
|
| -
|
| - return false;
|
| - }
|
| -
|
| - /**
|
| - * Returns true if the given Context is a HW-accelerated Activity.
|
| - *
|
| - * TODO(husky): Remove when initialize() is refactored (see TODO there)
|
| - */
|
| - private static boolean hasHardwareAcceleration(Context context) {
|
| - if (context instanceof Activity) {
|
| - return hasHardwareAcceleration((Activity) context);
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - /**
|
| - *
|
| - * @param containerView The view that will act as a container for all views created by this.
|
| - * @param internalDispatcher Handles dispatching all hidden or super methods to the
|
| - * containerView.
|
| - * @param nativeWebContents A pointer to the native web contents.
|
| - * @param windowAndroid An instance of the WindowAndroid.
|
| - */
|
| - // Perform important post-construction set up of the ContentViewCore.
|
| - // We do not require the containing view in the constructor to allow embedders to create a
|
| - // ContentViewCore without having fully created its containing view. The containing view
|
| - // is a vital component of the ContentViewCore, so embedders must exercise caution in what
|
| - // they do with the ContentViewCore before calling initialize().
|
| - // We supply the nativeWebContents pointer here rather than in the constructor to allow us
|
| - // to set the private browsing mode at a later point for the WebView implementation.
|
| - // Note that the caller remains the owner of the nativeWebContents and is responsible for
|
| - // deleting it after destroying the ContentViewCore.
|
| - public void initialize(ViewGroup containerView, InternalAccessDelegate internalDispatcher,
|
| - long nativeWebContents, WindowAndroid windowAndroid) {
|
| - // Check whether to use hardware acceleration. This is a bit hacky, and
|
| - // only works if the Context is actually an Activity (as it is in the
|
| - // Chrome application).
|
| - //
|
| - // What we're doing here is checking whether the app has *requested*
|
| - // hardware acceleration by setting the appropriate flags. This does not
|
| - // necessarily mean we're going to *get* hardware acceleration -- that's
|
| - // up to the Android framework.
|
| - //
|
| - // TODO(husky): Once the native code has been updated so that the
|
| - // HW acceleration flag can be set dynamically (Grace is doing this),
|
| - // move this check into onAttachedToWindow(), where we can test for
|
| - // HW support directly.
|
| - mHardwareAccelerated = hasHardwareAcceleration(mContext);
|
| -
|
| - mContainerView = containerView;
|
| - mPositionObserver = new ViewPositionObserver(mContainerView);
|
| - mPositionListener = new PositionObserver.Listener() {
|
| - @Override
|
| - public void onPositionChanged(int x, int y) {
|
| - if (isSelectionHandleShowing() || isInsertionHandleShowing()) {
|
| - temporarilyHideTextHandles();
|
| - }
|
| - }
|
| - };
|
| -
|
| - long windowNativePointer = windowAndroid != null ? windowAndroid.getNativePointer() : 0;
|
| -
|
| - long viewAndroidNativePointer = 0;
|
| - if (windowNativePointer != 0) {
|
| - mViewAndroid = new ViewAndroid(windowAndroid, getViewAndroidDelegate());
|
| - viewAndroidNativePointer = mViewAndroid.getNativePointer();
|
| - }
|
| -
|
| - mNativeContentViewCore = nativeInit(mHardwareAccelerated,
|
| - nativeWebContents, viewAndroidNativePointer, windowNativePointer);
|
| - mWebContents = nativeGetWebContentsAndroid(mNativeContentViewCore);
|
| - mContentSettings = new ContentSettings(this, mNativeContentViewCore);
|
| - initializeContainerView(internalDispatcher);
|
| -
|
| - mAccessibilityInjector = AccessibilityInjector.newInstance(this);
|
| -
|
| - String contentDescription = "Web View";
|
| - if (R.string.accessibility_content_view == 0) {
|
| - Log.w(TAG, "Setting contentDescription to 'Web View' as no value was specified.");
|
| - } else {
|
| - contentDescription = mContext.getResources().getString(
|
| - R.string.accessibility_content_view);
|
| - }
|
| - mContainerView.setContentDescription(contentDescription);
|
| - mWebContentsObserver = new WebContentsObserverAndroid(this) {
|
| - @Override
|
| - public void didStartLoading(String url) {
|
| - hidePopupDialog();
|
| - resetGestureDetectors();
|
| - }
|
| - };
|
| -
|
| - sendOrientationChangeEvent();
|
| - }
|
| -
|
| - @CalledByNative
|
| - void onNativeContentViewCoreDestroyed(long nativeContentViewCore) {
|
| - assert nativeContentViewCore == mNativeContentViewCore;
|
| - mNativeContentViewCore = 0;
|
| - }
|
| -
|
| - /**
|
| - * Set the Container view Internals.
|
| - * @param internalDispatcher Handles dispatching all hidden or super methods to the
|
| - * containerView.
|
| - */
|
| - public void setContainerViewInternals(InternalAccessDelegate internalDispatcher) {
|
| - mContainerViewInternals = internalDispatcher;
|
| - }
|
| -
|
| - /**
|
| - * Initializes the View that will contain all Views created by the ContentViewCore.
|
| - *
|
| - * @param internalDispatcher Handles dispatching all hidden or super methods to the
|
| - * containerView.
|
| - */
|
| - private void initializeContainerView(InternalAccessDelegate internalDispatcher) {
|
| - TraceEvent.begin();
|
| - mContainerViewInternals = internalDispatcher;
|
| -
|
| - mContainerView.setWillNotDraw(false);
|
| - mContainerView.setClickable(true);
|
| -
|
| - mZoomManager = new ZoomManager(mContext, this);
|
| - mContentViewGestureHandler = new ContentViewGestureHandler(mContext, this, mZoomManager);
|
| - mZoomControlsDelegate = new ZoomControlsDelegate() {
|
| - @Override
|
| - public void invokeZoomPicker() {}
|
| - @Override
|
| - public void dismissZoomPicker() {}
|
| - @Override
|
| - public void updateZoomControls() {}
|
| - };
|
| -
|
| - mRenderCoordinates.reset();
|
| - onRenderCoordinatesUpdated();
|
| -
|
| - initPopupZoomer(mContext);
|
| - mImeAdapter = createImeAdapter(mContext);
|
| - TraceEvent.end();
|
| - }
|
| -
|
| - private void initPopupZoomer(Context context) {
|
| - mPopupZoomer = new PopupZoomer(context);
|
| - mPopupZoomer.setOnVisibilityChangedListener(new PopupZoomer.OnVisibilityChangedListener() {
|
| - @Override
|
| - public void onPopupZoomerShown(final PopupZoomer zoomer) {
|
| - mContainerView.post(new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - if (mContainerView.indexOfChild(zoomer) == -1) {
|
| - mContainerView.addView(zoomer);
|
| - } else {
|
| - assert false : "PopupZoomer should never be shown without being hidden";
|
| - }
|
| - }
|
| - });
|
| - }
|
| -
|
| - @Override
|
| - public void onPopupZoomerHidden(final PopupZoomer zoomer) {
|
| - mContainerView.post(new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - if (mContainerView.indexOfChild(zoomer) != -1) {
|
| - mContainerView.removeView(zoomer);
|
| - mContainerView.invalidate();
|
| - } else {
|
| - assert false : "PopupZoomer should never be hidden without being shown";
|
| - }
|
| - }
|
| - });
|
| - }
|
| - });
|
| - // TODO(yongsheng): LONG_TAP is not enabled in PopupZoomer. So need to dispatch a LONG_TAP
|
| - // gesture if a user completes a tap on PopupZoomer UI after a LONG_PRESS gesture.
|
| - PopupZoomer.OnTapListener listener = new PopupZoomer.OnTapListener() {
|
| - @Override
|
| - public boolean onSingleTap(View v, MotionEvent e) {
|
| - mContainerView.requestFocus();
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeSingleTap(mNativeContentViewCore, e.getEventTime(),
|
| - e.getX(), e.getY(), true);
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - @Override
|
| - public boolean onLongPress(View v, MotionEvent e) {
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeLongPress(mNativeContentViewCore, e.getEventTime(),
|
| - e.getX(), e.getY(), true);
|
| - }
|
| - return true;
|
| - }
|
| - };
|
| - mPopupZoomer.setOnTapListener(listener);
|
| - }
|
| -
|
| - /**
|
| - * Destroy the internal state of the ContentView. This method may only be
|
| - * called after the ContentView has been removed from the view system. No
|
| - * other methods may be called on this ContentView after this method has
|
| - * been called.
|
| - */
|
| - public void destroy() {
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeOnJavaContentViewCoreDestroyed(mNativeContentViewCore);
|
| - }
|
| - mWebContents = null;
|
| - resetVSyncNotification();
|
| - mVSyncProvider = null;
|
| - if (mViewAndroid != null) mViewAndroid.destroy();
|
| - mNativeContentViewCore = 0;
|
| - mContentSettings = null;
|
| - mJavaScriptInterfaces.clear();
|
| - mRetainedJavaScriptObjects.clear();
|
| - unregisterAccessibilityContentObserver();
|
| - }
|
| -
|
| - private void unregisterAccessibilityContentObserver() {
|
| - if (mAccessibilityScriptInjectionObserver == null) {
|
| - return;
|
| - }
|
| - getContext().getContentResolver().unregisterContentObserver(
|
| - mAccessibilityScriptInjectionObserver);
|
| - mAccessibilityScriptInjectionObserver = null;
|
| - }
|
| -
|
| - /**
|
| - * Returns true initially, false after destroy() has been called.
|
| - * It is illegal to call any other public method after destroy().
|
| - */
|
| - public boolean isAlive() {
|
| - return mNativeContentViewCore != 0;
|
| - }
|
| -
|
| - /**
|
| - * This is only useful for passing over JNI to native code that requires ContentViewCore*.
|
| - * @return native ContentViewCore pointer.
|
| - */
|
| - @CalledByNative
|
| - public long getNativeContentViewCore() {
|
| - return mNativeContentViewCore;
|
| - }
|
| -
|
| - /**
|
| - * For internal use. Throws IllegalStateException if mNativeContentView is 0.
|
| - * Use this to ensure we get a useful Java stack trace, rather than a native
|
| - * crash dump, from use-after-destroy bugs in Java code.
|
| - */
|
| - void checkIsAlive() throws IllegalStateException {
|
| - if (!isAlive()) {
|
| - throw new IllegalStateException("ContentView used after destroy() was called");
|
| - }
|
| - }
|
| -
|
| - public void setContentViewClient(ContentViewClient client) {
|
| - if (client == null) {
|
| - throw new IllegalArgumentException("The client can't be null.");
|
| - }
|
| - mContentViewClient = client;
|
| - }
|
| -
|
| - ContentViewClient getContentViewClient() {
|
| - if (mContentViewClient == null) {
|
| - // We use the Null Object pattern to avoid having to perform a null check in this class.
|
| - // We create it lazily because most of the time a client will be set almost immediately
|
| - // after ContentView is created.
|
| - mContentViewClient = new ContentViewClient();
|
| - // We don't set the native ContentViewClient pointer here on purpose. The native
|
| - // implementation doesn't mind a null delegate and using one is better than passing a
|
| - // Null Object, since we cut down on the number of JNI calls.
|
| - }
|
| - return mContentViewClient;
|
| - }
|
| -
|
| - public int getBackgroundColor() {
|
| - if (mNativeContentViewCore != 0) {
|
| - return nativeGetBackgroundColor(mNativeContentViewCore);
|
| - }
|
| - return Color.WHITE;
|
| - }
|
| -
|
| - @CalledByNative
|
| - private void onBackgroundColorChanged(int color) {
|
| - getContentViewClient().onBackgroundColorChanged(color);
|
| - }
|
| -
|
| - /**
|
| - * Load url without fixing up the url string. Consumers of ContentView are responsible for
|
| - * ensuring the URL passed in is properly formatted (i.e. the scheme has been added if left
|
| - * off during user input).
|
| - *
|
| - * @param params Parameters for this load.
|
| - */
|
| - public void loadUrl(LoadUrlParams params) {
|
| - if (mNativeContentViewCore == 0) return;
|
| -
|
| - nativeLoadUrl(mNativeContentViewCore,
|
| - params.mUrl,
|
| - params.mLoadUrlType,
|
| - params.mTransitionType,
|
| - params.mUaOverrideOption,
|
| - params.getExtraHeadersString(),
|
| - params.mPostData,
|
| - params.mBaseUrlForDataUrl,
|
| - params.mVirtualUrlForDataUrl,
|
| - params.mCanLoadLocalResources);
|
| - }
|
| -
|
| - /**
|
| - * Stops loading the current web contents.
|
| - */
|
| - public void stopLoading() {
|
| - reportActionAfterDoubleTapUMA(ContentViewCore.UMAActionAfterDoubleTap.NAVIGATE_STOP);
|
| - if (mNativeContentViewCore != 0) nativeStopLoading(mNativeContentViewCore);
|
| - }
|
| -
|
| - /**
|
| - * Get the URL of the current page.
|
| - *
|
| - * @return The URL of the current page.
|
| - */
|
| - public String getUrl() {
|
| - if (mNativeContentViewCore != 0) return nativeGetURL(mNativeContentViewCore);
|
| - return null;
|
| - }
|
| -
|
| - /**
|
| - * Get the title of the current page.
|
| - *
|
| - * @return The title of the current page.
|
| - */
|
| - public String getTitle() {
|
| - if (mNativeContentViewCore != 0) return nativeGetTitle(mNativeContentViewCore);
|
| - return null;
|
| - }
|
| -
|
| - /**
|
| - * Shows an interstitial page driven by the passed in delegate.
|
| - *
|
| - * @param url The URL being blocked by the interstitial.
|
| - * @param delegate The delegate handling the interstitial.
|
| - */
|
| - @VisibleForTesting
|
| - public void showInterstitialPage(
|
| - String url, InterstitialPageDelegateAndroid delegate) {
|
| - if (mNativeContentViewCore == 0) return;
|
| - nativeShowInterstitialPage(mNativeContentViewCore, url, delegate.getNative());
|
| - }
|
| -
|
| - /**
|
| - * @return Whether the page is currently showing an interstitial, such as a bad HTTPS page.
|
| - */
|
| - public boolean isShowingInterstitialPage() {
|
| - return mNativeContentViewCore == 0 ?
|
| - false : nativeIsShowingInterstitialPage(mNativeContentViewCore);
|
| - }
|
| -
|
| - /**
|
| - * Mark any new frames that have arrived since this function was last called as non-pending.
|
| - *
|
| - * @return Whether there was a pending frame from the renderer.
|
| - */
|
| - public boolean consumePendingRendererFrame() {
|
| - boolean hadPendingFrame = mPendingRendererFrame;
|
| - mPendingRendererFrame = false;
|
| - return hadPendingFrame;
|
| - }
|
| -
|
| - /**
|
| - * @return Viewport width in physical pixels as set from onSizeChanged.
|
| - */
|
| - @CalledByNative
|
| - public int getViewportWidthPix() { return mViewportWidthPix; }
|
| -
|
| - /**
|
| - * @return Viewport height in physical pixels as set from onSizeChanged.
|
| - */
|
| - @CalledByNative
|
| - public int getViewportHeightPix() { return mViewportHeightPix; }
|
| -
|
| - /**
|
| - * @return Width of underlying physical surface.
|
| - */
|
| - @CalledByNative
|
| - public int getPhysicalBackingWidthPix() { return mPhysicalBackingWidthPix; }
|
| -
|
| - /**
|
| - * @return Height of underlying physical surface.
|
| - */
|
| - @CalledByNative
|
| - public int getPhysicalBackingHeightPix() { return mPhysicalBackingHeightPix; }
|
| -
|
| - /**
|
| - * @return Amount the output surface extends past the bottom of the window viewport.
|
| - */
|
| - @CalledByNative
|
| - public int getOverdrawBottomHeightPix() { return mOverdrawBottomHeightPix; }
|
| -
|
| - /**
|
| - * @return The amount to shrink the viewport relative to {@link #getViewportWidthPix()}.
|
| - */
|
| - @CalledByNative
|
| - public int getViewportSizeOffsetWidthPix() { return mViewportSizeOffsetWidthPix; }
|
| -
|
| - /**
|
| - * @return The amount to shrink the viewport relative to {@link #getViewportHeightPix()}.
|
| - */
|
| - @CalledByNative
|
| - public int getViewportSizeOffsetHeightPix() { return mViewportSizeOffsetHeightPix; }
|
| -
|
| - /**
|
| - * @see android.webkit.WebView#getContentHeight()
|
| - */
|
| - public float getContentHeightCss() {
|
| - return mRenderCoordinates.getContentHeightCss();
|
| - }
|
| -
|
| - /**
|
| - * @see android.webkit.WebView#getContentWidth()
|
| - */
|
| - public float getContentWidthCss() {
|
| - return mRenderCoordinates.getContentWidthCss();
|
| - }
|
| -
|
| - public Bitmap getBitmap() {
|
| - return getBitmap(getViewportWidthPix(), getViewportHeightPix());
|
| - }
|
| -
|
| - public Bitmap getBitmap(int width, int height) {
|
| - if (width == 0 || height == 0
|
| - || getViewportWidthPix() == 0 || getViewportHeightPix() == 0) {
|
| - return null;
|
| - }
|
| -
|
| - Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
| -
|
| - if (mNativeContentViewCore != 0 &&
|
| - nativePopulateBitmapFromCompositor(mNativeContentViewCore, b)) {
|
| - // If we successfully grabbed a bitmap, check if we have to draw the Android overlay
|
| - // components as well.
|
| - if (mContainerView.getChildCount() > 0) {
|
| - Canvas c = new Canvas(b);
|
| - c.scale(width / (float) getViewportWidthPix(),
|
| - height / (float) getViewportHeightPix());
|
| - mContainerView.draw(c);
|
| - }
|
| - return b;
|
| - }
|
| -
|
| - return null;
|
| - }
|
| -
|
| - /**
|
| - * Generates a bitmap of the content that is performance optimized based on capture time.
|
| - *
|
| - * <p>
|
| - * To have a consistent capture time across devices, we will scale down the captured bitmap
|
| - * where necessary to reduce the time to generate the bitmap.
|
| - *
|
| - * @param width The width of the content to be captured.
|
| - * @param height The height of the content to be captured.
|
| - * @return A pair of the generated bitmap, and the scale that needs to be applied to return the
|
| - * bitmap to it's original size (i.e. if the bitmap is scaled down 50%, this
|
| - * will be 2).
|
| - */
|
| - public Pair<Bitmap, Float> getScaledPerformanceOptimizedBitmap(int width, int height) {
|
| - float scale = 1f;
|
| - // On tablets, always scale down to MDPI for performance reasons.
|
| - if (DeviceUtils.isTablet(getContext())) {
|
| - scale = getContext().getResources().getDisplayMetrics().density;
|
| - }
|
| - return Pair.create(
|
| - getBitmap((int) (width / scale), (int) (height / scale)),
|
| - scale);
|
| - }
|
| -
|
| - // TODO(teddchoc): Remove all these navigation controller methods from here and have the
|
| - // embedders manage it.
|
| - /**
|
| - * @return Whether the current WebContents has a previous navigation entry.
|
| - */
|
| - public boolean canGoBack() {
|
| - return mWebContents != null && mWebContents.getNavigationController().canGoBack();
|
| - }
|
| -
|
| - /**
|
| - * @return Whether the current WebContents has a navigation entry after the current one.
|
| - */
|
| - public boolean canGoForward() {
|
| - return mWebContents != null && mWebContents.getNavigationController().canGoForward();
|
| - }
|
| -
|
| - /**
|
| - * @param offset The offset into the navigation history.
|
| - * @return Whether we can move in history by given offset
|
| - */
|
| - public boolean canGoToOffset(int offset) {
|
| - return mWebContents != null &&
|
| - mWebContents.getNavigationController().canGoToOffset(offset);
|
| - }
|
| -
|
| - /**
|
| - * Navigates to the specified offset from the "current entry". Does nothing if the offset is out
|
| - * of bounds.
|
| - * @param offset The offset into the navigation history.
|
| - */
|
| - public void goToOffset(int offset) {
|
| - if (mWebContents != null) mWebContents.getNavigationController().goToOffset(offset);
|
| - }
|
| -
|
| - @Override
|
| - public void goToNavigationIndex(int index) {
|
| - if (mWebContents != null) {
|
| - mWebContents.getNavigationController().goToNavigationIndex(index);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Goes to the navigation entry before the current one.
|
| - */
|
| - public void goBack() {
|
| - if (mWebContents != null) mWebContents.getNavigationController().goBack();
|
| - }
|
| -
|
| - /**
|
| - * Goes to the navigation entry following the current one.
|
| - */
|
| - public void goForward() {
|
| - if (mWebContents != null) mWebContents.getNavigationController().goForward();
|
| - }
|
| -
|
| - /**
|
| - * Loads the current navigation if there is a pending lazy load (after tab restore).
|
| - */
|
| - public void loadIfNecessary() {
|
| - if (mNativeContentViewCore != 0) nativeLoadIfNecessary(mNativeContentViewCore);
|
| - }
|
| -
|
| - /**
|
| - * Requests the current navigation to be loaded upon the next call to loadIfNecessary().
|
| - */
|
| - public void requestRestoreLoad() {
|
| - if (mNativeContentViewCore != 0) nativeRequestRestoreLoad(mNativeContentViewCore);
|
| - }
|
| -
|
| - /**
|
| - * Reload the current page.
|
| - */
|
| - public void reload(boolean checkForRepost) {
|
| - mAccessibilityInjector.addOrRemoveAccessibilityApisIfNecessary();
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeReload(mNativeContentViewCore, checkForRepost);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Reload the current page, ignoring the contents of the cache.
|
| - */
|
| - public void reloadIgnoringCache(boolean checkForRepost) {
|
| - mAccessibilityInjector.addOrRemoveAccessibilityApisIfNecessary();
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeReloadIgnoringCache(mNativeContentViewCore, checkForRepost);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Cancel the pending reload.
|
| - */
|
| - public void cancelPendingReload() {
|
| - if (mNativeContentViewCore != 0) nativeCancelPendingReload(mNativeContentViewCore);
|
| - }
|
| -
|
| - /**
|
| - * Continue the pending reload.
|
| - */
|
| - public void continuePendingReload() {
|
| - if (mNativeContentViewCore != 0) nativeContinuePendingReload(mNativeContentViewCore);
|
| - }
|
| -
|
| - /**
|
| - * Clears the ContentViewCore's page history in both the backwards and
|
| - * forwards directions.
|
| - */
|
| - public void clearHistory() {
|
| - if (mNativeContentViewCore != 0) nativeClearHistory(mNativeContentViewCore);
|
| - }
|
| -
|
| - /**
|
| - * @return The selected text (empty if no text selected).
|
| - */
|
| - public String getSelectedText() {
|
| - return mHasSelection ? mLastSelectedText : "";
|
| - }
|
| -
|
| - /**
|
| - * @return Whether the current selection is editable (false if no text selected).
|
| - */
|
| - public boolean isSelectionEditable() {
|
| - return mHasSelection ? mSelectionEditable : false;
|
| - }
|
| -
|
| - // End FrameLayout overrides.
|
| -
|
| - /**
|
| - * @see View#onTouchEvent(MotionEvent)
|
| - */
|
| - public boolean onTouchEvent(MotionEvent event) {
|
| - undoScrollFocusedEditableNodeIntoViewIfNeeded(false);
|
| - if (!mRequestedVSyncForInput) {
|
| - mRequestedVSyncForInput = true;
|
| - addVSyncSubscriber();
|
| - }
|
| - return mContentViewGestureHandler.onTouchEvent(event);
|
| - }
|
| -
|
| - /**
|
| - * @return ContentViewGestureHandler for all MotionEvent and gesture related calls.
|
| - */
|
| - ContentViewGestureHandler getContentViewGestureHandler() {
|
| - return mContentViewGestureHandler;
|
| - }
|
| -
|
| - @Override
|
| - public boolean sendTouchEvent(long timeMs, int action, TouchPoint[] pts) {
|
| - if (mNativeContentViewCore != 0) {
|
| - return nativeSendTouchEvent(mNativeContentViewCore, timeMs, action, pts);
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - @SuppressWarnings("unused")
|
| - @CalledByNative
|
| - private void hasTouchEventHandlers(boolean hasTouchHandlers) {
|
| - mContentViewGestureHandler.hasTouchEventHandlers(hasTouchHandlers);
|
| - }
|
| -
|
| - @SuppressWarnings("unused")
|
| - @CalledByNative
|
| - private void confirmTouchEvent(int ackResult) {
|
| - mContentViewGestureHandler.confirmTouchEvent(ackResult);
|
| - }
|
| -
|
| - @SuppressWarnings("unused")
|
| - @CalledByNative
|
| - private void onFlingStartEventAck(int ackResult) {
|
| - if (ackResult == ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS
|
| - && mGestureStateListener != null) {
|
| - mGestureStateListener.onUnhandledFlingStartEvent();
|
| - }
|
| - if (ackResult != ContentViewGestureHandler.INPUT_EVENT_ACK_STATE_CONSUMED) {
|
| - // No fling happened for the fling start event.
|
| - // Cancel the fling status set when sending GestureFlingStart.
|
| - getContentViewClient().onFlingStopped();
|
| - }
|
| - }
|
| -
|
| - @SuppressWarnings("unused")
|
| - @CalledByNative
|
| - private void onScrollUpdateGestureConsumed() {
|
| - if (mGestureStateListener != null) {
|
| - mGestureStateListener.onScrollUpdateGestureConsumed();
|
| - }
|
| - }
|
| -
|
| - private void reportActionAfterDoubleTapUMA(int type) {
|
| - mContentViewGestureHandler.reportActionAfterDoubleTapUMA(type);
|
| - }
|
| -
|
| - @Override
|
| - public boolean sendGesture(int type, long timeMs, int x, int y, Bundle b) {
|
| - if (offerGestureToEmbedder(type)) return false;
|
| - if (mNativeContentViewCore == 0) return false;
|
| - updateTextHandlesForGesture(type);
|
| - updateGestureStateListener(type, b);
|
| - switch (type) {
|
| - case ContentViewGestureHandler.GESTURE_SHOW_PRESSED_STATE:
|
| - nativeShowPressState(mNativeContentViewCore, timeMs, x, y);
|
| - return true;
|
| - case ContentViewGestureHandler.GESTURE_TAP_CANCEL:
|
| - nativeTapCancel(mNativeContentViewCore, timeMs, x, y);
|
| - return true;
|
| - case ContentViewGestureHandler.GESTURE_TAP_DOWN:
|
| - nativeTapDown(mNativeContentViewCore, timeMs, x, y);
|
| - return true;
|
| - case ContentViewGestureHandler.GESTURE_DOUBLE_TAP:
|
| - nativeDoubleTap(mNativeContentViewCore, timeMs, x, y);
|
| - return true;
|
| - case ContentViewGestureHandler.GESTURE_SINGLE_TAP_UP:
|
| - nativeSingleTap(mNativeContentViewCore, timeMs, x, y, false);
|
| - return true;
|
| - case ContentViewGestureHandler.GESTURE_SINGLE_TAP_CONFIRMED:
|
| - handleTapOrPress(timeMs, x, y, 0,
|
| - b.getBoolean(ContentViewGestureHandler.SHOW_PRESS, false));
|
| - return true;
|
| - case ContentViewGestureHandler.GESTURE_SINGLE_TAP_UNCONFIRMED:
|
| - nativeSingleTapUnconfirmed(mNativeContentViewCore, timeMs, x, y);
|
| - return true;
|
| - case ContentViewGestureHandler.GESTURE_LONG_PRESS:
|
| - handleTapOrPress(timeMs, x, y, IS_LONG_PRESS, false);
|
| - return true;
|
| - case ContentViewGestureHandler.GESTURE_LONG_TAP:
|
| - handleTapOrPress(timeMs, x, y, IS_LONG_TAP, false);
|
| - return true;
|
| - case ContentViewGestureHandler.GESTURE_SCROLL_START: {
|
| - int dx = b.getInt(ContentViewGestureHandler.DELTA_HINT_X);
|
| - int dy = b.getInt(ContentViewGestureHandler.DELTA_HINT_Y);
|
| - nativeScrollBegin(mNativeContentViewCore, timeMs, x, y, dx, dy);
|
| - return true;
|
| - }
|
| - case ContentViewGestureHandler.GESTURE_SCROLL_BY: {
|
| - int dx = b.getInt(ContentViewGestureHandler.DISTANCE_X);
|
| - int dy = b.getInt(ContentViewGestureHandler.DISTANCE_Y);
|
| - nativeScrollBy(mNativeContentViewCore, timeMs, x, y, dx, dy);
|
| - return true;
|
| - }
|
| - case ContentViewGestureHandler.GESTURE_SCROLL_END:
|
| - nativeScrollEnd(mNativeContentViewCore, timeMs);
|
| - return true;
|
| - case ContentViewGestureHandler.GESTURE_FLING_START:
|
| - mContentViewClient.onFlingStarted();
|
| - nativeFlingStart(mNativeContentViewCore, timeMs, x, y,
|
| - b.getInt(ContentViewGestureHandler.VELOCITY_X, 0),
|
| - b.getInt(ContentViewGestureHandler.VELOCITY_Y, 0));
|
| - return true;
|
| - case ContentViewGestureHandler.GESTURE_FLING_CANCEL:
|
| - nativeFlingCancel(mNativeContentViewCore, timeMs);
|
| - return true;
|
| - case ContentViewGestureHandler.GESTURE_PINCH_BEGIN:
|
| - nativePinchBegin(mNativeContentViewCore, timeMs, x, y);
|
| - return true;
|
| - case ContentViewGestureHandler.GESTURE_PINCH_BY:
|
| - nativePinchBy(mNativeContentViewCore, timeMs, x, y,
|
| - b.getFloat(ContentViewGestureHandler.DELTA, 0));
|
| - return true;
|
| - case ContentViewGestureHandler.GESTURE_PINCH_END:
|
| - nativePinchEnd(mNativeContentViewCore, timeMs);
|
| - return true;
|
| - default:
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - @VisibleForTesting
|
| - public void sendDoubleTapForTest(long timeMs, int x, int y, Bundle b) {
|
| - sendGesture(ContentViewGestureHandler.GESTURE_DOUBLE_TAP, timeMs, x, y, b);
|
| - }
|
| -
|
| - @Override
|
| - public void sendSingleTapUMA(int type) {
|
| - if (mNativeContentViewCore == 0) return;
|
| - nativeSendSingleTapUma(
|
| - mNativeContentViewCore,
|
| - type,
|
| - UMASingleTapType.COUNT);
|
| - }
|
| -
|
| - @Override
|
| - public void sendActionAfterDoubleTapUMA(int type,
|
| - boolean clickDelayEnabled) {
|
| - if (mNativeContentViewCore == 0) return;
|
| - nativeSendActionAfterDoubleTapUma(
|
| - mNativeContentViewCore,
|
| - type,
|
| - clickDelayEnabled,
|
| - UMAActionAfterDoubleTap.COUNT);
|
| - }
|
| -
|
| - public void setGestureStateListener(GestureStateListener pinchGestureStateListener) {
|
| - mGestureStateListener = pinchGestureStateListener;
|
| - }
|
| -
|
| - void updateGestureStateListener(int gestureType, Bundle b) {
|
| - if (mGestureStateListener == null) return;
|
| -
|
| - switch (gestureType) {
|
| - case ContentViewGestureHandler.GESTURE_PINCH_BEGIN:
|
| - mGestureStateListener.onPinchGestureStart();
|
| - break;
|
| - case ContentViewGestureHandler.GESTURE_PINCH_END:
|
| - mGestureStateListener.onPinchGestureEnd();
|
| - break;
|
| - case ContentViewGestureHandler.GESTURE_FLING_START:
|
| - mGestureStateListener.onFlingStartGesture(
|
| - b.getInt(ContentViewGestureHandler.VELOCITY_X, 0),
|
| - b.getInt(ContentViewGestureHandler.VELOCITY_Y, 0));
|
| - break;
|
| - case ContentViewGestureHandler.GESTURE_FLING_CANCEL:
|
| - mGestureStateListener.onFlingCancelGesture();
|
| - break;
|
| - default:
|
| - break;
|
| - }
|
| - }
|
| -
|
| - /** Callback interface for evaluateJavaScript(). */
|
| - public interface JavaScriptCallback {
|
| - void handleJavaScriptResult(String jsonResult);
|
| - }
|
| -
|
| - /**
|
| - * Injects the passed Javascript code in the current page and evaluates it.
|
| - * If a result is required, pass in a callback.
|
| - * Used in automation tests.
|
| - *
|
| - * @param script The Javascript to execute.
|
| - * @param callback The callback to be fired off when a result is ready. The script's
|
| - * result will be json encoded and passed as the parameter, and the call
|
| - * will be made on the main thread.
|
| - * If no result is required, pass null.
|
| - */
|
| - public void evaluateJavaScript(String script, JavaScriptCallback callback) {
|
| - if (mNativeContentViewCore == 0) return;
|
| - nativeEvaluateJavaScript(mNativeContentViewCore, script, callback, false);
|
| - }
|
| -
|
| - /**
|
| - * Injects the passed Javascript code in the current page and evaluates it.
|
| - * If there is no page existing, a new one will be created.
|
| - *
|
| - * @param script The Javascript to execute.
|
| - */
|
| - public void evaluateJavaScriptEvenIfNotYetNavigated(String script) {
|
| - if (mNativeContentViewCore == 0) return;
|
| - nativeEvaluateJavaScript(mNativeContentViewCore, script, null, true);
|
| - }
|
| -
|
| - /**
|
| - * To be called when the ContentView is shown.
|
| - */
|
| - public void onShow() {
|
| - assert mNativeContentViewCore != 0;
|
| - if (!mInForeground) {
|
| - int pid = nativeGetCurrentRenderProcessId(mNativeContentViewCore);
|
| - ChildProcessLauncher.getBindingManager().setInForeground(pid, true);
|
| - }
|
| - mInForeground = true;
|
| - nativeOnShow(mNativeContentViewCore);
|
| - setAccessibilityState(mAccessibilityManager.isEnabled());
|
| - }
|
| -
|
| - /**
|
| - * To be called when the ContentView is hidden.
|
| - */
|
| - public void onHide() {
|
| - assert mNativeContentViewCore != 0;
|
| - if (mInForeground) {
|
| - int pid = nativeGetCurrentRenderProcessId(mNativeContentViewCore);
|
| - ChildProcessLauncher.getBindingManager().setInForeground(pid, false);
|
| - }
|
| - mInForeground = false;
|
| - hidePopupDialog();
|
| - setInjectedAccessibility(false);
|
| - nativeOnHide(mNativeContentViewCore);
|
| - }
|
| -
|
| - /**
|
| - * Return the ContentSettings object used to retrieve the settings for this
|
| - * ContentViewCore. For modifications, ChromeNativePreferences is to be used.
|
| - * @return A ContentSettings object that can be used to retrieve this
|
| - * ContentViewCore's settings.
|
| - */
|
| - public ContentSettings getContentSettings() {
|
| - return mContentSettings;
|
| - }
|
| -
|
| - private void onRenderCoordinatesUpdated() {
|
| - if (mContentViewGestureHandler == null) return;
|
| -
|
| - // We disable double tap zoom for pages that have a width=device-width
|
| - // or narrower viewport (indicating that this is a mobile-optimized or
|
| - // responsive web design, so text will be legible without zooming).
|
| - // We also disable it for pages that disallow the user from zooming in
|
| - // or out (even if they don't have a device-width or narrower viewport).
|
| - mContentViewGestureHandler.updateShouldDisableDoubleTap(
|
| - mRenderCoordinates.hasMobileViewport() || mRenderCoordinates.hasFixedPageScale());
|
| - }
|
| -
|
| - private void hidePopupDialog() {
|
| - SelectPopupDialog.hide(this);
|
| - hideHandles();
|
| - hideSelectActionBar();
|
| - }
|
| -
|
| - void hideSelectActionBar() {
|
| - if (mActionMode != null) {
|
| - mActionMode.finish();
|
| - mActionMode = null;
|
| - }
|
| - }
|
| -
|
| - public boolean isSelectActionBarShowing() {
|
| - return mActionMode != null;
|
| - }
|
| -
|
| - private void resetGestureDetectors() {
|
| - mContentViewGestureHandler.resetGestureHandlers();
|
| - }
|
| -
|
| - /**
|
| - * @see View#onAttachedToWindow()
|
| - */
|
| - @SuppressWarnings("javadoc")
|
| - public void onAttachedToWindow() {
|
| - setAccessibilityState(mAccessibilityManager.isEnabled());
|
| - }
|
| -
|
| - /**
|
| - * @see View#onDetachedFromWindow()
|
| - */
|
| - @SuppressWarnings("javadoc")
|
| - public void onDetachedFromWindow() {
|
| - setInjectedAccessibility(false);
|
| - hidePopupDialog();
|
| - mZoomControlsDelegate.dismissZoomPicker();
|
| - unregisterAccessibilityContentObserver();
|
| - }
|
| -
|
| - /**
|
| - * @see View#onVisibilityChanged(android.view.View, int)
|
| - */
|
| - public void onVisibilityChanged(View changedView, int visibility) {
|
| - if (visibility != View.VISIBLE) {
|
| - mZoomControlsDelegate.dismissZoomPicker();
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * @see View#onCreateInputConnection(EditorInfo)
|
| - */
|
| - public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
|
| - if (!mImeAdapter.hasTextInputType()) {
|
| - // Although onCheckIsTextEditor will return false in this case, the EditorInfo
|
| - // is still used by the InputMethodService. Need to make sure the IME doesn't
|
| - // enter fullscreen mode.
|
| - outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN;
|
| - }
|
| - mInputConnection =
|
| - mAdapterInputConnectionFactory.get(mContainerView, mImeAdapter, outAttrs);
|
| - return mInputConnection;
|
| - }
|
| -
|
| - public Editable getEditableForTest() {
|
| - return mInputConnection.getEditable();
|
| - }
|
| -
|
| - /**
|
| - * @see View#onCheckIsTextEditor()
|
| - */
|
| - public boolean onCheckIsTextEditor() {
|
| - return mImeAdapter.hasTextInputType();
|
| - }
|
| -
|
| - /**
|
| - * @see View#onConfigurationChanged(Configuration)
|
| - */
|
| - @SuppressWarnings("javadoc")
|
| - public void onConfigurationChanged(Configuration newConfig) {
|
| - TraceEvent.begin();
|
| -
|
| - if (newConfig.keyboard != Configuration.KEYBOARD_NOKEYS) {
|
| - mImeAdapter.attach(nativeGetNativeImeAdapter(mNativeContentViewCore),
|
| - ImeAdapter.getTextInputTypeNone(),
|
| - AdapterInputConnection.INVALID_SELECTION,
|
| - AdapterInputConnection.INVALID_SELECTION);
|
| - InputMethodManager manager = (InputMethodManager)
|
| - getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
| - manager.restartInput(mContainerView);
|
| - }
|
| - mContainerViewInternals.super_onConfigurationChanged(newConfig);
|
| - // Make sure the size is up to date in JavaScript's window.onorientationchanged.
|
| - mContainerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
|
| - @Override
|
| - public void onLayoutChange(View v, int left, int top, int right, int bottom,
|
| - int oldLeft, int oldTop, int oldRight, int oldBottom) {
|
| - mContainerView.removeOnLayoutChangeListener(this);
|
| - sendOrientationChangeEvent();
|
| - }
|
| - });
|
| - // To request layout has side effect, but it seems OK as it only happen in
|
| - // onConfigurationChange and layout has to be changed in most case.
|
| - mContainerView.requestLayout();
|
| - TraceEvent.end();
|
| - }
|
| -
|
| - /**
|
| - * @see View#onSizeChanged(int, int, int, int)
|
| - */
|
| - @SuppressWarnings("javadoc")
|
| - public void onSizeChanged(int wPix, int hPix, int owPix, int ohPix) {
|
| - if (getViewportWidthPix() == wPix && getViewportHeightPix() == hPix) return;
|
| -
|
| - mViewportWidthPix = wPix;
|
| - mViewportHeightPix = hPix;
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeWasResized(mNativeContentViewCore);
|
| - }
|
| -
|
| - updateAfterSizeChanged();
|
| - }
|
| -
|
| - /**
|
| - * Called when the ContentView's position in the activity window changed. This information is
|
| - * used for cropping screenshots.
|
| - */
|
| - public void onLocationInWindowChanged(int x, int y) {
|
| - mLocationInWindowX = x;
|
| - mLocationInWindowY = y;
|
| - }
|
| -
|
| - /**
|
| - * Called when the underlying surface the compositor draws to changes size.
|
| - * This may be larger than the viewport size.
|
| - */
|
| - public void onPhysicalBackingSizeChanged(int wPix, int hPix) {
|
| - if (mPhysicalBackingWidthPix == wPix && mPhysicalBackingHeightPix == hPix) return;
|
| -
|
| - mPhysicalBackingWidthPix = wPix;
|
| - mPhysicalBackingHeightPix = hPix;
|
| -
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeWasResized(mNativeContentViewCore);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Called when the amount the surface is overdrawing off the bottom has changed.
|
| - * @param overdrawHeightPix The overdraw height.
|
| - */
|
| - public void onOverdrawBottomHeightChanged(int overdrawHeightPix) {
|
| - if (mOverdrawBottomHeightPix == overdrawHeightPix) return;
|
| -
|
| - mOverdrawBottomHeightPix = overdrawHeightPix;
|
| -
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeWasResized(mNativeContentViewCore);
|
| - }
|
| - }
|
| -
|
| - private void updateAfterSizeChanged() {
|
| - mPopupZoomer.hide(false);
|
| -
|
| - // Execute a delayed form focus operation because the OSK was brought
|
| - // up earlier.
|
| - if (!mFocusPreOSKViewportRect.isEmpty()) {
|
| - Rect rect = new Rect();
|
| - getContainerView().getWindowVisibleDisplayFrame(rect);
|
| - if (!rect.equals(mFocusPreOSKViewportRect)) {
|
| - // Only assume the OSK triggered the onSizeChanged if width was preserved.
|
| - if (rect.width() == mFocusPreOSKViewportRect.width()) {
|
| - scrollFocusedEditableNodeIntoView();
|
| - }
|
| - mFocusPreOSKViewportRect.setEmpty();
|
| - }
|
| - } else if (mUnfocusOnNextSizeChanged) {
|
| - undoScrollFocusedEditableNodeIntoViewIfNeeded(true);
|
| - mUnfocusOnNextSizeChanged = false;
|
| - }
|
| - }
|
| -
|
| - private void scrollFocusedEditableNodeIntoView() {
|
| - if (mNativeContentViewCore != 0) {
|
| - Runnable scrollTask = new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeScrollFocusedEditableNodeIntoView(mNativeContentViewCore);
|
| - }
|
| - }
|
| - };
|
| -
|
| - scrollTask.run();
|
| -
|
| - // The native side keeps track of whether the zoom and scroll actually occurred. It is
|
| - // more efficient to do it this way and sometimes fire an unnecessary message rather
|
| - // than synchronize with the renderer and always have an additional message.
|
| - mScrolledAndZoomedFocusedEditableNode = true;
|
| - }
|
| - }
|
| -
|
| - private void undoScrollFocusedEditableNodeIntoViewIfNeeded(boolean backButtonPressed) {
|
| - // The only call to this function that matters is the first call after the
|
| - // scrollFocusedEditableNodeIntoView function call.
|
| - // If the first call to this function is a result of a back button press we want to undo the
|
| - // preceding scroll. If the call is a result of some other action we don't want to perform
|
| - // an undo.
|
| - // All subsequent calls are ignored since only the scroll function sets
|
| - // mScrolledAndZoomedFocusedEditableNode to true.
|
| - if (mScrolledAndZoomedFocusedEditableNode && backButtonPressed &&
|
| - mNativeContentViewCore != 0) {
|
| - Runnable scrollTask = new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeUndoScrollFocusedEditableNodeIntoView(mNativeContentViewCore);
|
| - }
|
| - }
|
| - };
|
| -
|
| - scrollTask.run();
|
| - }
|
| - mScrolledAndZoomedFocusedEditableNode = false;
|
| - }
|
| -
|
| - /**
|
| - * @see View#onWindowFocusChanged(boolean)
|
| - */
|
| - public void onWindowFocusChanged(boolean hasWindowFocus) {
|
| - if (!hasWindowFocus) {
|
| - mContentViewGestureHandler.onWindowFocusLost();
|
| - }
|
| - }
|
| -
|
| - public void onFocusChanged(boolean gainFocus) {
|
| - if (!gainFocus) getContentViewClient().onImeStateChangeRequested(false);
|
| - if (mNativeContentViewCore != 0) nativeSetFocus(mNativeContentViewCore, gainFocus);
|
| - }
|
| -
|
| - /**
|
| - * @see View#onKeyUp(int, KeyEvent)
|
| - */
|
| - public boolean onKeyUp(int keyCode, KeyEvent event) {
|
| - if (mPopupZoomer.isShowing() && keyCode == KeyEvent.KEYCODE_BACK) {
|
| - mPopupZoomer.hide(true);
|
| - return true;
|
| - }
|
| - return mContainerViewInternals.super_onKeyUp(keyCode, event);
|
| - }
|
| -
|
| - /**
|
| - * @see View#dispatchKeyEventPreIme(KeyEvent)
|
| - */
|
| - public boolean dispatchKeyEventPreIme(KeyEvent event) {
|
| - try {
|
| - TraceEvent.begin();
|
| - if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && mImeAdapter.isActive()) {
|
| - mUnfocusOnNextSizeChanged = true;
|
| - } else {
|
| - undoScrollFocusedEditableNodeIntoViewIfNeeded(false);
|
| - }
|
| - return mContainerViewInternals.super_dispatchKeyEventPreIme(event);
|
| - } finally {
|
| - TraceEvent.end();
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * @see View#dispatchKeyEvent(KeyEvent)
|
| - */
|
| - public boolean dispatchKeyEvent(KeyEvent event) {
|
| - if (getContentViewClient().shouldOverrideKeyEvent(event)) {
|
| - return mContainerViewInternals.super_dispatchKeyEvent(event);
|
| - }
|
| -
|
| - if (mImeAdapter.dispatchKeyEvent(event)) return true;
|
| -
|
| - return mContainerViewInternals.super_dispatchKeyEvent(event);
|
| - }
|
| -
|
| - /**
|
| - * @see View#onHoverEvent(MotionEvent)
|
| - * Mouse move events are sent on hover enter, hover move and hover exit.
|
| - * They are sent on hover exit because sometimes it acts as both a hover
|
| - * move and hover exit.
|
| - */
|
| - public boolean onHoverEvent(MotionEvent event) {
|
| - TraceEvent.begin("onHoverEvent");
|
| - mContainerView.removeCallbacks(mFakeMouseMoveRunnable);
|
| - if (mBrowserAccessibilityManager != null) {
|
| - return mBrowserAccessibilityManager.onHoverEvent(event);
|
| - }
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeSendMouseMoveEvent(mNativeContentViewCore, event.getEventTime(),
|
| - event.getX(), event.getY());
|
| - }
|
| - TraceEvent.end("onHoverEvent");
|
| - return true;
|
| - }
|
| -
|
| - /**
|
| - * @see View#onGenericMotionEvent(MotionEvent)
|
| - */
|
| - public boolean onGenericMotionEvent(MotionEvent event) {
|
| - if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
|
| - switch (event.getAction()) {
|
| - case MotionEvent.ACTION_SCROLL:
|
| - nativeSendMouseWheelEvent(mNativeContentViewCore, event.getEventTime(),
|
| - event.getX(), event.getY(),
|
| - event.getAxisValue(MotionEvent.AXIS_VSCROLL));
|
| -
|
| - mContainerView.removeCallbacks(mFakeMouseMoveRunnable);
|
| - // Send a delayed onMouseMove event so that we end
|
| - // up hovering over the right position after the scroll.
|
| - final MotionEvent eventFakeMouseMove = MotionEvent.obtain(event);
|
| - mFakeMouseMoveRunnable = new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - onHoverEvent(eventFakeMouseMove);
|
| - }
|
| - };
|
| - mContainerView.postDelayed(mFakeMouseMoveRunnable, 250);
|
| - return true;
|
| - }
|
| - }
|
| - return mContainerViewInternals.super_onGenericMotionEvent(event);
|
| - }
|
| -
|
| - /**
|
| - * @see View#scrollBy(int, int)
|
| - * Currently the ContentView scrolling happens in the native side. In
|
| - * the Java view system, it is always pinned at (0, 0). scrollBy() and scrollTo()
|
| - * are overridden, so that View's mScrollX and mScrollY will be unchanged at
|
| - * (0, 0). This is critical for drawing ContentView correctly.
|
| - */
|
| - public void scrollBy(int xPix, int yPix) {
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeScrollBy(mNativeContentViewCore,
|
| - System.currentTimeMillis(), 0, 0, xPix, yPix);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * @see View#scrollTo(int, int)
|
| - */
|
| - public void scrollTo(int xPix, int yPix) {
|
| - if (mNativeContentViewCore == 0) return;
|
| - final float xCurrentPix = mRenderCoordinates.getScrollXPix();
|
| - final float yCurrentPix = mRenderCoordinates.getScrollYPix();
|
| - final float dxPix = xPix - xCurrentPix;
|
| - final float dyPix = yPix - yCurrentPix;
|
| - if (dxPix != 0 || dyPix != 0) {
|
| - long time = System.currentTimeMillis();
|
| - nativeScrollBegin(mNativeContentViewCore, time,
|
| - xCurrentPix, yCurrentPix, -dxPix, -dyPix);
|
| - nativeScrollBy(mNativeContentViewCore,
|
| - time, xCurrentPix, yCurrentPix, dxPix, dyPix);
|
| - nativeScrollEnd(mNativeContentViewCore, time);
|
| - }
|
| - }
|
| -
|
| - // NOTE: this can go away once ContentView.getScrollX() reports correct values.
|
| - // see: b/6029133
|
| - public int getNativeScrollXForTest() {
|
| - return mRenderCoordinates.getScrollXPixInt();
|
| - }
|
| -
|
| - // NOTE: this can go away once ContentView.getScrollY() reports correct values.
|
| - // see: b/6029133
|
| - public int getNativeScrollYForTest() {
|
| - return mRenderCoordinates.getScrollYPixInt();
|
| - }
|
| -
|
| - /**
|
| - * @see View#computeHorizontalScrollExtent()
|
| - */
|
| - @SuppressWarnings("javadoc")
|
| - public int computeHorizontalScrollExtent() {
|
| - return mRenderCoordinates.getLastFrameViewportWidthPixInt();
|
| - }
|
| -
|
| - /**
|
| - * @see View#computeHorizontalScrollOffset()
|
| - */
|
| - @SuppressWarnings("javadoc")
|
| - public int computeHorizontalScrollOffset() {
|
| - return mRenderCoordinates.getScrollXPixInt();
|
| - }
|
| -
|
| - /**
|
| - * @see View#computeHorizontalScrollRange()
|
| - */
|
| - @SuppressWarnings("javadoc")
|
| - public int computeHorizontalScrollRange() {
|
| - return mRenderCoordinates.getContentWidthPixInt();
|
| - }
|
| -
|
| - /**
|
| - * @see View#computeVerticalScrollExtent()
|
| - */
|
| - @SuppressWarnings("javadoc")
|
| - public int computeVerticalScrollExtent() {
|
| - return mRenderCoordinates.getLastFrameViewportHeightPixInt();
|
| - }
|
| -
|
| - /**
|
| - * @see View#computeVerticalScrollOffset()
|
| - */
|
| - @SuppressWarnings("javadoc")
|
| - public int computeVerticalScrollOffset() {
|
| - return mRenderCoordinates.getScrollYPixInt();
|
| - }
|
| -
|
| - /**
|
| - * @see View#computeVerticalScrollRange()
|
| - */
|
| - @SuppressWarnings("javadoc")
|
| - public int computeVerticalScrollRange() {
|
| - return mRenderCoordinates.getContentHeightPixInt();
|
| - }
|
| -
|
| - // End FrameLayout overrides.
|
| -
|
| - /**
|
| - * @see View#awakenScrollBars(int, boolean)
|
| - */
|
| - @SuppressWarnings("javadoc")
|
| - public boolean awakenScrollBars(int startDelay, boolean invalidate) {
|
| - // For the default implementation of ContentView which draws the scrollBars on the native
|
| - // side, calling this function may get us into a bad state where we keep drawing the
|
| - // scrollBars, so disable it by always returning false.
|
| - if (mContainerView.getScrollBarStyle() == View.SCROLLBARS_INSIDE_OVERLAY) {
|
| - return false;
|
| - } else {
|
| - return mContainerViewInternals.super_awakenScrollBars(startDelay, invalidate);
|
| - }
|
| - }
|
| -
|
| - private void handleTapOrPress(
|
| - long timeMs, float xPix, float yPix, int isLongPressOrTap, boolean showPress) {
|
| - if (mContainerView.isFocusable() && mContainerView.isFocusableInTouchMode()
|
| - && !mContainerView.isFocused()) {
|
| - mContainerView.requestFocus();
|
| - }
|
| -
|
| - if (!mPopupZoomer.isShowing()) mPopupZoomer.setLastTouch(xPix, yPix);
|
| -
|
| - if (isLongPressOrTap == IS_LONG_PRESS) {
|
| - getInsertionHandleController().allowAutomaticShowing();
|
| - getSelectionHandleController().allowAutomaticShowing();
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeLongPress(mNativeContentViewCore, timeMs, xPix, yPix, false);
|
| - }
|
| - } else if (isLongPressOrTap == IS_LONG_TAP) {
|
| - getInsertionHandleController().allowAutomaticShowing();
|
| - getSelectionHandleController().allowAutomaticShowing();
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeLongTap(mNativeContentViewCore, timeMs, xPix, yPix, false);
|
| - }
|
| - } else {
|
| - if (!showPress && mNativeContentViewCore != 0) {
|
| - nativeShowPressState(mNativeContentViewCore, timeMs, xPix, yPix);
|
| - }
|
| - if (mSelectionEditable) getInsertionHandleController().allowAutomaticShowing();
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeSingleTap(mNativeContentViewCore, timeMs, xPix, yPix, false);
|
| - }
|
| - }
|
| - }
|
| -
|
| - public void setZoomControlsDelegate(ZoomControlsDelegate zoomControlsDelegate) {
|
| - mZoomControlsDelegate = zoomControlsDelegate;
|
| - }
|
| -
|
| - public void updateMultiTouchZoomSupport(boolean supportsMultiTouchZoom) {
|
| - mZoomManager.updateMultiTouchSupport(supportsMultiTouchZoom);
|
| - }
|
| -
|
| - public void updateDoubleTapSupport(boolean supportsDoubleTap) {
|
| - mContentViewGestureHandler.updateDoubleTapSupport(supportsDoubleTap);
|
| - }
|
| -
|
| - public void selectPopupMenuItems(int[] indices) {
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeSelectPopupMenuItems(mNativeContentViewCore, indices);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Get the screen orientation from the OS and push it to WebKit.
|
| - *
|
| - * TODO(husky): Add a hook for mock orientations.
|
| - */
|
| - private void sendOrientationChangeEvent() {
|
| - if (mNativeContentViewCore == 0) return;
|
| -
|
| - WindowManager windowManager =
|
| - (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
|
| - switch (windowManager.getDefaultDisplay().getRotation()) {
|
| - case Surface.ROTATION_90:
|
| - nativeSendOrientationChangeEvent(mNativeContentViewCore, 90);
|
| - break;
|
| - case Surface.ROTATION_180:
|
| - nativeSendOrientationChangeEvent(mNativeContentViewCore, 180);
|
| - break;
|
| - case Surface.ROTATION_270:
|
| - nativeSendOrientationChangeEvent(mNativeContentViewCore, -90);
|
| - break;
|
| - case Surface.ROTATION_0:
|
| - nativeSendOrientationChangeEvent(mNativeContentViewCore, 0);
|
| - break;
|
| - default:
|
| - Log.w(TAG, "Unknown rotation!");
|
| - break;
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Register the delegate to be used when content can not be handled by
|
| - * the rendering engine, and should be downloaded instead. This will replace
|
| - * the current delegate, if any.
|
| - * @param delegate An implementation of ContentViewDownloadDelegate.
|
| - */
|
| - public void setDownloadDelegate(ContentViewDownloadDelegate delegate) {
|
| - mDownloadDelegate = delegate;
|
| - }
|
| -
|
| - // Called by DownloadController.
|
| - ContentViewDownloadDelegate getDownloadDelegate() {
|
| - return mDownloadDelegate;
|
| - }
|
| -
|
| - private SelectionHandleController getSelectionHandleController() {
|
| - if (mSelectionHandleController == null) {
|
| - mSelectionHandleController = new SelectionHandleController(
|
| - getContainerView(), mPositionObserver) {
|
| - @Override
|
| - public void selectBetweenCoordinates(int x1, int y1, int x2, int y2) {
|
| - if (mNativeContentViewCore != 0 && !(x1 == x2 && y1 == y2)) {
|
| - nativeSelectBetweenCoordinates(mNativeContentViewCore,
|
| - x1, y1 - mRenderCoordinates.getContentOffsetYPix(),
|
| - x2, y2 - mRenderCoordinates.getContentOffsetYPix());
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public void showHandles(int startDir, int endDir) {
|
| - super.showHandles(startDir, endDir);
|
| - showSelectActionBar();
|
| - }
|
| -
|
| - };
|
| -
|
| - mSelectionHandleController.hideAndDisallowAutomaticShowing();
|
| - }
|
| -
|
| - return mSelectionHandleController;
|
| - }
|
| -
|
| - private InsertionHandleController getInsertionHandleController() {
|
| - if (mInsertionHandleController == null) {
|
| - mInsertionHandleController = new InsertionHandleController(
|
| - getContainerView(), mPositionObserver) {
|
| - private static final int AVERAGE_LINE_HEIGHT = 14;
|
| -
|
| - @Override
|
| - public void setCursorPosition(int x, int y) {
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeMoveCaret(mNativeContentViewCore,
|
| - x, y - mRenderCoordinates.getContentOffsetYPix());
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public void paste() {
|
| - mImeAdapter.paste();
|
| - hideHandles();
|
| - }
|
| -
|
| - @Override
|
| - public int getLineHeight() {
|
| - return (int) Math.ceil(
|
| - mRenderCoordinates.fromLocalCssToPix(AVERAGE_LINE_HEIGHT));
|
| - }
|
| -
|
| - @Override
|
| - public void showHandle() {
|
| - super.showHandle();
|
| - }
|
| - };
|
| -
|
| - mInsertionHandleController.hideAndDisallowAutomaticShowing();
|
| - }
|
| -
|
| - return mInsertionHandleController;
|
| - }
|
| -
|
| - @VisibleForTesting
|
| - public InsertionHandleController getInsertionHandleControllerForTest() {
|
| - return mInsertionHandleController;
|
| - }
|
| -
|
| - @VisibleForTesting
|
| - public SelectionHandleController getSelectionHandleControllerForTest() {
|
| - return mSelectionHandleController;
|
| - }
|
| -
|
| - private void updateHandleScreenPositions() {
|
| - if (isSelectionHandleShowing()) {
|
| - mSelectionHandleController.setStartHandlePosition(
|
| - mStartHandlePoint.getXPix(), mStartHandlePoint.getYPix());
|
| - mSelectionHandleController.setEndHandlePosition(
|
| - mEndHandlePoint.getXPix(), mEndHandlePoint.getYPix());
|
| - }
|
| -
|
| - if (isInsertionHandleShowing()) {
|
| - mInsertionHandleController.setHandlePosition(
|
| - mInsertionHandlePoint.getXPix(), mInsertionHandlePoint.getYPix());
|
| - }
|
| - }
|
| -
|
| - private void hideHandles() {
|
| - if (mSelectionHandleController != null) {
|
| - mSelectionHandleController.hideAndDisallowAutomaticShowing();
|
| - }
|
| - if (mInsertionHandleController != null) {
|
| - mInsertionHandleController.hideAndDisallowAutomaticShowing();
|
| - }
|
| - mPositionObserver.removeListener(mPositionListener);
|
| - }
|
| -
|
| - private void showSelectActionBar() {
|
| - if (mActionMode != null) {
|
| - mActionMode.invalidate();
|
| - return;
|
| - }
|
| -
|
| - // Start a new action mode with a SelectActionModeCallback.
|
| - SelectActionModeCallback.ActionHandler actionHandler =
|
| - new SelectActionModeCallback.ActionHandler() {
|
| - @Override
|
| - public void selectAll() {
|
| - mImeAdapter.selectAll();
|
| - }
|
| -
|
| - @Override
|
| - public void cut() {
|
| - mImeAdapter.cut();
|
| - }
|
| -
|
| - @Override
|
| - public void copy() {
|
| - mImeAdapter.copy();
|
| - }
|
| -
|
| - @Override
|
| - public void paste() {
|
| - mImeAdapter.paste();
|
| - }
|
| -
|
| - @Override
|
| - public void share() {
|
| - final String query = getSelectedText();
|
| - if (TextUtils.isEmpty(query)) return;
|
| -
|
| - Intent send = new Intent(Intent.ACTION_SEND);
|
| - send.setType("text/plain");
|
| - send.putExtra(Intent.EXTRA_TEXT, query);
|
| - try {
|
| - Intent i = Intent.createChooser(send, getContext().getString(
|
| - R.string.actionbar_share));
|
| - i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
| - getContext().startActivity(i);
|
| - } catch (android.content.ActivityNotFoundException ex) {
|
| - // If no app handles it, do nothing.
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public void search() {
|
| - final String query = getSelectedText();
|
| - if (TextUtils.isEmpty(query)) return;
|
| -
|
| - // See if ContentViewClient wants to override
|
| - if (getContentViewClient().doesPerformWebSearch()) {
|
| - getContentViewClient().performWebSearch(query);
|
| - return;
|
| - }
|
| -
|
| - Intent i = new Intent(Intent.ACTION_WEB_SEARCH);
|
| - i.putExtra(SearchManager.EXTRA_NEW_SEARCH, true);
|
| - i.putExtra(SearchManager.QUERY, query);
|
| - i.putExtra(Browser.EXTRA_APPLICATION_ID, getContext().getPackageName());
|
| - if (!(getContext() instanceof Activity)) {
|
| - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
| - }
|
| - try {
|
| - getContext().startActivity(i);
|
| - } catch (android.content.ActivityNotFoundException ex) {
|
| - // If no app handles it, do nothing.
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public boolean isSelectionEditable() {
|
| - return mSelectionEditable;
|
| - }
|
| -
|
| - @Override
|
| - public void onDestroyActionMode() {
|
| - mActionMode = null;
|
| - if (mUnselectAllOnActionModeDismiss) mImeAdapter.unselect();
|
| - getContentViewClient().onContextualActionBarHidden();
|
| - }
|
| -
|
| - @Override
|
| - public boolean isShareAvailable() {
|
| - Intent intent = new Intent(Intent.ACTION_SEND);
|
| - intent.setType("text/plain");
|
| - return getContext().getPackageManager().queryIntentActivities(intent,
|
| - PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
|
| - }
|
| -
|
| - @Override
|
| - public boolean isWebSearchAvailable() {
|
| - if (getContentViewClient().doesPerformWebSearch()) return true;
|
| - Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
|
| - intent.putExtra(SearchManager.EXTRA_NEW_SEARCH, true);
|
| - return getContext().getPackageManager().queryIntentActivities(intent,
|
| - PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
|
| - }
|
| - };
|
| - mActionMode = null;
|
| - // On ICS, startActionMode throws an NPE when getParent() is null.
|
| - if (mContainerView.getParent() != null) {
|
| - mActionMode = mContainerView.startActionMode(
|
| - getContentViewClient().getSelectActionModeCallback(getContext(), actionHandler,
|
| - nativeIsIncognito(mNativeContentViewCore)));
|
| - }
|
| - mUnselectAllOnActionModeDismiss = true;
|
| - if (mActionMode == null) {
|
| - // There is no ActionMode, so remove the selection.
|
| - mImeAdapter.unselect();
|
| - } else {
|
| - getContentViewClient().onContextualActionBarShown();
|
| - }
|
| - }
|
| -
|
| - public boolean getUseDesktopUserAgent() {
|
| - if (mNativeContentViewCore != 0) {
|
| - return nativeGetUseDesktopUserAgent(mNativeContentViewCore);
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - /**
|
| - * Set whether or not we're using a desktop user agent for the currently loaded page.
|
| - * @param override If true, use a desktop user agent. Use a mobile one otherwise.
|
| - * @param reloadOnChange Reload the page if the UA has changed.
|
| - */
|
| - public void setUseDesktopUserAgent(boolean override, boolean reloadOnChange) {
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeSetUseDesktopUserAgent(mNativeContentViewCore, override, reloadOnChange);
|
| - }
|
| - }
|
| -
|
| - public void clearSslPreferences() {
|
| - nativeClearSslPreferences(mNativeContentViewCore);
|
| - }
|
| -
|
| - private boolean isSelectionHandleShowing() {
|
| - return mSelectionHandleController != null && mSelectionHandleController.isShowing();
|
| - }
|
| -
|
| - private boolean isInsertionHandleShowing() {
|
| - return mInsertionHandleController != null && mInsertionHandleController.isShowing();
|
| - }
|
| -
|
| - private void updateTextHandlesForGesture(int type) {
|
| - switch(type) {
|
| - case ContentViewGestureHandler.GESTURE_DOUBLE_TAP:
|
| - case ContentViewGestureHandler.GESTURE_SCROLL_START:
|
| - case ContentViewGestureHandler.GESTURE_FLING_START:
|
| - case ContentViewGestureHandler.GESTURE_PINCH_BEGIN:
|
| - temporarilyHideTextHandles();
|
| - break;
|
| -
|
| - default:
|
| - break;
|
| - }
|
| - }
|
| -
|
| - // Makes the insertion/selection handles invisible. They will fade back in shortly after the
|
| - // last call to scheduleTextHandleFadeIn (or temporarilyHideTextHandles).
|
| - private void temporarilyHideTextHandles() {
|
| - if (isSelectionHandleShowing() && !mSelectionHandleController.isDragging()) {
|
| - mSelectionHandleController.setHandleVisibility(HandleView.INVISIBLE);
|
| - }
|
| - if (isInsertionHandleShowing() && !mInsertionHandleController.isDragging()) {
|
| - mInsertionHandleController.setHandleVisibility(HandleView.INVISIBLE);
|
| - }
|
| - scheduleTextHandleFadeIn();
|
| - }
|
| -
|
| - private boolean allowTextHandleFadeIn() {
|
| - if (mContentViewGestureHandler.isNativeScrolling() ||
|
| - mContentViewGestureHandler.isNativePinching()) {
|
| - return false;
|
| - }
|
| -
|
| - if (mPopupZoomer.isShowing()) return false;
|
| -
|
| - return true;
|
| - }
|
| -
|
| - // Cancels any pending fade in and schedules a new one.
|
| - private void scheduleTextHandleFadeIn() {
|
| - if (!isInsertionHandleShowing() && !isSelectionHandleShowing()) return;
|
| -
|
| - if (mDeferredHandleFadeInRunnable == null) {
|
| - mDeferredHandleFadeInRunnable = new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - if (!allowTextHandleFadeIn()) {
|
| - // Delay fade in until it is allowed.
|
| - scheduleTextHandleFadeIn();
|
| - } else {
|
| - if (isSelectionHandleShowing()) {
|
| - mSelectionHandleController.beginHandleFadeIn();
|
| - }
|
| - if (isInsertionHandleShowing()) {
|
| - mInsertionHandleController.beginHandleFadeIn();
|
| - }
|
| - }
|
| - }
|
| - };
|
| - }
|
| -
|
| - mContainerView.removeCallbacks(mDeferredHandleFadeInRunnable);
|
| - mContainerView.postDelayed(mDeferredHandleFadeInRunnable, TEXT_HANDLE_FADE_IN_DELAY);
|
| - }
|
| -
|
| - /**
|
| - * Shows the IME if the focused widget could accept text input.
|
| - */
|
| - public void showImeIfNeeded() {
|
| - if (mNativeContentViewCore != 0) nativeShowImeIfNeeded(mNativeContentViewCore);
|
| - }
|
| -
|
| - @SuppressWarnings("unused")
|
| - @CalledByNative
|
| - private void updateFrameInfo(
|
| - float scrollOffsetX, float scrollOffsetY,
|
| - float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor,
|
| - float contentWidth, float contentHeight,
|
| - float viewportWidth, float viewportHeight,
|
| - float controlsOffsetYCss, float contentOffsetYCss,
|
| - float overdrawBottomHeightCss) {
|
| - TraceEvent.instant("ContentViewCore:updateFrameInfo");
|
| - // Adjust contentWidth/Height to be always at least as big as
|
| - // the actual viewport (as set by onSizeChanged).
|
| - contentWidth = Math.max(contentWidth,
|
| - mRenderCoordinates.fromPixToLocalCss(mViewportWidthPix));
|
| - contentHeight = Math.max(contentHeight,
|
| - mRenderCoordinates.fromPixToLocalCss(mViewportHeightPix));
|
| -
|
| - final float contentOffsetYPix = mRenderCoordinates.fromDipToPix(contentOffsetYCss);
|
| -
|
| - final boolean contentSizeChanged =
|
| - contentWidth != mRenderCoordinates.getContentWidthCss()
|
| - || contentHeight != mRenderCoordinates.getContentHeightCss();
|
| - final boolean scaleLimitsChanged =
|
| - minPageScaleFactor != mRenderCoordinates.getMinPageScaleFactor()
|
| - || maxPageScaleFactor != mRenderCoordinates.getMaxPageScaleFactor();
|
| - final boolean pageScaleChanged =
|
| - pageScaleFactor != mRenderCoordinates.getPageScaleFactor();
|
| - final boolean scrollChanged =
|
| - pageScaleChanged
|
| - || scrollOffsetX != mRenderCoordinates.getScrollX()
|
| - || scrollOffsetY != mRenderCoordinates.getScrollY();
|
| - final boolean contentOffsetChanged =
|
| - contentOffsetYPix != mRenderCoordinates.getContentOffsetYPix();
|
| -
|
| - final boolean needHidePopupZoomer = contentSizeChanged || scrollChanged;
|
| - final boolean needUpdateZoomControls = scaleLimitsChanged || scrollChanged;
|
| - final boolean needTemporarilyHideHandles = scrollChanged;
|
| -
|
| - if (needHidePopupZoomer) mPopupZoomer.hide(true);
|
| -
|
| - if (scrollChanged) {
|
| - mContainerViewInternals.onScrollChanged(
|
| - (int) mRenderCoordinates.fromLocalCssToPix(scrollOffsetX),
|
| - (int) mRenderCoordinates.fromLocalCssToPix(scrollOffsetY),
|
| - (int) mRenderCoordinates.getScrollXPix(),
|
| - (int) mRenderCoordinates.getScrollYPix());
|
| - }
|
| -
|
| - mRenderCoordinates.updateFrameInfo(
|
| - scrollOffsetX, scrollOffsetY,
|
| - contentWidth, contentHeight,
|
| - viewportWidth, viewportHeight,
|
| - pageScaleFactor, minPageScaleFactor, maxPageScaleFactor,
|
| - contentOffsetYPix);
|
| - onRenderCoordinatesUpdated();
|
| -
|
| - if (needTemporarilyHideHandles) temporarilyHideTextHandles();
|
| - if (needUpdateZoomControls) mZoomControlsDelegate.updateZoomControls();
|
| - if (contentOffsetChanged) updateHandleScreenPositions();
|
| -
|
| - // Update offsets for fullscreen.
|
| - final float deviceScale = mRenderCoordinates.getDeviceScaleFactor();
|
| - final float controlsOffsetPix = controlsOffsetYCss * deviceScale;
|
| - final float overdrawBottomHeightPix = overdrawBottomHeightCss * deviceScale;
|
| - getContentViewClient().onOffsetsForFullscreenChanged(
|
| - controlsOffsetPix, contentOffsetYPix, overdrawBottomHeightPix);
|
| -
|
| - mPendingRendererFrame = true;
|
| - if (mBrowserAccessibilityManager != null) {
|
| - mBrowserAccessibilityManager.notifyFrameInfoInitialized();
|
| - }
|
| -
|
| - // Update geometry for external video surface.
|
| - getContentViewClient().onGeometryChanged(-1, null);
|
| - }
|
| -
|
| - @CalledByNative
|
| - private void updateImeAdapter(int nativeImeAdapterAndroid, int textInputType,
|
| - String text, int selectionStart, int selectionEnd,
|
| - int compositionStart, int compositionEnd, boolean showImeIfNeeded, boolean requireAck) {
|
| - TraceEvent.begin();
|
| - mSelectionEditable = (textInputType != ImeAdapter.getTextInputTypeNone());
|
| -
|
| - if (mActionMode != null) mActionMode.invalidate();
|
| -
|
| - mImeAdapter.attachAndShowIfNeeded(nativeImeAdapterAndroid, textInputType,
|
| - selectionStart, selectionEnd, showImeIfNeeded);
|
| -
|
| - if (mInputConnection != null) {
|
| - mInputConnection.updateState(text, selectionStart, selectionEnd, compositionStart,
|
| - compositionEnd, requireAck);
|
| - }
|
| - TraceEvent.end();
|
| - }
|
| -
|
| - @SuppressWarnings("unused")
|
| - @CalledByNative
|
| - private void setTitle(String title) {
|
| - getContentViewClient().onUpdateTitle(title);
|
| - }
|
| -
|
| - /**
|
| - * Called (from native) when the <select> popup needs to be shown.
|
| - * @param items Items to show.
|
| - * @param enabled POPUP_ITEM_TYPEs for items.
|
| - * @param multiple Whether the popup menu should support multi-select.
|
| - * @param selectedIndices Indices of selected items.
|
| - */
|
| - @SuppressWarnings("unused")
|
| - @CalledByNative
|
| - private void showSelectPopup(String[] items, int[] enabled, boolean multiple,
|
| - int[] selectedIndices) {
|
| - assert items.length == enabled.length;
|
| - List<SelectPopupItem> popupItems = new ArrayList<SelectPopupItem>();
|
| - for (int i = 0; i < items.length; i++) {
|
| - popupItems.add(new SelectPopupItem(items[i], enabled[i]));
|
| - }
|
| - SelectPopupDialog.show(this, popupItems, multiple, selectedIndices);
|
| - }
|
| -
|
| - @SuppressWarnings("unused")
|
| - @CalledByNative
|
| - private void showDisambiguationPopup(Rect targetRect, Bitmap zoomedBitmap) {
|
| - mPopupZoomer.setBitmap(zoomedBitmap);
|
| - mPopupZoomer.show(targetRect);
|
| - temporarilyHideTextHandles();
|
| - }
|
| -
|
| - @SuppressWarnings("unused")
|
| - @CalledByNative
|
| - private TouchEventSynthesizer createTouchEventSynthesizer() {
|
| - return new TouchEventSynthesizer(this);
|
| - }
|
| -
|
| - @SuppressWarnings("unused")
|
| - @CalledByNative
|
| - private void onSelectionChanged(String text) {
|
| - mLastSelectedText = text;
|
| - }
|
| -
|
| - @SuppressWarnings("unused")
|
| - @CalledByNative
|
| - private void onSelectionBoundsChanged(Rect anchorRectDip, int anchorDir, Rect focusRectDip,
|
| - int focusDir, boolean isAnchorFirst) {
|
| - // All coordinates are in DIP.
|
| - int x1 = anchorRectDip.left;
|
| - int y1 = anchorRectDip.bottom;
|
| - int x2 = focusRectDip.left;
|
| - int y2 = focusRectDip.bottom;
|
| -
|
| - if (x1 != x2 || y1 != y2 ||
|
| - (mSelectionHandleController != null && mSelectionHandleController.isDragging())) {
|
| - if (mInsertionHandleController != null) {
|
| - mInsertionHandleController.hide();
|
| - }
|
| - if (isAnchorFirst) {
|
| - mStartHandlePoint.setLocalDip(x1, y1);
|
| - mEndHandlePoint.setLocalDip(x2, y2);
|
| - } else {
|
| - mStartHandlePoint.setLocalDip(x2, y2);
|
| - mEndHandlePoint.setLocalDip(x1, y1);
|
| - }
|
| -
|
| - boolean wereSelectionHandlesShowing = getSelectionHandleController().isShowing();
|
| -
|
| - getSelectionHandleController().onSelectionChanged(anchorDir, focusDir);
|
| - updateHandleScreenPositions();
|
| - mHasSelection = true;
|
| -
|
| - if (!wereSelectionHandlesShowing && getSelectionHandleController().isShowing()) {
|
| - // TODO(cjhopman): Remove this when there is a better signal that long press caused
|
| - // a selection. See http://crbug.com/150151.
|
| - mContainerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
| - }
|
| -
|
| - } else {
|
| - mUnselectAllOnActionModeDismiss = false;
|
| - hideSelectActionBar();
|
| - if (x1 != 0 && y1 != 0 && mSelectionEditable) {
|
| - // Selection is a caret, and a text field is focused.
|
| - if (mSelectionHandleController != null) {
|
| - mSelectionHandleController.hide();
|
| - }
|
| - mInsertionHandlePoint.setLocalDip(x1, y1);
|
| -
|
| - getInsertionHandleController().onCursorPositionChanged();
|
| - updateHandleScreenPositions();
|
| - InputMethodManager manager = (InputMethodManager)
|
| - getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
| - if (manager.isWatchingCursor(mContainerView)) {
|
| - final int xPix = (int) mInsertionHandlePoint.getXPix();
|
| - final int yPix = (int) mInsertionHandlePoint.getYPix();
|
| - manager.updateCursor(mContainerView, xPix, yPix, xPix, yPix);
|
| - }
|
| - } else {
|
| - // Deselection
|
| - if (mSelectionHandleController != null) {
|
| - mSelectionHandleController.hideAndDisallowAutomaticShowing();
|
| - }
|
| - if (mInsertionHandleController != null) {
|
| - mInsertionHandleController.hideAndDisallowAutomaticShowing();
|
| - }
|
| - }
|
| - mHasSelection = false;
|
| - }
|
| - if (isSelectionHandleShowing() || isInsertionHandleShowing()) {
|
| - mPositionObserver.addListener(mPositionListener);
|
| - }
|
| - }
|
| -
|
| - @SuppressWarnings("unused")
|
| - @CalledByNative
|
| - private static void onEvaluateJavaScriptResult(
|
| - String jsonResult, JavaScriptCallback callback) {
|
| - callback.handleJavaScriptResult(jsonResult);
|
| - }
|
| -
|
| - @SuppressWarnings("unused")
|
| - @CalledByNative
|
| - private void showPastePopup(int xDip, int yDip) {
|
| - mInsertionHandlePoint.setLocalDip(xDip, yDip);
|
| - getInsertionHandleController().showHandle();
|
| - updateHandleScreenPositions();
|
| - getInsertionHandleController().showHandleWithPastePopup();
|
| - }
|
| -
|
| - @SuppressWarnings("unused")
|
| - @CalledByNative
|
| - private void onRenderProcessSwap(int oldPid, int newPid) {
|
| - if (!mInForeground) {
|
| - ChildProcessLauncher.getBindingManager().setInForeground(newPid, false);
|
| - } else if (oldPid != newPid) {
|
| - ChildProcessLauncher.getBindingManager().setInForeground(oldPid, false);
|
| - ChildProcessLauncher.getBindingManager().setInForeground(newPid, true);
|
| - }
|
| -
|
| - attachImeAdapter();
|
| - }
|
| -
|
| - @SuppressWarnings("unused")
|
| - @CalledByNative
|
| - private void onWebContentsConnected() {
|
| - attachImeAdapter();
|
| - }
|
| -
|
| - /**
|
| - * Attaches the native ImeAdapter object to the java ImeAdapter to allow communication via JNI.
|
| - */
|
| - public void attachImeAdapter() {
|
| - if (mImeAdapter != null && mNativeContentViewCore != 0) {
|
| - mImeAdapter.attach(nativeGetNativeImeAdapter(mNativeContentViewCore));
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * @see View#hasFocus()
|
| - */
|
| - @CalledByNative
|
| - public boolean hasFocus() {
|
| - return mContainerView.hasFocus();
|
| - }
|
| -
|
| - /**
|
| - * Checks whether the ContentViewCore can be zoomed in.
|
| - *
|
| - * @return True if the ContentViewCore can be zoomed in.
|
| - */
|
| - // This method uses the term 'zoom' for legacy reasons, but relates
|
| - // to what chrome calls the 'page scale factor'.
|
| - public boolean canZoomIn() {
|
| - final float zoomInExtent = mRenderCoordinates.getMaxPageScaleFactor()
|
| - - mRenderCoordinates.getPageScaleFactor();
|
| - return zoomInExtent > ZOOM_CONTROLS_EPSILON;
|
| - }
|
| -
|
| - /**
|
| - * Checks whether the ContentViewCore can be zoomed out.
|
| - *
|
| - * @return True if the ContentViewCore can be zoomed out.
|
| - */
|
| - // This method uses the term 'zoom' for legacy reasons, but relates
|
| - // to what chrome calls the 'page scale factor'.
|
| - public boolean canZoomOut() {
|
| - final float zoomOutExtent = mRenderCoordinates.getPageScaleFactor()
|
| - - mRenderCoordinates.getMinPageScaleFactor();
|
| - return zoomOutExtent > ZOOM_CONTROLS_EPSILON;
|
| - }
|
| -
|
| - /**
|
| - * Zooms in the ContentViewCore by 25% (or less if that would result in
|
| - * zooming in more than possible).
|
| - *
|
| - * @return True if there was a zoom change, false otherwise.
|
| - */
|
| - // This method uses the term 'zoom' for legacy reasons, but relates
|
| - // to what chrome calls the 'page scale factor'.
|
| - public boolean zoomIn() {
|
| - if (!canZoomIn()) {
|
| - return false;
|
| - }
|
| - return pinchByDelta(1.25f);
|
| - }
|
| -
|
| - /**
|
| - * Zooms out the ContentViewCore by 20% (or less if that would result in
|
| - * zooming out more than possible).
|
| - *
|
| - * @return True if there was a zoom change, false otherwise.
|
| - */
|
| - // This method uses the term 'zoom' for legacy reasons, but relates
|
| - // to what chrome calls the 'page scale factor'.
|
| - public boolean zoomOut() {
|
| - if (!canZoomOut()) {
|
| - return false;
|
| - }
|
| - return pinchByDelta(0.8f);
|
| - }
|
| -
|
| - /**
|
| - * Resets the zoom factor of the ContentViewCore.
|
| - *
|
| - * @return True if there was a zoom change, false otherwise.
|
| - */
|
| - // This method uses the term 'zoom' for legacy reasons, but relates
|
| - // to what chrome calls the 'page scale factor'.
|
| - public boolean zoomReset() {
|
| - // The page scale factor is initialized to mNativeMinimumScale when
|
| - // the page finishes loading. Thus sets it back to mNativeMinimumScale.
|
| - if (!canZoomOut()) return false;
|
| - return pinchByDelta(
|
| - mRenderCoordinates.getMinPageScaleFactor()
|
| - / mRenderCoordinates.getPageScaleFactor());
|
| - }
|
| -
|
| - /**
|
| - * Simulate a pinch zoom gesture.
|
| - *
|
| - * @param delta the factor by which the current page scale should be multiplied by.
|
| - * @return whether the gesture was sent.
|
| - */
|
| - public boolean pinchByDelta(float delta) {
|
| - if (mNativeContentViewCore == 0) {
|
| - return false;
|
| - }
|
| -
|
| - long timeMs = System.currentTimeMillis();
|
| - int xPix = getViewportWidthPix() / 2;
|
| - int yPix = getViewportHeightPix() / 2;
|
| -
|
| - getContentViewGestureHandler().pinchBegin(timeMs, xPix, yPix);
|
| - getContentViewGestureHandler().pinchBy(timeMs, xPix, yPix, delta);
|
| - getContentViewGestureHandler().pinchEnd(timeMs);
|
| -
|
| - return true;
|
| - }
|
| -
|
| - /**
|
| - * Invokes the graphical zoom picker widget for this ContentView.
|
| - */
|
| - @Override
|
| - public void invokeZoomPicker() {
|
| - mZoomControlsDelegate.invokeZoomPicker();
|
| - }
|
| -
|
| - /**
|
| - * This will mimic {@link #addPossiblyUnsafeJavascriptInterface(Object, String, Class)}
|
| - * and automatically pass in {@link JavascriptInterface} as the required annotation.
|
| - *
|
| - * @param object The Java object to inject into the ContentViewCore's JavaScript context. Null
|
| - * values are ignored.
|
| - * @param name The name used to expose the instance in JavaScript.
|
| - */
|
| - public void addJavascriptInterface(Object object, String name) {
|
| - addPossiblyUnsafeJavascriptInterface(object, name, JavascriptInterface.class);
|
| - }
|
| -
|
| - /**
|
| - * This method injects the supplied Java object into the ContentViewCore.
|
| - * The object is injected into the JavaScript context of the main frame,
|
| - * using the supplied name. This allows the Java object to be accessed from
|
| - * JavaScript. Note that that injected objects will not appear in
|
| - * JavaScript until the page is next (re)loaded. For example:
|
| - * <pre> view.addJavascriptInterface(new Object(), "injectedObject");
|
| - * view.loadData("<!DOCTYPE html><title></title>", "text/html", null);
|
| - * view.loadUrl("javascript:alert(injectedObject.toString())");</pre>
|
| - * <p><strong>IMPORTANT:</strong>
|
| - * <ul>
|
| - * <li> addJavascriptInterface() can be used to allow JavaScript to control
|
| - * the host application. This is a powerful feature, but also presents a
|
| - * security risk. Use of this method in a ContentViewCore containing
|
| - * untrusted content could allow an attacker to manipulate the host
|
| - * application in unintended ways, executing Java code with the permissions
|
| - * of the host application. Use extreme care when using this method in a
|
| - * ContentViewCore which could contain untrusted content. Particular care
|
| - * should be taken to avoid unintentional access to inherited methods, such
|
| - * as {@link Object#getClass()}. To prevent access to inherited methods,
|
| - * pass an annotation for {@code requiredAnnotation}. This will ensure
|
| - * that only methods with {@code requiredAnnotation} are exposed to the
|
| - * Javascript layer. {@code requiredAnnotation} will be passed to all
|
| - * subsequently injected Java objects if any methods return an object. This
|
| - * means the same restrictions (or lack thereof) will apply. Alternatively,
|
| - * {@link #addJavascriptInterface(Object, String)} can be called, which
|
| - * automatically uses the {@link JavascriptInterface} annotation.
|
| - * <li> JavaScript interacts with Java objects on a private, background
|
| - * thread of the ContentViewCore. Care is therefore required to maintain
|
| - * thread safety.</li>
|
| - * </ul></p>
|
| - *
|
| - * @param object The Java object to inject into the
|
| - * ContentViewCore's JavaScript context. Null
|
| - * values are ignored.
|
| - * @param name The name used to expose the instance in
|
| - * JavaScript.
|
| - * @param requiredAnnotation Restrict exposed methods to ones with this
|
| - * annotation. If {@code null} all methods are
|
| - * exposed.
|
| - *
|
| - */
|
| - public void addPossiblyUnsafeJavascriptInterface(Object object, String name,
|
| - Class<? extends Annotation> requiredAnnotation) {
|
| - if (mNativeContentViewCore != 0 && object != null) {
|
| - mJavaScriptInterfaces.put(name, object);
|
| - nativeAddJavascriptInterface(mNativeContentViewCore, object, name, requiredAnnotation,
|
| - mRetainedJavaScriptObjects);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Removes a previously added JavaScript interface with the given name.
|
| - *
|
| - * @param name The name of the interface to remove.
|
| - */
|
| - public void removeJavascriptInterface(String name) {
|
| - mJavaScriptInterfaces.remove(name);
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeRemoveJavascriptInterface(mNativeContentViewCore, name);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Return the current scale of the ContentView.
|
| - * @return The current page scale factor.
|
| - */
|
| - public float getScale() {
|
| - return mRenderCoordinates.getPageScaleFactor();
|
| - }
|
| -
|
| - /**
|
| - * If the view is ready to draw contents to the screen. In hardware mode,
|
| - * the initialization of the surface texture may not occur until after the
|
| - * view has been added to the layout. This method will return {@code true}
|
| - * once the texture is actually ready.
|
| - */
|
| - public boolean isReady() {
|
| - if (mNativeContentViewCore == 0) return false;
|
| - return nativeIsRenderWidgetHostViewReady(mNativeContentViewCore);
|
| - }
|
| -
|
| - @CalledByNative
|
| - private void startContentIntent(String contentUrl) {
|
| - getContentViewClient().onStartContentIntent(getContext(), contentUrl);
|
| - }
|
| -
|
| - @Override
|
| - public void onAccessibilityStateChanged(boolean enabled) {
|
| - setAccessibilityState(enabled);
|
| - }
|
| -
|
| - /**
|
| - * Determines whether or not this ContentViewCore can handle this accessibility action.
|
| - * @param action The action to perform.
|
| - * @return Whether or not this action is supported.
|
| - */
|
| - public boolean supportsAccessibilityAction(int action) {
|
| - return mAccessibilityInjector.supportsAccessibilityAction(action);
|
| - }
|
| -
|
| - /**
|
| - * Attempts to perform an accessibility action on the web content. If the accessibility action
|
| - * cannot be processed, it returns {@code null}, allowing the caller to know to call the
|
| - * super {@link View#performAccessibilityAction(int, Bundle)} method and use that return value.
|
| - * Otherwise the return value from this method should be used.
|
| - * @param action The action to perform.
|
| - * @param arguments Optional action arguments.
|
| - * @return Whether the action was performed or {@code null} if the call should be delegated to
|
| - * the super {@link View} class.
|
| - */
|
| - public boolean performAccessibilityAction(int action, Bundle arguments) {
|
| - if (mAccessibilityInjector.supportsAccessibilityAction(action)) {
|
| - return mAccessibilityInjector.performAccessibilityAction(action, arguments);
|
| - }
|
| -
|
| - return false;
|
| - }
|
| -
|
| - /**
|
| - * Set the BrowserAccessibilityManager, used for native accessibility
|
| - * (not script injection). This is only set when system accessibility
|
| - * has been enabled.
|
| - * @param manager The new BrowserAccessibilityManager.
|
| - */
|
| - public void setBrowserAccessibilityManager(BrowserAccessibilityManager manager) {
|
| - mBrowserAccessibilityManager = manager;
|
| - }
|
| -
|
| - /**
|
| - * Get the BrowserAccessibilityManager, used for native accessibility
|
| - * (not script injection). This will return null when system accessibility
|
| - * is not enabled.
|
| - * @return This view's BrowserAccessibilityManager.
|
| - */
|
| - public BrowserAccessibilityManager getBrowserAccessibilityManager() {
|
| - return mBrowserAccessibilityManager;
|
| - }
|
| -
|
| - /**
|
| - * If native accessibility (not script injection) is enabled, and if this is
|
| - * running on JellyBean or later, returns an AccessibilityNodeProvider that
|
| - * implements native accessibility for this view. Returns null otherwise.
|
| - * Lazily initializes native accessibility here if it's allowed.
|
| - * @return The AccessibilityNodeProvider, if available, or null otherwise.
|
| - */
|
| - public AccessibilityNodeProvider getAccessibilityNodeProvider() {
|
| - if (mBrowserAccessibilityManager != null) {
|
| - return mBrowserAccessibilityManager.getAccessibilityNodeProvider();
|
| - }
|
| -
|
| - if (mNativeAccessibilityAllowed &&
|
| - !mNativeAccessibilityEnabled &&
|
| - mNativeContentViewCore != 0 &&
|
| - Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
| - mNativeAccessibilityEnabled = true;
|
| - nativeSetAccessibilityEnabled(mNativeContentViewCore, true);
|
| - }
|
| -
|
| - return null;
|
| - }
|
| -
|
| - /**
|
| - * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
|
| - */
|
| - public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
| - // Note: this is only used by the script-injecting accessibility code.
|
| - mAccessibilityInjector.onInitializeAccessibilityNodeInfo(info);
|
| - }
|
| -
|
| - /**
|
| - * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
|
| - */
|
| - public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
|
| - // Note: this is only used by the script-injecting accessibility code.
|
| - event.setClassName(this.getClass().getName());
|
| -
|
| - // Identify where the top-left of the screen currently points to.
|
| - event.setScrollX(mRenderCoordinates.getScrollXPixInt());
|
| - event.setScrollY(mRenderCoordinates.getScrollYPixInt());
|
| -
|
| - // The maximum scroll values are determined by taking the content dimensions and
|
| - // subtracting off the actual dimensions of the ChromeView.
|
| - int maxScrollXPix = Math.max(0, mRenderCoordinates.getMaxHorizontalScrollPixInt());
|
| - int maxScrollYPix = Math.max(0, mRenderCoordinates.getMaxVerticalScrollPixInt());
|
| - event.setScrollable(maxScrollXPix > 0 || maxScrollYPix > 0);
|
| -
|
| - // Setting the maximum scroll values requires API level 15 or higher.
|
| - final int SDK_VERSION_REQUIRED_TO_SET_SCROLL = 15;
|
| - if (Build.VERSION.SDK_INT >= SDK_VERSION_REQUIRED_TO_SET_SCROLL) {
|
| - event.setMaxScrollX(maxScrollXPix);
|
| - event.setMaxScrollY(maxScrollYPix);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Returns whether accessibility script injection is enabled on the device
|
| - */
|
| - public boolean isDeviceAccessibilityScriptInjectionEnabled() {
|
| - try {
|
| - if (CommandLine.getInstance().hasSwitch(
|
| - ContentSwitches.DISABLE_ACCESSIBILITY_SCRIPT_INJECTION)) {
|
| - return false;
|
| - }
|
| -
|
| - if (!mContentSettings.getJavaScriptEnabled()) {
|
| - return false;
|
| - }
|
| -
|
| - int result = getContext().checkCallingOrSelfPermission(
|
| - android.Manifest.permission.INTERNET);
|
| - if (result != PackageManager.PERMISSION_GRANTED) {
|
| - return false;
|
| - }
|
| -
|
| - Field field = Settings.Secure.class.getField("ACCESSIBILITY_SCRIPT_INJECTION");
|
| - field.setAccessible(true);
|
| - String accessibilityScriptInjection = (String) field.get(null);
|
| - ContentResolver contentResolver = getContext().getContentResolver();
|
| -
|
| - if (mAccessibilityScriptInjectionObserver == null) {
|
| - ContentObserver contentObserver = new ContentObserver(new Handler()) {
|
| - @Override
|
| - public void onChange(boolean selfChange, Uri uri) {
|
| - setAccessibilityState(mAccessibilityManager.isEnabled());
|
| - }
|
| - };
|
| - contentResolver.registerContentObserver(
|
| - Settings.Secure.getUriFor(accessibilityScriptInjection),
|
| - false,
|
| - contentObserver);
|
| - mAccessibilityScriptInjectionObserver = contentObserver;
|
| - }
|
| -
|
| - return Settings.Secure.getInt(contentResolver, accessibilityScriptInjection, 0) == 1;
|
| - } catch (NoSuchFieldException e) {
|
| - // Do nothing, default to false.
|
| - } catch (IllegalAccessException e) {
|
| - // Do nothing, default to false.
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - /**
|
| - * Returns whether or not accessibility injection is being used.
|
| - */
|
| - public boolean isInjectingAccessibilityScript() {
|
| - return mAccessibilityInjector.accessibilityIsAvailable();
|
| - }
|
| -
|
| - /**
|
| - * Turns browser accessibility on or off.
|
| - * If |state| is |false|, this turns off both native and injected accessibility.
|
| - * Otherwise, if accessibility script injection is enabled, this will enable the injected
|
| - * accessibility scripts. Native accessibility is enabled on demand.
|
| - */
|
| - public void setAccessibilityState(boolean state) {
|
| - if (!state) {
|
| - setInjectedAccessibility(false);
|
| - mNativeAccessibilityAllowed = false;
|
| - } else {
|
| - boolean useScriptInjection = isDeviceAccessibilityScriptInjectionEnabled();
|
| - setInjectedAccessibility(useScriptInjection);
|
| - mNativeAccessibilityAllowed = !useScriptInjection;
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Enable or disable injected accessibility features
|
| - */
|
| - public void setInjectedAccessibility(boolean enabled) {
|
| - mAccessibilityInjector.addOrRemoveAccessibilityApisIfNecessary();
|
| - mAccessibilityInjector.setScriptEnabled(enabled);
|
| - }
|
| -
|
| - /**
|
| - * Stop any TTS notifications that are currently going on.
|
| - */
|
| - public void stopCurrentAccessibilityNotifications() {
|
| - mAccessibilityInjector.onPageLostFocus();
|
| - }
|
| -
|
| - /**
|
| - * Inform WebKit that Fullscreen mode has been exited by the user.
|
| - */
|
| - public void exitFullscreen() {
|
| - if (mNativeContentViewCore != 0) nativeExitFullscreen(mNativeContentViewCore);
|
| - }
|
| -
|
| - /**
|
| - * Changes whether hiding the top controls is enabled.
|
| - *
|
| - * @param enableHiding Whether hiding the top controls should be enabled or not.
|
| - * @param enableShowing Whether showing the top controls should be enabled or not.
|
| - * @param animate Whether the transition should be animated or not.
|
| - */
|
| - public void updateTopControlsState(boolean enableHiding, boolean enableShowing,
|
| - boolean animate) {
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeUpdateTopControlsState(
|
| - mNativeContentViewCore, enableHiding, enableShowing, animate);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Callback factory method for nativeGetNavigationHistory().
|
| - */
|
| - @CalledByNative
|
| - private void addToNavigationHistory(Object history, int index, String url, String virtualUrl,
|
| - String originalUrl, String title, Bitmap favicon) {
|
| - NavigationEntry entry = new NavigationEntry(
|
| - index, url, virtualUrl, originalUrl, title, favicon);
|
| - ((NavigationHistory) history).addEntry(entry);
|
| - }
|
| -
|
| - /**
|
| - * Get a copy of the navigation history of the view.
|
| - */
|
| - public NavigationHistory getNavigationHistory() {
|
| - NavigationHistory history = new NavigationHistory();
|
| - if (mNativeContentViewCore != 0) {
|
| - int currentIndex = nativeGetNavigationHistory(mNativeContentViewCore, history);
|
| - history.setCurrentEntryIndex(currentIndex);
|
| - }
|
| - return history;
|
| - }
|
| -
|
| - @Override
|
| - public NavigationHistory getDirectedNavigationHistory(boolean isForward, int itemLimit) {
|
| - NavigationHistory history = new NavigationHistory();
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeGetDirectedNavigationHistory(
|
| - mNativeContentViewCore, history, isForward, itemLimit);
|
| - }
|
| - return history;
|
| - }
|
| -
|
| - /**
|
| - * @return The original request URL for the current navigation entry, or null if there is no
|
| - * current entry.
|
| - */
|
| - public String getOriginalUrlForActiveNavigationEntry() {
|
| - if (mNativeContentViewCore != 0) {
|
| - return nativeGetOriginalUrlForActiveNavigationEntry(mNativeContentViewCore);
|
| - }
|
| - return "";
|
| - }
|
| -
|
| - /**
|
| - * @return The cached copy of render positions and scales.
|
| - */
|
| - public RenderCoordinates getRenderCoordinates() {
|
| - return mRenderCoordinates;
|
| - }
|
| -
|
| - @CalledByNative
|
| - private int getLocationInWindowX() {
|
| - return mLocationInWindowX;
|
| - }
|
| -
|
| - @CalledByNative
|
| - private int getLocationInWindowY() {
|
| - return mLocationInWindowY;
|
| - }
|
| -
|
| - @CalledByNative
|
| - private static Rect createRect(int x, int y, int right, int bottom) {
|
| - return new Rect(x, y, right, bottom);
|
| - }
|
| -
|
| - public void attachExternalVideoSurface(int playerId, Surface surface) {
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeAttachExternalVideoSurface(mNativeContentViewCore, playerId, surface);
|
| - }
|
| - }
|
| -
|
| - public void detachExternalVideoSurface(int playerId) {
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeDetachExternalVideoSurface(mNativeContentViewCore, playerId);
|
| - }
|
| - }
|
| -
|
| - private boolean onAnimate(long frameTimeMicros) {
|
| - if (mNativeContentViewCore == 0) return false;
|
| - return nativeOnAnimate(mNativeContentViewCore, frameTimeMicros);
|
| - }
|
| -
|
| - private void animateIfNecessary(long frameTimeMicros) {
|
| - if (mNeedAnimate) {
|
| - mNeedAnimate = onAnimate(frameTimeMicros);
|
| - if (!mNeedAnimate) removeVSyncSubscriber();
|
| - }
|
| - }
|
| -
|
| - @CalledByNative
|
| - private void notifyExternalSurface(
|
| - int playerId, boolean isRequest, float x, float y, float width, float height) {
|
| - if (isRequest) getContentViewClient().onExternalVideoSurfaceRequested(playerId);
|
| - getContentViewClient().onGeometryChanged(playerId, new RectF(x, y, x + width, y + height));
|
| - }
|
| -
|
| - public void extractSmartClipData(int x, int y, int width, int height) {
|
| - if (mNativeContentViewCore != 0) {
|
| - nativeExtractSmartClipData(mNativeContentViewCore, x, y, width, height);
|
| - }
|
| - }
|
| -
|
| - @CalledByNative
|
| - private void onSmartClipDataExtracted(String result) {
|
| - if (mSmartClipDataListener != null ) {
|
| - mSmartClipDataListener.onSmartClipDataExtracted(result);
|
| - }
|
| - }
|
| -
|
| - public void setSmartClipDataListener(SmartClipDataListener listener) {
|
| - mSmartClipDataListener = listener;
|
| - }
|
| -
|
| - /**
|
| - * Offer a subset of gesture events to the embedding View,
|
| - * primarily for WebView compatibility.
|
| - *
|
| - * @param type The type of the event.
|
| - *
|
| - * @return true if the embedder handled the event.
|
| - */
|
| - private boolean offerGestureToEmbedder(int type) {
|
| - if (type == ContentViewGestureHandler.GESTURE_LONG_PRESS) {
|
| - return mContainerView.performLongClick();
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - private native long nativeInit(boolean hardwareAccelerated, long webContentsPtr,
|
| - long viewAndroidPtr, long windowAndroidPtr);
|
| -
|
| - @CalledByNative
|
| - private ContentVideoViewClient getContentVideoViewClient() {
|
| - return getContentViewClient().getContentVideoViewClient();
|
| - }
|
| -
|
| - @CalledByNative
|
| - private boolean shouldBlockMediaRequest(String url) {
|
| - return getContentViewClient().shouldBlockMediaRequest(url);
|
| - }
|
| -
|
| - @CalledByNative
|
| - private void onNativeFlingStopped() {
|
| - getContentViewClient().onFlingStopped();
|
| - }
|
| -
|
| - private native WebContents nativeGetWebContentsAndroid(long nativeContentViewCoreImpl);
|
| -
|
| - private native void nativeOnJavaContentViewCoreDestroyed(long nativeContentViewCoreImpl);
|
| -
|
| - private native void nativeLoadUrl(
|
| - long nativeContentViewCoreImpl,
|
| - String url,
|
| - int loadUrlType,
|
| - int transitionType,
|
| - int uaOverrideOption,
|
| - String extraHeaders,
|
| - byte[] postData,
|
| - String baseUrlForDataUrl,
|
| - String virtualUrlForDataUrl,
|
| - boolean canLoadLocalResources);
|
| -
|
| - private native String nativeGetURL(long nativeContentViewCoreImpl);
|
| -
|
| - private native String nativeGetTitle(long nativeContentViewCoreImpl);
|
| -
|
| - private native void nativeShowInterstitialPage(
|
| - long nativeContentViewCoreImpl, String url, long nativeInterstitialPageDelegateAndroid);
|
| - private native boolean nativeIsShowingInterstitialPage(long nativeContentViewCoreImpl);
|
| -
|
| - private native boolean nativeIsIncognito(long nativeContentViewCoreImpl);
|
| -
|
| - private native void nativeSetFocus(long nativeContentViewCoreImpl, boolean focused);
|
| -
|
| - private native void nativeSendOrientationChangeEvent(
|
| - long nativeContentViewCoreImpl, int orientation);
|
| -
|
| - // All touch events (including flings, scrolls etc) accept coordinates in physical pixels.
|
| - private native boolean nativeSendTouchEvent(
|
| - long nativeContentViewCoreImpl, long timeMs, int action, TouchPoint[] pts);
|
| -
|
| - private native int nativeSendMouseMoveEvent(
|
| - long nativeContentViewCoreImpl, long timeMs, float x, float y);
|
| -
|
| - private native int nativeSendMouseWheelEvent(
|
| - long nativeContentViewCoreImpl, long timeMs, float x, float y, float verticalAxis);
|
| -
|
| - private native void nativeScrollBegin(
|
| - long nativeContentViewCoreImpl, long timeMs, float x, float y, float hintX,
|
| - float hintY);
|
| -
|
| - private native void nativeScrollEnd(long nativeContentViewCoreImpl, long timeMs);
|
| -
|
| - private native void nativeScrollBy(
|
| - long nativeContentViewCoreImpl, long timeMs, float x, float y,
|
| - float deltaX, float deltaY);
|
| -
|
| - private native void nativeFlingStart(
|
| - long nativeContentViewCoreImpl, long timeMs, float x, float y, float vx, float vy);
|
| -
|
| - private native void nativeFlingCancel(long nativeContentViewCoreImpl, long timeMs);
|
| -
|
| - private native void nativeSingleTap(
|
| - long nativeContentViewCoreImpl, long timeMs, float x, float y, boolean linkPreviewTap);
|
| -
|
| - private native void nativeSingleTapUnconfirmed(
|
| - long nativeContentViewCoreImpl, long timeMs, float x, float y);
|
| -
|
| - private native void nativeShowPressState(
|
| - long nativeContentViewCoreImpl, long timeMs, float x, float y);
|
| -
|
| - private native void nativeTapCancel(
|
| - long nativeContentViewCoreImpl, long timeMs, float x, float y);
|
| -
|
| - private native void nativeTapDown(
|
| - long nativeContentViewCoreImpl, long timeMs, float x, float y);
|
| -
|
| - private native void nativeDoubleTap(
|
| - long nativeContentViewCoreImpl, long timeMs, float x, float y);
|
| -
|
| - private native void nativeLongPress(
|
| - long nativeContentViewCoreImpl, long timeMs, float x, float y, boolean linkPreviewTap);
|
| -
|
| - private native void nativeLongTap(
|
| - long nativeContentViewCoreImpl, long timeMs, float x, float y, boolean linkPreviewTap);
|
| -
|
| - private native void nativePinchBegin(
|
| - long nativeContentViewCoreImpl, long timeMs, float x, float y);
|
| -
|
| - private native void nativePinchEnd(long nativeContentViewCoreImpl, long timeMs);
|
| -
|
| - private native void nativePinchBy(long nativeContentViewCoreImpl, long timeMs,
|
| - float anchorX, float anchorY, float deltaScale);
|
| -
|
| - private native void nativeSelectBetweenCoordinates(
|
| - long nativeContentViewCoreImpl, float x1, float y1, float x2, float y2);
|
| -
|
| - private native void nativeMoveCaret(long nativeContentViewCoreImpl, float x, float y);
|
| -
|
| - private native void nativeLoadIfNecessary(long nativeContentViewCoreImpl);
|
| - private native void nativeRequestRestoreLoad(long nativeContentViewCoreImpl);
|
| -
|
| - private native void nativeStopLoading(long nativeContentViewCoreImpl);
|
| -
|
| - private native void nativeReload(long nativeContentViewCoreImpl, boolean checkForRepost);
|
| - private native void nativeReloadIgnoringCache(
|
| - long nativeContentViewCoreImpl, boolean checkForRepost);
|
| -
|
| - private native void nativeCancelPendingReload(long nativeContentViewCoreImpl);
|
| -
|
| - private native void nativeContinuePendingReload(long nativeContentViewCoreImpl);
|
| -
|
| - private native void nativeSelectPopupMenuItems(long nativeContentViewCoreImpl, int[] indices);
|
| -
|
| - private native void nativeScrollFocusedEditableNodeIntoView(long nativeContentViewCoreImpl);
|
| - private native void nativeUndoScrollFocusedEditableNodeIntoView(long nativeContentViewCoreImpl);
|
| -
|
| - private native void nativeClearHistory(long nativeContentViewCoreImpl);
|
| -
|
| - private native void nativeEvaluateJavaScript(long nativeContentViewCoreImpl,
|
| - String script, JavaScriptCallback callback, boolean startRenderer);
|
| -
|
| - private native int nativeGetNativeImeAdapter(long nativeContentViewCoreImpl);
|
| -
|
| - private native int nativeGetCurrentRenderProcessId(long nativeContentViewCoreImpl);
|
| -
|
| - private native int nativeGetBackgroundColor(long nativeContentViewCoreImpl);
|
| -
|
| - private native void nativeOnShow(long nativeContentViewCoreImpl);
|
| - private native void nativeOnHide(long nativeContentViewCoreImpl);
|
| -
|
| - private native void nativeSetUseDesktopUserAgent(long nativeContentViewCoreImpl,
|
| - boolean enabled, boolean reloadOnChange);
|
| - private native boolean nativeGetUseDesktopUserAgent(long nativeContentViewCoreImpl);
|
| -
|
| - private native void nativeClearSslPreferences(long nativeContentViewCoreImpl);
|
| -
|
| - private native void nativeAddJavascriptInterface(long nativeContentViewCoreImpl, Object object,
|
| - String name, Class requiredAnnotation, HashSet<Object> retainedObjectSet);
|
| -
|
| - private native void nativeRemoveJavascriptInterface(long nativeContentViewCoreImpl,
|
| - String name);
|
| -
|
| - private native int nativeGetNavigationHistory(long nativeContentViewCoreImpl, Object context);
|
| - private native void nativeGetDirectedNavigationHistory(long nativeContentViewCoreImpl,
|
| - Object context, boolean isForward, int maxEntries);
|
| - private native String nativeGetOriginalUrlForActiveNavigationEntry(
|
| - long nativeContentViewCoreImpl);
|
| -
|
| - private native void nativeUpdateVSyncParameters(long nativeContentViewCoreImpl,
|
| - long timebaseMicros, long intervalMicros);
|
| -
|
| - private native void nativeOnVSync(long nativeContentViewCoreImpl, long frameTimeMicros);
|
| -
|
| - private native boolean nativeOnAnimate(long nativeContentViewCoreImpl, long frameTimeMicros);
|
| -
|
| - private native boolean nativePopulateBitmapFromCompositor(long nativeContentViewCoreImpl,
|
| - Bitmap bitmap);
|
| -
|
| - private native void nativeWasResized(long nativeContentViewCoreImpl);
|
| -
|
| - private native boolean nativeIsRenderWidgetHostViewReady(long nativeContentViewCoreImpl);
|
| -
|
| - private native void nativeExitFullscreen(long nativeContentViewCoreImpl);
|
| - private native void nativeUpdateTopControlsState(long nativeContentViewCoreImpl,
|
| - boolean enableHiding, boolean enableShowing, boolean animate);
|
| -
|
| - private native void nativeShowImeIfNeeded(long nativeContentViewCoreImpl);
|
| -
|
| - private native void nativeAttachExternalVideoSurface(
|
| - long nativeContentViewCoreImpl, int playerId, Surface surface);
|
| -
|
| - private native void nativeDetachExternalVideoSurface(
|
| - long nativeContentViewCoreImpl, int playerId);
|
| -
|
| - private native void nativeSetAccessibilityEnabled(
|
| - long nativeContentViewCoreImpl, boolean enabled);
|
| -
|
| - private native void nativeSendSingleTapUma(long nativeContentViewCoreImpl,
|
| - int type, int count);
|
| -
|
| - private native void nativeSendActionAfterDoubleTapUma(long nativeContentViewCoreImpl,
|
| - int type, boolean hasDelay, int count);
|
| -
|
| - private native void nativeExtractSmartClipData(long nativeContentViewCoreImpl,
|
| - int x, int y, int w, int h);
|
| -}
|
|
|