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 |
index be34d7dcd57cad827f55dae5c70fc4d44f7cdb6f..31647c351fddb9a9b5469e00827981f6d6e2cb20 100644 |
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
@@ -46,10 +46,7 @@ import android.view.animation.AnimationUtils; |
import android.view.inputmethod.EditorInfo; |
import android.view.inputmethod.InputConnection; |
import android.view.inputmethod.InputMethodManager; |
-import android.widget.FrameLayout; |
-import android.widget.ImageView; |
-import org.chromium.base.ApiCompatibilityUtils; |
import org.chromium.base.CommandLine; |
import org.chromium.base.Log; |
import org.chromium.base.ObserverList; |
@@ -89,7 +86,6 @@ import org.chromium.ui.base.DeviceFormFactor; |
import org.chromium.ui.base.ViewAndroidDelegate; |
import org.chromium.ui.base.WindowAndroid; |
import org.chromium.ui.base.ime.TextInputType; |
-import org.chromium.ui.gfx.DeviceDisplayInfo; |
import org.chromium.ui.touch_selection.SelectionEventType; |
import java.lang.annotation.Annotation; |
@@ -97,10 +93,8 @@ import java.lang.ref.WeakReference; |
import java.util.ArrayList; |
import java.util.HashMap; |
import java.util.HashSet; |
-import java.util.LinkedHashMap; |
import java.util.List; |
import java.util.Map; |
-import java.util.Map.Entry; |
/** |
* Provides a Java-side 'wrapper' around a WebContent (native) instance. |
@@ -150,176 +144,6 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Screen |
private final HashSet<Object> mRetainedJavaScriptObjects = new HashSet<Object>(); |
/** |
- * A {@link ViewAndroidDelegate} that delegates to the current container view. |
- * |
- * <p>This delegate handles the replacement of container views transparently so |
- * that clients can safely hold to instances of this class. |
- */ |
- private static class ContentViewAndroidDelegate implements ViewAndroidDelegate { |
- // TODO(hush): use View#DRAG_FLAG_GLOBAL when Chromium starts to build with API 24. |
- private static final int DRAG_FLAG_GLOBAL = 1 << 8; |
- /** |
- * Represents the position of an anchor view. |
- */ |
- @VisibleForTesting |
- private static class Position { |
- private final float mX; |
- private final float mY; |
- private final float mWidth; |
- private final float mHeight; |
- |
- public Position(float x, float y, float width, float height) { |
- mX = x; |
- mY = y; |
- mWidth = width; |
- mHeight = height; |
- } |
- } |
- |
- private final RenderCoordinates mRenderCoordinates; |
- |
- /** |
- * The current container view. This view can be updated with |
- * {@link #updateCurrentContainerView()}. This needs to be a WeakReference |
- * because ViewAndroidDelegate is held strongly native side, which otherwise |
- * indefinitely prevents Android WebView from being garbage collected. |
- */ |
- private WeakReference<ViewGroup> mCurrentContainerView; |
- |
- /** |
- * List of anchor views stored in the order in which they were acquired mapped |
- * to their position. |
- */ |
- private final Map<View, Position> mAnchorViews = new LinkedHashMap<View, Position>(); |
- |
- ContentViewAndroidDelegate(ViewGroup containerView, RenderCoordinates renderCoordinates) { |
- mRenderCoordinates = renderCoordinates; |
- mCurrentContainerView = new WeakReference<>(containerView); |
- } |
- |
- @Override |
- public View acquireAnchorView() { |
- ViewGroup containerView = mCurrentContainerView.get(); |
- if (containerView == null) return null; |
- View anchorView = new View(containerView.getContext()); |
- mAnchorViews.put(anchorView, null); |
- containerView.addView(anchorView); |
- return anchorView; |
- } |
- |
- @Override |
- public void setAnchorViewPosition( |
- View view, float x, float y, float width, float height) { |
- mAnchorViews.put(view, new Position(x, y, width, height)); |
- doSetAnchorViewPosition(view, x, y, width, height); |
- } |
- |
- @SuppressWarnings("deprecation") // AbsoluteLayout |
- private void doSetAnchorViewPosition( |
- View view, float x, float y, float width, float height) { |
- if (view.getParent() == null) { |
- // Ignore. setAnchorViewPosition has been called after the anchor view has |
- // already been released. |
- return; |
- } |
- ViewGroup containerView = mCurrentContainerView.get(); |
- if (containerView == null) { |
- return; |
- } |
- assert view.getParent() == containerView; |
- |
- float scale = |
- (float) DeviceDisplayInfo.create(containerView.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 (containerView instanceof FrameLayout) { |
- int startMargin; |
- if (ApiCompatibilityUtils.isLayoutRtl(containerView)) { |
- startMargin = |
- containerView.getMeasuredWidth() - Math.round((width + x) * scale); |
- } else { |
- startMargin = leftMargin; |
- } |
- if (scaledWidth + startMargin > containerView.getWidth()) { |
- scaledWidth = containerView.getWidth() - startMargin; |
- } |
- FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( |
- scaledWidth, Math.round(height * scale)); |
- ApiCompatibilityUtils.setMarginStart(lp, startMargin); |
- lp.topMargin = topMargin; |
- view.setLayoutParams(lp); |
- } else if (containerView instanceof android.widget.AbsoluteLayout) { |
- // This fixes the offset due to a difference in |
- // scrolling model of WebView vs. Chrome. |
- // TODO(sgurun) fix this to use mContainerViewAtCreation.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 %s", containerView.getClass().getName()); |
- } |
- } |
- |
- @Override |
- public void releaseAnchorView(View anchorView) { |
- mAnchorViews.remove(anchorView); |
- ViewGroup containerView = mCurrentContainerView.get(); |
- if (containerView != null) { |
- containerView.removeView(anchorView); |
- } |
- } |
- |
- /** |
- * Updates (or sets for the first time) the current container view to which |
- * this class delegates. Existing anchor views are transferred from the old to |
- * the new container view. |
- */ |
- void updateCurrentContainerView(ViewGroup containerView) { |
- ViewGroup oldContainerView = mCurrentContainerView.get(); |
- mCurrentContainerView = new WeakReference<>(containerView); |
- for (Entry<View, Position> entry : mAnchorViews.entrySet()) { |
- View anchorView = entry.getKey(); |
- Position position = entry.getValue(); |
- if (oldContainerView != null) { |
- oldContainerView.removeView(anchorView); |
- } |
- containerView.addView(anchorView); |
- if (position != null) { |
- doSetAnchorViewPosition(anchorView, |
- position.mX, position.mY, position.mWidth, position.mHeight); |
- } |
- } |
- } |
- |
- @SuppressWarnings("deprecation") |
- @Override |
- public void startDragAndDrop(String text, Bitmap shadowImage) { |
- ClipData data = ClipData.newPlainText(null, text); |
- |
- ViewGroup containerView = mCurrentContainerView.get(); |
- if (containerView == null) return; |
- |
- ImageView imageView = new ImageView(containerView.getContext()); |
- imageView.setImageBitmap(shadowImage); |
- imageView.layout(0, 0, shadowImage.getWidth(), shadowImage.getHeight()); |
- |
- // TODO(hush): use View#startDragAndDrop when Chromium starts to build with API 24. |
- containerView.startDrag( |
- data, new View.DragShadowBuilder(imageView), null, DRAG_FLAG_GLOBAL); |
- } |
- } |
- |
- /** |
* A {@link WebContentsObserver} that listens to frame navigation events. |
*/ |
private static class ContentViewWebContentsObserver extends WebContentsObserver { |
@@ -625,7 +449,7 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Screen |
private boolean mFullscreenRequiredForOrientationLock = true; |
// A ViewAndroidDelegate that delegates to the current container view. |
- private ContentViewAndroidDelegate mViewAndroidDelegate; |
+ private ViewAndroidDelegate mViewAndroidDelegate; |
// A flag to determine if we enable hover feature or not. |
private Boolean mEnableTouchHover; |
@@ -733,7 +557,10 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Screen |
* |
* @return A ViewAndroidDelegate that can be used to add and remove views. |
*/ |
+ @VisibleForTesting |
public ViewAndroidDelegate getViewAndroidDelegate() { |
+ // TODO(jinsukkim): Remove this method since it is only used by tests that don't |
+ // necessarily require the delegate. |
return mViewAndroidDelegate; |
} |
@@ -813,17 +640,17 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Screen |
// 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, |
- WebContents webContents, WindowAndroid windowAndroid) { |
- createContentViewAndroidDelegate(); |
- setContainerView(containerView); |
+ public void initialize(ViewAndroidDelegate viewDelegate, |
+ InternalAccessDelegate internalDispatcher, WebContents webContents, |
+ WindowAndroid windowAndroid) { |
+ mViewAndroidDelegate = viewDelegate; |
+ setContainerView(viewDelegate.getContainerView()); |
long windowNativePointer = windowAndroid.getNativePointer(); |
assert windowNativePointer != 0; |
mZoomControlsDelegate = NO_OP_ZOOM_CONTROLS_DELEGATE; |
- |
- mNativeContentViewCore = nativeInit( |
- webContents, mViewAndroidDelegate, windowNativePointer, mRetainedJavaScriptObjects); |
+ mNativeContentViewCore = nativeInit(webContents, mViewAndroidDelegate, windowNativePointer, |
+ mRetainedJavaScriptObjects); |
mWebContents = nativeGetWebContentsAndroid(mNativeContentViewCore); |
setContainerViewInternals(internalDispatcher); |
@@ -850,11 +677,6 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Screen |
mPastePopupMenu = null; |
} |
- @VisibleForTesting |
- public void createContentViewAndroidDelegate() { |
- mViewAndroidDelegate = new ContentViewAndroidDelegate(mContainerView, mRenderCoordinates); |
- } |
- |
/** |
* Sets a new container view for this {@link ContentViewCore}. |
* |
@@ -884,7 +706,6 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Screen |
mContainerView = containerView; |
mContainerView.setClickable(true); |
- mViewAndroidDelegate.updateCurrentContainerView(mContainerView); |
for (ContainerViewObserver observer : mContainerViewObservers) { |
observer.onContainerViewChanged(mContainerView); |
} |
@@ -2526,6 +2347,8 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Screen |
/** |
* Called (from native) when the <select> popup needs to be shown. |
+ * @param anchorView View anchored for popup. |
+ * @param anchorWidth Width of the anchor view without dip scale applied. |
* @param nativeSelectPopupSourceFrame The native RenderFrameHost that owns the popup. |
* @param items Items to show. |
* @param enabled POPUP_ITEM_TYPEs for items. |
@@ -2534,8 +2357,9 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Screen |
*/ |
@SuppressWarnings("unused") |
@CalledByNative |
- private void showSelectPopup(long nativeSelectPopupSourceFrame, Rect bounds, String[] items, |
- int[] enabled, boolean multiple, int[] selectedIndices, boolean rightAligned) { |
+ private void showSelectPopup(View anchorView, float anchorWidth, |
+ long nativeSelectPopupSourceFrame, String[] items, int[] enabled, boolean multiple, |
+ int[] selectedIndices, boolean rightAligned) { |
if (mContainerView.getParent() == null || mContainerView.getVisibility() != View.VISIBLE) { |
mNativeSelectPopupSourceFrame = nativeSelectPopupSourceFrame; |
selectPopupMenuItems(null); |
@@ -2552,7 +2376,7 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Screen |
} |
if (DeviceFormFactor.isTablet(mContext) && !multiple && !isTouchExplorationEnabled()) { |
mSelectPopup = new SelectPopupDropdown( |
- this, popupItems, bounds, selectedIndices, rightAligned); |
+ this, anchorView, anchorWidth, popupItems, selectedIndices, rightAligned); |
} else { |
if (getWindowAndroid() == null) return; |
Context windowContext = getWindowAndroid().getContext().get(); |