Bug 1081353 - Eliminate PPluginIdentifier (r=bsmedberg)

This commit is contained in:
Bill McCloskey
2014-10-20 09:47:25 -07:00
parent 5c64f055d9
commit e5e5debbf4
18 changed files with 440 additions and 818 deletions

View File

@@ -6,10 +6,125 @@
#include "PluginScriptableObjectChild.h"
#include "PluginScriptableObjectUtils.h"
#include "PluginIdentifierChild.h"
#include "mozilla/plugins/PluginTypes.h"
using namespace mozilla::plugins;
/**
* NPIdentifiers in the plugin process use a tagged representation. The low bit
* stores the tag. If it's zero, the identifier is a string, and the value is a
* pointer to a StoredIdentifier. If the tag bit is 1, then the rest of the
* NPIdentifier value is the integer itself. Like the JSAPI, we require that all
* integers stored in NPIdentifier be non-negative.
*
* String identifiers are stored in the sIdentifiers hashtable to ensure
* uniqueness. The lifetime of these identifiers is only as long as the incoming
* IPC call from the chrome process. If the plugin wants to retain an
* identifier, it needs to call NPN_GetStringIdentifier, which causes the
* mPermanent flag to be set on the identifier. When this flag is set, the
* identifier is saved until the plugin process exits.
*
* The StackIdentifier RAII class is used to manage ownership of
* identifiers. Any identifier obtained from this class should not be used
* outside its scope, except when the MakePermanent() method has been called on
* it.
*
* The lifetime of an NPIdentifier in the plugin process is totally divorced
* from the lifetime of an NPIdentifier in the chrome process (where an
* NPIdentifier is stored as a jsid). The JS GC in the chrome process is able to
* trace through the entire heap, unlike in the plugin process, so there is no
* reason to retain identifiers there.
*/
PluginScriptableObjectChild::IdentifierTable PluginScriptableObjectChild::sIdentifiers;
/* static */ PluginScriptableObjectChild::StoredIdentifier*
PluginScriptableObjectChild::HashIdentifier(const nsCString& aIdentifier)
{
StoredIdentifier* stored = sIdentifiers.Get(aIdentifier);
if (stored) {
return stored;
}
stored = new StoredIdentifier(aIdentifier);
sIdentifiers.Put(aIdentifier, stored);
return stored;
}
/* static */ void
PluginScriptableObjectChild::UnhashIdentifier(StoredIdentifier* aStored)
{
MOZ_ASSERT(sIdentifiers.Get(aStored->mIdentifier));
sIdentifiers.Remove(aStored->mIdentifier);
}
/* static */ void
PluginScriptableObjectChild::ClearIdentifiers()
{
sIdentifiers.Clear();
}
PluginScriptableObjectChild::StackIdentifier::StackIdentifier(const PluginIdentifier& aIdentifier)
: mIdentifier(aIdentifier),
mStored(nullptr)
{
if (aIdentifier.type() == PluginIdentifier::TnsCString) {
mStored = PluginScriptableObjectChild::HashIdentifier(mIdentifier.get_nsCString());
}
}
PluginScriptableObjectChild::StackIdentifier::StackIdentifier(NPIdentifier aIdentifier)
: mStored(nullptr)
{
uintptr_t bits = reinterpret_cast<uintptr_t>(aIdentifier);
if (bits & 1) {
int32_t num = int32_t(bits >> 1);
mIdentifier = PluginIdentifier(num);
} else {
mStored = static_cast<StoredIdentifier*>(aIdentifier);
mIdentifier = mStored->mIdentifier;
}
}
PluginScriptableObjectChild::StackIdentifier::~StackIdentifier()
{
if (!mStored) {
return;
}
// Each StackIdentifier owns one reference to its StoredIdentifier. In
// addition, the sIdentifiers table owns a reference. If mPermanent is false
// and sIdentifiers has the last reference, then we want to remove the
// StoredIdentifier from the table (and destroy it).
StoredIdentifier *stored = mStored;
mStored = nullptr;
if (stored->mRefCnt == 1 && !stored->mPermanent) {
PluginScriptableObjectChild::UnhashIdentifier(stored);
}
}
NPIdentifier
PluginScriptableObjectChild::StackIdentifier::ToNPIdentifier() const
{
if (mStored) {
MOZ_ASSERT(mIdentifier.type() == PluginIdentifier::TnsCString);
MOZ_ASSERT((reinterpret_cast<uintptr_t>(mStored.get()) & 1) == 0);
return mStored;
}
int32_t num = mIdentifier.get_int32_t();
// The JS engine imposes this condition on int32s in jsids, so we assume it.
MOZ_ASSERT(num >= 0);
return reinterpret_cast<NPIdentifier>((num << 1) | 1);
}
static PluginIdentifier
FromNPIdentifier(NPIdentifier aIdentifier)
{
PluginScriptableObjectChild::StackIdentifier stack(aIdentifier);
return stack.GetIdentifier();
}
// static
NPObject*
PluginScriptableObjectChild::ScriptableAllocate(NPP aInstance,
@@ -85,7 +200,7 @@ PluginScriptableObjectChild::ScriptableHasMethod(NPObject* aObject,
NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
bool result;
actor->CallHasMethod(static_cast<PPluginIdentifierChild*>(aName), &result);
actor->CallHasMethod(FromNPIdentifier(aName), &result);
return result;
}
@@ -122,7 +237,7 @@ PluginScriptableObjectChild::ScriptableInvoke(NPObject* aObject,
Variant remoteResult;
bool success;
actor->CallInvoke(static_cast<PPluginIdentifierChild*>(aName), args,
actor->CallInvoke(FromNPIdentifier(aName), args,
&remoteResult, &success);
if (!success) {
@@ -196,7 +311,7 @@ PluginScriptableObjectChild::ScriptableHasProperty(NPObject* aObject,
NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
bool result;
actor->CallHasProperty(static_cast<PPluginIdentifierChild*>(aName), &result);
actor->CallHasProperty(FromNPIdentifier(aName), &result);
return result;
}
@@ -225,7 +340,7 @@ PluginScriptableObjectChild::ScriptableGetProperty(NPObject* aObject,
Variant result;
bool success;
actor->CallGetParentProperty(static_cast<PPluginIdentifierChild*>(aName),
actor->CallGetParentProperty(FromNPIdentifier(aName),
&result, &success);
if (!success) {
@@ -265,7 +380,7 @@ PluginScriptableObjectChild::ScriptableSetProperty(NPObject* aObject,
}
bool success;
actor->CallSetProperty(static_cast<PPluginIdentifierChild*>(aName), value,
actor->CallSetProperty(FromNPIdentifier(aName), value,
&success);
return success;
@@ -293,7 +408,7 @@ PluginScriptableObjectChild::ScriptableRemoveProperty(NPObject* aObject,
NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
bool success;
actor->CallRemoveProperty(static_cast<PPluginIdentifierChild*>(aName),
actor->CallRemoveProperty(FromNPIdentifier(aName),
&success);
return success;
@@ -321,7 +436,7 @@ PluginScriptableObjectChild::ScriptableEnumerate(NPObject* aObject,
NS_ASSERTION(actor, "This shouldn't ever be null!");
NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
AutoInfallibleTArray<PPluginIdentifierChild*, 10> identifiers;
AutoInfallibleTArray<PluginIdentifier, 10> identifiers;
bool success;
actor->CallEnumerate(&identifiers, &success);
@@ -343,8 +458,10 @@ PluginScriptableObjectChild::ScriptableEnumerate(NPObject* aObject,
}
for (uint32_t index = 0; index < *aCount; index++) {
(*aIdentifiers)[index] =
static_cast<PPluginIdentifierChild*>(identifiers[index]);
StackIdentifier id(identifiers[index]);
// Make the id permanent in case the plugin retains it.
id.MakePermanent();
(*aIdentifiers)[index] = id.ToNPIdentifier();
}
return true;
}
@@ -610,7 +727,7 @@ PluginScriptableObjectChild::AnswerInvalidate()
}
bool
PluginScriptableObjectChild::AnswerHasMethod(PPluginIdentifierChild* aId,
PluginScriptableObjectChild::AnswerHasMethod(const PluginIdentifier& aId,
bool* aHasMethod)
{
AssertPluginThread();
@@ -629,13 +746,13 @@ PluginScriptableObjectChild::AnswerHasMethod(PPluginIdentifierChild* aId,
return true;
}
PluginIdentifierChild::StackIdentifier id(aId);
*aHasMethod = mObject->_class->hasMethod(mObject, id->ToNPIdentifier());
StackIdentifier id(aId);
*aHasMethod = mObject->_class->hasMethod(mObject, id.ToNPIdentifier());
return true;
}
bool
PluginScriptableObjectChild::AnswerInvoke(PPluginIdentifierChild* aId,
PluginScriptableObjectChild::AnswerInvoke(const PluginIdentifier& aId,
const InfallibleTArray<Variant>& aArgs,
Variant* aResult,
bool* aSuccess)
@@ -673,8 +790,8 @@ PluginScriptableObjectChild::AnswerInvoke(PPluginIdentifierChild* aId,
NPVariant result;
VOID_TO_NPVARIANT(result);
PluginIdentifierChild::StackIdentifier id(aId);
bool success = mObject->_class->invoke(mObject, id->ToNPIdentifier(),
StackIdentifier id(aId);
bool success = mObject->_class->invoke(mObject, id.ToNPIdentifier(),
convertedArgs.Elements(), argCount,
&result);
@@ -775,7 +892,7 @@ PluginScriptableObjectChild::AnswerInvokeDefault(const InfallibleTArray<Variant>
}
bool
PluginScriptableObjectChild::AnswerHasProperty(PPluginIdentifierChild* aId,
PluginScriptableObjectChild::AnswerHasProperty(const PluginIdentifier& aId,
bool* aHasProperty)
{
AssertPluginThread();
@@ -794,13 +911,13 @@ PluginScriptableObjectChild::AnswerHasProperty(PPluginIdentifierChild* aId,
return true;
}
PluginIdentifierChild::StackIdentifier id(aId);
*aHasProperty = mObject->_class->hasProperty(mObject, id->ToNPIdentifier());
StackIdentifier id(aId);
*aHasProperty = mObject->_class->hasProperty(mObject, id.ToNPIdentifier());
return true;
}
bool
PluginScriptableObjectChild::AnswerGetChildProperty(PPluginIdentifierChild* aId,
PluginScriptableObjectChild::AnswerGetChildProperty(const PluginIdentifier& aId,
bool* aHasProperty,
bool* aHasMethod,
Variant* aResult,
@@ -824,8 +941,8 @@ PluginScriptableObjectChild::AnswerGetChildProperty(PPluginIdentifierChild* aId,
return true;
}
PluginIdentifierChild::StackIdentifier stackID(aId);
NPIdentifier id = stackID->ToNPIdentifier();
StackIdentifier stackID(aId);
NPIdentifier id = stackID.ToNPIdentifier();
*aHasProperty = mObject->_class->hasProperty(mObject, id);
*aHasMethod = mObject->_class->hasMethod(mObject, id);
@@ -850,7 +967,7 @@ PluginScriptableObjectChild::AnswerGetChildProperty(PPluginIdentifierChild* aId,
}
bool
PluginScriptableObjectChild::AnswerSetProperty(PPluginIdentifierChild* aId,
PluginScriptableObjectChild::AnswerSetProperty(const PluginIdentifier& aId,
const Variant& aValue,
bool* aSuccess)
{
@@ -871,8 +988,8 @@ PluginScriptableObjectChild::AnswerSetProperty(PPluginIdentifierChild* aId,
return true;
}
PluginIdentifierChild::StackIdentifier stackID(aId);
NPIdentifier id = stackID->ToNPIdentifier();
StackIdentifier stackID(aId);
NPIdentifier id = stackID.ToNPIdentifier();
if (!mObject->_class->hasProperty(mObject, id)) {
*aSuccess = false;
@@ -889,7 +1006,7 @@ PluginScriptableObjectChild::AnswerSetProperty(PPluginIdentifierChild* aId,
}
bool
PluginScriptableObjectChild::AnswerRemoveProperty(PPluginIdentifierChild* aId,
PluginScriptableObjectChild::AnswerRemoveProperty(const PluginIdentifier& aId,
bool* aSuccess)
{
AssertPluginThread();
@@ -909,8 +1026,8 @@ PluginScriptableObjectChild::AnswerRemoveProperty(PPluginIdentifierChild* aId,
return true;
}
PluginIdentifierChild::StackIdentifier stackID(aId);
NPIdentifier id = stackID->ToNPIdentifier();
StackIdentifier stackID(aId);
NPIdentifier id = stackID.ToNPIdentifier();
*aSuccess = mObject->_class->hasProperty(mObject, id) ?
mObject->_class->removeProperty(mObject, id) :
true;
@@ -919,7 +1036,7 @@ PluginScriptableObjectChild::AnswerRemoveProperty(PPluginIdentifierChild* aId,
}
bool
PluginScriptableObjectChild::AnswerEnumerate(InfallibleTArray<PPluginIdentifierChild*>* aProperties,
PluginScriptableObjectChild::AnswerEnumerate(InfallibleTArray<PluginIdentifier>* aProperties,
bool* aSuccess)
{
AssertPluginThread();
@@ -948,8 +1065,7 @@ PluginScriptableObjectChild::AnswerEnumerate(InfallibleTArray<PPluginIdentifierC
aProperties->SetCapacity(idCount);
for (uint32_t index = 0; index < idCount; index++) {
PluginIdentifierChild* id = static_cast<PluginIdentifierChild*>(ids[index]);
aProperties->AppendElement(id);
aProperties->AppendElement(FromNPIdentifier(ids[index]));
}
PluginModuleChild::sBrowserFuncs.memfree(ids);