bug 702334 - Fix deadlocks caused by Flash r=blassey

This commit is contained in:
James Willcox 2011-11-15 10:43:42 -05:00
parent 24855641ec
commit 08e4124e5c
5 changed files with 97 additions and 113 deletions

View File

@ -735,40 +735,25 @@ void nsNPAPIPluginInstance::SetDrawingModel(PRUint32 aModel)
{
mDrawingModel = aModel;
}
class SurfaceGetter : public nsRunnable {
public:
SurfaceGetter(NPPluginFuncs* aPluginFunctions, NPP_t aNPP) :
mHaveSurface(false), mPluginFunctions(aPluginFunctions), mNPP(aNPP) {
mLock = new Mutex("SurfaceGetter::Lock");
mCondVar = new CondVar(*mLock, "SurfaceGetter::CondVar");
SurfaceGetter(nsNPAPIPluginInstance* aInstance, NPPluginFuncs* aPluginFunctions, NPP_t aNPP) :
mInstance(aInstance), mPluginFunctions(aPluginFunctions), mNPP(aNPP) {
}
~SurfaceGetter() {
delete mLock;
delete mCondVar;
}
nsresult Run() {
MutexAutoLock lock(*mLock);
(*mPluginFunctions->getvalue)(&mNPP, kJavaSurface_ANPGetValue, &mSurface);
mHaveSurface = true;
mCondVar->Notify();
void* surface;
(*mPluginFunctions->getvalue)(&mNPP, kJavaSurface_ANPGetValue, &surface);
mInstance->SetJavaSurface(surface);
return NS_OK;
}
void* GetSurface() {
MutexAutoLock lock(*mLock);
mHaveSurface = false;
AndroidBridge::Bridge()->PostToJavaThread(this);
while (!mHaveSurface)
mCondVar->Wait();
return mSurface;
void RequestSurface() {
mozilla::AndroidBridge::Bridge()->PostToJavaThread(this);
}
private:
nsNPAPIPluginInstance* mInstance;
NPP_t mNPP;
void* mSurface;
Mutex* mLock;
CondVar* mCondVar;
bool mHaveSurface;
NPPluginFuncs* mPluginFunctions;
};
@ -778,14 +763,24 @@ void* nsNPAPIPluginInstance::GetJavaSurface()
if (mDrawingModel != kSurface_ANPDrawingModel)
return nsnull;
if (mSurface)
return mSurface;
nsCOMPtr<SurfaceGetter> sg = new SurfaceGetter(mPlugin->PluginFuncs(), mNPP);
mSurface = sg->GetSurface();
return mSurface;
}
void nsNPAPIPluginInstance::SetJavaSurface(void* aSurface)
{
mSurface = aSurface;
}
void nsNPAPIPluginInstance::RequestJavaSurface()
{
if (mSurfaceGetter.get())
return;
mSurfaceGetter = new SurfaceGetter(this, mPlugin->PluginFuncs(), mNPP);
((SurfaceGetter*)mSurfaceGetter.get())->RequestSurface();
}
#endif
nsresult nsNPAPIPluginInstance::GetDrawingModel(PRInt32* aModel)

View File

@ -49,6 +49,9 @@
#include "nsIChannel.h"
#include "nsInterfaceHashtable.h"
#include "nsHashKeys.h"
#ifdef MOZ_WIDGET_ANDROID
#include "nsIRunnable.h"
#endif
#include "mozilla/TimeStamp.h"
#include "mozilla/PluginLibrary.h"
@ -149,6 +152,8 @@ public:
#ifdef MOZ_WIDGET_ANDROID
void SetDrawingModel(PRUint32 aModel);
void* GetJavaSurface();
void SetJavaSurface(void* aSurface);
void RequestJavaSurface();
#endif
nsresult NewStreamListener(const char* aURL, void* notifyData,
@ -225,6 +230,7 @@ protected:
#ifdef MOZ_WIDGET_ANDROID
PRUint32 mDrawingModel;
nsCOMPtr<nsIRunnable> mSurfaceGetter;
#endif
enum {

View File

@ -331,6 +331,11 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
#endif
mWaitingForPaint = false;
#ifdef MOZ_WIDGET_ANDROID
mPluginViewAdded = false;
mLastPluginRect = gfxRect(0, 0, 0, 0);
#endif
}
nsPluginInstanceOwner::~nsPluginInstanceOwner()
@ -1673,9 +1678,53 @@ void nsPluginInstanceOwner::ScrollPositionDidChange(nscoord aX, nscoord aY)
}
#ifdef MOZ_WIDGET_ANDROID
void nsPluginInstanceOwner::AddPluginView(const gfxRect& aRect)
{
AndroidBridge::AutoLocalJNIFrame frame(1);
void* javaSurface = mInstance->GetJavaSurface();
if (!javaSurface) {
mInstance->RequestJavaSurface();
return;
}
if (aRect.IsEqualEdges(mLastPluginRect)) {
// Already added and in position, no work to do
return;
}
JNIEnv* env = GetJNIForThread();
jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell");
jmethodID method = env->GetStaticMethodID(cls,
"addPluginView",
"(Landroid/view/View;DDDD)V");
env->CallStaticVoidMethod(cls,
method,
javaSurface,
aRect.x,
aRect.y,
aRect.width,
aRect.height);
if (!mPluginViewAdded) {
ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = kLifecycle_ANPEventType;
event.data.lifecycle.action = kOnScreen_ANPLifecycleAction;
mInstance->HandleEvent(&event, nsnull);
mPluginViewAdded = true;
}
}
void nsPluginInstanceOwner::RemovePluginView()
{
if (mInstance && mObjectFrame) {
AndroidBridge::AutoLocalJNIFrame frame(1);
if (mInstance && mObjectFrame && mPluginViewAdded) {
mPluginViewAdded = false;
void* surface = mInstance->GetJavaSurface();
if (surface) {
JNIEnv* env = GetJNIForThread();
@ -1685,6 +1734,14 @@ void nsPluginInstanceOwner::RemovePluginView()
"removePluginView",
"(Landroid/view/View;)V");
env->CallStaticVoidMethod(cls, method, surface);
{
ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = kLifecycle_ANPEventType;
event.data.lifecycle.action = kOffScreen_ANPLifecycleAction;
mInstance->HandleEvent(&event, nsnull);
}
}
}
}
@ -2814,45 +2871,6 @@ void nsPluginInstanceOwner::Paint(const nsRect& aDirtyRect, HPS aHPS)
#ifdef MOZ_WIDGET_ANDROID
class AndroidPaintEventRunnable : public nsRunnable
{
public:
AndroidPaintEventRunnable(void* aSurface, nsNPAPIPluginInstance* inst, const gfxRect& aFrameRect)
: mSurface(aSurface), mInstance(inst), mFrameRect(aFrameRect) {
}
~AndroidPaintEventRunnable() {
}
NS_IMETHOD Run()
{
LOG("%p - AndroidPaintEventRunnable::Run\n", this);
if (!mInstance || !mSurface)
return NS_OK;
// This needs to happen on the gecko main thread.
JNIEnv* env = GetJNIForThread();
jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell");
jmethodID method = env->GetStaticMethodID(cls,
"addPluginView",
"(Landroid/view/View;DDDD)V");
env->CallStaticVoidMethod(cls,
method,
mSurface,
mFrameRect.x,
mFrameRect.y,
mFrameRect.width,
mFrameRect.height);
return NS_OK;
}
private:
void* mSurface;
nsCOMPtr<nsNPAPIPluginInstance> mInstance;
gfxRect mFrameRect;
};
void nsPluginInstanceOwner::Paint(gfxContext* aContext,
const gfxRect& aFrameRect,
const gfxRect& aDirtyRect)
@ -2864,33 +2882,7 @@ void nsPluginInstanceOwner::Paint(gfxContext* aContext,
mInstance->GetDrawingModel(&model);
if (model == kSurface_ANPDrawingModel) {
{
ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = kLifecycle_ANPEventType;
event.data.lifecycle.action = kOnScreen_ANPLifecycleAction;
mInstance->HandleEvent(&event, nsnull);
}
/*
gfxMatrix currentMatrix = aContext->CurrentMatrix();
gfxSize scale = currentMatrix.ScaleFactors(true);
printf_stderr("!!!!!!!! scale!!: %f x %f\n", scale.width, scale.height);
*/
JNIEnv* env = GetJNIForThread();
jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell");
jmethodID method = env->GetStaticMethodID(cls,
"addPluginView",
"(Landroid/view/View;DDDD)V");
env->CallStaticVoidMethod(cls,
method,
mInstance->GetJavaSurface(),
aFrameRect.x,
aFrameRect.y,
aFrameRect.width,
aFrameRect.height);
AddPluginView(aFrameRect);
return;
}
@ -3587,26 +3579,10 @@ void nsPluginInstanceOwner::UpdateWindowPositionAndClipRect(bool aSetWindow)
if (mPluginWindowVisible && mPluginDocumentActiveState) {
mPluginWindow->clipRect.right = mPluginWindow->width;
mPluginWindow->clipRect.bottom = mPluginWindow->height;
#ifdef MOZ_WIDGET_ANDROID
if (mInstance) {
ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = kLifecycle_ANPEventType;
event.data.lifecycle.action = kOnScreen_ANPLifecycleAction;
mInstance->HandleEvent(&event, nsnull);
}
#endif
} else {
mPluginWindow->clipRect.right = 0;
mPluginWindow->clipRect.bottom = 0;
#ifdef MOZ_WIDGET_ANDROID
if (mInstance) {
ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = kLifecycle_ANPEventType;
event.data.lifecycle.action = kOffScreen_ANPLifecycleAction;
mInstance->HandleEvent(&event, nsnull);
}
RemovePluginView();
#endif
}

View File

@ -310,7 +310,10 @@ private:
void FixUpURLS(const nsString &name, nsAString &value);
#ifdef ANDROID
void AddPluginView(const gfxRect& aRect);
void RemovePluginView();
bool mPluginViewAdded;
gfxRect mLastPluginRect;
#endif
nsPluginNativeWindow *mPluginWindow;

View File

@ -953,8 +953,12 @@ abstract public class GeckoApp
if (mGeckoLayout.indexOfChild(view) == -1) {
view.setWillNotDraw(false);
if (view instanceof SurfaceView)
((SurfaceView)view).setZOrderOnTop(true);
if (view instanceof SurfaceView) {
SurfaceView sview = (SurfaceView)view;
sview.setZOrderOnTop(false);
sview.setZOrderMediaOverlay(true);
}
mGeckoLayout.addView(view, lp);
} else {