| /* | 
 |  * Copyright 2008 Google Inc. | 
 |  *  | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); you may not | 
 |  * use this file except in compliance with the License. You may obtain a copy of | 
 |  * the License at | 
 |  *  | 
 |  * http://www.apache.org/licenses/LICENSE-2.0 | 
 |  *  | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | 
 |  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | 
 |  * License for the specific language governing permissions and limitations under | 
 |  * the License. | 
 |  */ | 
 |  | 
 | #include "Debug.h" | 
 |  | 
 | #include "JavaObject.h" | 
 | #include "Plugin.h" | 
 | #include "NPVariantUtil.h" | 
 | #include "NPVariantWrapper.h" | 
 |  | 
 | using std::string; | 
 |  | 
 | static string IdentifierName(NPIdentifier name) { | 
 |   string iname; | 
 |   if (NPN_IdentifierIsString(name)) { | 
 |     iname = NPN_UTF8FromIdentifier(name); | 
 |   } else { | 
 |     char buf[50]; | 
 |     snprintf(buf, sizeof(buf), "%d", NPN_IntFromIdentifier(name)); | 
 |     iname = buf; | 
 |   } | 
 |   return iname; | 
 | } | 
 |  | 
 | JavaObject* JavaObject::create(ScriptableInstance* plugin, int id) { | 
 |   Debug::log(Debug::Spam) << "Creating Java object id=" << id; | 
 |   NPClass* npClass = GetNPClass<JavaObject>(); | 
 |   NPObject* obj = NPN_CreateObject(plugin->getNPP(), npClass); | 
 |   Debug::log(Debug::Spam) << " addr=" << obj << Debug::flush; | 
 |   JavaObject* jObj = static_cast<JavaObject*>(obj); | 
 |   jObj->setObjectId(id); | 
 |   return jObj; | 
 | } | 
 |  | 
 | bool JavaObject::isInstance(NPObject* obj) { | 
 |   return obj->_class == GetNPClass<JavaObject>(); | 
 | } | 
 |  | 
 | JavaObject::~JavaObject() { | 
 |   if (plugin) { | 
 |     plugin->destroyJavaWrapper(this); | 
 |   } else { | 
 |     Debug::log(Debug::Spam) << "Destroying JavaObject " << objectId << " after plugin destroyed" | 
 |         << Debug::flush; | 
 |   } | 
 | } | 
 |  | 
 | bool JavaObject::enumeration(NPIdentifier** propReturn, uint32_t* count) { | 
 |   Debug::log(Debug::Debugging) << "JavaObject::enumeration(" << objectId << ")" | 
 |       << Debug::flush; | 
 |   int n = 1; | 
 |   NPIdentifier* props = static_cast<NPIdentifier*>(NPN_MemAlloc(sizeof(NPIdentifier) * n)); | 
 |   props[0] = idID; | 
 |   *propReturn = props; | 
 |   *count = n; | 
 |   return true; | 
 | } | 
 |  | 
 | bool JavaObject::getProperty(NPIdentifier prop, NPVariant *result) { | 
 |   if (!plugin) { | 
 |     Debug::log(Debug::Spam) << "Ignoring getProperty on " << objectId << " after plugin destroyed" | 
 |         << Debug::flush; | 
 |     VOID_TO_NPVARIANT(*result); | 
 |     return true; | 
 |   } | 
 |   Debug::log(Debug::Spam) << "JavaObject::getProperty(" << objectId << ")" << Debug::flush; | 
 |   if (NPN_IdentifierIsString(prop)) { | 
 |     if (prop == plugin->toStringID) { | 
 |       return plugin->JavaObject_getToStringTearOff(result); | 
 |     } | 
 |     if (prop == idID) { | 
 |       INT32_TO_NPVARIANT(objectId, *result); | 
 |       return true; | 
 |     } | 
 |     // all other properties are numeric dispatchIDs | 
 |     return false; | 
 |   } | 
 |   int dispId = NPN_IntFromIdentifier(prop); | 
 |   // JavaObject_getProperty will retain the return value if needed. | 
 |   return plugin->JavaObject_getProperty(objectId, dispId, result); | 
 | } | 
 |  | 
 | bool JavaObject::hasMethod(NPIdentifier method) { | 
 |   if (!plugin) { | 
 |     Debug::log(Debug::Spam) << "Ignoring hasMethod on " << objectId << " after plugin destroyed" | 
 |         << Debug::flush; | 
 |     return true; | 
 |   } | 
 |   Debug::log(Debug::Spam) << "JavaObject::hasMethod(" << objectId << ", method=" | 
 |       << IdentifierName(method) << ")" << Debug::flush; | 
 |   return false; | 
 | //  return !NPN_IdentifierIsString(method); | 
 | } | 
 |  | 
 | bool JavaObject::hasProperty(NPIdentifier prop) { | 
 |   if (!plugin) { | 
 |     Debug::log(Debug::Spam) << "Ignoring hasProperty on " << objectId << " after plugin destroyed" | 
 |         << Debug::flush; | 
 |     return true; | 
 |   } | 
 |   Debug::log(Debug::Spam) << "JavaObject::hasProperty(" << objectId << ", prop=" | 
 |       << IdentifierName(prop) << ")" << Debug::flush; | 
 |   return !NPN_IdentifierIsString(prop) || prop == idID || prop == plugin->toStringID; | 
 | } | 
 |  | 
 | bool JavaObject::invokeDefault(const NPVariant *args, uint32_t argCount, NPVariant *result) { | 
 |   if (argCount < 2 || !NPVariantUtil::isInt(args[0]) | 
 |       || (!NPVariantUtil::isNull(args[1]) && !NPVariantUtil::isObject(args[1]))) { | 
 |     Debug::log(Debug::Error) << "incorrect arguments to invokeDefault" << Debug::flush; | 
 |     return false; | 
 |   } | 
 |   if (!plugin) { | 
 |     Debug::log(Debug::Spam) << "Ignoring invokeDefault on " << objectId << " after plugin destroyed" | 
 |         << Debug::flush; | 
 |     VOID_TO_NPVARIANT(*result); | 
 |     return true; | 
 |   } | 
 |   Debug::log(Debug::Debugging) << "JavaObject::invokeDefault(" << objectId; | 
 |   for (uint32_t i = 0; i < argCount; ++i) { | 
 |     Debug::log(Debug::Debugging) << ", " << NPVariantProxy::toString(args[i]); | 
 |   } | 
 |   Debug::log(Debug::Debugging) << ")" << Debug::flush; | 
 |   int dispId = NPVariantUtil::getAsInt(args[0]); | 
 |   int objId = objectId; | 
 |   if (!NPVariantUtil::isNull(args[1])) { | 
 |     NPObject* thisObj = NPVariantUtil::getAsObject(args[1]); | 
 |     if (isInstance(thisObj)) { | 
 |       JavaObject* thisJavaObj = static_cast<JavaObject*>(thisObj); | 
 |       objId = thisJavaObj->objectId; | 
 |     } | 
 |   } | 
 |   // JavaObject_invoke will retain the return value if needed. | 
 |   return plugin->JavaObject_invoke(objId, dispId, args + 2, argCount - 2, result); | 
 | } | 
 |  | 
 | bool JavaObject::invoke(NPIdentifier name, const NPVariant *args, | 
 |     uint32_t argCount, NPVariant *result) { | 
 |   VOID_TO_NPVARIANT(*result); | 
 |   if (!plugin) { | 
 |     Debug::log(Debug::Spam) << "Ignoring invoke on " << objectId << " after plugin destroyed" | 
 |         << Debug::flush; | 
 |     return true; | 
 |   } | 
 |   string methodName(NPN_UTF8FromIdentifier(name)); | 
 |   Debug::log(Debug::Spam) << "JavaObject::invoke(" << objectId << ", method=" | 
 |       << methodName << ")" << Debug::flush; | 
 |   if (name == plugin->toStringID) { | 
 |     // -1 is magic and means a raw toString(). | 
 |     return plugin->JavaObject_invoke(objectId, -1, args, argCount, result); | 
 |   } | 
 |   // toString is the only method we support invoking directly on a Java wrapper | 
 |   return false; | 
 | } | 
 |  | 
 | bool JavaObject::setProperty(NPIdentifier prop, const NPVariant *value) { | 
 |   if (!plugin) { | 
 |     Debug::log(Debug::Spam) << "Ignoring setProperty on " << objectId << " after plugin destroyed" | 
 |         << Debug::flush; | 
 |     return true; | 
 |   } | 
 |   Debug::log(Debug::Spam) << "JavaObject::setProperty(" << objectId << ", val=" | 
 |       << NPVariantProxy::toString(*value) << ")" << Debug::flush; | 
 |   if (NPN_IdentifierIsString(prop)) { | 
 |     // any non-numeric properties are read-only | 
 |     return false; | 
 |   } | 
 |   int dispId = NPN_IntFromIdentifier(prop);  | 
 |   return plugin->JavaObject_setProperty(objectId, dispId, value); | 
 | } |