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 fb2d0785ac509a9a747796b7dd4290866cb3cb5a..a463fd5626a7a61fc4cb1bce750f53bd1975e180 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; |
@@ -55,9 +56,11 @@ import org.chromium.base.annotations.JNINamespace; |
import org.chromium.base.annotations.SuppressFBWarnings; |
import org.chromium.components.navigation_interception.InterceptNavigationDelegate; |
import org.chromium.components.navigation_interception.NavigationParams; |
+import org.chromium.content.browser.ContentViewAndroidDelegate; |
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; |
@@ -78,11 +81,14 @@ 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 AwContentViewAndroidDelegate mViewAndroidDelegate; |
private WindowAndroidWrapper mWindowAndroid; |
private WebContents mWebContents; |
private NavigationController mNavigationController; |
@@ -810,7 +817,9 @@ public class AwContents implements SmartClipProvider, |
ContentViewCore.ZoomControlsDelegate zoomControlsDelegate, |
WindowAndroid windowAndroid) { |
ContentViewCore contentViewCore = new ContentViewCore(context); |
- contentViewCore.initialize(containerView, internalDispatcher, webContents, |
+ AwContentViewAndroidDelegate viewDelegate = new AwContentViewAndroidDelegate( |
+ containerView, contentViewCore.getRenderCoordinates()); |
+ contentViewCore.initialize(containerView, viewDelegate, internalDispatcher, webContents, |
windowAndroid); |
contentViewCore.addGestureStateListener(gestureStateListener); |
contentViewCore.setContentViewClient(contentViewClient); |
@@ -818,6 +827,94 @@ public class AwContents implements SmartClipProvider, |
return contentViewCore; |
} |
+ /** |
+ * Implementation of the interface {@link org.chromium.ui.base.ViewAndroidDelegate} |
+ * for WebView. |
+ */ |
+ public static class AwContentViewAndroidDelegate extends ContentViewAndroidDelegate { |
+ /** |
+ * 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<>(); |
+ |
+ AwContentViewAndroidDelegate(ViewGroup containerView, RenderCoordinates renderCoordinates) { |
+ super(null, renderCoordinates); |
+ mContainerView = new WeakReference<>(containerView); |
+ } |
+ |
+ @Override |
+ public void addView(View anchorView, float x, float y, float width, float height) { |
+ ViewGroup containerView = mContainerView.get(); |
+ if (containerView == null) return; |
+ containerView.addView(anchorView); |
+ mAnchorViews.put(anchorView, new Position(x, y, width, height)); |
+ setAnchorViewPosition(containerView, anchorView, x, y, width, height); |
+ } |
+ |
+ @Override |
+ public void releaseAnchorView(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) { |
+ setAnchorViewPosition(containerView, anchorView, |
+ position.mX, position.mY, position.mWidth, position.mHeight); |
+ } |
+ } |
+ } |
+ |
+ @SuppressWarnings("deprecation") // AbsoluteLayout |
+ @Override |
+ protected void setAnchorViewLayoutParams(ViewGroup containerView, View view, |
+ float x, float y, float width, float height, float scale, |
+ int leftMargin, int topMargin, int scaledWidth) { |
+ if (containerView instanceof FrameLayout) { |
+ super.setAnchorViewLayoutParams(containerView, view, x, y, width, height, |
+ scale, leftMargin, topMargin, scaledWidth); |
+ 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(); |
+ |
+ android.widget.AbsoluteLayout.LayoutParams lp = |
+ new android.widget.AbsoluteLayout.LayoutParams( |
+ scaledWidth, (int) (height * scale), leftMargin, topMargin); |
+ view.setLayoutParams(lp); |
+ } |
+ } |
+ |
boolean isFullScreen() { |
return mFullScreenTransitionsState.isFullScreen(); |
} |
@@ -917,6 +1014,7 @@ public class AwContents implements SmartClipProvider, |
updateNativeAwGLFunctor(); |
mContainerView.setWillNotDraw(false); |
+ mViewAndroidDelegate.updateCurrentContainerView(mContainerView); |
mContentViewCore.setContainerView(mContainerView); |
if (mAwPdfExporter != null) { |
mAwPdfExporter.setContainerView(mContainerView); |
@@ -1040,6 +1138,8 @@ public class AwContents implements SmartClipProvider, |
mContentViewCore = createAndInitializeContentViewCore(mContainerView, mContext, |
mInternalAccessAdapter, webContents, new AwGestureStateListener(), |
mContentViewClient, mZoomControls, mWindowAndroid.getWindowAndroid()); |
+ mViewAndroidDelegate = (AwContentViewAndroidDelegate) |
+ mContentViewCore.getViewAndroidDelegate(); |
nativeSetJavaPeers(mNativeAwContents, this, mWebContentsDelegate, mContentsClientBridge, |
mIoThreadClient, mInterceptNavigationDelegate); |
mWebContents = mContentViewCore.getWebContents(); |