| /* |
| * 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 "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 || !NPVariantProxy::isInt(args[0]) |
| || (!NPVariantProxy::isNull(args[1]) && !NPVariantProxy::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 = NPVariantProxy::getAsInt(args[0]); |
| int objId = objectId; |
| if (!NPVariantProxy::isNull(args[1])) { |
| NPObject* thisObj = NPVariantProxy::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); |
| } |