mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Fixing bug 386773. Add implementation for NPN_PluginThreadAsyncCall(). r=joshmoz@gmail.com, sr=brendan@mozilla.org
This commit is contained in:
parent
fcde0538ee
commit
cfb5411441
@ -37,7 +37,7 @@
|
||||
|
||||
|
||||
/*
|
||||
* npapi.h $Revision: 3.45 $
|
||||
* npapi.h $Revision: 3.46 $
|
||||
* Netscape client plug-in API spec
|
||||
*/
|
||||
|
||||
@ -120,7 +120,7 @@
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#define NP_VERSION_MAJOR 0
|
||||
#define NP_VERSION_MINOR 18
|
||||
#define NP_VERSION_MINOR 19
|
||||
|
||||
|
||||
/* The OS/2 version of Netscape uses RC_DATA to define the
|
||||
@ -639,18 +639,19 @@ enum NPEventType {
|
||||
/*
|
||||
* Version feature information
|
||||
*/
|
||||
#define NPVERS_HAS_STREAMOUTPUT 8
|
||||
#define NPVERS_HAS_NOTIFICATION 9
|
||||
#define NPVERS_HAS_LIVECONNECT 9
|
||||
#define NPVERS_WIN16_HAS_LIVECONNECT 9
|
||||
#define NPVERS_68K_HAS_LIVECONNECT 11
|
||||
#define NPVERS_HAS_WINDOWLESS 11
|
||||
#define NPVERS_HAS_XPCONNECT_SCRIPTING 13
|
||||
#define NPVERS_HAS_NPRUNTIME_SCRIPTING 14
|
||||
#define NPVERS_HAS_FORM_VALUES 15
|
||||
#define NPVERS_HAS_POPUPS_ENABLED_STATE 16
|
||||
#define NPVERS_HAS_RESPONSE_HEADERS 17
|
||||
#define NPVERS_HAS_NPOBJECT_ENUM 18
|
||||
#define NPVERS_HAS_STREAMOUTPUT 8
|
||||
#define NPVERS_HAS_NOTIFICATION 9
|
||||
#define NPVERS_HAS_LIVECONNECT 9
|
||||
#define NPVERS_WIN16_HAS_LIVECONNECT 9
|
||||
#define NPVERS_68K_HAS_LIVECONNECT 11
|
||||
#define NPVERS_HAS_WINDOWLESS 11
|
||||
#define NPVERS_HAS_XPCONNECT_SCRIPTING 13
|
||||
#define NPVERS_HAS_NPRUNTIME_SCRIPTING 14
|
||||
#define NPVERS_HAS_FORM_VALUES 15
|
||||
#define NPVERS_HAS_POPUPS_ENABLED_STATE 16
|
||||
#define NPVERS_HAS_RESPONSE_HEADERS 17
|
||||
#define NPVERS_HAS_NPOBJECT_ENUM 18
|
||||
#define NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL 19
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Function Prototypes */
|
||||
@ -743,6 +744,9 @@ void NP_LOADDS NPN_InvalidateRegion(NPP instance, NPRegion invalidRegion);
|
||||
void NP_LOADDS NPN_ForceRedraw(NPP instance);
|
||||
void NP_LOADDS NPN_PushPopupsEnabledState(NPP instance, NPBool enabled);
|
||||
void NP_LOADDS NPN_PopPopupsEnabledState(NPP instance);
|
||||
void NP_LOADDS NPN_PluginThreadAsyncCall(NPP instance,
|
||||
void (*func) (void *),
|
||||
void *userData);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
|
||||
/*
|
||||
* npupp.h $Revision: 3.24 $
|
||||
* npupp.h $Revision: 3.25 $
|
||||
* function call mecahnics needed by platform specific glue code.
|
||||
*/
|
||||
|
||||
@ -484,6 +484,13 @@ typedef bool (* NP_LOADDS NPN_EnumerateUPP)(NPP npp, NPObject *obj, NPIdentifier
|
||||
#define CallNPN_EnumerateProc(FUNC, ARG1, ARG2, ARG3, ARG4) \
|
||||
(*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4))
|
||||
|
||||
/* NPN_Enumerate */
|
||||
typedef void (* NP_LOADDS NPN_PluginThreadAsyncCallUPP)(NPP instance, void (*func)(void *), void *userData);
|
||||
#define NewNPN_PluginThreadAsyncCallProc(FUNC) \
|
||||
((NPN_PluginThreadAsyncCallUPP) (FUNC))
|
||||
#define CallNPN_PluginThreadAsyncCallProc(FUNC, ARG1, ARG2, ARG3) \
|
||||
(*(FUNC))((ARG1), (ARG2), (ARG3))
|
||||
|
||||
|
||||
/******************************************************************************************
|
||||
* The actual plugin function table definitions
|
||||
@ -554,6 +561,7 @@ typedef struct _NPNetscapeFuncs {
|
||||
NPN_PushPopupsEnabledStateUPP pushpopupsenabledstate;
|
||||
NPN_PopPopupsEnabledStateUPP poppopupsenabledstate;
|
||||
NPN_EnumerateUPP enumerate;
|
||||
NPN_PluginThreadAsyncCallUPP pluginthreadasynccall;
|
||||
} NPNetscapeFuncs;
|
||||
|
||||
|
||||
|
@ -40,10 +40,13 @@
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "prmem.h"
|
||||
#include "prclist.h"
|
||||
#include "nsAutoLock.h"
|
||||
#include "ns4xPlugin.h"
|
||||
#include "ns4xPluginInstance.h"
|
||||
#include "ns4xPluginStreamListener.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "nsIMemory.h"
|
||||
#include "nsIPluginStreamListener.h"
|
||||
@ -82,6 +85,9 @@
|
||||
|
||||
#include "nsJSNPRuntime.h"
|
||||
|
||||
static PRLock *sPluginThreadAsyncCallLock = nsnull;
|
||||
static PRCList sPendingAsyncCalls = PR_INIT_STATIC_CLIST(&sPendingAsyncCalls);
|
||||
|
||||
// POST/GET stream type
|
||||
enum eNPPStreamTypeInternal {
|
||||
eNPPStreamTypeInternal_Get,
|
||||
@ -160,6 +166,9 @@ PR_BEGIN_EXTERN_C
|
||||
static void NP_CALLBACK
|
||||
_poppopupsenabledstate(NPP npp);
|
||||
|
||||
static void NP_CALLBACK
|
||||
_pluginthreadasynccall(NPP instance, void (*func)(void *), void *userData);
|
||||
|
||||
static const char* NP_CALLBACK
|
||||
_useragent(NPP npp);
|
||||
|
||||
@ -375,6 +384,14 @@ ns4xPlugin::CheckClassInitialized(void)
|
||||
CALLBACKS.poppopupsenabledstate =
|
||||
NewNPN_PopPopupsEnabledStateProc(FP2TV(_poppopupsenabledstate));
|
||||
|
||||
CALLBACKS.pluginthreadasynccall =
|
||||
NewNPN_PluginThreadAsyncCallProc(FP2TV(_pluginthreadasynccall));
|
||||
|
||||
if (!sPluginThreadAsyncCallLock) {
|
||||
sPluginThreadAsyncCallLock =
|
||||
nsAutoLock::NewLock("sPluginThreadAsyncCallLock");
|
||||
}
|
||||
|
||||
initialized = TRUE;
|
||||
|
||||
NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,("NPN callbacks initialized\n"));
|
||||
@ -2185,4 +2202,151 @@ _poppopupsenabledstate(NPP npp)
|
||||
inst->PopPopupsEnabledState();
|
||||
}
|
||||
|
||||
class nsPluginThreadRunnable : public nsRunnable,
|
||||
public PRCList
|
||||
{
|
||||
public:
|
||||
nsPluginThreadRunnable(NPP instance, void (*func)(void *), void *userData);
|
||||
virtual ~nsPluginThreadRunnable();
|
||||
|
||||
NS_IMETHOD Run();
|
||||
|
||||
PRBool IsForInstance(NPP instance)
|
||||
{
|
||||
return (mInstance == instance);
|
||||
}
|
||||
|
||||
void Invalidate()
|
||||
{
|
||||
mFunc = nsnull;
|
||||
}
|
||||
|
||||
PRBool IsValid()
|
||||
{
|
||||
return (mFunc != nsnull);
|
||||
}
|
||||
|
||||
private:
|
||||
NPP mInstance;
|
||||
void (*mFunc)(void *);
|
||||
void *mUserData;
|
||||
};
|
||||
|
||||
nsPluginThreadRunnable::nsPluginThreadRunnable(NPP instance,
|
||||
void (*func)(void *),
|
||||
void *userData)
|
||||
: mInstance(instance), mFunc(func), mUserData(userData)
|
||||
{
|
||||
if (!sPluginThreadAsyncCallLock) {
|
||||
// Failed to create lock, not much we can do here then...
|
||||
mFunc = nsnull;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
PR_INIT_CLIST(this);
|
||||
|
||||
{
|
||||
nsAutoLock lock(sPluginThreadAsyncCallLock);
|
||||
|
||||
ns4xPluginInstance *inst = (ns4xPluginInstance *)instance->ndata;
|
||||
if (!inst || !inst->IsStarted()) {
|
||||
// The plugin was stopped, ignore this async call.
|
||||
mFunc = nsnull;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
PR_APPEND_LINK(this, &sPendingAsyncCalls);
|
||||
}
|
||||
}
|
||||
|
||||
nsPluginThreadRunnable::~nsPluginThreadRunnable()
|
||||
{
|
||||
if (!sPluginThreadAsyncCallLock) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
nsAutoLock lock(sPluginThreadAsyncCallLock);
|
||||
|
||||
PR_REMOVE_LINK(this);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginThreadRunnable::Run()
|
||||
{
|
||||
if (mFunc) {
|
||||
NS_TRY_SAFE_CALL_VOID(mFunc(mUserData), nsnull, nsnull);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void NP_CALLBACK
|
||||
_pluginthreadasynccall(NPP instance, void (*func)(void *), void *userData)
|
||||
{
|
||||
nsRefPtr<nsPluginThreadRunnable> evt =
|
||||
new nsPluginThreadRunnable(instance, func, userData);
|
||||
|
||||
if (evt && evt->IsValid()) {
|
||||
NS_DispatchToMainThread(evt);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OnPluginDestroy(NPP instance)
|
||||
{
|
||||
if (!sPluginThreadAsyncCallLock) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
nsAutoLock lock(sPluginThreadAsyncCallLock);
|
||||
|
||||
if (PR_CLIST_IS_EMPTY(&sPendingAsyncCalls)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsPluginThreadRunnable *r =
|
||||
(nsPluginThreadRunnable *)PR_LIST_HEAD(&sPendingAsyncCalls);
|
||||
|
||||
do {
|
||||
if (r->IsForInstance(instance)) {
|
||||
r->Invalidate();
|
||||
}
|
||||
|
||||
r = (nsPluginThreadRunnable *)PR_NEXT_LINK(r);
|
||||
} while (r != &sPendingAsyncCalls);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OnShutdown()
|
||||
{
|
||||
NS_ASSERTION(PR_CLIST_IS_EMPTY(&sPendingAsyncCalls),
|
||||
"Pending async plugin call list not cleaned up!");
|
||||
|
||||
if (sPluginThreadAsyncCallLock) {
|
||||
nsAutoLock::DestroyLock(sPluginThreadAsyncCallLock);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EnterAsyncPluginThreadCallLock()
|
||||
{
|
||||
if (sPluginThreadAsyncCallLock) {
|
||||
PR_Lock(sPluginThreadAsyncCallLock);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ExitAsyncPluginThreadCallLock()
|
||||
{
|
||||
if (sPluginThreadAsyncCallLock) {
|
||||
PR_Unlock(sPluginThreadAsyncCallLock);
|
||||
}
|
||||
}
|
||||
|
||||
NPP NPPStack::sCurrentNPP = nsnull;
|
||||
|
@ -253,6 +253,17 @@ PeekException();
|
||||
void
|
||||
PopException();
|
||||
|
||||
void
|
||||
OnPluginDestroy(NPP instance);
|
||||
|
||||
void
|
||||
OnShutdown();
|
||||
|
||||
void
|
||||
EnterAsyncPluginThreadCallLock();
|
||||
void
|
||||
ExitAsyncPluginThreadCallLock();
|
||||
|
||||
class NPPStack
|
||||
{
|
||||
public:
|
||||
|
@ -869,8 +869,8 @@ NS_IMETHODIMP ns4xPluginInstance::Start(void)
|
||||
|
||||
if(mStarted)
|
||||
return NS_OK;
|
||||
else
|
||||
return InitializePlugin(mPeer);
|
||||
|
||||
return InitializePlugin(mPeer);
|
||||
}
|
||||
|
||||
|
||||
@ -900,6 +900,14 @@ NS_IMETHODIMP ns4xPluginInstance::Stop(void)
|
||||
if(!mStarted)
|
||||
return NS_OK;
|
||||
|
||||
// Make sure we lock while we're writing to mStarted after we've
|
||||
// started as other threads might be checking that inside a lock.
|
||||
EnterAsyncPluginThreadCallLock();
|
||||
mStarted = PR_FALSE;
|
||||
ExitAsyncPluginThreadCallLock();
|
||||
|
||||
OnPluginDestroy(&fNPP);
|
||||
|
||||
if (fCallbacks->destroy == NULL)
|
||||
return NS_ERROR_FAILURE; // XXX right error?
|
||||
|
||||
@ -925,8 +933,6 @@ NS_IMETHODIMP ns4xPluginInstance::Stop(void)
|
||||
NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("NPP Destroy called: this=%p, npp=%p, return=%d\n", this, &fNPP, error));
|
||||
|
||||
mStarted = PR_FALSE;
|
||||
|
||||
nsJSNPRuntime::OnPluginDestroy(&fNPP);
|
||||
|
||||
if(error != NPERR_NO_ERROR)
|
||||
|
@ -6355,6 +6355,7 @@ NS_IMETHODIMP nsPluginHostImpl::Observe(nsISupports *aSubject,
|
||||
{
|
||||
if (!nsCRT::strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, aTopic))
|
||||
{
|
||||
OnShutdown();
|
||||
Destroy();
|
||||
UnloadUnusedLibraries();
|
||||
sInst->Release();
|
||||
|
Loading…
Reference in New Issue
Block a user