Chromium Code Reviews| 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 0a0e8530776bffcb7df689bea0ff2b19e862f171..972360b86b6aeb3b246e46e78ee7e81f7d1eb518 100644 |
| --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java |
| +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java |
| @@ -77,6 +77,7 @@ import java.net.URL; |
| import java.util.HashMap; |
| import java.util.Locale; |
| import java.util.Map; |
| +import java.util.WeakHashMap; |
| import java.util.concurrent.Callable; |
| /** |
| @@ -207,7 +208,7 @@ public class AwContents implements SmartClipProvider, |
| private final Context mContext; |
| private final int mAppTargetSdkVersion; |
| private ContentViewCore mContentViewCore; |
| - private WindowAndroid mWindowAndroid; |
| + private WindowAndroidWrapper mWindowAndroid; |
| private WebContents mWebContents; |
| private NavigationController mNavigationController; |
| private final AwContentsClient mContentsClient; |
| @@ -287,16 +288,13 @@ public class AwContents implements SmartClipProvider, |
| private static final class DestroyRunnable implements Runnable { |
| private final long mNativeAwContents; |
| - private final WindowAndroid mWindowAndroid; |
| - private DestroyRunnable(long nativeAwContents, WindowAndroid windowAndroid) { |
| + private DestroyRunnable(long nativeAwContents) { |
| mNativeAwContents = nativeAwContents; |
| - mWindowAndroid = windowAndroid; |
| } |
| @Override |
| public void run() { |
| nativeDestroy(mNativeAwContents); |
| - mWindowAndroid.destroy(); |
| } |
| } |
| @@ -848,6 +846,60 @@ public class AwContents implements SmartClipProvider, |
| mContainerView.requestLayout(); |
| } |
| + // This class destroys the WindowAndroid when after it is gc-ed. |
| + private static class WindowAndroidWrapper { |
| + private final WindowAndroid mWindowAndroid; |
| + private final CleanupReference mCleanupReference; |
| + |
| + private static final class DestroyRunnable implements Runnable { |
| + private final WindowAndroid mWindowAndroid; |
| + private DestroyRunnable(WindowAndroid windowAndroid) { |
| + mWindowAndroid = windowAndroid; |
| + } |
| + @Override |
| + public void run() { |
| + mWindowAndroid.destroy(); |
| + } |
| + } |
| + |
| + public WindowAndroidWrapper(WindowAndroid windowAndroid) { |
| + mWindowAndroid = windowAndroid; |
| + mCleanupReference = |
| + new CleanupReference(this, new DestroyRunnable(windowAndroid)); |
| + } |
| + |
| + public WindowAndroid getWindowAndroid() { |
| + return mWindowAndroid; |
| + } |
| + } |
| + private static WindowAndroidWrapper sCachedWindowAndroid; |
| + private static WeakHashMap<Activity, WindowAndroidWrapper> sActivityWindowMap; |
|
Torne
2015/05/15 12:48:13
The hash map won't release the WindowAndroidWrappe
boliu
2015/05/15 13:34:01
Yeah I think that's fine. If another webview is cr
|
| + |
| + // getWindowAndroid is only called on UI thread, so there are no threading issues with lazy |
| + // initialization. |
| + @SuppressFBWarnings("LI_LAZY_INIT_STATIC") |
| + private static WindowAndroidWrapper getWindowAndroid(Context context) { |
| + // TODO(boliu): WebView does not currently initialize ApplicationStatus, crbug.com/470582. |
| + Activity activity = ContentViewCore.activityFromContext(context); |
| + if (activity == null) { |
| + if (sCachedWindowAndroid == null) { |
| + sCachedWindowAndroid = new WindowAndroidWrapper( |
| + new WindowAndroid(context.getApplicationContext())); |
| + } |
| + return sCachedWindowAndroid; |
| + } |
| + |
| + if (sActivityWindowMap == null) sActivityWindowMap = new WeakHashMap<>(); |
| + WindowAndroidWrapper activityWindowAndroid = sActivityWindowMap.get(activity); |
| + if (activityWindowAndroid == null) { |
| + final boolean listenToActivityState = false; |
| + activityWindowAndroid = new WindowAndroidWrapper( |
| + new ActivityWindowAndroid(activity, listenToActivityState)); |
| + sActivityWindowMap.put(activity, activityWindowAndroid); |
| + } |
| + return activityWindowAndroid; |
| + } |
| + |
| /* Common initialization routine for adopting a native AwContents instance into this |
| * java instance. |
| * |
| @@ -871,15 +923,10 @@ public class AwContents implements SmartClipProvider, |
| WebContents webContents = nativeGetWebContents(mNativeAwContents); |
| - // WebView does not currently initialize ApplicationStatus, crbug.com/470582. |
| - final boolean listenToActivityState = false; |
| - Activity activity = ContentViewCore.activityFromContext(mContext); |
| - mWindowAndroid = activity != null |
| - ? new ActivityWindowAndroid(activity, listenToActivityState) |
| - : new WindowAndroid(mContext.getApplicationContext()); |
| - mContentViewCore = createAndInitializeContentViewCore( |
| - mContainerView, mContext, mInternalAccessAdapter, webContents, |
| - new AwGestureStateListener(), mContentViewClient, mZoomControls, mWindowAndroid); |
| + mWindowAndroid = getWindowAndroid(mContext); |
| + mContentViewCore = createAndInitializeContentViewCore(mContainerView, mContext, |
| + mInternalAccessAdapter, webContents, new AwGestureStateListener(), |
| + mContentViewClient, mZoomControls, mWindowAndroid.getWindowAndroid()); |
| nativeSetJavaPeers(mNativeAwContents, this, mWebContentsDelegate, mContentsClientBridge, |
| mIoThreadClient, mInterceptNavigationDelegate); |
| mWebContents = mContentViewCore.getWebContents(); |
| @@ -892,7 +939,7 @@ public class AwContents implements SmartClipProvider, |
| // The native side object has been bound to this java instance, so now is the time to |
| // bind all the native->java relationships. |
| mCleanupReference = |
| - new CleanupReference(this, new DestroyRunnable(mNativeAwContents, mWindowAndroid)); |
| + new CleanupReference(this, new DestroyRunnable(mNativeAwContents)); |
| } |
| private void installWebContentsObserver() { |
| @@ -2452,7 +2499,7 @@ public class AwContents implements SmartClipProvider, |
| @CalledByNative |
| private void postInvalidateOnAnimation() { |
| - if (!mWindowAndroid.isInsideVSync()) { |
| + if (!mWindowAndroid.getWindowAndroid().isInsideVSync()) { |
| mContainerView.postInvalidateOnAnimation(); |
| } else { |
| mContainerView.invalidate(); |