Updating npapi plugin to remove gwtId from Jso objects (idenity fix), adds a second map in LocalObjects. Review at http://gwt-code-reviews.appspot.com/1469803 git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10423 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/plugins/npapi/JavaObject.cpp b/plugins/npapi/JavaObject.cpp index 16f7a09..adbdbc8 100644 --- a/plugins/npapi/JavaObject.cpp +++ b/plugins/npapi/JavaObject.cpp
@@ -18,6 +18,7 @@ #include "JavaObject.h" #include "Plugin.h" +#include "NPVariantUtil.h" #include "NPVariantWrapper.h" using std::string; @@ -116,8 +117,8 @@ } 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]))) { + 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; } @@ -132,10 +133,10 @@ Debug::log(Debug::Debugging) << ", " << NPVariantProxy::toString(args[i]); } Debug::log(Debug::Debugging) << ")" << Debug::flush; - int dispId = NPVariantProxy::getAsInt(args[0]); + int dispId = NPVariantUtil::getAsInt(args[0]); int objId = objectId; - if (!NPVariantProxy::isNull(args[1])) { - NPObject* thisObj = NPVariantProxy::getAsObject(args[1]); + if (!NPVariantUtil::isNull(args[1])) { + NPObject* thisObj = NPVariantUtil::getAsObject(args[1]); if (isInstance(thisObj)) { JavaObject* thisJavaObj = static_cast<JavaObject*>(thisObj); objId = thisJavaObj->objectId;
diff --git a/plugins/npapi/LocalObjectTable.h b/plugins/npapi/LocalObjectTable.h index acfbf2f..57a5887 100644 --- a/plugins/npapi/LocalObjectTable.h +++ b/plugins/npapi/LocalObjectTable.h
@@ -21,24 +21,43 @@ #include "Debug.h" #include "mozincludes.h" +#include "NPVariantUtil.h" class LocalObjectTable { private: + /* The host expects Value objects to have int's for JSO id's, hence the + * dual mapping. ObjectMap is for host communication (Value.getJsObjectId) + * and the IdMap is for browser communication (NPObject to ID). + */ typedef std::map<int, NPObject*> ObjectMap; + typedef std::map<NPObject*,int> IdMap; + + NPP npp; int nextId; ObjectMap objects; + IdMap ids; bool dontFree; + bool jsIdentitySafe; + + const NPIdentifier gwtId; + void setFree(int id) { - if (objects.erase(id) != 1) { + NPObject *obj = getById(id); + if(!obj) { Debug::log(Debug::Error) << "setFree(id=" << id << "): object not in table" << Debug::flush; + return; } + ids.erase(obj); + objects.erase(id); } public: - LocalObjectTable(): nextId(0), dontFree(false) { + LocalObjectTable(NPP npp, bool jsIdentitySafe): + nextId(0), dontFree(false), jsIdentitySafe(jsIdentitySafe), + gwtId(NPN_GetStringIdentifier("__gwt_ObjectId")) { } virtual ~LocalObjectTable(); @@ -49,29 +68,67 @@ int add(NPObject* obj) { int id = nextId++; set(id, obj); + + if (!jsIdentitySafe) { + NPVariant idVariant; + Debug::log(Debug::Debugging) << "LocalObjectTable::set(): setting expando(" + << id << ")" << Debug::flush; + INT32_TO_NPVARIANT(id,idVariant); + if (!NPN_SetProperty(npp, obj, gwtId, &idVariant)) { + Debug::log(Debug::Error) << "Setting GWT id on object failed" << Debug::flush; + } + } + return id; } void set(int id, NPObject* obj) { - Debug::log(Debug::Spam) << "LocalObjectTable::set(id=" << id << ",obj=" << (void*)obj + Debug::log(Debug::Debugging) << "LocalObjectTable::set(id=" << id << ",obj=" << (void*)obj << ")" << Debug::flush; + if (!jsIdentitySafe) { + ObjectMap::iterator it; + it = objects.find(id); + if( it != objects.end() ) { + if (it->second != obj) { + //The JSO has changed and we need to update the map, releasing + //the old and remembering the new object. + ids.erase(it->second); + NPN_ReleaseObject(it->second); + NPN_RetainObject(obj); + } else { + //do nothing; object exists and is already mapped + return; + } + } else { + //New insertion, retain the object in the table + NPN_RetainObject(obj); + } + } else { + //Not dealing with identity hack, retain + NPN_RetainObject(obj); + } objects[id] = obj; + ids[obj] = id; + // keep track that we hold a reference in the table - NPN_RetainObject(obj); } void free(int id) { - Debug::log(Debug::Spam) << "LocalObjectTable::free(id=" << id << ")" << Debug::flush; + Debug::log(Debug::Debugging) << "LocalObjectTable::free(id=" << id << ")" << Debug::flush; ObjectMap::iterator it = objects.find(id); if (it == objects.end()) { Debug::log(Debug::Error) << "Freeing freed object slot " << id << Debug::flush; return; } + if (!jsIdentitySafe) { + Debug::log(Debug::Debugging) << "removing expando!" << Debug::flush; + NPN_RemoveProperty(npp, it->second, gwtId); + } + setFree(id); if (!dontFree) { NPObject* obj = it->second; NPN_ReleaseObject(obj); } - setFree(id); } void freeAll() { @@ -85,7 +142,7 @@ objects.clear(); } - NPObject* get(int id) { + NPObject* getById(int id) { ObjectMap::iterator it = objects.find(id); if (it == objects.end()) { Debug::log(Debug::Error) << "LocalObjectTable::get(id=" << id @@ -94,6 +151,30 @@ return it->second; } + int getObjectId(NPObject* jsObject) { + int id = -1; + if(!jsIdentitySafe) { + NPVariant idVariant; + VOID_TO_NPVARIANT(idVariant); + Debug::log(Debug::Debugging) << "LocalObjectTable::get(): expando test" + << Debug::flush; + if (NPN_GetProperty(npp, jsObject, gwtId, &idVariant) && + NPVariantUtil::isInt(idVariant)) { + id = NPVariantUtil::getAsInt(idVariant); + Debug::log(Debug::Debugging) << "LocalObjectTable::get(): expando: " + << id << Debug::flush; + set(id, jsObject); + } + NPN_ReleaseVariantValue(&idVariant); + } else { + IdMap::iterator it = ids.find(jsObject); + if (it != ids.end()) { + id = it->second; + } + } + return id; + } + void setDontFree(bool dontFree) { this->dontFree = dontFree; }
diff --git a/plugins/npapi/NPVariantUtil.h b/plugins/npapi/NPVariantUtil.h new file mode 100644 index 0000000..2ca7ea5 --- /dev/null +++ b/plugins/npapi/NPVariantUtil.h
@@ -0,0 +1,132 @@ +#ifndef _H_NPVariantUtil +#define _H_NPVariantUtil + +#include "Debug.h" +#include "mozincludes.h" + +/** + * Wraps an NPVariant and provides various helper functions + */ +class NPVariantUtil { +public: + static int isBoolean(const NPVariant& variant) { + return NPVARIANT_IS_BOOLEAN(variant); + } + + static bool getAsBoolean(const NPVariant& variant) { + return NPVARIANT_TO_BOOLEAN(variant); + } + + // Return true if the variant is holding a regular integer or an integral double. + static int isInt(const NPVariant& variant) { + if (NPVARIANT_IS_INT32(variant)) { + return 1; + } else if (NPVARIANT_IS_DOUBLE(variant)) { + // As of http://trac.webkit.org/changeset/72974 we get doubles for all + // numerical variants out of V8. + double d = NPVARIANT_TO_DOUBLE(variant); + int i = static_cast<int>(d); + // Verify that d is an integral value in range. + return (d == static_cast<double>(i)); + } else { + return 0; + } + } + + static int getAsInt(const NPVariant& variant) { + if (isInt(variant)) { + if (NPVARIANT_IS_INT32(variant)) { + return NPVARIANT_TO_INT32(variant); + } else if (NPVARIANT_IS_DOUBLE(variant)) { + return static_cast<int>(NPVARIANT_TO_DOUBLE(variant)); + } + } + + Debug::log(Debug::Error) << "getAsInt: variant " << + NPVariantUtil::toString(variant) << "not int" << Debug::flush; + return 0; + } + + static int isNull(const NPVariant& variant) { + return NPVARIANT_IS_NULL(variant); + } + + static int isObject(const NPVariant& variant) { + return NPVARIANT_IS_OBJECT(variant); + } + + static NPObject* getAsObject(const NPVariant& variant) { + if (NPVARIANT_IS_OBJECT(variant)) { + return NPVARIANT_TO_OBJECT(variant); + } + Debug::log(Debug::Error) << "getAsObject: variant not object" << Debug::flush; + return 0; + } + + static int isString(const NPVariant& variant) { + return NPVARIANT_IS_STRING(variant); + } + + static const NPString* getAsNPString(const NPVariant& variant) { + if (NPVARIANT_IS_STRING(variant)) { + return &NPVARIANT_TO_STRING(variant); + } + Debug::log(Debug::Error) << "getAsNPString: variant not string" << Debug::flush; + return 0; + } + + static std::string toString(const NPVariant& variant) { + std::string retval; + // TODO(jat): remove sprintfs + char buf[40]; + NPObject* npObj; + switch (variant.type) { + case NPVariantType_Void: + retval = "undef"; + break; + case NPVariantType_Null: + retval = "null"; + break; + case NPVariantType_Bool: + retval = "bool("; + retval += (NPVARIANT_TO_BOOLEAN(variant) ? "true" : "false"); + retval += ')'; + break; + case NPVariantType_Int32: + retval = "int("; + snprintf(buf, sizeof(buf), "%d)", NPVARIANT_TO_INT32(variant)); + retval += buf; + break; + case NPVariantType_Double: + retval = "double("; + snprintf(buf, sizeof(buf), "%g)", NPVARIANT_TO_DOUBLE(variant)); + retval += buf; + break; + case NPVariantType_String: + { + retval = "string("; + NPString str = NPVARIANT_TO_STRING(variant); + retval += std::string(str.UTF8Characters, str.UTF8Length); + retval += ')'; + } + break; + case NPVariantType_Object: + npObj = NPVARIANT_TO_OBJECT(variant); + snprintf(buf, sizeof(buf), "obj(class=%p, ", npObj->_class); + retval = buf; + snprintf(buf, sizeof(buf), "count=%d, ", npObj->referenceCount); + retval += buf; + snprintf(buf, sizeof(buf), "%p)", npObj); + retval += buf; + break; + default: + snprintf(buf, sizeof(buf), "Unknown type %d", variant.type); + retval = buf; + break; + } + return retval; + } + +}; + +#endif
diff --git a/plugins/npapi/NPVariantWrapper.h b/plugins/npapi/NPVariantWrapper.h index 6d7689d..a1844c5 100644 --- a/plugins/npapi/NPVariantWrapper.h +++ b/plugins/npapi/NPVariantWrapper.h
@@ -15,6 +15,7 @@ #include "Platform.h" #include "mozincludes.h" +#include "NPVariantUtil.h" #include "Value.h" #include "LocalObjectTable.h" @@ -62,105 +63,39 @@ } int isBoolean() const { - return isBoolean(variant); - } - - static int isBoolean(const NPVariant& variant) { - return NPVARIANT_IS_BOOLEAN(variant); + return NPVariantUtil::isBoolean(variant); } bool getAsBoolean() const { - return getAsBoolean(variant); - } - - static bool getAsBoolean(const NPVariant& variant) { - return NPVARIANT_TO_BOOLEAN(variant); + return NPVariantUtil::getAsBoolean(variant); } int isInt() const { - return isInt(variant); + return NPVariantUtil::isInt(variant); } - // Return true if the variant is holding a regular integer or an integral double. - static int isInt(const NPVariant& variant) { - if (NPVARIANT_IS_INT32(variant)) { - return 1; - } else if (NPVARIANT_IS_DOUBLE(variant)) { - // As of http://trac.webkit.org/changeset/72974 we get doubles for all - // numerical variants out of V8. - double d = NPVARIANT_TO_DOUBLE(variant); - int i = static_cast<int>(d); - // Verify that d is an integral value in range. - return (d == static_cast<double>(i)); - } else { - return 0; - } - } - int getAsInt() const { - return getAsInt(variant); - } - - static int getAsInt(const NPVariant& variant) { - if (isInt(variant)) { - if (NPVARIANT_IS_INT32(variant)) { - return NPVARIANT_TO_INT32(variant); - } else if (NPVARIANT_IS_DOUBLE(variant)) { - return static_cast<int>(NPVARIANT_TO_DOUBLE(variant)); - } - } - - Debug::log(Debug::Error) << "getAsInt: variant " << - NPVariantProxy::toString(variant) << "not int" << Debug::flush; - return 0; + return NPVariantUtil::getAsInt(variant); } int isNull() const { - return isNull(variant); + return NPVariantUtil::isNull(variant); } - static int isNull(const NPVariant& variant) { - return NPVARIANT_IS_NULL(variant); - } - int isObject() const { - return isObject(variant); + return NPVariantUtil::isObject(variant); } - static int isObject(const NPVariant& variant) { - return NPVARIANT_IS_OBJECT(variant); - } - NPObject* getAsObject() const { - return getAsObject(variant); - } - - static NPObject* getAsObject(const NPVariant& variant) { - if (NPVARIANT_IS_OBJECT(variant)) { - return NPVARIANT_TO_OBJECT(variant); - } - Debug::log(Debug::Error) << "getAsObject: variant not object" << Debug::flush; - return 0; + return NPVariantUtil::getAsObject(variant); } int isString() const { - return isString(variant); + return NPVariantUtil::isString(variant); } - static int isString(const NPVariant& variant) { - return NPVARIANT_IS_STRING(variant); - } - const NPString* getAsNPString() const { - return getAsNPString(variant); - } - - static const NPString* getAsNPString(const NPVariant& variant) { - if (NPVARIANT_IS_STRING(variant)) { - return &NPVARIANT_TO_STRING(variant); - } - Debug::log(Debug::Error) << "getAsNPString: variant not string" << Debug::flush; - return 0; + return NPVariantUtil::getAsNPString(variant); } Value getAsValue(ScriptableInstance& scriptInstance, bool unwrapJava = true) const { @@ -465,35 +400,35 @@ } bool isBoolean() const { - return NPVariantProxy::isBoolean(variant); + return NPVariantUtil::isBoolean(variant); } int isInt() const { - return NPVariantProxy::isInt(variant); + return NPVariantUtil::isInt(variant); } int isObject() const { - return NPVariantProxy::isObject(variant); + return NPVariantUtil::isObject(variant); } int isString() const { - return NPVariantProxy::isString(variant); + return NPVariantUtil::isString(variant); } bool getAsBoolean() const { - return NPVariantProxy::getAsBoolean(variant); + return NPVariantUtil::getAsBoolean(variant); } int getAsInt() const { - return NPVariantProxy::getAsInt(variant); + return NPVariantUtil::getAsInt(variant); } NPObject* getAsObject() const { - return NPVariantProxy::getAsObject(variant); + return NPVariantUtil::getAsObject(variant); } const NPString* getAsNPString() const { - return NPVariantProxy::getAsNPString(variant); + return NPVariantUtil::getAsNPString(variant); } Value getAsValue(ScriptableInstance& scriptInstance, bool unwrapJava = true) const {
diff --git a/plugins/npapi/ScriptableInstance.cpp b/plugins/npapi/ScriptableInstance.cpp index 4344a5b..bc79d17 100644 --- a/plugins/npapi/ScriptableInstance.cpp +++ b/plugins/npapi/ScriptableInstance.cpp
@@ -33,6 +33,8 @@ const static string INCLUDE_STR = "include"; const static string EXCLUDE_STR = "exclude"; +bool ScriptableInstance::jsIdentitySafe = false; + static inline string convertToString(const NPString& str) { return string(GetNPStringUTF8Characters(str), GetNPStringUTF8Length(str)); } @@ -58,7 +60,7 @@ ScriptableInstance::ScriptableInstance(NPP npp) : NPObjectWrapper<ScriptableInstance>(npp), plugin(*reinterpret_cast<Plugin*>(npp->pdata)), _channel(new HostChannel()), - localObjects(), + localObjects(npp,ScriptableInstance::jsIdentitySafe), _connectId(NPN_GetStringIdentifier("connect")), initID(NPN_GetStringIdentifier("init")), toStringID(NPN_GetStringIdentifier("toString")), @@ -68,9 +70,9 @@ urlID(NPN_GetStringIdentifier("url")), includeID(NPN_GetStringIdentifier("include")), getHostPermissionID(NPN_GetStringIdentifier("getHostPermission")), + testJsIdentityID(NPN_GetStringIdentifier("testJsIdentity")), connectedID(NPN_GetStringIdentifier("connected")), statsID(NPN_GetStringIdentifier("stats")), - gwtId(NPN_GetStringIdentifier("__gwt_ObjectId")), jsDisconnectedID(NPN_GetStringIdentifier("__gwt_disconnected")), jsInvokeID(NPN_GetStringIdentifier("__gwt_jsInvoke")), jsResultID(NPN_GetStringIdentifier("__gwt_makeResult")), @@ -82,6 +84,7 @@ if (NPN_GetValue(npp, NPNVWindowNPObject, &window) != NPERR_NO_ERROR) { Debug::log(Debug::Error) << "Error getting window object" << Debug::flush; } + } ScriptableInstance::~ScriptableInstance() { @@ -115,7 +118,7 @@ bool ScriptableInstance::tryGetStringPrimitive(NPObject* obj, NPVariant& result) { if (NPN_HasMethod(getNPP(), obj, jsValueOfID)) { if (NPN_Invoke(getNPP(), obj, jsValueOfID, 0, 0, &result) - && NPVariantProxy::isString(result)) { + && NPVariantUtil::isString(result)) { return true; } NPVariantProxy::release(result); @@ -188,7 +191,8 @@ name == initID || name == toStringID || name == loadHostEntriesID || - name == getHostPermissionID) { + name == getHostPermissionID || + name == testJsIdentityID ) { return true; } return false; @@ -214,6 +218,8 @@ loadHostEntries(args, argCount, result); } else if (name == getHostPermissionID) { getHostPermission(args, argCount, result); + } else if (name == testJsIdentityID) { + testJsIdentity(args, argCount, result); } return true; } @@ -242,7 +248,7 @@ //============================================================================= void ScriptableInstance::init(const NPVariant* args, unsigned argCount, NPVariant* result) { - if (argCount != 1 || !NPVariantProxy::isObject(args[0])) { + if (argCount != 1 || !NPVariantUtil::isObject(args[0])) { // TODO: better failure? Debug::log(Debug::Error) << "ScriptableInstance::init called with incorrect arguments:\n"; for (unsigned i = 0; i < argCount; ++i) { @@ -256,7 +262,7 @@ NPN_ReleaseObject(window); } // replace our window object with that passed by the caller - window = NPVariantProxy::getAsObject(args[0]); + window = NPVariantUtil::getAsObject(args[0]); NPN_RetainObject(window); BOOLEAN_TO_NPVARIANT(true, *result); result->type = NPVariantType_Bool; @@ -271,7 +277,7 @@ //window.location.href NPN_GetProperty(getNPP(), locationVariant.getAsObject(), hrefID, hrefVariant.addressForReturn()); - const NPString* locationHref = NPVariantProxy::getAsNPString(hrefVariant); + const NPString* locationHref = NPVariantUtil::getAsNPString(hrefVariant); return convertToString(*locationHref); } @@ -282,7 +288,7 @@ AllowedConnections::clearRules(); for (unsigned i = 0; i < argCount; ++i) { //Get the host entry object {url: "somehost.net", include: true/false} - NPObject* hostEntry = NPVariantProxy::getAsObject(args[i]); + NPObject* hostEntry = NPVariantUtil::getAsObject(args[i]); if (!hostEntry) { Debug::log(Debug::Error) << "Got a host entry that is not an object.\n"; break; @@ -322,7 +328,7 @@ } void ScriptableInstance::getHostPermission(const NPVariant* args, unsigned argCount, NPVariant* result) { - if (argCount != 1 || !NPVariantProxy::isString(args[0])) { + if (argCount != 1 || !NPVariantUtil::isString(args[0])) { Debug::log(Debug::Error) << "ScriptableInstance::getHostPermission called with incorrect arguments.\n"; } @@ -347,12 +353,34 @@ NPVariantProxy(*this, *result) = retStr; } +void ScriptableInstance::testJsIdentity(const NPVariant* args, unsigned argCount, NPVariant* result) { + if (argCount != 2 || !NPVariantUtil::isObject(args[0]) || + !NPVariantUtil::isObject(args[1]) ) { + Debug::log(Debug::Error) << "ScriptableInstance::testJsIdentity called" + << " with incorrect arguments.\n"; + } + NPObject* obj1 = NPVariantUtil::getAsObject(args[0]); + NPObject* obj2 = NPVariantUtil::getAsObject(args[1]); + Debug::log(Debug::Info) << "obj1:" << obj1 << " obj2:" << obj2 + << Debug::flush; + if( obj1 == obj2 ) { + Debug::log(Debug::Info) << "Idenity check passed; not using expando!" + << Debug::flush; + ScriptableInstance::jsIdentitySafe = true; + } else { + Debug::log(Debug::Info) << "Idenity check failed; using expando" + << Debug::flush; + ScriptableInstance::jsIdentitySafe = false; + } +} + + void ScriptableInstance::connect(const NPVariant* args, unsigned argCount, NPVariant* result) { - if (argCount != 5 || !NPVariantProxy::isString(args[0]) - || !NPVariantProxy::isString(args[1]) - || !NPVariantProxy::isString(args[2]) - || !NPVariantProxy::isString(args[3]) - || !NPVariantProxy::isString(args[4])) { + if (argCount != 5 || !NPVariantUtil::isString(args[0]) + || !NPVariantUtil::isString(args[1]) + || !NPVariantUtil::isString(args[2]) + || !NPVariantUtil::isString(args[3]) + || !NPVariantUtil::isString(args[4])) { // TODO: better failure? Debug::log(Debug::Error) << "ScriptableInstance::connect called with incorrect arguments:\n"; for (unsigned i = 0; i < argCount; ++i) { @@ -432,18 +460,9 @@ } int ScriptableInstance::getLocalObjectRef(NPObject* obj) { - NPVariantWrapper wrappedRetVal(*this); - int id; - if (NPN_GetProperty(getNPP(), obj, gwtId, wrappedRetVal.addressForReturn()) - && wrappedRetVal.isInt()) { - id = wrappedRetVal.getAsInt(); - localObjects.set(id, obj); - } else { + int id = localObjects.getObjectId(obj); + if(id == -1) { id = localObjects.add(obj); - wrappedRetVal = id; - if (!NPN_SetProperty(getNPP(), obj, gwtId, wrappedRetVal.address())) { - Debug::log(Debug::Error) << "Setting GWT id on object failed" << Debug::flush; - } } return id; } @@ -464,13 +483,8 @@ void ScriptableInstance::freeValue(HostChannel& channel, int idCount, const int* const ids) { Debug::log(Debug::Debugging) << "freeValue(#ids=" << idCount << ")" << Debug::flush; for (int i = 0; i < idCount; ++i) { - Debug::log(Debug::Spam) << " id=" << ids[i] << Debug::flush; - NPObject* obj = localObjects.get(ids[i]); - if (!NPN_RemoveProperty(getNPP(), obj, gwtId)) { - Debug::log(Debug::Error) << "Unable to remove GWT ID from object " << ids[i] << Debug::flush; - } else { - localObjects.free(ids[i]); - } + Debug::log(Debug::Spam) << " id=" << ids[i] << Debug::flush; + localObjects.free(ids[i]); } } @@ -494,7 +508,7 @@ return Value(); } int id = args[0].getInt(); - NPObject* obj = localObjects.get(id); + NPObject* obj = localObjects.getById(id); NPIdentifier propID; if (args[1].isString()) { string propName = args[1].getString(); @@ -523,7 +537,7 @@ return Value(); } int id = args[0].getInt(); - NPObject* obj = localObjects.get(id); + NPObject* obj = localObjects.getById(id); NPIdentifier propID; if (args[1].isString()) { string propName = args[1].getString(); @@ -677,7 +691,7 @@ Value propertyValue = ServerMethods::getProperty(*_channel, this, objectId, dispId); if (propertyValue.isJsObject()) { // TODO(jat): special-case for testing - NPObject* npObj = localObjects.get(propertyValue.getJsObjectId()); + NPObject* npObj = localObjects.getById(propertyValue.getJsObjectId()); OBJECT_TO_NPVARIANT(npObj, *result); NPN_RetainObject(npObj); } else { @@ -685,12 +699,12 @@ } Debug::log(Debug::Debugging) << " return val=" << propertyValue << ", NPVariant=" << *result << Debug::flush; - if (NPVariantProxy::isObject(*result)) { - dumpObjectBytes(NPVariantProxy::getAsObject(*result)); + if (NPVariantUtil::isObject(*result)) { + dumpObjectBytes(NPVariantUtil::getAsObject(*result)); } - if (NPVariantProxy::isObject(*result)) { + if (NPVariantUtil::isObject(*result)) { Debug::log(Debug::Debugging) << " final return refcount = " - << NPVariantProxy::getAsObject(*result)->referenceCount << Debug::flush; + << NPVariantUtil::getAsObject(*result)->referenceCount << Debug::flush; } return true; } @@ -699,17 +713,17 @@ const NPVariant* npValue) { Debug::log(Debug::Debugging) << "JavaObject_setProperty(objectid=" << objectId << ", dispId=" << dispId << ", value=" << *npValue << ")" << Debug::flush; - if (NPVariantProxy::isObject(*npValue)) { + if (NPVariantUtil::isObject(*npValue)) { Debug::log(Debug::Debugging) << " before localObj: refcount = " - << NPVariantProxy::getAsObject(*npValue)->referenceCount << Debug::flush; + << NPVariantUtil::getAsObject(*npValue)->referenceCount << Debug::flush; } Value value = NPVariantProxy::getAsValue(*npValue, *this, true); - if (NPVariantProxy::isObject(*npValue)) { + if (NPVariantUtil::isObject(*npValue)) { Debug::log(Debug::Debugging) << " after localObj: refcount = " - << NPVariantProxy::getAsObject(*npValue)->referenceCount << Debug::flush; + << NPVariantUtil::getAsObject(*npValue)->referenceCount << Debug::flush; } - if (NPVariantProxy::isObject(*npValue)) { - dumpObjectBytes(NPVariantProxy::getAsObject(*npValue)); + if (NPVariantUtil::isObject(*npValue)) { + dumpObjectBytes(NPVariantUtil::getAsObject(*npValue)); } Debug::log(Debug::Debugging) << " as value: " << value << Debug::flush; // TODO: no way to set an actual exception object! (Could ClassCastException on server.)
diff --git a/plugins/npapi/ScriptableInstance.h b/plugins/npapi/ScriptableInstance.h index a24e085..1bea653 100644 --- a/plugins/npapi/ScriptableInstance.h +++ b/plugins/npapi/ScriptableInstance.h
@@ -64,7 +64,8 @@ void dumpJSresult(const char* js); int getLocalObjectRef(NPObject* obj); - NPObject* getLocalObject(int refid) { return localObjects.get(refid); } + + NPObject* getLocalObject(int refid) { return localObjects.getById(refid); } bool tryGetStringPrimitive(NPObject* obj, NPVariant& result); @@ -87,6 +88,7 @@ HostChannel* _channel; LocalObjectTable localObjects; + static bool jsIdentitySafe; int savedValueIdx; // Identifiers @@ -100,10 +102,10 @@ const NPIdentifier urlID; const NPIdentifier includeID; const NPIdentifier getHostPermissionID; + const NPIdentifier testJsIdentityID; const NPIdentifier connectedID; const NPIdentifier statsID; - const NPIdentifier gwtId; const NPIdentifier jsDisconnectedID; const NPIdentifier jsInvokeID; @@ -133,7 +135,7 @@ void init(const NPVariant* args, unsigned argCount, NPVariant* result); void loadHostEntries(const NPVariant* args, unsigned argCount, NPVariant* result); void getHostPermission(const NPVariant* args, unsigned argCount, NPVariant* result); - + void testJsIdentity(const NPVariant* args, unsigned argCount, NPVariant* result); Value clientMethod_getProperty(HostChannel& channel, int numArgs, const Value* const args); Value clientMethod_setProperty(HostChannel& channel, int numArgs, const Value* const args);
diff --git a/plugins/npapi/prebuilt/gwt-dev-plugin/background.html b/plugins/npapi/prebuilt/gwt-dev-plugin/background.html index fe60956..73f674d 100644 --- a/plugins/npapi/prebuilt/gwt-dev-plugin/background.html +++ b/plugins/npapi/prebuilt/gwt-dev-plugin/background.html
@@ -65,6 +65,9 @@ var icon = null; console.log("got permission " + permission + " for host " + host + '/ code ' + code); + var idObject = {}; + plugin.testJsIdentity( idObject, idObject ); + if (permission == 'include') { icon = enabledIcon; } else if (permission == 'exclude') {