PluginIdentifierParent::StackIdentifier::StackIdentifier
    (NPObject* aObject, NPIdentifier aIdentifier)
  : mIdentifier(NULL)
{
  PluginInstanceParent* inst = GetInstance(aObject);
  mIdentifier = inst->Module()->GetIdentifierForNPIdentifier(inst->GetNPP(), aIdentifier);
}
bool
PluginScriptableObjectParent::AnswerEnumerate(InfallibleTArray<PPluginIdentifierParent*>* aProperties,
                                              bool* aSuccess)
{
  if (!mObject) {
    NS_WARNING("Calling AnswerEnumerate with an invalidated object!");
    *aSuccess = false;
    return true;
  }

  NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
  NS_ASSERTION(mType == LocalObject, "Bad type!");

  PluginInstanceParent* instance = GetInstance();
  if (!instance) {
    NS_ERROR("No instance?!");
    *aSuccess = false;
    return true;
  }

  const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
  if (!npn) {
    NS_WARNING("No netscape funcs?!");
    *aSuccess = false;
    return true;
  }

  NPIdentifier* ids;
  uint32_t idCount;
  if (!npn->enumerate(instance->GetNPP(), mObject, &ids, &idCount)) {
    *aSuccess = false;
    return true;
  }

  aProperties->SetCapacity(idCount);

  mozilla::AutoSafeJSContext cx;
  for (uint32_t index = 0; index < idCount; index++) {
    // Because of GC hazards, all identifiers returned from enumerate
    // must be made permanent.
    if (_identifierisstring(ids[index])) {
      JSString* str = NPIdentifierToString(ids[index]);
      if (!JS_StringHasBeenInterned(cx, str)) {
        DebugOnly<JSString*> str2 = JS_InternJSString(cx, str);
        NS_ASSERTION(str2 == str, "Interning a JS string which is currently an ID should return itself.");
      }
    }
    PluginIdentifierParent* id =
      instance->Module()->GetIdentifierForNPIdentifier(instance->GetNPP(), ids[index]);
    aProperties->AppendElement(id);
    NS_ASSERTION(!id->IsTemporary(), "Should only have permanent identifiers!");
  }

  npn->memfree(ids);
  *aSuccess = true;
  return true;
}