Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Unified Diff: content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java

Issue 639413002: [aw] Reuse WebContents PowerSaveBlocker in fullscreen. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@testsForPowerSaver
Patch Set: Nits Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 ba0c70ebeaa44f086df6ca89bf046cf7f4b47a4d..e9cdf106c14156f9153785c012c30a53ddf08f0e 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
@@ -87,8 +87,10 @@ import java.lang.reflect.Field;
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.
@@ -143,6 +145,136 @@ public class ContentViewCore
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 class ContentViewAndroidDelegate implements ViewAndroidDelegate {
+ /**
+ * Represents the position of an anchor view.
+ */
+ @VisibleForTesting
+ private 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;
+ }
+ }
+
+ /**
+ * The current container view. This view can be updated with
+ * {@link #updateCurrentContainerView()}.
+ */
+ private ViewGroup mCurrentContainerView;
+
+ /**
+ * List of anchor views stored in the order in which they were acquired mapped
+ * to their position.
+ */
+ private Map<View, Position> mAnchorViews = new LinkedHashMap<View, Position>();
+
+ @Override
+ public View acquireAnchorView() {
+ View anchorView = new View(mContext);
+ mAnchorViews.put(anchorView, null);
+ mCurrentContainerView.addView(anchorView);
+ return anchorView;
+ }
+
+ @Override
+ @SuppressWarnings("deprecation") // AbsoluteLayout
+ 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);
+ }
+
+ 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;
+ }
+ assert view.getParent() == mCurrentContainerView;
+
+ float scale = (float) DeviceDisplayInfo.create(mContext).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 (mCurrentContainerView instanceof FrameLayout) {
+ int startMargin;
+ if (ApiCompatibilityUtils.isLayoutRtl(mCurrentContainerView)) {
+ startMargin = mCurrentContainerView.getMeasuredWidth()
+ - Math.round((width + x) * scale);
+ } else {
+ startMargin = leftMargin;
+ }
+ if (scaledWidth + startMargin > mCurrentContainerView.getWidth()) {
+ scaledWidth = mCurrentContainerView.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 (mCurrentContainerView 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 " + mCurrentContainerView.getClass().getName());
+ }
+ }
+
+ @Override
+ public void releaseAnchorView(View anchorView) {
+ mAnchorViews.remove(anchorView);
+ mCurrentContainerView.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 oldContainerView = mCurrentContainerView;
+ mCurrentContainerView = mContainerView;
+ for (Entry<View, Position> entry : mAnchorViews.entrySet()) {
+ View anchorView = entry.getKey();
+ Position position = entry.getValue();
+ oldContainerView.removeView(anchorView);
+ mCurrentContainerView.addView(anchorView);
+ if (position != null) {
+ doSetAnchorViewPosition(anchorView,
+ position.mX, position.mY, position.mWidth, position.mHeight);
+ }
+ }
+ }
+ }
+
+ /**
* Interface that consumers of {@link ContentViewCore} must implement to allow the proper
* dispatching of view methods through the containing view.
*
@@ -361,6 +493,9 @@ public class ContentViewCore
// screen orientation.
private boolean mFullscreenRequiredForOrientationLock = true;
+ // A ViewAndroidDelegate that delegates to the current container view.
+ private ContentViewAndroidDelegate mViewAndroidDelegate;
+
/**
* Constructs a new ContentViewCore. Embedders must call initialize() after constructing
* a ContentViewCore and before using it.
@@ -429,9 +564,11 @@ public class ContentViewCore
}
/**
- * Returns a delegate that can be used to add and remove views from the ContainerView.
+ * Returns a delegate that can be used to add and remove views from the current
+ * container view. Clients can safely hold to instances of this class as it handles the
+ * replacement of container views transparently.
*
- * NOTE: Use with care, as not all ContentViewCore users setup their ContainerView in the same
+ * NOTE: Use with care, as not all ContentViewCore users setup their container view 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
@@ -439,77 +576,8 @@ public class ContentViewCore
*
* @return A ViewAndroidDelegate that can be used to add and remove views.
*/
- @VisibleForTesting
public ViewAndroidDelegate getViewAndroidDelegate() {
- return new ViewAndroidDelegate() {
- // mContainerView can change, but this ViewAndroidDelegate can only be used to
- // add and remove views from the mContainerViewAtCreation.
- private final ViewGroup mContainerViewAtCreation = mContainerView;
-
- @Override
- public View acquireAnchorView() {
- View anchorView = new View(mContext);
- mContainerViewAtCreation.addView(anchorView);
- return anchorView;
- }
-
- @Override
- @SuppressWarnings("deprecation") // AbsoluteLayout
- public void setAnchorViewPosition(
- 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;
- }
- assert view.getParent() == mContainerViewAtCreation;
-
- float scale = (float) DeviceDisplayInfo.create(mContext).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 (mContainerViewAtCreation instanceof FrameLayout) {
- int startMargin;
- if (ApiCompatibilityUtils.isLayoutRtl(mContainerViewAtCreation)) {
- startMargin = mContainerViewAtCreation.getMeasuredWidth()
- - Math.round((width + x) * scale);
- } else {
- startMargin = leftMargin;
- }
- if (scaledWidth + startMargin > mContainerViewAtCreation.getWidth()) {
- scaledWidth = mContainerViewAtCreation.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 (mContainerViewAtCreation 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 " + mContainerViewAtCreation.getClass().getName());
- }
- }
-
- @Override
- public void releaseAnchorView(View anchorView) {
- mContainerViewAtCreation.removeView(anchorView);
- }
- };
+ return mViewAndroidDelegate;
}
@VisibleForTesting
@@ -537,6 +605,11 @@ public class ContentViewCore
return mInputConnection;
}
+ @VisibleForTesting
+ ViewAndroid getViewAndroid() {
+ return mViewAndroid;
+ }
+
private ImeAdapter createImeAdapter(Context context) {
return new ImeAdapter(mInputMethodManagerWrapper,
new ImeAdapter.ImeAdapterDelegate() {
@@ -605,11 +678,12 @@ public class ContentViewCore
// deleting it after destroying the ContentViewCore.
public void initialize(ViewGroup containerView, InternalAccessDelegate internalDispatcher,
long nativeWebContents, WindowAndroid windowAndroid) {
+ createContentViewAndroidDelegate();
setContainerView(containerView);
-
long windowNativePointer = windowAndroid.getNativePointer();
assert windowNativePointer != 0;
- mViewAndroid = new ViewAndroid(windowAndroid, getViewAndroidDelegate());
+ createViewAndroid(windowAndroid);
+
long viewAndroidNativePointer = mViewAndroid.getNativePointer();
assert viewAndroidNativePointer != 0;
@@ -648,13 +722,23 @@ public class ContentViewCore
};
}
+ @VisibleForTesting
+ void createContentViewAndroidDelegate() {
+ mViewAndroidDelegate = new ContentViewAndroidDelegate();
+ }
+
+ @VisibleForTesting
+ void createViewAndroid(WindowAndroid windowAndroid) {
+ mViewAndroid = new ViewAndroid(windowAndroid, mViewAndroidDelegate);
+ }
+
/**
* Sets a new container view for this {@link ContentViewCore}.
*
- * <p>WARNING: This is not a general purpose method and has been designed with WebView
- * fullscreen in mind. Please be aware that it might not be appropriate for other use cases
- * and that it has a number of limitations. For example the PopupZoomer only works with the
- * container view with which this ContentViewCore has been initialized.
+ * <p>WARNING: This method can also be used to replace the existing container view,
+ * but you should only do it if you have a very good reason to. Replacing the
+ * container view has been designed to support fullscreen in the Webview so it
+ * might not be appropriate for other use cases.
*
* <p>This method only performs a small part of replacing the container view and
* embedders are responsible for:
@@ -678,6 +762,7 @@ public class ContentViewCore
mPositionObserver = new ViewPositionObserver(mContainerView);
mContainerView.setWillNotDraw(false);
mContainerView.setClickable(true);
+ mViewAndroidDelegate.updateCurrentContainerView();
TraceEvent.end();
}
@@ -696,7 +781,8 @@ public class ContentViewCore
mContainerViewInternals = internalDispatcher;
}
- private void initPopupZoomer(Context context) {
+ @VisibleForTesting
+ void initPopupZoomer(Context context) {
mPopupZoomer = new PopupZoomer(context);
mPopupZoomer.setOnVisibilityChangedListener(new PopupZoomer.OnVisibilityChangedListener() {
// mContainerView can change, but this OnVisibilityChangedListener can only be used

Powered by Google App Engine
This is Rietveld 408576698