Ensure the plugin's native code is never called with an invalid NPP pointer.

This commit is contained in:
Derek Sollenberger
2009-12-01 08:26:20 -05:00
parent e62ce17ac9
commit 51cce58c45
7 changed files with 78 additions and 3 deletions

View File

@@ -45,6 +45,27 @@ int SubPlugin::getPluginHeight() {
return obj->window->height; return obj->window->height;
} }
void SurfaceSubPlugin::setJavaInterface(jobject javaInterface) {
// if one exists then free its reference and notify the object that it is no
// longer attached to the native instance
JNIEnv* env = NULL;
if (m_javaInterface && gVM->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) {
// detach the native code from the object
jclass javaClass = env->GetObjectClass(m_javaInterface);
jmethodID invalMethod = env->GetMethodID(javaClass, "invalidateNPP", "()V");
env->CallVoidMethod(m_javaInterface, invalMethod);
// delete the reference
env->DeleteGlobalRef(m_javaInterface);
m_javaInterface = NULL;
}
//set the value
m_javaInterface = javaInterface;
}
static void pluginInvalidate(NPObject *obj); static void pluginInvalidate(NPObject *obj);
static bool pluginHasProperty(NPObject *obj, NPIdentifier name); static bool pluginHasProperty(NPObject *obj, NPIdentifier name);
static bool pluginHasMethod(NPObject *obj, NPIdentifier name); static bool pluginHasMethod(NPObject *obj, NPIdentifier name);

View File

@@ -61,6 +61,10 @@ public:
virtual void surfaceCreated(jobject) = 0; virtual void surfaceCreated(jobject) = 0;
virtual void surfaceChanged(int format, int width, int height) = 0; virtual void surfaceChanged(int format, int width, int height) = 0;
virtual void surfaceDestroyed() = 0; virtual void surfaceDestroyed() = 0;
void setJavaInterface(jobject);
jobject m_javaInterface;
}; };
enum PluginTypes { enum PluginTypes {

View File

@@ -40,6 +40,7 @@ extern ANPPaintInterfaceV0 gPaintI;
extern ANPSurfaceInterfaceV0 gSurfaceI; extern ANPSurfaceInterfaceV0 gSurfaceI;
extern ANPSystemInterfaceV0 gSystemI; extern ANPSystemInterfaceV0 gSystemI;
extern ANPTypefaceInterfaceV0 gTypefaceI; extern ANPTypefaceInterfaceV0 gTypefaceI;
extern ANPWindowInterfaceV0 gWindowI;
#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0])) #define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
@@ -53,6 +54,9 @@ static uint32_t getMSecs() {
BackgroundPlugin::BackgroundPlugin(NPP inst) : SurfaceSubPlugin(inst) { BackgroundPlugin::BackgroundPlugin(NPP inst) : SurfaceSubPlugin(inst) {
// initialize the java interface
m_javaInterface = NULL;
// initialize the drawing surface // initialize the drawing surface
m_surface = NULL; m_surface = NULL;
@@ -71,6 +75,7 @@ BackgroundPlugin::BackgroundPlugin(NPP inst) : SurfaceSubPlugin(inst) {
} }
BackgroundPlugin::~BackgroundPlugin() { BackgroundPlugin::~BackgroundPlugin() {
setJavaInterface(NULL);
surfaceDestroyed(); surfaceDestroyed();
} }

View File

@@ -33,6 +33,18 @@ static SurfaceSubPlugin* getPluginObject(int npp) {
return NULL; return NULL;
} }
static jboolean javaInit(JNIEnv* env, jobject thiz, jint npp) {
SurfaceSubPlugin* obj = getPluginObject(npp);
if (obj) {
jobject globalObject = env->NewGlobalRef(thiz);
obj->setJavaInterface(globalObject);
return true;
} else {
return false;
}
}
static void surfaceCreated(JNIEnv* env, jobject thiz, jint npp, jobject surface) { static void surfaceCreated(JNIEnv* env, jobject thiz, jint npp, jobject surface) {
SurfaceSubPlugin* obj = getPluginObject(npp); SurfaceSubPlugin* obj = getPluginObject(npp);
jobject globalSurface = env->NewGlobalRef(surface); jobject globalSurface = env->NewGlobalRef(surface);
@@ -70,6 +82,7 @@ static jboolean isFixedSurface(JNIEnv* env, jobject thiz, jint npp) {
* JNI registration. * JNI registration.
*/ */
static JNINativeMethod gJavaSamplePluginMethods[] = { static JNINativeMethod gJavaSamplePluginMethods[] = {
{ "nativeJavaInit", "(I)Z", (void*) javaInit },
{ "nativeSurfaceCreated", "(ILandroid/view/View;)V", (void*) surfaceCreated }, { "nativeSurfaceCreated", "(ILandroid/view/View;)V", (void*) surfaceCreated },
{ "nativeSurfaceChanged", "(IIII)V", (void*) surfaceChanged }, { "nativeSurfaceChanged", "(IIII)V", (void*) surfaceChanged },
{ "nativeSurfaceDestroyed", "(I)V", (void*) surfaceDestroyed }, { "nativeSurfaceDestroyed", "(I)V", (void*) surfaceDestroyed },

View File

@@ -50,6 +50,9 @@ PaintPlugin::PaintPlugin(NPP inst) : SurfaceSubPlugin(inst) {
memset(&m_colorToggle, 0, sizeof(m_colorToggle)); memset(&m_colorToggle, 0, sizeof(m_colorToggle));
memset(&m_clearSurface, 0, sizeof(m_clearSurface)); memset(&m_clearSurface, 0, sizeof(m_clearSurface));
// initialize the java interface
m_javaInterface = NULL;
// initialize the drawing surface // initialize the drawing surface
m_surface = NULL; m_surface = NULL;
@@ -85,6 +88,7 @@ PaintPlugin::~PaintPlugin() {
gPathI.deletePath(m_touchPath); gPathI.deletePath(m_touchPath);
gPaintI.deletePaint(m_paintSurface); gPaintI.deletePaint(m_paintSurface);
gPaintI.deletePaint(m_paintButton); gPaintI.deletePaint(m_paintButton);
setJavaInterface(NULL);
surfaceDestroyed(); surfaceDestroyed();
} }

View File

@@ -45,6 +45,9 @@ extern ANPWindowInterfaceV0 gWindowI;
VideoPlugin::VideoPlugin(NPP inst) : SurfaceSubPlugin(inst) { VideoPlugin::VideoPlugin(NPP inst) : SurfaceSubPlugin(inst) {
// initialize the java interface
m_javaInterface = NULL;
// initialize the drawing surface // initialize the drawing surface
m_surface = NULL; m_surface = NULL;
@@ -57,6 +60,7 @@ VideoPlugin::VideoPlugin(NPP inst) : SurfaceSubPlugin(inst) {
} }
VideoPlugin::~VideoPlugin() { VideoPlugin::~VideoPlugin() {
setJavaInterface(NULL);
surfaceDestroyed(); surfaceDestroyed();
} }

View File

@@ -51,9 +51,13 @@ public class SamplePlugin implements NativePlugin {
private int npp; private int npp;
private Context context; private Context context;
private boolean validNPP = false;
private Object nppLock = new Object();
public void initializePlugin(int npp, Context context) { public void initializePlugin(int npp, Context context) {
this.npp = npp; this.npp = npp;
this.context = context; this.context = context;
this.validNPP = nativeJavaInit(npp);
} }
public SurfaceDrawingModel getEmbeddedSurface() { public SurfaceDrawingModel getEmbeddedSurface() {
@@ -64,6 +68,14 @@ public class SamplePlugin implements NativePlugin {
return new FullScreenSurface(); return new FullScreenSurface();
} }
// called by JNI
private void invalidateNPP() {
synchronized (nppLock) {
validNPP = false;
}
}
private native boolean nativeJavaInit(int npp);
private native void nativeSurfaceCreated(int npp, View surfaceView); private native void nativeSurfaceCreated(int npp, View surfaceView);
private native void nativeSurfaceChanged(int npp, int format, int width, int height); private native void nativeSurfaceChanged(int npp, int format, int width, int height);
private native void nativeSurfaceDestroyed(int npp); private native void nativeSurfaceDestroyed(int npp);
@@ -85,16 +97,28 @@ public class SamplePlugin implements NativePlugin {
view.getHolder().addCallback(new Callback() { view.getHolder().addCallback(new Callback() {
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
synchronized (nppLock) {
if (validNPP) {
nativeSurfaceChanged(npp, format, width, height); nativeSurfaceChanged(npp, format, width, height);
} }
}
}
public void surfaceCreated(SurfaceHolder holder) { public void surfaceCreated(SurfaceHolder holder) {
synchronized (nppLock) {
if (validNPP) {
nativeSurfaceCreated(npp, view); nativeSurfaceCreated(npp, view);
} }
}
}
public void surfaceDestroyed(SurfaceHolder holder) { public void surfaceDestroyed(SurfaceHolder holder) {
synchronized (nppLock) {
if (validNPP) {
nativeSurfaceDestroyed(npp); nativeSurfaceDestroyed(npp);
} }
}
}
}); });
// TODO provide way for native plugin code to reset the size // TODO provide way for native plugin code to reset the size