Move ContentViewCore native ownership to WebContents
This means the nest of native objects (once built up) have the same life-times, and the mismatch is handled at the JNI boundary. GC might cause WebContents to get deleted before ContentViewCore (if AwContents is finalized before the java ContentViewCore) BUG= Review URL: https://chromiumcodereview.appspot.com/11067002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@162052 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
content
browser
public
@ -65,24 +65,66 @@ enum PopupItemType {
|
|||||||
POPUP_ITEM_TYPE_ENABLED
|
POPUP_ITEM_TYPE_ENABLED
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace content {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
jfieldID g_native_content_view;
|
jfieldID g_native_content_view;
|
||||||
|
|
||||||
|
const void* kContentViewUserDataKey = &kContentViewUserDataKey;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace content {
|
// Enables a callback when the underlying WebContents is destroyed, to enable
|
||||||
|
// nulling the back-pointer.
|
||||||
|
class ContentViewCoreImpl::ContentViewUserData
|
||||||
|
: public base::SupportsUserData::Data {
|
||||||
|
public:
|
||||||
|
explicit ContentViewUserData(ContentViewCoreImpl* content_view_core)
|
||||||
|
: content_view_core_(content_view_core) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~ContentViewUserData() {
|
||||||
|
// TODO(joth): When chrome has finished removing the TabContents class (see
|
||||||
|
// crbug.com/107201) consider inverting relationship, so ContentViewCore
|
||||||
|
// would own WebContents. That effectively implies making the WebContents
|
||||||
|
// destructor private on Android.
|
||||||
|
delete content_view_core_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentViewCoreImpl* get() const { return content_view_core_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Not using scoped_ptr as ContentViewCoreImpl destructor is private.
|
||||||
|
ContentViewCoreImpl* content_view_core_;
|
||||||
|
|
||||||
|
DISALLOW_IMPLICIT_CONSTRUCTORS(ContentViewUserData);
|
||||||
|
};
|
||||||
|
|
||||||
struct ContentViewCoreImpl::JavaObject {
|
struct ContentViewCoreImpl::JavaObject {
|
||||||
ScopedJavaGlobalRef<jclass> rect_clazz;
|
ScopedJavaGlobalRef<jclass> rect_clazz;
|
||||||
jmethodID rect_constructor;
|
jmethodID rect_constructor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// static
|
||||||
|
ContentViewCoreImpl* ContentViewCoreImpl::FromWebContents(
|
||||||
|
content::WebContents* web_contents) {
|
||||||
|
ContentViewCoreImpl::ContentViewUserData* data =
|
||||||
|
reinterpret_cast<ContentViewCoreImpl::ContentViewUserData*>(
|
||||||
|
web_contents->GetUserData(kContentViewUserDataKey));
|
||||||
|
return data ? data->get() : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
ContentViewCore* ContentViewCore::FromWebContents(
|
||||||
|
content::WebContents* web_contents) {
|
||||||
|
return ContentViewCoreImpl::FromWebContents(web_contents);
|
||||||
|
}
|
||||||
|
|
||||||
ContentViewCore* ContentViewCore::GetNativeContentViewCore(JNIEnv* env,
|
ContentViewCore* ContentViewCore::GetNativeContentViewCore(JNIEnv* env,
|
||||||
jobject obj) {
|
jobject obj) {
|
||||||
return reinterpret_cast<ContentViewCore*>(
|
return reinterpret_cast<ContentViewCore*>(
|
||||||
env->GetIntField(obj, g_native_content_view));
|
env->GetIntField(obj, g_native_content_view));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ContentViewCoreImpl::ContentViewCoreImpl(JNIEnv* env, jobject obj,
|
ContentViewCoreImpl::ContentViewCoreImpl(JNIEnv* env, jobject obj,
|
||||||
bool hardware_accelerated,
|
bool hardware_accelerated,
|
||||||
WebContents* web_contents,
|
WebContents* web_contents,
|
||||||
@ -119,31 +161,42 @@ ContentViewCoreImpl::ContentViewCoreImpl(JNIEnv* env, jobject obj,
|
|||||||
webkit_glue::BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
|
webkit_glue::BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
|
||||||
web_contents->SetUserAgentOverride(spoofed_ua);
|
web_contents->SetUserAgentOverride(spoofed_ua);
|
||||||
|
|
||||||
InitWebContents(web_contents);
|
InitWebContents();
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentViewCoreImpl::~ContentViewCoreImpl() {
|
ContentViewCoreImpl::~ContentViewCoreImpl() {
|
||||||
|
JNIEnv* env = base::android::AttachCurrentThread();
|
||||||
|
ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
|
||||||
|
java_ref_.reset();
|
||||||
|
if (!j_obj.is_null()) {
|
||||||
|
Java_ContentViewCore_onNativeContentViewCoreDestroyed(
|
||||||
|
env, j_obj.obj(), reinterpret_cast<jint>(this));
|
||||||
|
}
|
||||||
// Make sure nobody calls back into this object while we are tearing things
|
// Make sure nobody calls back into this object while we are tearing things
|
||||||
// down.
|
// down.
|
||||||
notification_registrar_.RemoveAll();
|
notification_registrar_.RemoveAll();
|
||||||
|
|
||||||
delete java_object_;
|
delete java_object_;
|
||||||
java_object_ = NULL;
|
java_object_ = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv* env,
|
||||||
|
jobject obj) {
|
||||||
|
DCHECK(env->IsSameObject(java_ref_.get(env).obj(), obj));
|
||||||
java_ref_.reset();
|
java_ref_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContentViewCoreImpl::Destroy(JNIEnv* env, jobject obj) {
|
void ContentViewCoreImpl::InitWebContents() {
|
||||||
delete this;
|
DCHECK(web_contents_);
|
||||||
}
|
|
||||||
|
|
||||||
void ContentViewCoreImpl::InitWebContents(WebContents* web_contents) {
|
|
||||||
web_contents_ = static_cast<WebContentsImpl*>(web_contents);
|
|
||||||
notification_registrar_.Add(this,
|
notification_registrar_.Add(this,
|
||||||
NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
|
NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
|
||||||
Source<NavigationController>(&web_contents_->GetController()));
|
Source<NavigationController>(&web_contents_->GetController()));
|
||||||
|
|
||||||
static_cast<WebContentsViewAndroid*>(web_contents_->GetView())->
|
static_cast<WebContentsViewAndroid*>(web_contents_->GetView())->
|
||||||
SetContentViewCore(this);
|
SetContentViewCore(this);
|
||||||
|
DCHECK(!web_contents_->GetUserData(kContentViewUserDataKey));
|
||||||
|
web_contents_->SetUserData(kContentViewUserDataKey,
|
||||||
|
new ContentViewUserData(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContentViewCoreImpl::Observe(int type,
|
void ContentViewCoreImpl::Observe(int type,
|
||||||
|
@ -35,6 +35,7 @@ class RenderWidgetHostViewAndroid;
|
|||||||
class ContentViewCoreImpl : public ContentViewCore,
|
class ContentViewCoreImpl : public ContentViewCore,
|
||||||
public NotificationObserver {
|
public NotificationObserver {
|
||||||
public:
|
public:
|
||||||
|
static ContentViewCoreImpl* FromWebContents(WebContents* web_contents);
|
||||||
ContentViewCoreImpl(JNIEnv* env,
|
ContentViewCoreImpl(JNIEnv* env,
|
||||||
jobject obj,
|
jobject obj,
|
||||||
bool hardware_accelerated,
|
bool hardware_accelerated,
|
||||||
@ -42,7 +43,6 @@ class ContentViewCoreImpl : public ContentViewCore,
|
|||||||
ui::WindowAndroid* window_android);
|
ui::WindowAndroid* window_android);
|
||||||
|
|
||||||
// ContentViewCore implementation.
|
// ContentViewCore implementation.
|
||||||
virtual void Destroy(JNIEnv* env, jobject obj) OVERRIDE;
|
|
||||||
virtual base::android::ScopedJavaLocalRef<jobject> GetJavaObject() OVERRIDE;
|
virtual base::android::ScopedJavaLocalRef<jobject> GetJavaObject() OVERRIDE;
|
||||||
virtual WebContents* GetWebContents() const OVERRIDE;
|
virtual WebContents* GetWebContents() const OVERRIDE;
|
||||||
virtual ui::WindowAndroid* GetWindowAndroid() OVERRIDE;
|
virtual ui::WindowAndroid* GetWindowAndroid() OVERRIDE;
|
||||||
@ -55,6 +55,8 @@ class ContentViewCoreImpl : public ContentViewCore,
|
|||||||
// Methods called from Java via JNI
|
// Methods called from Java via JNI
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void OnJavaContentViewCoreDestroyed(JNIEnv* env, jobject obj);
|
||||||
|
|
||||||
// Notifies the ContentViewCore that items were selected in the currently
|
// Notifies the ContentViewCore that items were selected in the currently
|
||||||
// showing select popup.
|
// showing select popup.
|
||||||
void SelectPopupMenuItems(JNIEnv* env, jobject obj, jintArray indices);
|
void SelectPopupMenuItems(JNIEnv* env, jobject obj, jintArray indices);
|
||||||
@ -211,23 +213,22 @@ class ContentViewCoreImpl : public ContentViewCore,
|
|||||||
gfx::Rect GetBounds() const;
|
gfx::Rect GetBounds() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class ContentViewUserData;
|
||||||
|
friend class ContentViewUserData;
|
||||||
|
virtual ~ContentViewCoreImpl();
|
||||||
|
|
||||||
// NotificationObserver implementation.
|
// NotificationObserver implementation.
|
||||||
virtual void Observe(int type,
|
virtual void Observe(int type,
|
||||||
const NotificationSource& source,
|
const NotificationSource& source,
|
||||||
const NotificationDetails& details) OVERRIDE;
|
const NotificationDetails& details) OVERRIDE;
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
// Private methods that call to Java via JNI
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
virtual ~ContentViewCoreImpl();
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// Other private methods and data
|
// Other private methods and data
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
void InitJNI(JNIEnv* env, jobject obj);
|
void InitJNI(JNIEnv* env, jobject obj);
|
||||||
|
|
||||||
void InitWebContents(content::WebContents* web_contents);
|
void InitWebContents();
|
||||||
|
|
||||||
RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid();
|
RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid();
|
||||||
|
|
||||||
|
@ -40,7 +40,6 @@ import org.chromium.base.WeakContext;
|
|||||||
import org.chromium.content.app.AppResource;
|
import org.chromium.content.app.AppResource;
|
||||||
import org.chromium.content.browser.ContentViewGestureHandler.MotionEventDelegate;
|
import org.chromium.content.browser.ContentViewGestureHandler.MotionEventDelegate;
|
||||||
import org.chromium.content.browser.accessibility.AccessibilityInjector;
|
import org.chromium.content.browser.accessibility.AccessibilityInjector;
|
||||||
import org.chromium.content.common.CleanupReference;
|
|
||||||
import org.chromium.content.common.TraceEvent;
|
import org.chromium.content.common.TraceEvent;
|
||||||
import org.chromium.ui.gfx.NativeWindow;
|
import org.chromium.ui.gfx.NativeWindow;
|
||||||
|
|
||||||
@ -132,19 +131,6 @@ public class ContentViewCore implements MotionEventDelegate {
|
|||||||
boolean super_awakenScrollBars(int startDelay, boolean invalidate);
|
boolean super_awakenScrollBars(int startDelay, boolean invalidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class DestroyRunnable implements Runnable {
|
|
||||||
private final int mNativeContentViewCore;
|
|
||||||
private DestroyRunnable(int nativeContentViewCore) {
|
|
||||||
mNativeContentViewCore = nativeContentViewCore;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
nativeDestroy(mNativeContentViewCore);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private CleanupReference mCleanupReference;
|
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private ViewGroup mContainerView;
|
private ViewGroup mContainerView;
|
||||||
private InternalAccessDelegate mContainerViewInternals;
|
private InternalAccessDelegate mContainerViewInternals;
|
||||||
@ -450,8 +436,6 @@ public class ContentViewCore implements MotionEventDelegate {
|
|||||||
mContainerView = containerView;
|
mContainerView = containerView;
|
||||||
mNativeContentViewCore = nativeInit(mHardwareAccelerated, nativeWebContents,
|
mNativeContentViewCore = nativeInit(mHardwareAccelerated, nativeWebContents,
|
||||||
nativeWindow.getNativePointer());
|
nativeWindow.getNativePointer());
|
||||||
mCleanupReference = new CleanupReference(
|
|
||||||
this, new DestroyRunnable(mNativeContentViewCore));
|
|
||||||
mContentSettings = new ContentSettings(
|
mContentSettings = new ContentSettings(
|
||||||
this, mNativeContentViewCore, isAccessFromFileURLsGrantedByDefault);
|
this, mNativeContentViewCore, isAccessFromFileURLsGrantedByDefault);
|
||||||
initializeContainerView(internalDispatcher);
|
initializeContainerView(internalDispatcher);
|
||||||
@ -478,6 +462,12 @@ public class ContentViewCore implements MotionEventDelegate {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@CalledByNative
|
||||||
|
void onNativeContentViewCoreDestroyed(int nativeContentViewCore) {
|
||||||
|
assert nativeContentViewCore == mNativeContentViewCore;
|
||||||
|
mNativeContentViewCore = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the View that will contain all Views created by the ContentViewCore.
|
* Initializes the View that will contain all Views created by the ContentViewCore.
|
||||||
*
|
*
|
||||||
@ -566,7 +556,9 @@ public class ContentViewCore implements MotionEventDelegate {
|
|||||||
*/
|
*/
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
hidePopupDialog();
|
hidePopupDialog();
|
||||||
mCleanupReference.cleanupNow();
|
if (mNativeContentViewCore != 0) {
|
||||||
|
nativeOnJavaContentViewCoreDestroyed(mNativeContentViewCore);
|
||||||
|
}
|
||||||
mNativeContentViewCore = 0;
|
mNativeContentViewCore = 0;
|
||||||
// Do not propagate the destroy() to settings, as the client may still hold a reference to
|
// Do not propagate the destroy() to settings, as the client may still hold a reference to
|
||||||
// that and could still be using it.
|
// that and could still be using it.
|
||||||
@ -2082,7 +2074,7 @@ public class ContentViewCore implements MotionEventDelegate {
|
|||||||
private native int nativeInit(boolean hardwareAccelerated, int webContentsPtr,
|
private native int nativeInit(boolean hardwareAccelerated, int webContentsPtr,
|
||||||
int windowAndroidPtr);
|
int windowAndroidPtr);
|
||||||
|
|
||||||
private static native void nativeDestroy(int nativeContentViewCore);
|
private native void nativeOnJavaContentViewCoreDestroyed(int nativeContentViewCoreImpl);
|
||||||
|
|
||||||
private native void nativeLoadUrl(
|
private native void nativeLoadUrl(
|
||||||
int nativeContentViewCoreImpl,
|
int nativeContentViewCoreImpl,
|
||||||
|
@ -22,11 +22,10 @@ class WebContents;
|
|||||||
// public interface used by native code outside of the content module.
|
// public interface used by native code outside of the content module.
|
||||||
class ContentViewCore {
|
class ContentViewCore {
|
||||||
public:
|
public:
|
||||||
static ContentViewCore* Create(
|
// Returns the existing ContentViewCore for |web_contents|, or NULL.
|
||||||
JNIEnv* env, jobject obj, WebContents* web_contents);
|
static ContentViewCore* FromWebContents(WebContents* web_contents);
|
||||||
static ContentViewCore* GetNativeContentViewCore(JNIEnv* env, jobject obj);
|
static ContentViewCore* GetNativeContentViewCore(JNIEnv* env, jobject obj);
|
||||||
|
|
||||||
virtual void Destroy(JNIEnv* env, jobject obj) = 0;
|
|
||||||
virtual WebContents* GetWebContents() const = 0;
|
virtual WebContents* GetWebContents() const = 0;
|
||||||
virtual base::android::ScopedJavaLocalRef<jobject> GetJavaObject() = 0;
|
virtual base::android::ScopedJavaLocalRef<jobject> GetJavaObject() = 0;
|
||||||
virtual ui::WindowAndroid* GetWindowAndroid() = 0;
|
virtual ui::WindowAndroid* GetWindowAndroid() = 0;
|
||||||
|
Reference in New Issue
Block a user