blob: 16f7a09ccec6206c2f77474aec7ebcde83d88685 [file] [log] [blame]
/*
* 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);
}