Index: android_webview/java/src/org/chromium/android_webview/AwContents.java |
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java |
index 65d815924c7e950517e8fcde222ed5a0bdff2aad..f76961795031929532a4ba30c926c1fc3396cf8f 100644 |
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java |
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java |
@@ -42,6 +42,7 @@ import android.view.inputmethod.EditorInfo; |
import android.view.inputmethod.InputConnection; |
import android.webkit.JavascriptInterface; |
import android.webkit.ValueCallback; |
+import android.widget.FrameLayout; |
import org.chromium.android_webview.permission.AwGeolocationCallback; |
import org.chromium.android_webview.permission.AwPermissionRequest; |
@@ -58,6 +59,7 @@ import org.chromium.components.navigation_interception.NavigationParams; |
import org.chromium.content.browser.ContentViewClient; |
import org.chromium.content.browser.ContentViewCore; |
import org.chromium.content.browser.ContentViewStatics; |
+import org.chromium.content.browser.RenderCoordinates; |
import org.chromium.content.browser.SmartClipProvider; |
import org.chromium.content.common.CleanupReference; |
import org.chromium.content_public.browser.GestureStateListener; |
@@ -73,16 +75,20 @@ import org.chromium.net.NetError; |
import org.chromium.net.NetworkChangeNotifier; |
import org.chromium.ui.base.ActivityWindowAndroid; |
import org.chromium.ui.base.PageTransition; |
+import org.chromium.ui.base.ViewAndroidDelegate; |
import org.chromium.ui.base.WindowAndroid; |
import org.chromium.ui.gfx.DeviceDisplayInfo; |
import java.io.File; |
import java.lang.annotation.Annotation; |
+import java.lang.ref.WeakReference; |
import java.net.MalformedURLException; |
import java.net.URL; |
import java.util.HashMap; |
+import java.util.LinkedHashMap; |
import java.util.Locale; |
import java.util.Map; |
+import java.util.Map.Entry; |
import java.util.WeakHashMap; |
import java.util.concurrent.Callable; |
@@ -92,7 +98,7 @@ import java.util.concurrent.Callable; |
* primary entry point for the WebViewProvider implementation; it holds a 1:1 object |
* relationship with application WebView instances. |
* (We define this class independent of the hidden WebViewProvider interfaces, to allow |
- * continuous build & test in the open source SDK-based tree). |
+ * continuous build & test in the open source SDK-based tree). |
*/ |
@JNINamespace("android_webview") |
public class AwContents implements SmartClipProvider, |
@@ -264,6 +270,7 @@ public class AwContents implements SmartClipProvider, |
private final Context mContext; |
private final int mAppTargetSdkVersion; |
private ContentViewCore mContentViewCore; |
+ private AwViewAndroidDelegate mViewAndroidDelegate; |
private WindowAndroidWrapper mWindowAndroid; |
private WebContents mWebContents; |
private NavigationController mNavigationController; |
@@ -803,19 +810,146 @@ public class AwContents implements SmartClipProvider, |
onContainerViewChanged(); |
} |
- private static ContentViewCore createAndInitializeContentViewCore(ViewGroup containerView, |
- Context context, InternalAccessDelegate internalDispatcher, WebContents webContents, |
- GestureStateListener gestureStateListener, |
- ContentViewClient contentViewClient, |
+ private static void initializeContentViewCore(ContentViewCore contentViewCore, |
+ ViewGroup containerView, Context context, ViewAndroidDelegate viewDelegate, |
+ InternalAccessDelegate internalDispatcher, WebContents webContents, |
+ GestureStateListener gestureStateListener, ContentViewClient contentViewClient, |
ContentViewCore.ZoomControlsDelegate zoomControlsDelegate, |
WindowAndroid windowAndroid) { |
- ContentViewCore contentViewCore = new ContentViewCore(context); |
- contentViewCore.initialize(containerView, internalDispatcher, webContents, |
+ contentViewCore.initialize(containerView, viewDelegate, internalDispatcher, webContents, |
windowAndroid); |
contentViewCore.addGestureStateListener(gestureStateListener); |
contentViewCore.setContentViewClient(contentViewClient); |
contentViewCore.setZoomControlsDelegate(zoomControlsDelegate); |
- return contentViewCore; |
+ } |
+ |
+ /** |
+ * Implementation of the abstract class |
+ * {@link org.chromium.ui.base.ViewAndroid.ViewAndroidDelegate) for WebView. |
+ */ |
+ public static class AwViewAndroidDelegate extends ViewAndroidDelegate { |
boliu
2016/07/25 22:15:26
pull out into separate file?
Jinsuk Kim
2016/07/27 10:02:43
Pulled out to AwViewAndroidDelegate.java
|
+ /** |
+ * 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> mContainerView; |
+ |
+ /** |
+ * 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<>(); |
+ |
+ private final RenderCoordinates mRenderCoordinates; |
+ |
+ /** |
+ * Represents the position of an anchor view. |
+ */ |
+ @VisibleForTesting |
+ private static class Position { |
+ public final float mX; |
+ public final float mY; |
+ public final float mWidth; |
+ public final float mHeight; |
+ public final int mLeftMargin; |
+ public final int mTopMargin; |
+ |
+ public Position(float x, float y, float width, float height, int leftMargin, |
+ int topMargin) { |
+ mX = x; |
+ mY = y; |
+ mWidth = width; |
+ mHeight = height; |
+ mLeftMargin = leftMargin; |
+ mTopMargin = topMargin; |
+ } |
+ } |
+ |
+ AwViewAndroidDelegate(ViewGroup containerView, RenderCoordinates renderCoordinates) { |
+ mContainerView = new WeakReference<>(containerView); |
+ mRenderCoordinates = renderCoordinates; |
+ } |
+ |
+ @Override |
+ public View acquireView() { |
+ ViewGroup containerView = mContainerView.get(); |
+ if (containerView == null) return null; |
+ View anchorView = new View(containerView.getContext()); |
+ containerView.addView(anchorView); |
+ // |mAnchorViews| will be updated with the right view position in |setViewPosition|. |
+ mAnchorViews.put(anchorView, null); |
+ return anchorView; |
+ } |
+ |
+ @Override |
+ public void removeView(View anchorView) { |
+ mAnchorViews.remove(anchorView); |
+ ViewGroup containerView = mContainerView.get(); |
+ if (containerView != null) { |
+ containerView.removeView(anchorView); |
+ } |
+ } |
+ |
+ /** |
+ * Updates the current container view to which this class delegates. Existing anchor views |
+ * are transferred from the old to the new container view. |
+ */ |
+ public void updateCurrentContainerView(ViewGroup containerView) { |
+ ViewGroup oldContainerView = mContainerView.get(); |
+ mContainerView = 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) { |
+ float scale = (float) DeviceDisplayInfo.create(containerView.getContext()) |
+ .getDIPScale(); |
+ setViewPosition(anchorView, position.mX, position.mY, |
+ position.mWidth, position.mHeight, scale, |
+ position.mLeftMargin, position.mTopMargin); |
+ } |
+ } |
+ } |
+ |
+ @SuppressWarnings("deprecation") // AbsoluteLayout |
+ @Override |
+ public void setViewPosition(View anchorView, float x, float y, float width, float height, |
+ float scale, int leftMargin, int topMargin) { |
+ ViewGroup containerView = getContainerView(); |
+ if (!mAnchorViews.containsKey(anchorView) || containerView == null) return; |
no sievers
2016/07/25 17:37:32
Yes, I think that's good enough to check because i
|
+ |
+ mAnchorViews.put(anchorView, new Position(x, y, width, height, leftMargin, topMargin)); |
+ |
+ if (containerView instanceof FrameLayout) { |
+ super.setViewPosition(anchorView, x, y, width, height, scale, leftMargin, |
+ topMargin); |
+ return; |
+ } |
+ // 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(); |
+ |
+ int scaledWidth = Math.round(width * scale); |
+ int scaledHeight = Math.round(height * scale); |
+ android.widget.AbsoluteLayout.LayoutParams lp = |
+ new android.widget.AbsoluteLayout.LayoutParams( |
+ scaledWidth, scaledHeight, leftMargin, topMargin); |
+ anchorView.setLayoutParams(lp); |
+ } |
+ |
+ @Override |
+ protected ViewGroup getContainerView() { |
+ return mContainerView.get(); |
+ } |
} |
boolean isFullScreen() { |
@@ -917,6 +1051,7 @@ public class AwContents implements SmartClipProvider, |
updateNativeAwGLFunctor(); |
mContainerView.setWillNotDraw(false); |
+ mViewAndroidDelegate.updateCurrentContainerView(mContainerView); |
mContentViewCore.setContainerView(mContainerView); |
if (mAwPdfExporter != null) { |
mAwPdfExporter.setContainerView(mContainerView); |
@@ -1037,9 +1172,13 @@ public class AwContents implements SmartClipProvider, |
WebContents webContents = nativeGetWebContents(mNativeAwContents); |
mWindowAndroid = getWindowAndroid(mContext); |
- mContentViewCore = createAndInitializeContentViewCore(mContainerView, mContext, |
- mInternalAccessAdapter, webContents, new AwGestureStateListener(), |
- mContentViewClient, mZoomControls, mWindowAndroid.getWindowAndroid()); |
+ mContentViewCore = new ContentViewCore(mContext); |
+ mViewAndroidDelegate = new AwViewAndroidDelegate(mContainerView, |
+ mContentViewCore.getRenderCoordinates()); |
+ initializeContentViewCore(mContentViewCore, mContainerView, mContext, |
+ mViewAndroidDelegate, mInternalAccessAdapter, webContents, |
+ new AwGestureStateListener(), mContentViewClient, mZoomControls, |
+ mWindowAndroid.getWindowAndroid()); |
nativeSetJavaPeers(mNativeAwContents, this, mWebContentsDelegate, mContentsClientBridge, |
mIoThreadClient, mInterceptNavigationDelegate); |
mWebContents = mContentViewCore.getWebContents(); |