Update Chrome plugin naming, cleanup leftover garbage, commit object
freeing code that was never committed.
This was originally committed to the changes/jat/single-xpi branch by
mistake.
Patch by: jat
Review by: rice (TBR)
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@6779 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/plugins/npapi/LocalObjectTable.h b/plugins/npapi/LocalObjectTable.h
index 9ff809d..7d95509 100644
--- a/plugins/npapi/LocalObjectTable.h
+++ b/plugins/npapi/LocalObjectTable.h
@@ -16,8 +16,7 @@
* the License.
*/
-#include <vector>
-#include <algorithm>
+#include <map>
#include "Debug.h"
@@ -25,27 +24,21 @@
class LocalObjectTable {
private:
- static const int INITIAL_OBJECT_TABLE_SIZE = 300;
+ typedef std::map<int, NPObject*> ObjectMap;
- int nextFree;
- std::vector<NPObject*> objects;
+ int nextId;
+ ObjectMap objects;
bool dontFree;
- bool isFree(int id) {
- // low bit is set for free pointers, object pointers can't be odd
- NPObject* obj = objects[id];
- return !obj || (reinterpret_cast<long long>(obj) & 1);
- }
-
void setFree(int id) {
- objects[id] = reinterpret_cast<NPObject*>((nextFree << 1) | 1LL);
- nextFree = id;
+ if (objects.erase(id) != 1) {
+ Debug::log(Debug::Error) << "setFree(id=" << id << "): object not in table"
+ << Debug::flush;
+ }
}
public:
LocalObjectTable() {
- nextFree = -1;
- objects.reserve(INITIAL_OBJECT_TABLE_SIZE);
dontFree = false;
}
@@ -55,64 +48,51 @@
* Add a new object, which must not be in the table, and return a new id for it.
*/
int add(NPObject* obj) {
- int id;
- if (nextFree >= 0) {
- id = nextFree;
- nextFree = int(reinterpret_cast<long long>(objects[nextFree])) >> 1;
- objects[id] = obj;
- } else {
- id = static_cast<int>(objects.size());
- objects.push_back(obj);
- }
- Debug::log(Debug::Spam) << "LocalObjectTable::add(obj=" << obj << "): id=" << id
- << Debug::flush;
- // keep track that we hold a reference in the table
- NPN_RetainObject(obj);
+ int id = nextId++;
+ set(id, obj);
return id;
}
+ void set(int id, NPObject* obj) {
+ Debug::log(Debug::Info) << "LocalObjectTable::set(id=" << id << ",obj=" << (void*)obj
+ << ")" << Debug::flush;
+ objects[id] = obj;
+ // 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;
- if (unsigned(id) >= objects.size()) {
- Debug::log(Debug::Error) << "LocalObjectTable::free(id=" << id << "): invalid index (size="
- << objects.size() << Debug::flush;
- return;
- }
- if (isFree(id)) {
+ Debug::log(Debug::Info) << "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;
}
- NPObject* obj = objects[id];
setFree(id);
if (!dontFree) {
+ NPObject* obj = it->second;
NPN_ReleaseObject(obj);
}
}
void freeAll() {
- Debug::log(Debug::Spam) << "LocalObjectTable::freeAll()" << Debug::flush;
- for (unsigned i = 0; i < objects.size(); ++i) {
- if (!isFree(i)) {
- NPObject* obj = objects[i];
- setFree(i);
- if (!dontFree) {
- NPN_ReleaseObject(obj);
- }
+ Debug::log(Debug::Info) << "LocalObjectTable::freeAll()" << Debug::flush;
+ for (ObjectMap::const_iterator it = objects.begin(); it != objects.end(); ++it) {
+ NPObject* obj = it->second;
+ if (!dontFree) {
+ NPN_ReleaseObject(obj);
}
}
+ objects.clear();
}
NPObject* get(int id) {
- if (unsigned(id) >= objects.size()) {
- Debug::log(Debug::Error) << "LocalObjectTable::get(id=" << id << "): invalid index (size="
- << objects.size() << Debug::flush;
- return 0;
+ ObjectMap::iterator it = objects.find(id);
+ if (it == objects.end()) {
+ Debug::log(Debug::Error) << "LocalObjectTable::get(id=" << id
+ << "): no object found" << Debug::flush;
}
- if (isFree(id)) {
- Debug::log(Debug::Error) << "Getting freed object slot " << id << Debug::flush;
- return 0;
- }
- return objects[id];
+ return it->second;
}
void setDontFree(bool dontFree) {
diff --git a/plugins/npapi/ScriptableInstance.cpp b/plugins/npapi/ScriptableInstance.cpp
index 6a137bd..6149ffc 100644
--- a/plugins/npapi/ScriptableInstance.cpp
+++ b/plugins/npapi/ScriptableInstance.cpp
@@ -1,276 +1,276 @@
-/*
- * 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 <cstring>
-
-#include "ScriptableInstance.h"
-#include "InvokeMessage.h"
-#include "ReturnMessage.h"
-#include "ServerMethods.h"
-#include "AllowedConnections.h"
-#include "Preferences.h"
-#include "AllowDialog.h"
-
-#include "mozincludes.h"
-#include "scoped_ptr/scoped_ptr.h"
-#include "NPVariantWrapper.h"
-
-using std::string;
-using std::endl;
-
-static inline string convertToString(const NPString& str) {
- return string(GetNPStringUTF8Characters(str), GetNPStringUTF8Length(str));
-}
-
-string ScriptableInstance::computeTabIdentity() {
- return "";
-}
-
-void ScriptableInstance::dumpObjectBytes(NPObject* obj) {
- char buf[20];
- Debug::log(Debug::Debugging) << " object bytes:\n";
- const unsigned char* ptr = reinterpret_cast<const unsigned char*>(obj);
- for (int i = 0; i < 24; ++i) {
- snprintf(buf, sizeof(buf), " %02x", ptr[i]);
- Debug::log(Debug::Debugging) << buf;
- }
- NPVariant objVar;
- OBJECT_TO_NPVARIANT(obj, objVar);
- Debug::log(Debug::Debugging) << " obj.toString()="
- << NPVariantProxy::toString(objVar) << Debug::flush;
-}
-
-ScriptableInstance::ScriptableInstance(NPP npp) : NPObjectWrapper<ScriptableInstance>(npp),
- plugin(*reinterpret_cast<Plugin*>(npp->pdata)),
- _channel(new HostChannel()),
- localObjects(),
- _connectId(NPN_GetStringIdentifier("connect")),
- initID(NPN_GetStringIdentifier("init")),
- toStringID(NPN_GetStringIdentifier("toString")),
- connectedID(NPN_GetStringIdentifier("connected")),
- statsID(NPN_GetStringIdentifier("stats")),
- gwtId(NPN_GetStringIdentifier("__gwt_ObjectId")),
- jsInvokeID(NPN_GetStringIdentifier("__gwt_jsInvoke")),
- jsResultID(NPN_GetStringIdentifier("__gwt_makeResult")),
- jsTearOffID(NPN_GetStringIdentifier("__gwt_makeTearOff")),
- jsValueOfID(NPN_GetStringIdentifier("valueOf")),
- idx0(NPN_GetIntIdentifier(0)),
- idx1(NPN_GetIntIdentifier(1)) {
- savedValueIdx = -1;
- if (NPN_GetValue(npp, NPNVWindowNPObject, &window) != NPERR_NO_ERROR) {
- Debug::log(Debug::Error) << "Error getting window object" << Debug::flush;
- }
-}
-
-ScriptableInstance::~ScriptableInstance() {
- // TODO(jat): free any remaining Java objects held by JS, then make
- // the JS wrapper handle that situation gracefully
- if (window) {
- NPN_ReleaseObject(window);
- }
- for (hash_map<int, JavaObject*>::iterator it = javaObjects.begin(); it != javaObjects.end();
- ++it) {
- Debug::log(Debug::Spam) << " disconnecting Java wrapper " << it->first << Debug::flush;
- it->second->disconnectPlugin();
- }
- if (_channel) {
- _channel->disconnectFromHost();
- delete _channel;
- }
-}
-
-void ScriptableInstance::dumpJSresult(const char* js) {
- NPString npScript;
- dupString(js, npScript);
- NPVariantWrapper wrappedRetVal(*this);
- if (!NPN_Evaluate(getNPP(), window, &npScript, wrappedRetVal.addressForReturn())) {
- Debug::log(Debug::Error) << " *** dumpJSresult failed" << Debug::flush;
- return;
- }
- Debug::log(Debug::Info) << "dumpWindow=" << wrappedRetVal.toString() << Debug::flush;
-}
-
-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)) {
- return true;
- }
- NPVariantProxy::release(result);
- }
- return false;
-}
-
-bool ScriptableInstance::makeResult(bool isException, const Value& value, NPVariant* result) {
- Debug::log(Debug::Debugging) << "makeResult(" << isException << ", " << value << ")"
- << Debug::flush;
- Value temp;
- if (value.getType() == Value::JAVA_OBJECT) {
- int javaId = value.getJavaObjectId();
- // We may have previously released the proxy for the same object id,
- // but have not yet sent a free message back to the server.
- javaObjectsToFree.erase(javaId);
- }
- NPVariantArray varArgs(*this, 3);
- varArgs[0] = isException ? 1 : 0;
- varArgs[1] = value;
- NPVariantWrapper retVal(*this);
- return NPN_Invoke(getNPP(), window, jsResultID, varArgs.getArray(), varArgs.getSize(), result);
-}
-
-//=====================================================================================
-// NPObject methods
-//=====================================================================================
-
-bool ScriptableInstance::hasProperty(NPIdentifier name) {
- if (!NPN_IdentifierIsString(name)) {
- // all numeric properties are ok, as we assume only JSNI code is making
- // the field access via dispatchID
- return true;
- }
- // TODO: special-case toString tear-offs
- return name == statsID || name == connectedID;
-}
-
-bool ScriptableInstance::getProperty(NPIdentifier name, NPVariant* variant) {
- Debug::log(Debug::Debugging) << "ScriptableInstance::getProperty(name="
- << NPN_UTF8FromIdentifier(name) << ")" << Debug::flush;
- bool retVal = false;
- VOID_TO_NPVARIANT(*variant);
- if (name == connectedID) {
- BOOLEAN_TO_NPVARIANT(_channel->isConnected(), *variant);
- retVal = true;
- } else if (name == statsID) {
- NPVariantProxy::assignFrom(*variant, "<stats data>");
- retVal = true;
- }
- if (retVal) {
- // TODO: testing
- Debug::log(Debug::Debugging) << " return value " << *variant
- << Debug::flush;
- }
- return retVal;
-}
-
-bool ScriptableInstance::setProperty(NPIdentifier name, const NPVariant* variant) {
- Debug::log(Debug::Debugging) << "ScriptableInstance::setProperty(name="
- << NPN_UTF8FromIdentifier(name) << ", value=" << *variant << ")"
- << Debug::flush;
- return false;
-}
-
-bool ScriptableInstance::hasMethod(NPIdentifier name) {
- Debug::log(Debug::Debugging) << "ScriptableInstance::hasMethod(name=" << NPN_UTF8FromIdentifier(name) << ")"
- << Debug::flush;
- if (name == _connectId || name == initID || name == toStringID) {
- return true;
- }
- return false;
-}
-
-bool ScriptableInstance::invoke(NPIdentifier name, const NPVariant* args, unsigned argCount,
- NPVariant* result) {
- NPUTF8* uname = NPN_UTF8FromIdentifier(name);
- Debug::log(Debug::Debugging) << "ScriptableInstance::invoke(name=" << uname << ",#args=" << argCount << ")"
- << Debug::flush;
- VOID_TO_NPVARIANT(*result);
- if (name == _connectId) {
- connect(args, argCount, result);
- } else if (name == initID) {
- init(args, argCount, result);
- } else if (name == toStringID) {
- // TODO(jat): figure out why this doesn't show in Firebug
- string val("[GWT OOPHM Plugin: connected=");
- val += _channel->isConnected() ? 'Y' : 'N';
- val += ']';
- NPVariantProxy::assignFrom(*result, val);
- }
- return true;
-}
-
-bool ScriptableInstance::invokeDefault(const NPVariant* args, unsigned argCount,
- NPVariant* result) {
- Debug::log(Debug::Debugging) << "ScriptableInstance::invokeDefault(#args=" << argCount << ")"
- << Debug::flush;
- VOID_TO_NPVARIANT(*result);
- return true;
-}
-
-bool ScriptableInstance::enumeration(NPIdentifier** propReturn, uint32_t* count) {
- Debug::log(Debug::Debugging) << "ScriptableInstance::enumeration()" << Debug::flush;
- int n = 2;
- NPIdentifier* props = static_cast<NPIdentifier*>(NPN_MemAlloc(sizeof(NPIdentifier) * n));
- props[0] = connectedID;
- props[1] = statsID;
- *propReturn = props;
- *count = n;
- return true;
-}
-
-//=====================================================================================
-// internal methods
-//=====================================================================================
-
-void ScriptableInstance::init(const NPVariant* args, unsigned argCount, NPVariant* result) {
- if (argCount != 1 || !NPVariantProxy::isObject(args[0])) {
- // TODO: better failure?
- Debug::log(Debug::Error) << "ScriptableInstance::init called with incorrect arguments:\n";
- for (unsigned i = 0; i < argCount; ++i) {
- Debug::log(Debug::Error) << " " << i << " " << NPVariantProxy::toString(args[i]) << "\n";
- }
- Debug::log(Debug::Error) << Debug::flush;
- result->type = NPVariantType_Void;
- return;
- }
- if (window) {
- NPN_ReleaseObject(window);
- }
- // replace our window object with that passed by the caller
- window = NPVariantProxy::getAsObject(args[0]);
- NPN_RetainObject(window);
- BOOLEAN_TO_NPVARIANT(true, *result);
- result->type = NPVariantType_Bool;
-}
-
-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])) {
- // TODO: better failure?
- Debug::log(Debug::Error) << "ScriptableInstance::connect called with incorrect arguments:\n";
- for (unsigned i = 0; i < argCount; ++i) {
- Debug::log(Debug::Error) << " " << i << " " << NPVariantProxy::toString(args[i]) << "\n";
- }
- Debug::log(Debug::Error) << Debug::flush;
- result->type = NPVariantType_Void;
- return;
- }
- const NPString url = args[0].value.stringValue;
- const NPString sessionKey = args[1].value.stringValue;
- const NPString hostAddr = args[2].value.stringValue;
- const NPString moduleName = args[3].value.stringValue;
- const NPString hostedHtmlVersion = args[4].value.stringValue;
- Debug::log(Debug::Info) << "ScriptableInstance::connect(url=" << NPVariantProxy::toString(args[0])
- << ",sessionKey=" << NPVariantProxy::toString(args[1]) << ",host=" << NPVariantProxy::toString(args[2])
- << ",module=" << NPVariantProxy::toString(args[3]) << ",hostedHtmlVers=" << NPVariantProxy::toString(args[4])
- << ")" << Debug::flush;
- const std::string urlStr = convertToString(url);
-
+/*
+ * 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 <cstring>
+
+#include "ScriptableInstance.h"
+#include "InvokeMessage.h"
+#include "ReturnMessage.h"
+#include "ServerMethods.h"
+#include "AllowedConnections.h"
+#include "Preferences.h"
+#include "AllowDialog.h"
+
+#include "mozincludes.h"
+#include "scoped_ptr/scoped_ptr.h"
+#include "NPVariantWrapper.h"
+
+using std::string;
+using std::endl;
+
+static inline string convertToString(const NPString& str) {
+ return string(GetNPStringUTF8Characters(str), GetNPStringUTF8Length(str));
+}
+
+string ScriptableInstance::computeTabIdentity() {
+ return "";
+}
+
+void ScriptableInstance::dumpObjectBytes(NPObject* obj) {
+ char buf[20];
+ Debug::log(Debug::Debugging) << " object bytes:\n";
+ const unsigned char* ptr = reinterpret_cast<const unsigned char*>(obj);
+ for (int i = 0; i < 24; ++i) {
+ snprintf(buf, sizeof(buf), " %02x", ptr[i]);
+ Debug::log(Debug::Debugging) << buf;
+ }
+ NPVariant objVar;
+ OBJECT_TO_NPVARIANT(obj, objVar);
+ Debug::log(Debug::Debugging) << " obj.toString()="
+ << NPVariantProxy::toString(objVar) << Debug::flush;
+}
+
+ScriptableInstance::ScriptableInstance(NPP npp) : NPObjectWrapper<ScriptableInstance>(npp),
+ plugin(*reinterpret_cast<Plugin*>(npp->pdata)),
+ _channel(new HostChannel()),
+ localObjects(),
+ _connectId(NPN_GetStringIdentifier("connect")),
+ initID(NPN_GetStringIdentifier("init")),
+ toStringID(NPN_GetStringIdentifier("toString")),
+ connectedID(NPN_GetStringIdentifier("connected")),
+ statsID(NPN_GetStringIdentifier("stats")),
+ gwtId(NPN_GetStringIdentifier("__gwt_ObjectId")),
+ jsInvokeID(NPN_GetStringIdentifier("__gwt_jsInvoke")),
+ jsResultID(NPN_GetStringIdentifier("__gwt_makeResult")),
+ jsTearOffID(NPN_GetStringIdentifier("__gwt_makeTearOff")),
+ jsValueOfID(NPN_GetStringIdentifier("valueOf")),
+ idx0(NPN_GetIntIdentifier(0)),
+ idx1(NPN_GetIntIdentifier(1)) {
+ savedValueIdx = -1;
+ if (NPN_GetValue(npp, NPNVWindowNPObject, &window) != NPERR_NO_ERROR) {
+ Debug::log(Debug::Error) << "Error getting window object" << Debug::flush;
+ }
+}
+
+ScriptableInstance::~ScriptableInstance() {
+ // TODO(jat): free any remaining Java objects held by JS, then make
+ // the JS wrapper handle that situation gracefully
+ if (window) {
+ NPN_ReleaseObject(window);
+ }
+ for (hash_map<int, JavaObject*>::iterator it = javaObjects.begin(); it != javaObjects.end();
+ ++it) {
+ Debug::log(Debug::Spam) << " disconnecting Java wrapper " << it->first << Debug::flush;
+ it->second->disconnectPlugin();
+ }
+ if (_channel) {
+ _channel->disconnectFromHost();
+ delete _channel;
+ }
+}
+
+void ScriptableInstance::dumpJSresult(const char* js) {
+ NPString npScript;
+ dupString(js, npScript);
+ NPVariantWrapper wrappedRetVal(*this);
+ if (!NPN_Evaluate(getNPP(), window, &npScript, wrappedRetVal.addressForReturn())) {
+ Debug::log(Debug::Error) << " *** dumpJSresult failed" << Debug::flush;
+ return;
+ }
+ Debug::log(Debug::Info) << "dumpWindow=" << wrappedRetVal.toString() << Debug::flush;
+}
+
+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)) {
+ return true;
+ }
+ NPVariantProxy::release(result);
+ }
+ return false;
+}
+
+bool ScriptableInstance::makeResult(bool isException, const Value& value, NPVariant* result) {
+ Debug::log(Debug::Debugging) << "makeResult(" << isException << ", " << value << ")"
+ << Debug::flush;
+ Value temp;
+ if (value.getType() == Value::JAVA_OBJECT) {
+ int javaId = value.getJavaObjectId();
+ // We may have previously released the proxy for the same object id,
+ // but have not yet sent a free message back to the server.
+ javaObjectsToFree.erase(javaId);
+ }
+ NPVariantArray varArgs(*this, 3);
+ varArgs[0] = isException ? 1 : 0;
+ varArgs[1] = value;
+ NPVariantWrapper retVal(*this);
+ return NPN_Invoke(getNPP(), window, jsResultID, varArgs.getArray(), varArgs.getSize(), result);
+}
+
+//=============================================================================
+// NPObject methods
+//=============================================================================
+
+bool ScriptableInstance::hasProperty(NPIdentifier name) {
+ if (!NPN_IdentifierIsString(name)) {
+ // all numeric properties are ok, as we assume only JSNI code is making
+ // the field access via dispatchID
+ return true;
+ }
+ // TODO: special-case toString tear-offs
+ return name == statsID || name == connectedID;
+}
+
+bool ScriptableInstance::getProperty(NPIdentifier name, NPVariant* variant) {
+ Debug::log(Debug::Debugging) << "ScriptableInstance::getProperty(name="
+ << NPN_UTF8FromIdentifier(name) << ")" << Debug::flush;
+ bool retVal = false;
+ VOID_TO_NPVARIANT(*variant);
+ if (name == connectedID) {
+ BOOLEAN_TO_NPVARIANT(_channel->isConnected(), *variant);
+ retVal = true;
+ } else if (name == statsID) {
+ NPVariantProxy::assignFrom(*variant, "<stats data>");
+ retVal = true;
+ }
+ if (retVal) {
+ // TODO: testing
+ Debug::log(Debug::Debugging) << " return value " << *variant
+ << Debug::flush;
+ }
+ return retVal;
+}
+
+bool ScriptableInstance::setProperty(NPIdentifier name, const NPVariant* variant) {
+ Debug::log(Debug::Debugging) << "ScriptableInstance::setProperty(name="
+ << NPN_UTF8FromIdentifier(name) << ", value=" << *variant << ")"
+ << Debug::flush;
+ return false;
+}
+
+bool ScriptableInstance::hasMethod(NPIdentifier name) {
+ Debug::log(Debug::Debugging) << "ScriptableInstance::hasMethod(name=" << NPN_UTF8FromIdentifier(name) << ")"
+ << Debug::flush;
+ if (name == _connectId || name == initID || name == toStringID) {
+ return true;
+ }
+ return false;
+}
+
+bool ScriptableInstance::invoke(NPIdentifier name, const NPVariant* args, unsigned argCount,
+ NPVariant* result) {
+ NPUTF8* uname = NPN_UTF8FromIdentifier(name);
+ Debug::log(Debug::Debugging) << "ScriptableInstance::invoke(name=" << uname << ",#args=" << argCount << ")"
+ << Debug::flush;
+ VOID_TO_NPVARIANT(*result);
+ if (name == _connectId) {
+ connect(args, argCount, result);
+ } else if (name == initID) {
+ init(args, argCount, result);
+ } else if (name == toStringID) {
+ // TODO(jat): figure out why this doesn't show in Firebug
+ string val("[GWT OOPHM Plugin: connected=");
+ val += _channel->isConnected() ? 'Y' : 'N';
+ val += ']';
+ NPVariantProxy::assignFrom(*result, val);
+ }
+ return true;
+}
+
+bool ScriptableInstance::invokeDefault(const NPVariant* args, unsigned argCount,
+ NPVariant* result) {
+ Debug::log(Debug::Debugging) << "ScriptableInstance::invokeDefault(#args=" << argCount << ")"
+ << Debug::flush;
+ VOID_TO_NPVARIANT(*result);
+ return true;
+}
+
+bool ScriptableInstance::enumeration(NPIdentifier** propReturn, uint32_t* count) {
+ Debug::log(Debug::Debugging) << "ScriptableInstance::enumeration()" << Debug::flush;
+ int n = 2;
+ NPIdentifier* props = static_cast<NPIdentifier*>(NPN_MemAlloc(sizeof(NPIdentifier) * n));
+ props[0] = connectedID;
+ props[1] = statsID;
+ *propReturn = props;
+ *count = n;
+ return true;
+}
+
+//=============================================================================
+// internal methods
+//=============================================================================
+
+void ScriptableInstance::init(const NPVariant* args, unsigned argCount, NPVariant* result) {
+ if (argCount != 1 || !NPVariantProxy::isObject(args[0])) {
+ // TODO: better failure?
+ Debug::log(Debug::Error) << "ScriptableInstance::init called with incorrect arguments:\n";
+ for (unsigned i = 0; i < argCount; ++i) {
+ Debug::log(Debug::Error) << " " << i << " " << NPVariantProxy::toString(args[i]) << "\n";
+ }
+ Debug::log(Debug::Error) << Debug::flush;
+ result->type = NPVariantType_Void;
+ return;
+ }
+ if (window) {
+ NPN_ReleaseObject(window);
+ }
+ // replace our window object with that passed by the caller
+ window = NPVariantProxy::getAsObject(args[0]);
+ NPN_RetainObject(window);
+ BOOLEAN_TO_NPVARIANT(true, *result);
+ result->type = NPVariantType_Bool;
+}
+
+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])) {
+ // TODO: better failure?
+ Debug::log(Debug::Error) << "ScriptableInstance::connect called with incorrect arguments:\n";
+ for (unsigned i = 0; i < argCount; ++i) {
+ Debug::log(Debug::Error) << " " << i << " " << NPVariantProxy::toString(args[i]) << "\n";
+ }
+ Debug::log(Debug::Error) << Debug::flush;
+ result->type = NPVariantType_Void;
+ return;
+ }
+ const NPString url = args[0].value.stringValue;
+ const NPString sessionKey = args[1].value.stringValue;
+ const NPString hostAddr = args[2].value.stringValue;
+ const NPString moduleName = args[3].value.stringValue;
+ const NPString hostedHtmlVersion = args[4].value.stringValue;
+ Debug::log(Debug::Info) << "ScriptableInstance::connect(url=" << NPVariantProxy::toString(args[0])
+ << ",sessionKey=" << NPVariantProxy::toString(args[1]) << ",host=" << NPVariantProxy::toString(args[2])
+ << ",module=" << NPVariantProxy::toString(args[3]) << ",hostedHtmlVers=" << NPVariantProxy::toString(args[4])
+ << ")" << Debug::flush;
+ const std::string urlStr = convertToString(url);
+
Preferences::loadAccessList();
bool allowed = false;
if (!AllowedConnections::matchesRule(urlStr, &allowed)) {
@@ -281,387 +281,388 @@
Preferences::addNewRule(host, !allowed);
}
}
- if (!allowed) {
- BOOLEAN_TO_NPVARIANT(false, *result);
- result->type = NPVariantType_Bool;
- return;
- }
-
- bool connected = false;
- unsigned port = 9997; // TODO(jat): should there be a default?
- int n = GetNPStringUTF8Length(hostAddr);
- scoped_ptr<char> host(new char[n + 1]);
- const char* s = GetNPStringUTF8Characters(hostAddr);
- char* d = host.get();
- while (n > 0 && *s != ':') {
- n--;
- *d++ = *s++;
- }
- *d = 0;
- if (n > 0) {
- port = atoi(s + 1);
- }
- Debug::log(Debug::Info) << " host=" << host.get() << ",port=" << port << Debug::flush;
-
-
- if (!_channel->connectToHost(host.get(), port)) {
- BOOLEAN_TO_NPVARIANT(false, *result);
- result->type = NPVariantType_Bool;
- }
-
- string hostedHtmlVersionStr = convertToString(hostedHtmlVersion);
- if (!_channel->init(this, BROWSERCHANNEL_PROTOCOL_VERSION,
- BROWSERCHANNEL_PROTOCOL_VERSION, hostedHtmlVersionStr)) {
- BOOLEAN_TO_NPVARIANT(false, *result);
- result->type = NPVariantType_Bool;
- }
-
- string moduleNameStr = convertToString(moduleName);
- string userAgent(NPN_UserAgent(getNPP()));
- string tabKeyStr = computeTabIdentity();
- string sessionKeyStr = convertToString(sessionKey);
- Debug::log(Debug::Debugging) << " connected, sending loadModule" << Debug::flush;
- connected = LoadModuleMessage::send(*_channel, urlStr, tabKeyStr, sessionKeyStr,
- moduleNameStr, userAgent, this);
- BOOLEAN_TO_NPVARIANT(connected, *result);
- result->type = NPVariantType_Bool;
-}
-
-int ScriptableInstance::getLocalObjectRef(NPObject* obj) {
- NPVariantWrapper wrappedRetVal(*this);
- int id;
- if (NPN_GetProperty(getNPP(), obj, gwtId, wrappedRetVal.addressForReturn())
- && wrappedRetVal.isInt()) {
- id = wrappedRetVal.getAsInt();
- } else {
- 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;
-}
-
-void ScriptableInstance::fatalError(HostChannel& channel, const std::string& message) {
- // TODO(jat): better error handling
- Debug::log(Debug::Error) << "Fatal error: " << message << Debug::flush;
-}
-
-void ScriptableInstance::dupString(const char* str, NPString& npString) {
- npString.UTF8Length = static_cast<uint32_t>(strlen(str));
- NPUTF8* chars = static_cast<NPUTF8*>(NPN_MemAlloc(npString.UTF8Length));
- memcpy(chars, str, npString.UTF8Length);
- npString.UTF8Characters = chars;
-}
-
-// SessionHandler methods
-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]);
- }
- }
-}
-
-void ScriptableInstance::loadJsni(HostChannel& channel, const std::string& js) {
- NPString npScript;
- dupString(js.c_str(), npScript);
- NPVariantWrapper npResult(*this);
- Debug::log(Debug::Spam) << "loadJsni - \n" << js << Debug::flush;
- if (!NPN_Evaluate(getNPP(), window, &npScript, npResult.addressForReturn())) {
- Debug::log(Debug::Error) << "loadJsni failed\n" << js << Debug::flush;
- }
-}
-
-Value ScriptableInstance::clientMethod_getProperty(HostChannel& channel, int numArgs, const Value* const args) {
- if (numArgs != 2 || !args[0].isInt() || (!args[1].isString() && !args[1].isInt())) {
- Debug::log(Debug::Error) << "Incorrect invocation of getProperty: #args=" << numArgs << ":";
- for (int i = 0; i < numArgs; ++i) {
- Debug::log(Debug::Error) << " " << i << "=" << args[i].toString();
- }
- Debug::log(Debug::Error) << Debug::flush;
- return Value();
- }
- int id = args[0].getInt();
- NPObject* obj = localObjects.get(id);
- NPIdentifier propID;
- if (args[1].isString()) {
- std::string propName = args[1].getString();
- propID = NPN_GetStringIdentifier(propName.c_str());
- } else {
- int propNum = args[1].getInt();
- propID = NPN_GetIntIdentifier(propNum);
- }
- NPVariantWrapper npResult(*this);
- if (!NPN_GetProperty(getNPP(), obj, propID, npResult.addressForReturn())) {
- Debug::log(Debug::Warning) << "getProperty(id=" << id << ", prop="
- << NPN_UTF8FromIdentifier(propID) << ") failed" << Debug::flush;
- return Value();
- }
- return npResult.getAsValue(*this);
-}
-
-Value ScriptableInstance::clientMethod_setProperty(HostChannel& channel, int numArgs, const Value* const args) {
- if (numArgs != 2 || !args[0].isInt() || (!args[1].isString() && !args[1].isInt())) {
- Debug::log(Debug::Error) << "Incorrect invocation of setProperty: #args="
- << numArgs << ":";
- for (int i = 0; i < numArgs; ++i) {
- Debug::log(Debug::Error) << " " << i << "=" << args[i].toString();
- }
- Debug::log(Debug::Error) << Debug::flush;
- return Value();
- }
- int id = args[0].getInt();
- NPObject* obj = localObjects.get(id);
- NPIdentifier propID;
- if (args[1].isString()) {
- std::string propName = args[1].getString();
- propID = NPN_GetStringIdentifier(propName.c_str());
- } else {
- int propNum = args[1].getInt();
- propID = NPN_GetIntIdentifier(propNum);
- }
- NPVariantWrapper npValue(*this);
- npValue.operator=(args[2]);
- if (!NPN_SetProperty(getNPP(), obj, propID, npValue.address())) {
- Debug::log(Debug::Warning) << "setProperty(id=" << id << ", prop="
- << NPN_UTF8FromIdentifier(propID) << ", val=" << args[2].toString()
- << ") failed" << Debug::flush;
- return Value();
- }
- return Value();
-}
-
-/**
- * SessionHandler.invoke - used by LoadModule and reactToMessages* to process server-side
- * requests to invoke methods in Javascript or the plugin.
- */
-bool ScriptableInstance::invokeSpecial(HostChannel& channel, SpecialMethodId dispatchId,
- int numArgs, const Value* const args, Value* returnValue) {
- switch (dispatchId) {
- case SessionHandler::HasMethod:
- case SessionHandler::HasProperty:
- break;
- case SessionHandler::SetProperty:
- *returnValue = clientMethod_setProperty(channel, numArgs, args);
- return false;
- case SessionHandler::GetProperty:
- *returnValue = clientMethod_getProperty(channel, numArgs, args);
- return false;
- default:
- break;
- }
- Debug::log(Debug::Error) << "Unexpected special method " << dispatchId
- << " called on plugin; #args=" << numArgs << ":";
- for (int i = 0; i < numArgs; ++i) {
- Debug::log(Debug::Error) << " " << i << "=" << args[i].toString();
- }
- Debug::log(Debug::Error) << Debug::flush;
- // TODO(jat): should we create a real exception object?
- std::string buf("unexpected invokeSpecial(");
- buf += static_cast<int>(dispatchId);
- buf += ")";
- returnValue->setString(buf);
- return true;
-}
-
-bool ScriptableInstance::invoke(HostChannel& channel, const Value& thisRef,
- const std::string& methodName, int numArgs, const Value* const args,
- Value* returnValue) {
- Debug::log(Debug::Debugging) << "invokeJS(" << methodName << ", this="
- << thisRef.toString() << ", numArgs=" << numArgs << ")" << Debug::flush;
- NPVariantArray varArgs(*this, numArgs + 2);
- varArgs[0] = thisRef;
- varArgs[1] = methodName;
- for (int i = 0; i < numArgs; ++i) {
- varArgs[i + 2] = args[i];
- }
- const NPVariant* argArray = varArgs.getArray();
- if (Debug::level(Debug::Spam)) {
- for (int i = 0; i < varArgs.getSize(); ++i) {
- Debug::log(Debug::Spam) << " arg " << i << " is "
- << NPVariantProxy::toString(argArray[i]) << Debug::flush;
- }
- }
- NPVariantWrapper wrappedRetVal(*this);
- if (!NPN_Invoke(getNPP(), window, jsInvokeID, argArray, varArgs.getSize(),
- wrappedRetVal.addressForReturn())) {
- Debug::log(Debug::Error) << "*** invokeJS(" << methodName << ", this="
- << thisRef.toString() << ", numArgs=" << numArgs << ") failed"
- << Debug::flush;
- // TODO(jat): should we create a real exception object?
- returnValue->setString("invoke of " + methodName + " failed");
- return true;
- }
- Debug::log(Debug::Spam) << " wrapped return is " << wrappedRetVal.toString() << Debug::flush;
- NPVariantWrapper exceptFlag(*this);
- NPVariantWrapper retval(*this);
- NPObject* wrappedArray = wrappedRetVal.getAsObject();
- if (!NPN_GetProperty(getNPP(), wrappedArray, idx0, exceptFlag.addressForReturn())) {
- Debug::log(Debug::Error) << " Error getting element 0 of wrapped return value ("
- << wrappedRetVal << ") on call to " << methodName << Debug::flush;
- }
- if (!NPN_GetProperty(getNPP(), wrappedArray, idx1, retval.addressForReturn())) {
- Debug::log(Debug::Error) << " Error getting element 1 of wrapped return value ("
- << wrappedRetVal << ") on call to " << methodName << Debug::flush;
- }
- Debug::log(Debug::Debugging) << " return value " << retval.toString() << Debug::flush;
- *returnValue = retval.getAsValue(*this);
- if (exceptFlag.isInt() && exceptFlag.getAsInt() != 0) {
- Debug::log(Debug::Debugging) << " exception: " << retval << Debug::flush;
- return true;
- }
- return false;
-}
-
-bool ScriptableInstance::JavaObject_invoke(int objectId, int dispId,
- const NPVariant* args, uint32_t numArgs, NPVariant* result) {
- Debug::log(Debug::Debugging) << "JavaObject_invoke(dispId= " << dispId << ", numArgs=" << numArgs << ")" << Debug::flush;
- if (Debug::level(Debug::Spam)) {
- for (uint32_t i = 0; i < numArgs; ++i) {
- Debug::log(Debug::Spam) << " " << i << " = " << args[i] << Debug::flush;
- }
- }
-
- bool isRawToString = false;
- if (dispId == -1) {
- dispId = 0;
- isRawToString = true;
- }
-
- Value javaThis;
- javaThis.setJavaObject(objectId);
- scoped_array<Value> vargs(new Value[numArgs]);
- for (unsigned i = 0; i < numArgs; ++i) {
- vargs[i] = NPVariantProxy::getAsValue(args[i], *this);
- }
- if (!InvokeMessage::send(*_channel, javaThis, dispId, numArgs, vargs.get())) {
- Debug::log(Debug::Error) << "JavaObject_invoke: failed to send invoke message" << Debug::flush;
- // TODO(jat): returning false here spams the browser console
- return true;
- }
- Debug::log(Debug::Debugging) << " return from invoke" << Debug::flush;
- scoped_ptr<ReturnMessage> retMsg(_channel->reactToMessagesWhileWaitingForReturn(this));
- if (!retMsg.get()) {
- Debug::log(Debug::Error) << "JavaObject_invoke: failed to get return value" << Debug::flush;
- return false;
- }
- if (isRawToString) {
- // toString() needs the raw value
- NPVariantProxy::assignFrom(*this, *result, retMsg->getReturnValue());
- return !retMsg->isException();
- }
- // Wrap the result
- return makeResult(retMsg->isException(), retMsg->getReturnValue(), result);
-}
-
-bool ScriptableInstance::JavaObject_getProperty(int objectId, int dispId,
- NPVariant* result) {
- Debug::log(Debug::Debugging) << "JavaObject_getProperty(objectid="
- << objectId << ", dispId=" << dispId << ")" << Debug::flush;
- VOID_TO_NPVARIANT(*result);
- Value propertyValue = ServerMethods::getProperty(*_channel, this, objectId, dispId);
- if (propertyValue.isJsObject()) {
- // TODO(jat): special-case for testing
- NPObject* npObj = localObjects.get(propertyValue.getJsObjectId());
- OBJECT_TO_NPVARIANT(npObj, *result);
- NPN_RetainObject(npObj);
- } else {
- NPVariantProxy::assignFrom(*this, *result, propertyValue);
- }
- Debug::log(Debug::Debugging) << " return val=" << propertyValue
- << ", NPVariant=" << *result << Debug::flush;
- if (NPVariantProxy::isObject(*result)) {
- dumpObjectBytes(NPVariantProxy::getAsObject(*result));
- }
- if (NPVariantProxy::isObject(*result)) {
- Debug::log(Debug::Debugging) << " final return refcount = "
- << NPVariantProxy::getAsObject(*result)->referenceCount << Debug::flush;
- }
- return true;
-}
-
-bool ScriptableInstance::JavaObject_setProperty(int objectId, int dispId,
- const NPVariant* npValue) {
- Debug::log(Debug::Debugging) << "JavaObject_setProperty(objectid="
- << objectId << ", dispId=" << dispId << ", value=" << *npValue << ")" << Debug::flush;
- if (NPVariantProxy::isObject(*npValue)) {
- Debug::log(Debug::Debugging) << " before localObj: refcount = "
- << NPVariantProxy::getAsObject(*npValue)->referenceCount << Debug::flush;
- }
- Value value = NPVariantProxy::getAsValue(*npValue, *this, true);
- if (NPVariantProxy::isObject(*npValue)) {
- Debug::log(Debug::Debugging) << " after localObj: refcount = "
- << NPVariantProxy::getAsObject(*npValue)->referenceCount << Debug::flush;
- }
- if (NPVariantProxy::isObject(*npValue)) {
- dumpObjectBytes(NPVariantProxy::getAsObject(*npValue));
- }
- Debug::log(Debug::Debugging) << " as value: " << value << Debug::flush;
- // TODO: no way to set an actual exception object! (Could ClassCastException on server.)
- return ServerMethods::setProperty(*_channel, this, objectId, dispId, value);
-}
-
-bool ScriptableInstance::JavaObject_getToStringTearOff(NPVariant* result) {
- Debug::log(Debug::Debugging) << "JavaObject_getToStringTearOff()" << Debug::flush;
- VOID_TO_NPVARIANT(*result);
-
- Value temp;
- NPVariantArray varArgs(*this, 3);
- temp.setNull(); varArgs[0] = temp; // proxy: no proxy needed
- temp.setInt(0); varArgs[1] = temp; // dispId: always 0 for toString()
- temp.setInt(0); varArgs[2] = temp; // argCount: always 0 for toString()
-
- if (!NPN_Invoke(getNPP(), window, jsTearOffID, varArgs.getArray(), 3, result)) {
- Debug::log(Debug::Error) << "*** JavaObject_getToStringTearOff() failed"
- << Debug::flush;
- return true;
- }
- return true;
-}
-
-JavaObject* ScriptableInstance::createJavaWrapper(int objectId) {
- Debug::log(Debug::Debugging) << "createJavaWrapper(objectId=" << objectId << ")" << Debug::flush;
- JavaObject* jObj;
- hash_map<int, JavaObject*>::iterator it = javaObjects.find(objectId);
- if (it != javaObjects.end()) {
- jObj = it->second;
- NPN_RetainObject(jObj);
- return jObj;
- }
- jObj = JavaObject::create(this, objectId);
- javaObjects[objectId] = jObj;
- return jObj;
-}
-
-void ScriptableInstance::destroyJavaWrapper(JavaObject* jObj) {
- int objectId = jObj->getObjectId();
- if (!javaObjects.erase(objectId)) {
- Debug::log(Debug::Error) << "destroyJavaWrapper(id=" << objectId
- << "): trying to free unknown JavaObject" << Debug::flush;
- }
- Debug::log(Debug::Debugging) << "destroyJavaWrapper(id=" << objectId << ")" << Debug::flush;
- javaObjectsToFree.insert(objectId);
-}
-
-void ScriptableInstance::sendFreeValues(HostChannel& channel) {
- unsigned n = javaObjectsToFree.size();
- if (n) {
- scoped_array<int> ids(new int[n]);
- int i = 0;
- for (std::set<int>::iterator it = javaObjectsToFree.begin();
- it != javaObjectsToFree.end(); ++it) {
- ids[i++] = *it;
- }
- if (ServerMethods::freeJava(channel, this, n, ids.get())) {
- javaObjectsToFree.clear();
- }
- }
-}
-
+ if (!allowed) {
+ BOOLEAN_TO_NPVARIANT(false, *result);
+ result->type = NPVariantType_Bool;
+ return;
+ }
+
+ bool connected = false;
+ unsigned port = 9997; // TODO(jat): should there be a default?
+ int n = GetNPStringUTF8Length(hostAddr);
+ scoped_ptr<char> host(new char[n + 1]);
+ const char* s = GetNPStringUTF8Characters(hostAddr);
+ char* d = host.get();
+ while (n > 0 && *s != ':') {
+ n--;
+ *d++ = *s++;
+ }
+ *d = 0;
+ if (n > 0) {
+ port = atoi(s + 1);
+ }
+ Debug::log(Debug::Info) << " host=" << host.get() << ",port=" << port << Debug::flush;
+
+
+ if (!_channel->connectToHost(host.get(), port)) {
+ BOOLEAN_TO_NPVARIANT(false, *result);
+ result->type = NPVariantType_Bool;
+ }
+
+ string hostedHtmlVersionStr = convertToString(hostedHtmlVersion);
+ if (!_channel->init(this, BROWSERCHANNEL_PROTOCOL_VERSION,
+ BROWSERCHANNEL_PROTOCOL_VERSION, hostedHtmlVersionStr)) {
+ BOOLEAN_TO_NPVARIANT(false, *result);
+ result->type = NPVariantType_Bool;
+ }
+
+ string moduleNameStr = convertToString(moduleName);
+ string userAgent(NPN_UserAgent(getNPP()));
+ string tabKeyStr = computeTabIdentity();
+ string sessionKeyStr = convertToString(sessionKey);
+ Debug::log(Debug::Debugging) << " connected, sending loadModule" << Debug::flush;
+ connected = LoadModuleMessage::send(*_channel, urlStr, tabKeyStr, sessionKeyStr,
+ moduleNameStr, userAgent, this);
+ BOOLEAN_TO_NPVARIANT(connected, *result);
+ result->type = NPVariantType_Bool;
+}
+
+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 {
+ 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;
+}
+
+void ScriptableInstance::fatalError(HostChannel& channel, const std::string& message) {
+ // TODO(jat): better error handling
+ Debug::log(Debug::Error) << "Fatal error: " << message << Debug::flush;
+}
+
+void ScriptableInstance::dupString(const char* str, NPString& npString) {
+ npString.UTF8Length = static_cast<uint32_t>(strlen(str));
+ NPUTF8* chars = static_cast<NPUTF8*>(NPN_MemAlloc(npString.UTF8Length));
+ memcpy(chars, str, npString.UTF8Length);
+ npString.UTF8Characters = chars;
+}
+
+// SessionHandler methods
+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]);
+ }
+ }
+}
+
+void ScriptableInstance::loadJsni(HostChannel& channel, const std::string& js) {
+ NPString npScript;
+ dupString(js.c_str(), npScript);
+ NPVariantWrapper npResult(*this);
+ Debug::log(Debug::Spam) << "loadJsni - \n" << js << Debug::flush;
+ if (!NPN_Evaluate(getNPP(), window, &npScript, npResult.addressForReturn())) {
+ Debug::log(Debug::Error) << "loadJsni failed\n" << js << Debug::flush;
+ }
+}
+
+Value ScriptableInstance::clientMethod_getProperty(HostChannel& channel, int numArgs, const Value* const args) {
+ if (numArgs != 2 || !args[0].isInt() || (!args[1].isString() && !args[1].isInt())) {
+ Debug::log(Debug::Error) << "Incorrect invocation of getProperty: #args=" << numArgs << ":";
+ for (int i = 0; i < numArgs; ++i) {
+ Debug::log(Debug::Error) << " " << i << "=" << args[i].toString();
+ }
+ Debug::log(Debug::Error) << Debug::flush;
+ return Value();
+ }
+ int id = args[0].getInt();
+ NPObject* obj = localObjects.get(id);
+ NPIdentifier propID;
+ if (args[1].isString()) {
+ std::string propName = args[1].getString();
+ propID = NPN_GetStringIdentifier(propName.c_str());
+ } else {
+ int propNum = args[1].getInt();
+ propID = NPN_GetIntIdentifier(propNum);
+ }
+ NPVariantWrapper npResult(*this);
+ if (!NPN_GetProperty(getNPP(), obj, propID, npResult.addressForReturn())) {
+ Debug::log(Debug::Warning) << "getProperty(id=" << id << ", prop="
+ << NPN_UTF8FromIdentifier(propID) << ") failed" << Debug::flush;
+ return Value();
+ }
+ return npResult.getAsValue(*this);
+}
+
+Value ScriptableInstance::clientMethod_setProperty(HostChannel& channel, int numArgs, const Value* const args) {
+ if (numArgs != 2 || !args[0].isInt() || (!args[1].isString() && !args[1].isInt())) {
+ Debug::log(Debug::Error) << "Incorrect invocation of setProperty: #args="
+ << numArgs << ":";
+ for (int i = 0; i < numArgs; ++i) {
+ Debug::log(Debug::Error) << " " << i << "=" << args[i].toString();
+ }
+ Debug::log(Debug::Error) << Debug::flush;
+ return Value();
+ }
+ int id = args[0].getInt();
+ NPObject* obj = localObjects.get(id);
+ NPIdentifier propID;
+ if (args[1].isString()) {
+ std::string propName = args[1].getString();
+ propID = NPN_GetStringIdentifier(propName.c_str());
+ } else {
+ int propNum = args[1].getInt();
+ propID = NPN_GetIntIdentifier(propNum);
+ }
+ NPVariantWrapper npValue(*this);
+ npValue.operator=(args[2]);
+ if (!NPN_SetProperty(getNPP(), obj, propID, npValue.address())) {
+ Debug::log(Debug::Warning) << "setProperty(id=" << id << ", prop="
+ << NPN_UTF8FromIdentifier(propID) << ", val=" << args[2].toString()
+ << ") failed" << Debug::flush;
+ return Value();
+ }
+ return Value();
+}
+
+/**
+ * SessionHandler.invoke - used by LoadModule and reactToMessages* to process server-side
+ * requests to invoke methods in Javascript or the plugin.
+ */
+bool ScriptableInstance::invokeSpecial(HostChannel& channel, SpecialMethodId dispatchId,
+ int numArgs, const Value* const args, Value* returnValue) {
+ switch (dispatchId) {
+ case SessionHandler::HasMethod:
+ case SessionHandler::HasProperty:
+ break;
+ case SessionHandler::SetProperty:
+ *returnValue = clientMethod_setProperty(channel, numArgs, args);
+ return false;
+ case SessionHandler::GetProperty:
+ *returnValue = clientMethod_getProperty(channel, numArgs, args);
+ return false;
+ default:
+ break;
+ }
+ Debug::log(Debug::Error) << "Unexpected special method " << dispatchId
+ << " called on plugin; #args=" << numArgs << ":";
+ for (int i = 0; i < numArgs; ++i) {
+ Debug::log(Debug::Error) << " " << i << "=" << args[i].toString();
+ }
+ Debug::log(Debug::Error) << Debug::flush;
+ // TODO(jat): should we create a real exception object?
+ std::string buf("unexpected invokeSpecial(");
+ buf += static_cast<int>(dispatchId);
+ buf += ")";
+ returnValue->setString(buf);
+ return true;
+}
+
+bool ScriptableInstance::invoke(HostChannel& channel, const Value& thisRef,
+ const std::string& methodName, int numArgs, const Value* const args,
+ Value* returnValue) {
+ Debug::log(Debug::Debugging) << "invokeJS(" << methodName << ", this="
+ << thisRef.toString() << ", numArgs=" << numArgs << ")" << Debug::flush;
+ NPVariantArray varArgs(*this, numArgs + 2);
+ varArgs[0] = thisRef;
+ varArgs[1] = methodName;
+ for (int i = 0; i < numArgs; ++i) {
+ varArgs[i + 2] = args[i];
+ }
+ const NPVariant* argArray = varArgs.getArray();
+ if (Debug::level(Debug::Spam)) {
+ for (int i = 0; i < varArgs.getSize(); ++i) {
+ Debug::log(Debug::Spam) << " arg " << i << " is "
+ << NPVariantProxy::toString(argArray[i]) << Debug::flush;
+ }
+ }
+ NPVariantWrapper wrappedRetVal(*this);
+ if (!NPN_Invoke(getNPP(), window, jsInvokeID, argArray, varArgs.getSize(),
+ wrappedRetVal.addressForReturn())) {
+ Debug::log(Debug::Error) << "*** invokeJS(" << methodName << ", this="
+ << thisRef.toString() << ", numArgs=" << numArgs << ") failed"
+ << Debug::flush;
+ // TODO(jat): should we create a real exception object?
+ returnValue->setString("invoke of " + methodName + " failed");
+ return true;
+ }
+ Debug::log(Debug::Spam) << " wrapped return is " << wrappedRetVal.toString() << Debug::flush;
+ NPVariantWrapper exceptFlag(*this);
+ NPVariantWrapper retval(*this);
+ NPObject* wrappedArray = wrappedRetVal.getAsObject();
+ if (!NPN_GetProperty(getNPP(), wrappedArray, idx0, exceptFlag.addressForReturn())) {
+ Debug::log(Debug::Error) << " Error getting element 0 of wrapped return value ("
+ << wrappedRetVal << ") on call to " << methodName << Debug::flush;
+ }
+ if (!NPN_GetProperty(getNPP(), wrappedArray, idx1, retval.addressForReturn())) {
+ Debug::log(Debug::Error) << " Error getting element 1 of wrapped return value ("
+ << wrappedRetVal << ") on call to " << methodName << Debug::flush;
+ }
+ Debug::log(Debug::Debugging) << " return value " << retval.toString() << Debug::flush;
+ *returnValue = retval.getAsValue(*this);
+ if (exceptFlag.isInt() && exceptFlag.getAsInt() != 0) {
+ Debug::log(Debug::Debugging) << " exception: " << retval << Debug::flush;
+ return true;
+ }
+ return false;
+}
+
+bool ScriptableInstance::JavaObject_invoke(int objectId, int dispId,
+ const NPVariant* args, uint32_t numArgs, NPVariant* result) {
+ Debug::log(Debug::Debugging) << "JavaObject_invoke(dispId= " << dispId << ", numArgs=" << numArgs << ")" << Debug::flush;
+ if (Debug::level(Debug::Spam)) {
+ for (uint32_t i = 0; i < numArgs; ++i) {
+ Debug::log(Debug::Spam) << " " << i << " = " << args[i] << Debug::flush;
+ }
+ }
+
+ bool isRawToString = false;
+ if (dispId == -1) {
+ dispId = 0;
+ isRawToString = true;
+ }
+
+ Value javaThis;
+ javaThis.setJavaObject(objectId);
+ scoped_array<Value> vargs(new Value[numArgs]);
+ for (unsigned i = 0; i < numArgs; ++i) {
+ vargs[i] = NPVariantProxy::getAsValue(args[i], *this);
+ }
+ if (!InvokeMessage::send(*_channel, javaThis, dispId, numArgs, vargs.get())) {
+ Debug::log(Debug::Error) << "JavaObject_invoke: failed to send invoke message" << Debug::flush;
+ // TODO(jat): returning false here spams the browser console
+ return true;
+ }
+ Debug::log(Debug::Debugging) << " return from invoke" << Debug::flush;
+ scoped_ptr<ReturnMessage> retMsg(_channel->reactToMessagesWhileWaitingForReturn(this));
+ if (!retMsg.get()) {
+ Debug::log(Debug::Error) << "JavaObject_invoke: failed to get return value" << Debug::flush;
+ return false;
+ }
+ if (isRawToString) {
+ // toString() needs the raw value
+ NPVariantProxy::assignFrom(*this, *result, retMsg->getReturnValue());
+ return !retMsg->isException();
+ }
+ // Wrap the result
+ return makeResult(retMsg->isException(), retMsg->getReturnValue(), result);
+}
+
+bool ScriptableInstance::JavaObject_getProperty(int objectId, int dispId,
+ NPVariant* result) {
+ Debug::log(Debug::Debugging) << "JavaObject_getProperty(objectid="
+ << objectId << ", dispId=" << dispId << ")" << Debug::flush;
+ VOID_TO_NPVARIANT(*result);
+ Value propertyValue = ServerMethods::getProperty(*_channel, this, objectId, dispId);
+ if (propertyValue.isJsObject()) {
+ // TODO(jat): special-case for testing
+ NPObject* npObj = localObjects.get(propertyValue.getJsObjectId());
+ OBJECT_TO_NPVARIANT(npObj, *result);
+ NPN_RetainObject(npObj);
+ } else {
+ NPVariantProxy::assignFrom(*this, *result, propertyValue);
+ }
+ Debug::log(Debug::Debugging) << " return val=" << propertyValue
+ << ", NPVariant=" << *result << Debug::flush;
+ if (NPVariantProxy::isObject(*result)) {
+ dumpObjectBytes(NPVariantProxy::getAsObject(*result));
+ }
+ if (NPVariantProxy::isObject(*result)) {
+ Debug::log(Debug::Debugging) << " final return refcount = "
+ << NPVariantProxy::getAsObject(*result)->referenceCount << Debug::flush;
+ }
+ return true;
+}
+
+bool ScriptableInstance::JavaObject_setProperty(int objectId, int dispId,
+ const NPVariant* npValue) {
+ Debug::log(Debug::Debugging) << "JavaObject_setProperty(objectid="
+ << objectId << ", dispId=" << dispId << ", value=" << *npValue << ")" << Debug::flush;
+ if (NPVariantProxy::isObject(*npValue)) {
+ Debug::log(Debug::Debugging) << " before localObj: refcount = "
+ << NPVariantProxy::getAsObject(*npValue)->referenceCount << Debug::flush;
+ }
+ Value value = NPVariantProxy::getAsValue(*npValue, *this, true);
+ if (NPVariantProxy::isObject(*npValue)) {
+ Debug::log(Debug::Debugging) << " after localObj: refcount = "
+ << NPVariantProxy::getAsObject(*npValue)->referenceCount << Debug::flush;
+ }
+ if (NPVariantProxy::isObject(*npValue)) {
+ dumpObjectBytes(NPVariantProxy::getAsObject(*npValue));
+ }
+ Debug::log(Debug::Debugging) << " as value: " << value << Debug::flush;
+ // TODO: no way to set an actual exception object! (Could ClassCastException on server.)
+ return ServerMethods::setProperty(*_channel, this, objectId, dispId, value);
+}
+
+bool ScriptableInstance::JavaObject_getToStringTearOff(NPVariant* result) {
+ Debug::log(Debug::Debugging) << "JavaObject_getToStringTearOff()" << Debug::flush;
+ VOID_TO_NPVARIANT(*result);
+
+ Value temp;
+ NPVariantArray varArgs(*this, 3);
+ temp.setNull(); varArgs[0] = temp; // proxy: no proxy needed
+ temp.setInt(0); varArgs[1] = temp; // dispId: always 0 for toString()
+ temp.setInt(0); varArgs[2] = temp; // argCount: always 0 for toString()
+
+ if (!NPN_Invoke(getNPP(), window, jsTearOffID, varArgs.getArray(), 3, result)) {
+ Debug::log(Debug::Error) << "*** JavaObject_getToStringTearOff() failed"
+ << Debug::flush;
+ return true;
+ }
+ return true;
+}
+
+JavaObject* ScriptableInstance::createJavaWrapper(int objectId) {
+ Debug::log(Debug::Debugging) << "createJavaWrapper(objectId=" << objectId << ")" << Debug::flush;
+ JavaObject* jObj;
+ hash_map<int, JavaObject*>::iterator it = javaObjects.find(objectId);
+ if (it != javaObjects.end()) {
+ jObj = it->second;
+ NPN_RetainObject(jObj);
+ return jObj;
+ }
+ jObj = JavaObject::create(this, objectId);
+ javaObjects[objectId] = jObj;
+ return jObj;
+}
+
+void ScriptableInstance::destroyJavaWrapper(JavaObject* jObj) {
+ int objectId = jObj->getObjectId();
+ if (!javaObjects.erase(objectId)) {
+ Debug::log(Debug::Error) << "destroyJavaWrapper(id=" << objectId
+ << "): trying to free unknown JavaObject" << Debug::flush;
+ }
+ Debug::log(Debug::Debugging) << "destroyJavaWrapper(id=" << objectId << ")" << Debug::flush;
+ javaObjectsToFree.insert(objectId);
+}
+
+void ScriptableInstance::sendFreeValues(HostChannel& channel) {
+ unsigned n = javaObjectsToFree.size();
+ if (n) {
+ scoped_array<int> ids(new int[n]);
+ int i = 0;
+ for (std::set<int>::iterator it = javaObjectsToFree.begin();
+ it != javaObjectsToFree.end(); ++it) {
+ ids[i++] = *it;
+ }
+ if (ServerMethods::freeJava(channel, this, n, ids.get())) {
+ javaObjectsToFree.clear();
+ }
+ }
+}
+
diff --git a/plugins/npapi/VisualStudio/npapi-plugin.vcproj b/plugins/npapi/VisualStudio/npapi-plugin.vcproj
index d338c7f..5826c32 100755
--- a/plugins/npapi/VisualStudio/npapi-plugin.vcproj
+++ b/plugins/npapi/VisualStudio/npapi-plugin.vcproj
@@ -63,9 +63,9 @@
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib"
ShowProgress="2"
- OutputFile="$(ProjectDir)\..\prebuilt\gwtdmp\WINNT_x86-msvc\npOOPHM.dll"
+ OutputFile="$(ProjectDir)\..\prebuilt\gwt-dev-plugin\WINNT_x86-msvc\npGwtDevPlugin.dll"
LinkIncremental="1"
- ModuleDefinitionFile="$(ProjectDir)\..\npOOPHM.def"
+ ModuleDefinitionFile="$(ProjectDir)\..\npGwtDevPlugin.def"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
SubSystem="2"
@@ -144,10 +144,10 @@
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib"
ShowProgress="2"
- OutputFile="$(ProjectDir)\..\prebuilt\gwtdmp\WINNT_x86-msvc\npOOPHM.dll"
+ OutputFile="$(ProjectDir)\..\prebuilt\gwt-dev-plugin\WINNT_x86-msvc\npGwtDevPlugin.dll"
LinkIncremental="0"
AdditionalLibraryDirectories=""
- ModuleDefinitionFile="..\npOOPHM.def"
+ ModuleDefinitionFile="..\npGwtDevPlugin.def"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
SubSystem="2"
@@ -349,7 +349,7 @@
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
- RelativePath="..\npOOPHM.rc"
+ RelativePath="..\npGwtDevPlugin.rc"
>
</File>
</Filter>
@@ -423,7 +423,7 @@
>
</File>
<File
- RelativePath="..\npOOPHM.def"
+ RelativePath="..\npGwtDevPlugin.def"
>
</File>
<File
diff --git a/plugins/npapi/liboophm.r b/plugins/npapi/liboophm.r
deleted file mode 100644
index 251d5f4..0000000
--- a/plugins/npapi/liboophm.r
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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 <Carbon/Carbon.r>
-
-// To compile run:
-// Rez liboophm.r -o liboophm.rsrc -useDF
-// mv liboophm.rsrc prebuilt/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/Resources/liboophm.rsrc
-
-resource 'STR#' (126) {
- { "GWT Hosted-mode plugin", "GWT Hosted-mode plugin" }
-};
diff --git a/plugins/npapi/npOOPHM.def b/plugins/npapi/npGwtDevPlugin.def
similarity index 100%
rename from plugins/npapi/npOOPHM.def
rename to plugins/npapi/npGwtDevPlugin.def
diff --git a/plugins/npapi/npOOPHM.rc b/plugins/npapi/npGwtDevPlugin.rc
similarity index 100%
rename from plugins/npapi/npOOPHM.rc
rename to plugins/npapi/npGwtDevPlugin.rc
diff --git a/plugins/npapi/oophm.xpi b/plugins/npapi/oophm.xpi
deleted file mode 100644
index 425cdba..0000000
--- a/plugins/npapi/oophm.xpi
+++ /dev/null
Binary files differ
diff --git a/plugins/npapi/prebuilt/gwtdmp/background.html b/plugins/npapi/prebuilt/gwt-dev-plugin/background.html
similarity index 100%
rename from plugins/npapi/prebuilt/gwtdmp/background.html
rename to plugins/npapi/prebuilt/gwt-dev-plugin/background.html
diff --git a/plugins/npapi/prebuilt/gwtdmp/gwt128.png b/plugins/npapi/prebuilt/gwt-dev-plugin/gwt128.png
similarity index 100%
rename from plugins/npapi/prebuilt/gwtdmp/gwt128.png
rename to plugins/npapi/prebuilt/gwt-dev-plugin/gwt128.png
Binary files differ
diff --git a/plugins/npapi/prebuilt/gwtdmp/gwt16.png b/plugins/npapi/prebuilt/gwt-dev-plugin/gwt16.png
similarity index 100%
rename from plugins/npapi/prebuilt/gwtdmp/gwt16.png
rename to plugins/npapi/prebuilt/gwt-dev-plugin/gwt16.png
Binary files differ
diff --git a/plugins/npapi/prebuilt/gwtdmp/gwt32.png b/plugins/npapi/prebuilt/gwt-dev-plugin/gwt32.png
similarity index 100%
rename from plugins/npapi/prebuilt/gwtdmp/gwt32.png
rename to plugins/npapi/prebuilt/gwt-dev-plugin/gwt32.png
Binary files differ
diff --git a/plugins/npapi/prebuilt/gwtdmp/gwt48.png b/plugins/npapi/prebuilt/gwt-dev-plugin/gwt48.png
similarity index 100%
rename from plugins/npapi/prebuilt/gwtdmp/gwt48.png
rename to plugins/npapi/prebuilt/gwt-dev-plugin/gwt48.png
Binary files differ
diff --git a/plugins/npapi/prebuilt/gwtdmp/gwt64.png b/plugins/npapi/prebuilt/gwt-dev-plugin/gwt64.png
similarity index 100%
rename from plugins/npapi/prebuilt/gwtdmp/gwt64.png
rename to plugins/npapi/prebuilt/gwt-dev-plugin/gwt64.png
Binary files differ
diff --git a/plugins/npapi/prebuilt/gwtdmp/manifest.json b/plugins/npapi/prebuilt/gwt-dev-plugin/manifest.json
similarity index 70%
rename from plugins/npapi/prebuilt/gwtdmp/manifest.json
rename to plugins/npapi/prebuilt/gwt-dev-plugin/manifest.json
index 4dfc66a..fc73f5f 100644
--- a/plugins/npapi/prebuilt/gwtdmp/manifest.json
+++ b/plugins/npapi/prebuilt/gwt-dev-plugin/manifest.json
@@ -1,7 +1,8 @@
{
- "name": "GWT Development Mode Plugin",
+ "name": "GWT Developer Plugin",
"version": "0.9.0",
"description": "A plugin to enable debugging with GWT's Development Mode",
+ "update_url": "https://dl-ssl.google.com/gwt/plugins/chrome/updates.xml",
"icons": {
"16": "gwt16.png",
"32": "gwt32.png",
@@ -17,6 +18,6 @@
}
],
"plugins": [
- { "path": "WINNT_x86-msvc/npOOPHM.dll", "public": true }
+ { "path": "WINNT_x86-msvc/npGwtDevPlugin.dll", "public": true }
]
}
diff --git a/plugins/npapi/prebuilt/gwtdmp/record_tab_id.js b/plugins/npapi/prebuilt/gwt-dev-plugin/record_tab_id.js
similarity index 100%
rename from plugins/npapi/prebuilt/gwtdmp/record_tab_id.js
rename to plugins/npapi/prebuilt/gwt-dev-plugin/record_tab_id.js
diff --git a/plugins/npapi/prebuilt/gwtdmp.crx b/plugins/npapi/prebuilt/gwtdmp.crx
deleted file mode 100644
index 1538642..0000000
--- a/plugins/npapi/prebuilt/gwtdmp.crx
+++ /dev/null
Binary files differ
diff --git a/plugins/npapi/prebuilt/gwtdmp/WINNT_x86-msvc/npOOPHM.dll b/plugins/npapi/prebuilt/gwtdmp/WINNT_x86-msvc/npOOPHM.dll
deleted file mode 100644
index a1dcaa9..0000000
--- a/plugins/npapi/prebuilt/gwtdmp/WINNT_x86-msvc/npOOPHM.dll
+++ /dev/null
Binary files differ