mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 641685 - Make plugin object map a singleton in the plugin process (r=bsmedberg)
This patches moves the object map (which tracks the PluginScriptableObjectChild and PluginInstanceChild for a given NPObject) from the PluginModuleChild to a global variable. This change prepares the way for having multiple PluginModuleChild instances in a given plugin process.
This commit is contained in:
parent
b51bf9c156
commit
652d9ae8c5
@ -2393,7 +2393,7 @@ PluginInstanceChild::GetActorForNPObject(NPObject* aObject)
|
||||
}
|
||||
|
||||
PluginScriptableObjectChild* actor =
|
||||
PluginModuleChild::current()->GetActorForNPObject(aObject);
|
||||
PluginScriptableObjectChild::GetActorForNPObject(aObject);
|
||||
if (actor) {
|
||||
// Plugin-provided object that we've previously wrapped.
|
||||
return actor;
|
||||
@ -3729,7 +3729,7 @@ PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
|
||||
ClearAllSurfaces();
|
||||
|
||||
mDeletingHash = new nsTHashtable<DeletingObjectEntry>;
|
||||
PluginModuleChild::current()->FindNPObjectsForInstance(this);
|
||||
PluginScriptableObjectChild::NotifyOfInstanceShutdown(this);
|
||||
|
||||
mDeletingHash->EnumerateEntries(InvalidateObject, nullptr);
|
||||
mDeletingHash->EnumerateEntries(DeleteObject, nullptr);
|
||||
|
@ -55,7 +55,8 @@ class PluginInstanceChild : public PPluginInstanceChild
|
||||
{
|
||||
friend class BrowserStreamChild;
|
||||
friend class PluginStreamChild;
|
||||
friend class StreamNotifyChild;
|
||||
friend class StreamNotifyChild;
|
||||
friend class PluginScriptableObjectChild;
|
||||
|
||||
#ifdef OS_WIN
|
||||
friend LRESULT CALLBACK PluginWindowProc(HWND hWnd,
|
||||
|
@ -732,59 +732,6 @@ PluginModuleChild::GetUserAgent()
|
||||
return NullableStringGet(mUserAgent);
|
||||
}
|
||||
|
||||
bool
|
||||
PluginModuleChild::RegisterActorForNPObject(NPObject* aObject,
|
||||
PluginScriptableObjectChild* aActor)
|
||||
{
|
||||
AssertPluginThread();
|
||||
NS_ASSERTION(aObject && aActor, "Null pointer!");
|
||||
|
||||
NPObjectData* d = mObjectMap.GetEntry(aObject);
|
||||
if (!d) {
|
||||
NS_ERROR("NPObject not in object table");
|
||||
return false;
|
||||
}
|
||||
|
||||
d->actor = aActor;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PluginModuleChild::UnregisterActorForNPObject(NPObject* aObject)
|
||||
{
|
||||
AssertPluginThread();
|
||||
NS_ASSERTION(aObject, "Null pointer!");
|
||||
|
||||
NPObjectData* d = mObjectMap.GetEntry(aObject);
|
||||
NS_ASSERTION(d, "NPObject not in object table");
|
||||
if (d) {
|
||||
d->actor = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PluginScriptableObjectChild*
|
||||
PluginModuleChild::GetActorForNPObject(NPObject* aObject)
|
||||
{
|
||||
AssertPluginThread();
|
||||
NS_ASSERTION(aObject, "Null pointer!");
|
||||
|
||||
NPObjectData* d = mObjectMap.GetEntry(aObject);
|
||||
if (!d) {
|
||||
NS_ERROR("Plugin using object not created with NPN_CreateObject?");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return d->actor;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool
|
||||
PluginModuleChild::NPObjectIsRegistered(NPObject* aObject)
|
||||
{
|
||||
return !!mObjectMap.GetEntry(aObject);
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FIXME/cjones: just getting this out of the way for the moment ...
|
||||
|
||||
@ -1549,7 +1496,7 @@ _setexception(NPObject* aNPObj,
|
||||
PluginModuleChild* self = PluginModuleChild::current();
|
||||
PluginScriptableObjectChild* actor = nullptr;
|
||||
if (aNPObj) {
|
||||
actor = self->GetActorForNPObject(aNPObj);
|
||||
actor = PluginScriptableObjectChild::GetActorForNPObject(aNPObj);
|
||||
if (!actor) {
|
||||
NS_ERROR("Failed to get actor!");
|
||||
return;
|
||||
@ -2050,10 +1997,7 @@ PluginModuleChild::NPN_CreateObject(NPP aNPP, NPClass* aClass)
|
||||
NS_LOG_ADDREF(newObject, 1, "NPObject", sizeof(NPObject));
|
||||
}
|
||||
|
||||
NPObjectData* d = static_cast<PluginModuleChild*>(i->Manager())
|
||||
->mObjectMap.PutEntry(newObject);
|
||||
NS_ASSERTION(!d->instance, "New NPObject already mapped?");
|
||||
d->instance = i;
|
||||
PluginScriptableObjectChild::RegisterObject(newObject, i);
|
||||
|
||||
return newObject;
|
||||
}
|
||||
@ -2077,15 +2021,15 @@ PluginModuleChild::NPN_ReleaseObject(NPObject* aNPObj)
|
||||
{
|
||||
AssertPluginThread();
|
||||
|
||||
NPObjectData* d = current()->mObjectMap.GetEntry(aNPObj);
|
||||
if (!d) {
|
||||
PluginInstanceChild* instance = PluginScriptableObjectChild::GetInstanceForNPObject(aNPObj);
|
||||
if (!instance) {
|
||||
NS_ERROR("Releasing object not in mObjectMap?");
|
||||
return;
|
||||
}
|
||||
|
||||
DeletingObjectEntry* doe = nullptr;
|
||||
if (d->instance->mDeletingHash) {
|
||||
doe = d->instance->mDeletingHash->GetEntry(aNPObj);
|
||||
if (instance->mDeletingHash) {
|
||||
doe = instance->mDeletingHash->GetEntry(aNPObj);
|
||||
if (!doe) {
|
||||
NS_ERROR("An object for a destroyed instance isn't in the instance deletion hash");
|
||||
return;
|
||||
@ -2114,29 +2058,11 @@ PluginModuleChild::DeallocNPObject(NPObject* aNPObj)
|
||||
child::_memfree(aNPObj);
|
||||
}
|
||||
|
||||
NPObjectData* d = current()->mObjectMap.GetEntry(aNPObj);
|
||||
if (d->actor)
|
||||
d->actor->NPObjectDestroyed();
|
||||
PluginScriptableObjectChild* actor = PluginScriptableObjectChild::GetActorForNPObject(aNPObj);
|
||||
if (actor)
|
||||
actor->NPObjectDestroyed();
|
||||
|
||||
current()->mObjectMap.RemoveEntry(aNPObj);
|
||||
}
|
||||
|
||||
void
|
||||
PluginModuleChild::FindNPObjectsForInstance(PluginInstanceChild* instance)
|
||||
{
|
||||
NS_ASSERTION(instance->mDeletingHash, "filling null mDeletingHash?");
|
||||
mObjectMap.EnumerateEntries(CollectForInstance, instance);
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
PluginModuleChild::CollectForInstance(NPObjectData* d, void* userArg)
|
||||
{
|
||||
PluginInstanceChild* instance = static_cast<PluginInstanceChild*>(userArg);
|
||||
if (d->instance == instance) {
|
||||
NPObject* o = d->GetKey();
|
||||
instance->mDeletingHash->PutEntry(o);
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
PluginScriptableObjectChild::UnregisterObject(aNPObj);
|
||||
}
|
||||
|
||||
NPIdentifier
|
||||
|
@ -157,17 +157,6 @@ public:
|
||||
|
||||
static PluginModuleChild* current();
|
||||
|
||||
bool RegisterActorForNPObject(NPObject* aObject,
|
||||
PluginScriptableObjectChild* aActor);
|
||||
|
||||
void UnregisterActorForNPObject(NPObject* aObject);
|
||||
|
||||
PluginScriptableObjectChild* GetActorForNPObject(NPObject* aObject);
|
||||
|
||||
#ifdef DEBUG
|
||||
bool NPObjectIsRegistered(NPObject* aObject);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The child implementation of NPN_CreateObject.
|
||||
*/
|
||||
@ -353,26 +342,6 @@ private:
|
||||
NestedLoopTimer *mNestedLoopTimerObject;
|
||||
#endif
|
||||
|
||||
struct NPObjectData : public nsPtrHashKey<NPObject>
|
||||
{
|
||||
explicit NPObjectData(const NPObject* key)
|
||||
: nsPtrHashKey<NPObject>(key)
|
||||
, instance(nullptr)
|
||||
, actor(nullptr)
|
||||
{ }
|
||||
|
||||
// never nullptr
|
||||
PluginInstanceChild* instance;
|
||||
|
||||
// sometimes nullptr (no actor associated with an NPObject)
|
||||
PluginScriptableObjectChild* actor;
|
||||
};
|
||||
/**
|
||||
* mObjectMap contains all the currently active NPObjects (from NPN_CreateObject until the
|
||||
* final release/dealloc, whether or not an actor is currently associated with the object.
|
||||
*/
|
||||
nsTHashtable<NPObjectData> mObjectMap;
|
||||
|
||||
public: // called by PluginInstanceChild
|
||||
/**
|
||||
* Dealloc an NPObject after last-release or when the associated instance
|
||||
@ -384,15 +353,7 @@ public: // called by PluginInstanceChild
|
||||
return mFunctions.destroy(instance->GetNPP(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill PluginInstanceChild.mDeletingHash with all the remaining NPObjects
|
||||
* associated with that instance.
|
||||
*/
|
||||
void FindNPObjectsForInstance(PluginInstanceChild* instance);
|
||||
|
||||
private:
|
||||
static PLDHashOperator CollectForInstance(NPObjectData* d, void* userArg);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
virtual void EnteredCall() MOZ_OVERRIDE;
|
||||
virtual void ExitedCall() MOZ_OVERRIDE;
|
||||
|
@ -539,7 +539,7 @@ PluginScriptableObjectChild::~PluginScriptableObjectChild()
|
||||
AssertPluginThread();
|
||||
|
||||
if (mObject) {
|
||||
PluginModuleChild::current()->UnregisterActorForNPObject(mObject);
|
||||
UnregisterActor(mObject);
|
||||
|
||||
if (mObject->_class == GetClass()) {
|
||||
NS_ASSERTION(mType == Proxy, "Wrong type!");
|
||||
@ -569,8 +569,8 @@ PluginScriptableObjectChild::InitializeProxy()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!PluginModuleChild::current()->RegisterActorForNPObject(object, this)) {
|
||||
NS_ERROR("RegisterActorForNPObject failed");
|
||||
if (!RegisterActor(object)) {
|
||||
NS_ERROR("RegisterActor failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -594,8 +594,8 @@ PluginScriptableObjectChild::InitializeLocal(NPObject* aObject)
|
||||
NS_ASSERTION(!mProtectCount, "Should be zero!");
|
||||
mProtectCount++;
|
||||
|
||||
if (!PluginModuleChild::current()->RegisterActorForNPObject(aObject, this)) {
|
||||
NS_ERROR("RegisterActorForNPObject failed");
|
||||
if (!RegisterActor(aObject)) {
|
||||
NS_ERROR("RegisterActor failed");
|
||||
}
|
||||
|
||||
mObject = aObject;
|
||||
@ -688,7 +688,7 @@ PluginScriptableObjectChild::DropNPObject()
|
||||
|
||||
// We think we're about to be deleted, but we could be racing with the other
|
||||
// process.
|
||||
PluginModuleChild::current()->UnregisterActorForNPObject(mObject);
|
||||
UnregisterActor(mObject);
|
||||
mObject = nullptr;
|
||||
|
||||
SendUnprotect();
|
||||
@ -1181,3 +1181,105 @@ PluginScriptableObjectChild::Evaluate(NPString* aScript,
|
||||
ConvertToVariant(result, *aResult);
|
||||
return true;
|
||||
}
|
||||
|
||||
nsTHashtable<PluginScriptableObjectChild::NPObjectData>* PluginScriptableObjectChild::sObjectMap;
|
||||
|
||||
bool
|
||||
PluginScriptableObjectChild::RegisterActor(NPObject* aObject)
|
||||
{
|
||||
AssertPluginThread();
|
||||
MOZ_ASSERT(aObject, "Null pointer!");
|
||||
|
||||
NPObjectData* d = sObjectMap->GetEntry(aObject);
|
||||
if (!d) {
|
||||
NS_ERROR("NPObject not in object table");
|
||||
return false;
|
||||
}
|
||||
|
||||
d->actor = this;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PluginScriptableObjectChild::UnregisterActor(NPObject* aObject)
|
||||
{
|
||||
AssertPluginThread();
|
||||
MOZ_ASSERT(aObject, "Null pointer!");
|
||||
|
||||
NPObjectData* d = sObjectMap->GetEntry(aObject);
|
||||
MOZ_ASSERT(d, "NPObject not in object table");
|
||||
if (d) {
|
||||
d->actor = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ PluginScriptableObjectChild*
|
||||
PluginScriptableObjectChild::GetActorForNPObject(NPObject* aObject)
|
||||
{
|
||||
AssertPluginThread();
|
||||
MOZ_ASSERT(aObject, "Null pointer!");
|
||||
|
||||
NPObjectData* d = sObjectMap->GetEntry(aObject);
|
||||
if (!d) {
|
||||
NS_ERROR("Plugin using object not created with NPN_CreateObject?");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return d->actor;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PluginScriptableObjectChild::RegisterObject(NPObject* aObject, PluginInstanceChild* aInstance)
|
||||
{
|
||||
AssertPluginThread();
|
||||
|
||||
if (!sObjectMap) {
|
||||
sObjectMap = new nsTHashtable<PluginScriptableObjectChild::NPObjectData>();
|
||||
}
|
||||
|
||||
NPObjectData* d = sObjectMap->PutEntry(aObject);
|
||||
MOZ_ASSERT(!d->instance, "New NPObject already mapped?");
|
||||
d->instance = aInstance;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PluginScriptableObjectChild::UnregisterObject(NPObject* aObject)
|
||||
{
|
||||
AssertPluginThread();
|
||||
|
||||
sObjectMap->RemoveEntry(aObject);
|
||||
|
||||
if (!sObjectMap->Count()) {
|
||||
delete sObjectMap;
|
||||
sObjectMap = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ PluginInstanceChild*
|
||||
PluginScriptableObjectChild::GetInstanceForNPObject(NPObject* aObject)
|
||||
{
|
||||
AssertPluginThread();
|
||||
NPObjectData* d = sObjectMap->GetEntry(aObject);
|
||||
if (!d) {
|
||||
return nullptr;
|
||||
}
|
||||
return d->instance;
|
||||
}
|
||||
|
||||
/* static */ PLDHashOperator
|
||||
PluginScriptableObjectChild::CollectForInstance(NPObjectData* d, void* userArg)
|
||||
{
|
||||
PluginInstanceChild* instance = static_cast<PluginInstanceChild*>(userArg);
|
||||
if (d->instance == instance) {
|
||||
NPObject* o = d->GetKey();
|
||||
instance->mDeletingHash->PutEntry(o);
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PluginScriptableObjectChild::NotifyOfInstanceShutdown(PluginInstanceChild* aInstance)
|
||||
{
|
||||
AssertPluginThread();
|
||||
sObjectMap->EnumerateEntries(CollectForInstance, aInstance);
|
||||
}
|
||||
|
@ -217,6 +217,22 @@ public:
|
||||
|
||||
static void ClearIdentifiers();
|
||||
|
||||
bool RegisterActor(NPObject* aObject);
|
||||
void UnregisterActor(NPObject* aObject);
|
||||
|
||||
static PluginScriptableObjectChild* GetActorForNPObject(NPObject* aObject);
|
||||
|
||||
static void RegisterObject(NPObject* aObject, PluginInstanceChild* aInstance);
|
||||
static void UnregisterObject(NPObject* aObject);
|
||||
|
||||
static PluginInstanceChild* GetInstanceForNPObject(NPObject* aObject);
|
||||
|
||||
/**
|
||||
* Fill PluginInstanceChild.mDeletingHash with all the remaining NPObjects
|
||||
* associated with that instance.
|
||||
*/
|
||||
static void NotifyOfInstanceShutdown(PluginInstanceChild* aInstance);
|
||||
|
||||
private:
|
||||
static NPObject*
|
||||
ScriptableAllocate(NPP aInstance,
|
||||
@ -297,6 +313,29 @@ private:
|
||||
|
||||
typedef nsDataHashtable<nsCStringHashKey, nsRefPtr<StoredIdentifier>> IdentifierTable;
|
||||
static IdentifierTable sIdentifiers;
|
||||
|
||||
struct NPObjectData : public nsPtrHashKey<NPObject>
|
||||
{
|
||||
explicit NPObjectData(const NPObject* key)
|
||||
: nsPtrHashKey<NPObject>(key),
|
||||
instance(nullptr),
|
||||
actor(nullptr)
|
||||
{ }
|
||||
|
||||
// never nullptr
|
||||
PluginInstanceChild* instance;
|
||||
|
||||
// sometimes nullptr (no actor associated with an NPObject)
|
||||
PluginScriptableObjectChild* actor;
|
||||
};
|
||||
|
||||
static PLDHashOperator CollectForInstance(NPObjectData* d, void* userArg);
|
||||
|
||||
/**
|
||||
* mObjectMap contains all the currently active NPObjects (from NPN_CreateObject until the
|
||||
* final release/dealloc, whether or not an actor is currently associated with the object.
|
||||
*/
|
||||
static nsTHashtable<NPObjectData>* sObjectMap;
|
||||
};
|
||||
|
||||
} /* namespace plugins */
|
||||
|
@ -1985,6 +1985,10 @@ scriptableRemoveProperty(NPObject* npobj, NPIdentifier name)
|
||||
for (int i = 0; i < int(ARRAY_LENGTH(sPluginPropertyIdentifiers)); i++) {
|
||||
if (name == sPluginPropertyIdentifiers[i]) {
|
||||
NPN_ReleaseVariantValue(&sPluginPropertyValues[i]);
|
||||
|
||||
// Avoid double frees (see test_propertyAndMethod.html, which deletes a
|
||||
// property that doesn't exist).
|
||||
VOID_TO_NPVARIANT(sPluginPropertyValues[i]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user