Initial checkin of OOPHM plugins into trunk.  Testing of non-XPCOM plugins
is still required, and more platforms need to be built.


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5868 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/plugins/npapi/JavaObject.cpp b/plugins/npapi/JavaObject.cpp
new file mode 100644
index 0000000..16f7a09
--- /dev/null
+++ b/plugins/npapi/JavaObject.cpp
@@ -0,0 +1,181 @@
+/*
+ * 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);
+}
diff --git a/plugins/npapi/JavaObject.h b/plugins/npapi/JavaObject.h
new file mode 100644
index 0000000..c5dc310
--- /dev/null
+++ b/plugins/npapi/JavaObject.h
@@ -0,0 +1,67 @@
+#ifndef JAVAOBJECT_H_
+#define JAVAOBJECT_H_
+/*
+ * 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 <string>
+#include <vector>
+
+#include "mozincludes.h"
+#include "Plugin.h"
+#include "ScriptableInstance.h"
+#include "Debug.h"
+#include "HashMap.h"
+
+class JavaObject : public NPObjectWrapper<JavaObject> {
+  friend class ScriptableInstance;
+private:
+  ScriptableInstance* plugin;
+  int objectId;
+  
+  NPIdentifier idID;
+
+public:
+  JavaObject(NPP npp) : NPObjectWrapper<JavaObject>(npp),
+      plugin(reinterpret_cast<Plugin*>(npp->pdata)->getScriptableInstance()),
+      idID(NPN_GetStringIdentifier("id")) {}
+  virtual ~JavaObject();
+  static JavaObject* create(ScriptableInstance* plugin, int id);
+  static bool isInstance(NPObject* obj);
+  
+  virtual bool enumeration(NPIdentifier** names, uint32_t* count);
+  virtual bool hasMethod(NPIdentifier name);
+  virtual bool invoke(NPIdentifier name, const NPVariant *args, uint32_t num_args,
+      NPVariant *result);
+  virtual bool invokeDefault(const NPVariant *args, uint32_t num_args, NPVariant *result);
+  virtual bool hasProperty(NPIdentifier name);
+  virtual bool getProperty(NPIdentifier name, NPVariant *result);
+  virtual bool setProperty(NPIdentifier name, const NPVariant *value);
+  
+  void setObjectId(int objectId) {
+    this->objectId = objectId;
+  }
+
+  int getObjectId() const {
+    return objectId;
+  }
+private:
+  // Called by a Plugin instance when it is about to be destroyed.
+  void disconnectPlugin() {
+    plugin = 0;
+  }
+};
+
+#endif /*JAVAOBJECT_H_*/
diff --git a/plugins/npapi/LocalObjectTable.cpp b/plugins/npapi/LocalObjectTable.cpp
new file mode 100644
index 0000000..a450381
--- /dev/null
+++ b/plugins/npapi/LocalObjectTable.cpp
@@ -0,0 +1,8 @@
+#include "mozincludes.h"
+#include "LocalObjectTable.h"
+
+LocalObjectTable::~LocalObjectTable() {
+  if (!dontFree) {
+    freeAll();
+  }
+}
diff --git a/plugins/npapi/LocalObjectTable.h b/plugins/npapi/LocalObjectTable.h
new file mode 100644
index 0000000..cc8beb7
--- /dev/null
+++ b/plugins/npapi/LocalObjectTable.h
@@ -0,0 +1,133 @@
+#ifndef H_LocalObjectTable
+#define H_LocalObjectTable
+/*
+ * 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 <vector>
+#include <algorithm>
+
+#include "Debug.h"
+
+#include "mozincludes.h"
+
+class LocalObjectTable {
+private:
+  static const int INITIAL_OBJECT_TABLE_SIZE = 300;
+
+  int nextFree;
+  std::vector<NPObject*> 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;
+  }
+public:
+  LocalObjectTable() {
+    nextFree = -1;
+    objects.reserve(INITIAL_OBJECT_TABLE_SIZE);
+    dontFree = false;
+  }
+
+  virtual ~LocalObjectTable();
+
+  int add(NPObject* obj) {
+    int id = find(obj);
+    if (id >= 0) {
+      Debug::log(Debug::Spam) << "LocalObjectTable::add(obj=" << obj
+          << "): returning old id=" << id << Debug::flush;
+      return 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);
+    return id;
+  }
+
+  // TODO(jat): sublinear search
+  int find(NPObject* obj) {
+    std::vector<NPObject*>::iterator it = std::find(objects.begin(), objects.end(), obj);
+    if (it == objects.end()) {
+      return -1;
+    }
+    return static_cast<int>(it - objects.begin());
+  }
+
+  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::Error) << "Freeing freed object slot " << id << Debug::flush;
+      return;
+    }
+    NPObject* obj = objects[id];
+    setFree(id);
+    if (!dontFree) {
+      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);
+        }
+      }
+    }
+  }
+
+  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;
+    }
+    if (isFree(id)) {
+      Debug::log(Debug::Error) << "Getting freed object slot " << id << Debug::flush;
+      return 0;
+    }
+    return objects[id];
+  }
+
+  void setDontFree(bool dontFree) {
+    this->dontFree = dontFree;
+  }
+};
+
+#endif
diff --git a/plugins/npapi/Makefile b/plugins/npapi/Makefile
new file mode 100644
index 0000000..bb3a850
--- /dev/null
+++ b/plugins/npapi/Makefile
@@ -0,0 +1,125 @@
+include ../config.mk
+
+INC=-I. -I../common -Inpapi
+CFLAGS=-Wall -g -O2 -fPIC $(INC) -rdynamic -m$(FLAG32BIT) -DLINUX -DBROWSER_NPAPI
+CXXFLAGS=$(CFLAGS)
+
+INSTDIR := extension/platform/Linux_$(ARCH)-gcc3/plugins
+
+HDRS= LocalObjectTable.h NPVariantWrapper.h Plugin.h ScriptableInstance.h mozincludes.h \
+	JavaObject.h ScriptableInstance.h
+
+COMMON= ../common/libcommon$(FLAG32BIT).a
+OBJS=	main.o Plugin.o LocalObjectTable.o JavaObject.o npn_bindings.o \
+	ScriptableInstance.o
+
+SRCS=	main.cpp Plugin.cpp LocalObjectTable.cpp JavaObject.cpp \
+	npn_bindings.cc ScriptableInstance.cpp
+
+all:: oophm.xpi
+
+oophm.xpi: extension $(INSTDIR)/liboophm.so liboophm.so extension/install.rdf
+	-rm -f oophm.xpi
+	cd extension; zip -r -D -9 -o ../$@ * -x '*/.svn/*' -x 'META-INF/*'
+
+oophm-signed.xpi: $(INSTDIR)/liboophm.so extension/install.rdf \
+  extension/META-INF/zigbert.sf
+	-rm -f $@
+	cd extension; zip -9 ../$@ META-INF/zigbert.rsa; zip -r -D -9 -o ../$@ * -x '*/.svn/*' -x META-INF/zigbert.rsa
+
+extension: prebuilt/extension
+	-rm -rf extension
+	cp -r --preserve=mode $< $@
+
+$(INSTDIR):
+	-mkdir -p $@
+
+extension/META-INF/zigbert.sf: $(INSTDIR)/liboophm.so
+	signtool -d certdb -k 'GWT Plugin' -x .svn extension/
+
+extension/install.rdf: install-template.rdf version
+	sed s/GWT_OOPHM_VERSION/`cat version`/ install-template.rdf >$@
+
+version: computeversion $(HDRS) $(SRCS) $(COMMON)
+	./computeversion >$@
+
+$(INSTDIR)/liboophm.so: liboophm.so
+	cp $< $@
+
+liboophm.so: $(OBJS) $(COMMON) $(INSTDIR)
+	g++ -m$(FLAG32BIT) -shared -o $@ $(OBJS) $(COMMON)
+
+$(COMMON): common
+	cd ../common; make
+
+$(OBJS): 
+
+.PHONY: all realclean clean depend common install install-platform
+
+install:: oophm.xpi
+	-cp --preserve=mode $< prebuilt
+
+install-platform:: liboophm.so
+	-mkdir -p $(subst extension,prebuilt/extension,$(INSTDIR))
+	-cp --preserve=mode $< $(subst extension,prebuilt/extension,$(INSTDIR))
+
+realclean:: clean
+
+clean::
+	-rm -f $(OBJS)
+	-rm -f extension/platform/*/plugins/*.{so,dll}
+
+depend::
+	g++ -MM $(CFLAGS) $(SRCS) >>Makefile
+#	makedepend -- $(CFLAGS) -- $(SRCS)
+
+# DO NOT DELETE
+main.o: main.cpp ../common/Debug.h ../common/Platform.h \
+  ../common/DebugLevel.h mozincludes.h npapi/npapi.h npapi/nphostapi.h \
+  npapi/npapi.h npapi/npruntime.h npapi/npapi.h npapi/npruntime.h \
+  NPObjectWrapper.h Plugin.h ScriptableInstance.h ../common/HostChannel.h ../common/Message.h \
+  ../common/ReturnMessage.h ../common/BrowserChannel.h ../common/Value.h \
+  ../common/Debug.h ../common/SessionHandler.h \
+  ../common/LoadModuleMessage.h ../common/HostChannel.h \
+  LocalObjectTable.h ../common/SessionHandler.h \
+  ../common/scoped_ptr/scoped_ptr.h ../common/AllowedConnections.h
+Plugin.o: Plugin.cpp Plugin.h ScriptableInstance.h ../common/Debug.h ../common/Platform.h \
+  ../common/DebugLevel.h mozincludes.h npapi/npapi.h npapi/nphostapi.h \
+  npapi/npapi.h npapi/npruntime.h npapi/npapi.h npapi/npruntime.h \
+  NPObjectWrapper.h ../common/HostChannel.h ../common/Message.h \
+  ../common/ReturnMessage.h ../common/BrowserChannel.h ../common/Value.h \
+  ../common/Debug.h ../common/SessionHandler.h ../common/AllowedConnections.h \
+  ../common/LoadModuleMessage.h ../common/HostChannel.h \
+  LocalObjectTable.h ../common/SessionHandler.h ../common/InvokeMessage.h \
+  ../common/ReturnMessage.h ../common/ServerMethods.h \
+  ../common/scoped_ptr/scoped_ptr.h NPVariantWrapper.h \
+  ../common/Platform.h ../common/Value.h JavaObject.h ../common/HashMap.h
+ScriptableInstance.o: ScriptableInstance.cpp Plugin.h ScriptableInstance.h ../common/Debug.h \
+  ../common/Platform.h \
+  ../common/DebugLevel.h mozincludes.h npapi/npapi.h npapi/nphostapi.h \
+  npapi/npapi.h npapi/npruntime.h npapi/npapi.h npapi/npruntime.h \
+  NPObjectWrapper.h ../common/HostChannel.h ../common/Message.h \
+  ../common/ReturnMessage.h ../common/BrowserChannel.h ../common/Value.h \
+  ../common/Debug.h ../common/SessionHandler.h ../common/AllowedConnections.h \
+  ../common/LoadModuleMessage.h ../common/HostChannel.h \
+  LocalObjectTable.h ../common/SessionHandler.h ../common/InvokeMessage.h \
+  ../common/ReturnMessage.h ../common/ServerMethods.h \
+  ../common/scoped_ptr/scoped_ptr.h NPVariantWrapper.h \
+  ../common/Platform.h ../common/Value.h JavaObject.h ../common/HashMap.h
+LocalObjectTable.o: LocalObjectTable.cpp mozincludes.h npapi/npapi.h \
+  npapi/nphostapi.h npapi/npapi.h npapi/npruntime.h npapi/npapi.h \
+  npapi/npruntime.h NPObjectWrapper.h LocalObjectTable.h \
+  ../common/Debug.h ../common/Platform.h ../common/DebugLevel.h
+JavaObject.o: JavaObject.cpp JavaObject.h mozincludes.h npapi/npapi.h \
+  npapi/nphostapi.h npapi/npapi.h npapi/npruntime.h npapi/npapi.h \
+  npapi/npruntime.h NPObjectWrapper.h Plugin.h ScriptableInstance.h ../common/Debug.h \
+  ../common/Platform.h ../common/DebugLevel.h ../common/HostChannel.h \
+  ../common/Message.h ../common/ReturnMessage.h ../common/AllowedConnections.h \
+  ../common/BrowserChannel.h ../common/Value.h ../common/Debug.h \
+  ../common/SessionHandler.h ../common/LoadModuleMessage.h \
+  ../common/HostChannel.h LocalObjectTable.h ../common/SessionHandler.h \
+  ../common/HashMap.h NPVariantWrapper.h ../common/Platform.h \
+  ../common/Value.h
+npn_bindings.o: npn_bindings.cc mozincludes.h npapi/npapi.h \
+  npapi/nphostapi.h npapi/npapi.h npapi/npruntime.h npapi/npapi.h \
+  npapi/npruntime.h NPObjectWrapper.h
diff --git a/plugins/npapi/Makefile.mac b/plugins/npapi/Makefile.mac
new file mode 100644
index 0000000..771d89f
--- /dev/null
+++ b/plugins/npapi/Makefile.mac
@@ -0,0 +1,130 @@
+INC=-I. -I../common
+FLAG32BIT=$(shell ./get32bitflag arch)
+CFLAGS=-g -O2 -fPIC $(INC) -m$(FLAG32BIT) -D__mac -DXP_MACOSX -DXP_UNIX -DBROWSER_NPAPI
+CXXFLAGS=$(CFLAGS)
+
+INSTDIR := extension/platform/$(shell ./getarch arch)/plugins/oophm.plugin/Contents/MacOS
+RESDIR := extension/platform/$(shell ./getarch arch)/plugins/oophm.plugin/Contents/Resources
+
+HDRS= LocalObjectTable.h NPVariantWrapper.h Plugin.h mozincludes.h \
+	JavaObject.h ScriptableInstance.h
+
+COMMON= ../common/libcommon$(FLAG32BIT).a
+OBJS=	main.o Plugin.o LocalObjectTable.o JavaObject.o npn_bindings.o \
+	ScriptableInstance.o
+
+SRCS=	main.cpp Plugin.cpp LocalObjectTable.cpp JavaObject.cpp \
+	npn_bindings.cc ScriptableInstance.cpp
+
+oophm.xpi: arch extension $(INSTDIR)/liboophm $(RESDIR)/liboophm.rsrc \
+  liboophm extension/install.rdf
+	-rm -f oophm.xpi
+	cd extension; zip -r -D -9 -o ../$@ * -x '*/.svn/*' -x 'META-INF/*'
+
+oophm-signed.xpi: arch $(INSTDIR)/liboophm $(RESDIR)/liboophm.rsrc \
+  extension/install.rdf extension/META-INF/zigbert.sf
+	-rm -f $@
+	cd extension; zip -9 ../$@ META-INF/zigbert.rsa; zip -r -D -9 -o ../$@ * -x '*/.svn/*' -x META-INF/zigbert.rsa
+
+extension: prebuilt/extension
+	-rm -rf extension
+	cp -r $< $@
+
+$(INSTDIR):
+	-mkdir -p $@
+
+extension/META-INF/zigbert.sf: $(INSTDIR)/liboophm
+	signtool -d certdb -k 'GWT Plugin' -x .svn extension/
+
+extension/install.rdf: install-template.rdf version
+	sed s/GWT_OOPHM_VERSION/`cat version`/ install-template.rdf >$@
+
+version: computeversion $(HDRS) $(SRCS) $(COMMON)
+	./computeversion >$@
+
+arch: computearch
+	./computearch arch
+	@echo "Restart make"
+	@exit 1
+
+$(INSTDIR)/liboophm: liboophm
+	cp $< $@
+
+$(RESDIR)/liboophm.rsrc: liboophm.rsrc
+	cp $< $@
+
+liboophm.rsrc: liboophm.r
+	/Developer/Tools/Rez $< -o $@ -useDF
+
+liboophm: $(OBJS) $(COMMON) $(INSTDIR)
+	g++ -m$(FLAG32BIT) -bundle -o $@ $(OBJS) $(COMMON)
+
+$(COMMON): common
+	cd ../common; make -f Makefile.mac
+
+$(OBJS): arch
+
+.PHONY: all realclean clean depend common install install-platform
+
+install: oophm.xpi
+	-cp $< prebuilt
+
+install-platform: liboophm liboophm.rsrc
+	-mkdir -p $(subst extension,prebuilt/extension,$(INSTDIR))
+	-mkdir -p $(subst extension,prebuilt/extension,$(RESDIR))
+	-cp liboophm $(subst extension,prebuilt/extension,$(INSTDIR))
+	-cp liboophm.rsrc $(subst extension,prebuilt/extension,$(RESDIR))
+
+realclean: clean
+	-rm -f arch
+
+clean:
+	-rm -f $(OBJS) liboophm liboophm.rsrc
+	-rm -rf extension
+
+depend:
+	g++ -MM $(CFLAGS) $(SRCS) >>Makefile.mac
+#	makedepend -- $(CFLAGS) -- $(SRCS)
+
+# DO NOT DELETE
+main.o: main.cpp ../common/Debug.h ../common/Platform.h \
+  ../common/DebugLevel.h mozincludes.h npapi/npapi.h npapi/nphostapi.h \
+  npapi/npapi.h npapi/npruntime.h npapi/npruntime.h NPObjectWrapper.h \
+  Plugin.h ScriptableInstance.h ../common/HostChannel.h ../common/Platform.h \
+  ../common/Message.h ../common/ReturnMessage.h ../common/Message.h \
+  ../common/BrowserChannel.h ../common/Value.h ../common/Debug.h \
+  ../common/BrowserChannel.h ../common/Value.h ../common/SessionHandler.h \
+  ../common/LoadModuleMessage.h ../common/Message.h \
+  ../common/BrowserChannel.h ../common/HostChannel.h \
+  ../common/SessionHandler.h LocalObjectTable.h \
+  ../common/scoped_ptr/scoped_ptr.h
+Plugin.o: Plugin.cpp Plugin.h ScriptableInstance.h ../common/Debug.h ../common/Platform.h \
+  ../common/DebugLevel.h mozincludes.h npapi/npapi.h npapi/nphostapi.h \
+  npapi/npapi.h npapi/npruntime.h npapi/npruntime.h NPObjectWrapper.h \
+  ../common/HostChannel.h ../common/Platform.h ../common/Message.h \
+  ../common/ReturnMessage.h ../common/Message.h \
+  ../common/BrowserChannel.h ../common/Value.h ../common/Debug.h \
+  ../common/BrowserChannel.h ../common/Value.h ../common/SessionHandler.h \
+  ../common/LoadModuleMessage.h ../common/Message.h \
+  ../common/BrowserChannel.h ../common/HostChannel.h \
+  ../common/SessionHandler.h LocalObjectTable.h ../common/InvokeMessage.h \
+  ../common/Message.h ../common/BrowserChannel.h ../common/Value.h \
+  ../common/ServerMethods.h ../common/Value.h \
+  ../common/scoped_ptr/scoped_ptr.h NPVariantWrapper.h JavaObject.h
+LocalObjectTable.o: LocalObjectTable.cpp mozincludes.h npapi/npapi.h \
+  npapi/nphostapi.h npapi/npapi.h npapi/npruntime.h npapi/npruntime.h \
+  NPObjectWrapper.h LocalObjectTable.h ../common/Debug.h \
+  ../common/Platform.h ../common/DebugLevel.h
+JavaObject.o: JavaObject.cpp JavaObject.h mozincludes.h npapi/npapi.h \
+  npapi/nphostapi.h npapi/npapi.h npapi/npruntime.h npapi/npruntime.h \
+  NPObjectWrapper.h Plugin.h ScriptableInstance.h ../common/Debug.h ../common/Platform.h \
+  ../common/DebugLevel.h ../common/HostChannel.h ../common/Platform.h \
+  ../common/Message.h ../common/ReturnMessage.h ../common/Message.h \
+  ../common/BrowserChannel.h ../common/Value.h ../common/Debug.h \
+  ../common/BrowserChannel.h ../common/Value.h ../common/SessionHandler.h \
+  ../common/LoadModuleMessage.h ../common/Message.h \
+  ../common/BrowserChannel.h ../common/HostChannel.h \
+  ../common/SessionHandler.h LocalObjectTable.h NPVariantWrapper.h
+npn_bindings.o: npn_bindings.cc mozincludes.h npapi/npapi.h \
+  npapi/nphostapi.h npapi/npapi.h npapi/npruntime.h npapi/npruntime.h \
+  NPObjectWrapper.h
diff --git a/plugins/npapi/Makefile.sun b/plugins/npapi/Makefile.sun
new file mode 100644
index 0000000..3d11a75
--- /dev/null
+++ b/plugins/npapi/Makefile.sun
@@ -0,0 +1,115 @@
+INC=-I. -I../common
+FLAG32BIT=$(shell ./get32bitflag arch)
+CFLAGS=-fast -g0 -Kpic -noex -xO3 -xlibmil -xlibmopt -features=tmplife -norunpath -xbuiltin=%all -mt $(INC) -m$(FLAG32BIT) -DXP_UNIX -DLINUX -DBROWSER_NPAPI
+CXXFLAGS=$(CFLAGS)
+CXX=CC
+
+INSTDIR := extension/platform/$(shell ./getarch arch)/plugins
+
+HDRS= LocalObjectTable.h NPVariantWrapper.h Plugin.h mozincludes.h \
+	JavaObject.h ScriptableInstance.h
+
+COMMON= ../common/libcommon$(FLAG32BIT).a
+OBJS=	main.o Plugin.o LocalObjectTable.o JavaObject.o npn_bindings.o \
+	ScriptableInstance.o
+
+SRCS=	main.cpp Plugin.cpp LocalObjectTable.cpp JavaObject.cpp \
+	npn_bindings.cc ScriptableInstance.cpp
+
+all:: oophm.xpi
+
+oophm.xpi: arch extension $(INSTDIR)/liboophm.so liboophm.so extension/install.rdf
+	-rm -f oophm.xpi
+	cd extension; zip -r -D -9 -o ../$@ * -x '*/.svn/*' -x 'META-INF/*'
+
+oophm-signed.xpi: arch $(INSTDIR)/liboophm.so extension/install.rdf \
+  extension/META-INF/zigbert.sf
+	-rm -f $@
+	cd extension; zip -9 ../$@ META-INF/zigbert.rsa; zip -r -D -9 -o ../$@ * -x '*/.svn/*' -x META-INF/zigbert.rsa
+
+extension: prebuilt/extension
+	-rm -rf extension
+	cp -r --preserve=mode $< $@
+
+extension/install.rdf: extension install-template.rdf version
+	sed s/GWT_OOPHM_VERSION/`cat version`/ install-template.rdf >$@
+
+$(INSTDIR):
+	-mkdir -p $@
+
+extension/META-INF/zigbert.sf: $(INSTDIR)/liboophm.so
+	signtool -d certdb -k 'GWT Plugin' -x .svn extension/
+
+version: computeversion $(HDRS) $(SRCS) $(COMMON)
+	./computeversion >$@
+
+arch: computearch
+	./computearch arch
+	@echo "Restart make"
+	@exit 1
+
+$(INSTDIR)/liboophm.so: liboophm.so
+	cp $< $@
+
+liboophm.so: $(OBJS) $(COMMON) $(INSTDIR)
+	$(CXX) -m$(FLAG32BIT) -G -o $@ $(OBJS) $(COMMON)
+
+$(COMMON): common
+	cd ../common; make -f Makefile.sun
+
+$(OBJS): arch
+
+.PHONY: all realclean clean depend common install install-platform
+
+install: oophm.xpi
+	-cp --preserve=mode $< prebuilt
+
+install-platform: liboophm.so
+	-mkdir -p $(subst extension,prebuilt/extension,$(INSTDIR))
+	-cp --preserve=mode $< $(subst extension,prebuilt/extension,$(INSTDIR))
+
+realclean: clean
+	-rm -f arch
+
+clean:
+	-rm -f $(OBJS)
+	-rm -f extension/platform/*/plugins/*.{so,dll}
+
+depend:
+	$(CXX) -MM $(CFLAGS) $(SRCS) >>Makefile
+#	makedepend -- $(CFLAGS) -- $(SRCS)
+
+# DO NOT DELETE
+main.o: main.cpp ../common/Debug.h ../common/DebugLevel.h mozincludes.h \
+  npapi/npapi.h npapi/nphostapi.h ./npapi/npapi.h ./npapi/npruntime.h \
+  ./npapi/npapi.h npapi/npruntime.h NPObjectWrapper.h Plugin.h ScriptableInstance.h \
+  ../common/HostChannel.h ../common/Platform.h ../common/Message.h \
+  ../common/ReturnMessage.h ../common/BrowserChannel.h ../common/Value.h \
+  ../common/SessionHandler.h ../common/LoadModuleMessage.h \
+  ../common/HostChannel.h LocalObjectTable.h ../common/SessionHandler.h \
+  ../common/scoped_ptr/scoped_ptr.h
+Plugin.o: Plugin.cpp Plugin.h ScriptableInstance.h ../common/Debug.h ../common/DebugLevel.h \
+  mozincludes.h npapi/npapi.h npapi/nphostapi.h ./npapi/npapi.h \
+  ./npapi/npruntime.h ./npapi/npapi.h npapi/npruntime.h NPObjectWrapper.h \
+  ../common/HostChannel.h ../common/Platform.h ../common/Message.h \
+  ../common/ReturnMessage.h ../common/BrowserChannel.h ../common/Value.h \
+  ../common/SessionHandler.h ../common/LoadModuleMessage.h \
+  ../common/HostChannel.h LocalObjectTable.h ../common/SessionHandler.h \
+  ../common/InvokeMessage.h ../common/ReturnMessage.h \
+  ../common/ServerMethods.h ../common/scoped_ptr/scoped_ptr.h \
+  NPVariantWrapper.h ../common/Platform.h ../common/Value.h JavaObject.h
+LocalObjectTable.o: LocalObjectTable.cpp mozincludes.h npapi/npapi.h \
+  npapi/nphostapi.h ./npapi/npapi.h ./npapi/npruntime.h ./npapi/npapi.h \
+  npapi/npruntime.h NPObjectWrapper.h LocalObjectTable.h
+JavaObject.o: JavaObject.cpp JavaObject.h mozincludes.h npapi/npapi.h \
+  npapi/nphostapi.h ./npapi/npapi.h ./npapi/npruntime.h ./npapi/npapi.h \
+  npapi/npruntime.h NPObjectWrapper.h Plugin.h ScriptableInstance.h ../common/Debug.h \
+  ../common/DebugLevel.h ../common/HostChannel.h ../common/Platform.h \
+  ../common/Message.h ../common/ReturnMessage.h \
+  ../common/BrowserChannel.h ../common/Value.h ../common/SessionHandler.h \
+  ../common/LoadModuleMessage.h ../common/HostChannel.h \
+  LocalObjectTable.h ../common/SessionHandler.h NPVariantWrapper.h \
+  ../common/Platform.h ../common/Value.h
+npn_bindings.o: npn_bindings.cc mozincludes.h npapi/npapi.h \
+  npapi/nphostapi.h ./npapi/npapi.h ./npapi/npruntime.h ./npapi/npapi.h \
+  npapi/npruntime.h NPObjectWrapper.h
diff --git a/plugins/npapi/NPObjectWrapper.h b/plugins/npapi/NPObjectWrapper.h
new file mode 100644
index 0000000..89280fab
--- /dev/null
+++ b/plugins/npapi/NPObjectWrapper.h
@@ -0,0 +1,169 @@
+// Copyright 2007, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without 
+// modification, are permitted provided that the following conditions are met:
+//
+//  1. Redistributions of source code must retain the above copyright notice, 
+//     this list of conditions and the following disclaimer.
+//  2. Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//  3. Neither the name of Google Inc. nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Modified from gears/base/npapi/plugin.h
+
+#ifndef _H_NPObjectWrapper
+#define _H_NPObjectWrapper
+
+#include <cstdio>
+#include "mozincludes.h"
+
+// This is a base class for the bridge between the JavaScript engine and the plugin.
+template<class Wrapper>
+class NPObjectWrapper : public NPObject {
+ public:
+  // NPClass callbacks.
+  static NPObject* Allocate(NPP npp, NPClass *npclass) {
+    Wrapper* obj = new Wrapper(npp);
+    return obj;
+  }
+
+  static void Deallocate(NPObject *npobj) {
+    delete static_cast<Wrapper*>(npobj);
+  }
+
+  static bool Enumeration(NPObject *npobj, NPIdentifier** value,
+      uint32_t *count) {
+    Wrapper* obj = static_cast<Wrapper*>(npobj);
+    return obj->enumeration(value, count);
+  }
+
+  static bool HasMethod(NPObject *npobj, NPIdentifier name) {
+    Wrapper* obj = static_cast<Wrapper*>(npobj);
+    return obj->hasMethod(name);
+  }
+
+  static bool Invoke(NPObject *npobj, NPIdentifier name, const NPVariant *args,
+      uint32_t num_args, NPVariant *result) {
+    Wrapper* obj = static_cast<Wrapper*>(npobj);
+    return obj->invoke(name, args, num_args, result);
+  }
+
+  static bool InvokeDefault(NPObject *npobj, const NPVariant *args,
+      uint32_t num_args, NPVariant *result) {
+    Wrapper* obj = static_cast<Wrapper*>(npobj);
+    return obj->invokeDefault(args, num_args, result);
+  }
+
+  static bool HasProperty(NPObject *npobj, NPIdentifier name) {
+    Wrapper* obj = static_cast<Wrapper*>(npobj);
+    return obj->hasProperty(name);
+  }
+
+  static bool GetProperty(NPObject *npobj, NPIdentifier name,
+        NPVariant *result) {
+    Wrapper* obj = static_cast<Wrapper*>(npobj);
+    return obj->getProperty(name, result);
+  }
+
+  static bool SetProperty(NPObject *npobj, NPIdentifier name,
+                          const NPVariant *value) {
+    Wrapper* obj = static_cast<Wrapper*>(npobj);
+    return obj->setProperty(name, value);
+  }
+
+  virtual ~NPObjectWrapper() {}
+
+  /**
+   * *value must be memory allocated with NPN_MemAlloc, as the caller will call NPN_MemFree.
+   */
+  virtual bool enumeration(NPIdentifier** value, uint32_t* count) {
+    return false;
+  }
+
+  /**
+   * Caller must release the result value when it no longer needs it,
+   * so implementation must return an extra refcount.
+   */
+  virtual bool getProperty(NPIdentifier name, NPVariant *result) {
+    return false;
+  }
+  
+  virtual bool hasMethod(NPIdentifier name) {
+    return false;
+  }
+
+  virtual bool hasProperty(NPIdentifier name) {
+    return false;
+  }
+  
+  /**
+   * Caller must release the result value when it no longer needs it,
+   * so implementation must return an extra refcount.
+   */
+  virtual bool invoke(NPIdentifier name, const NPVariant *args,
+      uint32_t num_args, NPVariant *result) {
+    return false;
+  }
+
+  /**
+   * Caller must release the result value when it no longer needs it,
+   * so implementation must return an extra refcount.
+   */
+  virtual bool invokeDefault(const NPVariant *args, uint32_t num_args,
+      NPVariant *result) {
+    return false;
+  }
+
+   virtual bool setProperty(NPIdentifier name, const NPVariant *value) {
+     return false;
+   }
+
+  protected:
+    NPObjectWrapper(NPP instance) : npp(instance) {}
+
+  public:
+    const NPP getNPP() const {
+      return npp;
+    }
+
+  private:
+    NPP npp;
+    DISALLOW_EVIL_CONSTRUCTORS(NPObjectWrapper);
+};
+
+// Get the NPClass for a NPObject wrapper (the type must derive from NPObjectWrapper).
+template<class Wrapper>
+NPClass* GetNPClass() {
+  static NPClass plugin_class = {
+    NP_CLASS_STRUCT_VERSION,
+    NPObjectWrapper<Wrapper>::Allocate,
+    NPObjectWrapper<Wrapper>::Deallocate,
+    NULL,  // Invalidate,
+    NPObjectWrapper<Wrapper>::HasMethod,
+    NPObjectWrapper<Wrapper>::Invoke,
+    NPObjectWrapper<Wrapper>::InvokeDefault,
+    NPObjectWrapper<Wrapper>::HasProperty,
+    NPObjectWrapper<Wrapper>::GetProperty,
+    NPObjectWrapper<Wrapper>::SetProperty,
+    NULL,  // RemoveProperty,
+    NPObjectWrapper<Wrapper>::Enumeration,
+  };
+
+  return &plugin_class;
+}
+
+#endif // GEARS_BASE_NPAPI_PLUGIN_H__
diff --git a/plugins/npapi/NPVariantWrapper.h b/plugins/npapi/NPVariantWrapper.h
new file mode 100644
index 0000000..0a469c9
--- /dev/null
+++ b/plugins/npapi/NPVariantWrapper.h
@@ -0,0 +1,567 @@
+#ifndef _H_NPVariantWrapper
+#define _H_NPVariantWrapper
+
+#include <string>
+#include <ostream>
+
+#ifdef sun
+// Sun's cstring doesn't define strlen/etc
+#include <string.h>
+#endif
+#include <cstring>
+#include <stdio.h>
+
+#include "Debug.h"
+#include "Platform.h"
+
+#include "mozincludes.h"
+
+#include "Value.h"
+#include "LocalObjectTable.h"
+#include "Plugin.h"
+#include "JavaObject.h"
+
+/**
+ * Contains NPVariantProxy, NPVariantWrapper, and NPVariantArray
+ */
+
+/**
+ * Wraps an NPVariant and provides various conversion functions.  The variant
+ * provided retained at create time.
+ */
+class NPVariantProxy {
+  friend class NPVariantArray;
+private:
+  ScriptableInstance& plugin;
+  NPVariant& variant;
+public:
+  NPVariantProxy(ScriptableInstance& plugin, NPVariant& variant)
+      : plugin(plugin), variant(variant)
+  {
+    VOID_TO_NPVARIANT(variant);
+  }
+  
+  NPVariantProxy(ScriptableInstance& plugin, NPVariant& variant, bool noinit)
+      : plugin(plugin), variant(variant)
+  {
+  }
+
+  ~NPVariantProxy() {
+  }
+  
+  operator NPVariant() const {
+    return variant;
+  }
+  
+  const NPVariant* operator->() const {
+	return &variant;
+  }
+
+  const NPVariant* address() const {
+    return &variant;
+  }
+
+  int isInt() const {
+    return isInt(variant);
+  }
+  
+  static int isInt(const NPVariant& variant) {
+    return NPVARIANT_IS_INT32(variant);
+  }
+
+  int getAsInt() const {
+    return getAsInt(variant);
+  }
+
+  static int getAsInt(const NPVariant& variant) {
+    if (NPVARIANT_IS_INT32(variant)) {
+      return NPVARIANT_TO_INT32(variant);
+    }
+    Debug::log(Debug::Error) << "getAsInt: variant not int" << Debug::flush;
+    return 0;
+  }
+
+  int isNull() const {
+    return isNull(variant);
+  }
+  
+  static int isNull(const NPVariant& variant) {
+    return NPVARIANT_IS_NULL(variant);
+  }
+
+  int isObject() const {
+    return 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;
+  }
+
+  int isString() const {
+    return 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;
+  }
+
+  Value getAsValue(ScriptableInstance& scriptInstance, bool unwrapJava = true) const {
+    return getAsValue(variant, scriptInstance, unwrapJava);
+  }
+
+  static Value getAsValue(const NPVariant& variant, ScriptableInstance& scriptInstance,
+      bool unwrapJava = true) {
+    Value val;
+    if (NPVARIANT_IS_VOID(variant)) {
+      val.setUndefined();
+    } else if (NPVARIANT_IS_NULL(variant)) {
+      val.setNull();
+    } else if (NPVARIANT_IS_BOOLEAN(variant)) {
+      val.setBoolean(NPVARIANT_TO_BOOLEAN(variant));
+    } else if (NPVARIANT_IS_INT32(variant)) {
+      val.setInt(NPVARIANT_TO_INT32(variant));      
+    } else if (NPVARIANT_IS_DOUBLE(variant)) {
+      val.setDouble(NPVARIANT_TO_DOUBLE(variant));
+    } else if (NPVARIANT_IS_STRING(variant)) {
+      NPString str = NPVARIANT_TO_STRING(variant);
+      val.setString(GetNPStringUTF8Characters(str), GetNPStringUTF8Length(str));
+    } else if (NPVARIANT_IS_OBJECT(variant)) {
+      NPObject* obj = NPVARIANT_TO_OBJECT(variant);
+      if (unwrapJava && JavaObject::isInstance(obj)) {
+        JavaObject* jObj = static_cast<JavaObject*>(obj);
+        val.setJavaObject(jObj->getObjectId());
+      } else {
+        NPVariant result;
+        VOID_TO_NPVARIANT(result);
+        if (scriptInstance.tryGetStringPrimitive(obj, result)) {
+          NPString str = NPVARIANT_TO_STRING(result);
+          val.setString(GetNPStringUTF8Characters(str), GetNPStringUTF8Length(str));
+          release(result);
+        } else {
+          val.setJsObjectId(scriptInstance.getLocalObjectRef(obj));
+        }
+      }
+    } else {
+      Debug::log(Debug::Error) << "Unsupported NPVariant type " << variant.type << Debug::flush;
+    }
+    return val;
+  }
+  
+  /**
+   * The incoming variant is not altered, and is not even required to have
+   * its contents retained.  Any object will get an extra refcount on it
+   * when copied to this variant, and strings will be copied.
+   */
+  NPVariantProxy& operator=(const NPVariant& newval) {
+    assignFrom(variant, newval);
+    return *this;
+  }
+
+  /**
+   * The incoming variant is not altered, and is not even required to have
+   * its contents retained.  Any object will get an extra refcount on it
+   * when copied to this variant, and strings will be copied.
+   */
+  static void assignFrom(NPVariant& variant, const NPVariant& newval) {
+    release(variant);
+    variant = newval;
+    if (NPVARIANT_IS_STRING(newval)) {
+      int n = variant.value.stringValue.UTF8Length;
+      char* strBytes = reinterpret_cast<char*>(NPN_MemAlloc(n));
+      memcpy(strBytes, variant.value.stringValue.UTF8Characters, n);
+      variant.value.stringValue.UTF8Characters = strBytes;
+    } else {
+      retain(variant);
+    }
+  }
+
+  NPVariantProxy& operator=(NPObject* obj) {
+    assignFrom(variant, obj);
+    return *this;
+  }
+  
+  static void assignFrom(NPVariant& variant, NPObject* obj) {
+    release(variant);
+    OBJECT_TO_NPVARIANT(obj, variant);
+    retain(variant);
+  }
+
+  // Convenience method for C++ code
+  NPVariantProxy& operator=(int intVal) {
+    assignFrom(variant, intVal);
+    return *this;
+  }
+
+  // Convenience method for C++ code
+  static void assignFrom(NPVariant& variant, int intVal) {
+    NPVariant newvar;
+    INT32_TO_NPVARIANT(intVal, newvar);
+    assignFrom(variant, newvar);
+  }
+
+  // Convenience method for C++ code
+  NPVariantProxy& operator=(const std::string& strval) {
+    assignFrom(variant, strval);
+    return *this;
+  }
+
+  // Convenience method for C++ code
+  static void assignFrom(NPVariant& variant, const std::string& strval) {
+    NPVariant newvar;
+    STDSTRING_TO_NPVARIANT(strval, newvar);
+    assignFrom(variant, newvar);
+  }
+  
+  // Convenience method for C++ code
+  NPVariantProxy& operator=(const char* strval) {
+    assignFrom(variant, strval);
+    return *this;
+  }
+
+  // Convenience method for C++ code
+  static void assignFrom(NPVariant& variant, const char* strval) {
+    NPVariant newvar;
+    STRINGZ_TO_NPVARIANT(strval, newvar);
+    assignFrom(variant, newvar);
+  }
+
+  NPVariantProxy& operator=(const Value& newval) {
+    assignFrom(plugin, variant, newval);
+    return *this;
+  }
+
+  static void assignFrom(ScriptableInstance& plugin, NPVariant& variant, const Value& newval) {
+    NPVariant newvar;
+    VOID_TO_NPVARIANT(newvar);
+    if (newval.isBoolean()) {
+      BOOLEAN_TO_NPVARIANT(newval.getBoolean(), newvar);
+    } else if (newval.isByte()) {
+      INT32_TO_NPVARIANT(newval.getByte(), newvar);
+    } else if (newval.isChar()) {
+      INT32_TO_NPVARIANT(newval.getChar(), newvar);
+    } else if (newval.isShort()) {
+      INT32_TO_NPVARIANT(newval.getShort(), newvar);
+    } else if (newval.isInt()) {
+      int value = newval.getInt();
+      // Firefox NPAPI bug: 32-bit ints get mapped to int jsvals, regardless of range.
+      // However, int jsvals are 31 bits, so we need to use a double if the value is
+      // not representable in a 31 bit signed 2's-complement value.
+      if (value >= 0x40000000 || value < -0x40000000) {
+        DOUBLE_TO_NPVARIANT(static_cast<double>(value), newvar);
+      } else {
+        INT32_TO_NPVARIANT(value, newvar);
+      }
+    } else if (newval.isFloat()) {
+      DOUBLE_TO_NPVARIANT(newval.getFloat(), newvar);
+    } else if (newval.isDouble()) {
+      DOUBLE_TO_NPVARIANT(newval.getDouble(), newvar);
+    } else if (newval.isNull()) {
+      NULL_TO_NPVARIANT(newvar);
+    } else if (newval.isUndefined()) {
+      VOID_TO_NPVARIANT(newvar);
+    } else if (newval.isString()) {
+      assignFrom(variant, newval.getString());
+      return;
+    } else if (newval.isJavaObject()) {
+      if (1) {
+        JavaObject* jObj = plugin.createJavaWrapper(newval.getJavaObjectId());
+        NPObject* obj = jObj;
+        OBJECT_TO_NPVARIANT(obj, newvar);
+      } else {
+        VOID_TO_NPVARIANT(newvar);
+      }
+    } else if (newval.isJsObject()) {
+      OBJECT_TO_NPVARIANT(plugin.getLocalObject(newval.getJsObjectId()),
+    	  newvar);
+    } else {
+      Debug::log(Debug::Error) << "Unsupported NPVariant type " << newval.getType() << Debug::flush;
+    }
+    assignFrom(variant, newvar);
+  }
+
+  std::string toString() const {
+    return toString(variant);
+  }
+
+  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);
+        if (JavaObject::isInstance(npObj)) {
+          JavaObject* javaObj = static_cast<JavaObject*>(npObj);
+          snprintf(buf, sizeof(buf), "javaObj(id=%d, ", javaObj->getObjectId());
+        } else {
+          snprintf(buf, sizeof(buf), "jsObj(class=%p, ", npObj->_class);
+        }
+        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;
+  }
+
+public:
+  void release() {
+    release(variant);
+  }
+
+  static void release(NPVariant& variant) {
+    NPN_ReleaseVariantValue(&variant);
+  }
+
+  void retain() {
+    retain(variant);
+  }
+
+  static void retain(NPVariant& variant) {
+    if (NPVARIANT_IS_OBJECT(variant)) {
+      NPN_RetainObject(NPVARIANT_TO_OBJECT(variant));
+    }
+  }
+};
+
+inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, const NPVariant& var) {
+  return dbg << NPVariantProxy::toString(var);
+}
+
+inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, const NPVariantProxy& var) {
+  return dbg << var.toString();
+}
+
+/**
+ * Variation of NPVariantProxy that provides its own variant and always frees it
+ * when the wrapper goes away.
+ */
+class NPVariantWrapper  {
+private:
+  ScriptableInstance& plugin;
+  NPVariant variant;
+public:
+  NPVariantWrapper(ScriptableInstance& plugin) : plugin(plugin) {
+    VOID_TO_NPVARIANT(variant);
+  }
+
+  ~NPVariantWrapper() {
+    release();
+  }
+
+  operator NPVariant() const {
+    return variant;
+  }
+
+  const NPVariant* operator->() const {
+  return &variant;
+  }
+
+  const NPVariant* address() const {
+    return &variant;
+  }
+
+  /**
+   * Get the address for use as a return value.  Since the value can be trashed,
+   * we need to release any data we currently hold.
+   */
+  NPVariant* addressForReturn() {
+    NPVariantProxy::release(variant);
+    VOID_TO_NPVARIANT(variant);
+    NPVariantProxy::retain(variant); // does nothing, present for consistency
+    return &variant;
+  }
+
+  int isInt() const {
+    return NPVariantProxy::isInt(variant);
+  }
+  
+  int isObject() const {
+    return NPVariantProxy::isObject(variant);
+  }
+  
+  int isString() const {
+    return NPVariantProxy::isString(variant);
+  }
+  
+  int getAsInt() const {
+    return NPVariantProxy::getAsInt(variant);
+  }
+
+  NPObject* getAsObject() const {
+    return NPVariantProxy::getAsObject(variant);
+  }
+
+  const NPString* getAsNPString() const {
+    return NPVariantProxy::getAsNPString(variant);
+  }
+
+  Value getAsValue(ScriptableInstance& scriptInstance, bool unwrapJava = true) const {
+    return NPVariantProxy::getAsValue(variant, scriptInstance, unwrapJava);
+  }
+
+  /**
+   * The incoming variant is not altered, and is not even required to have
+   * its contents retained.  Any object will get an extra refcount on it
+   * when copied to this variant, and strings will be copied.
+   */
+  NPVariantWrapper& operator=(const NPVariant& newval) {
+    NPVariantProxy::assignFrom(variant, newval);
+    return *this;
+  }
+
+  NPVariantWrapper& operator=(const Value& newval) {
+    NPVariantProxy::assignFrom(plugin, variant, newval);
+    return *this;
+  }
+  
+  NPVariantWrapper& operator=(NPObject* obj) {
+    NPVariantProxy::assignFrom(variant, obj);
+    return *this;
+  }
+  
+  // Convenience method for C++ code
+  NPVariantWrapper& operator=(const std::string& strval) {
+    NPVariantProxy::assignFrom(variant, strval);
+    return *this;
+  }
+
+  // Convenience method for C++ code
+  NPVariantWrapper& operator=(const char* strval) {
+    NPVariantProxy::assignFrom(variant, strval);
+    return *this;
+  }
+
+  void release() {
+    NPVariantProxy::release(variant);
+  }
+
+  void retain() {
+    NPVariantProxy::retain(variant);
+  }
+
+  std::string toString() const {
+    return NPVariantProxy::toString(variant);
+  }
+};
+
+inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, const NPVariantWrapper& var) {
+  dbg << var.toString();
+  return dbg;
+}
+
+/**
+ * Maintains an array of NPVariants and cleans them up when it is destroyed.
+ */
+class NPVariantArray {
+private:
+	ScriptableInstance& plugin;
+  int size;
+  NPVariant* args;
+
+public:
+  NPVariantArray(ScriptableInstance& plugin, int size) : plugin(plugin), size(size) {
+    args = new NPVariant[size];
+    for (int i = 0; i < size; ++i) {
+      VOID_TO_NPVARIANT(args[i]);
+    }
+  }
+
+  ~NPVariantArray() {
+    for (int i = 0; i < size; ++i) {
+      NPN_ReleaseVariantValue(&args[i]);
+    }
+    delete [] args;
+  }
+
+  const NPVariant* getArray() const {
+    return args;
+  }
+
+  int getSize() const {
+    return size;
+  }
+
+  const NPVariant& operator[](int idx) const {
+    if (idx >= size) {
+      printf("NPVariantArray[idx=%d] const: size=%d\n", idx, size);
+    }
+    return args[idx];
+  }
+
+  NPVariantProxy operator[](int idx) {
+    if (idx >= size) {
+      printf("NPVariantArray[idx=%d]: size=%d\n", idx, size);
+    }
+    return NPVariantProxy(plugin, args[idx], true);
+  }
+};
+
+inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, const NPVariantArray& var) {
+  dbg << "[";
+  for (int i = 0; i < var.getSize(); ++i) {
+    dbg << " " << var[i]; 
+  }
+  dbg << " ]";
+  return dbg;
+}
+
+#endif
diff --git a/plugins/npapi/Plugin.cpp b/plugins/npapi/Plugin.cpp
new file mode 100644
index 0000000..4abe7a4
--- /dev/null
+++ b/plugins/npapi/Plugin.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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 "Plugin.h"
+#include "ScriptableInstance.h"
+#include "InvokeMessage.h"
+#include "ReturnMessage.h"
+#include "ServerMethods.h"
+#include "mozincludes.h"
+#include "scoped_ptr/scoped_ptr.h"
+#include "NPVariantWrapper.h"
+
+using std::string;
+using std::endl;
+
+Plugin::Plugin(NPP npp) : npp(npp) {
+  this->scriptableInstance = static_cast<ScriptableInstance*>(NPN_CreateObject(npp,
+	  GetNPClass<ScriptableInstance>()));
+}
+
+Plugin::Plugin(NPP npp, ScriptableInstance* scriptableInstance) : npp(npp),
+    scriptableInstance(scriptableInstance) {
+}
+
+Plugin::~Plugin() {
+  Debug::log(Debug::Debugging) << "Plugin destroyed" << Debug::flush;
+  if (scriptableInstance) {
+    scriptableInstance->pluginDeath();
+    NPN_ReleaseObject(scriptableInstance);
+    scriptableInstance = 0;
+  }
+}
diff --git a/plugins/npapi/Plugin.h b/plugins/npapi/Plugin.h
new file mode 100644
index 0000000..b5d989a
--- /dev/null
+++ b/plugins/npapi/Plugin.h
@@ -0,0 +1,55 @@
+#ifndef _H_Plugin
+#define _H_Plugin
+/*
+ * 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 <vector>
+
+#include "Debug.h"
+
+#include "mozincludes.h"
+#include "HostChannel.h"
+#include "LoadModuleMessage.h"
+#include "LocalObjectTable.h"
+#include "SessionHandler.h"
+#include "HashMap.h"
+
+using std::vector;
+
+class ScriptableInstance;
+
+class Plugin {
+  friend class JavaObject;
+public:
+  Plugin(NPP);
+  Plugin(NPP, ScriptableInstance*);
+  ~Plugin();
+  
+  const NPNetscapeFuncs* getBrowser() { return &GetNPNFuncs(); }
+  ScriptableInstance* getScriptableInstance() { return scriptableInstance; }
+  NPP getNPP() { return npp; }
+
+  static const uint32_t VERSION = 1;
+private:  
+  
+  NPP npp;
+  ScriptableInstance* scriptableInstance;
+  
+  NPObject* window;
+
+};
+
+#endif
diff --git a/plugins/npapi/README.txt b/plugins/npapi/README.txt
new file mode 100644
index 0000000..ca89e98
--- /dev/null
+++ b/plugins/npapi/README.txt
@@ -0,0 +1,5 @@
+This plugin is obsolete and out of date, due to a problem with the NPAPI
+plugin getting reloaded by Firefox when window.enableScrolling is changed.
+
+The code is kept since it will be useful for future NPAPI-based plugins,
+such as for Chrome.
diff --git a/plugins/npapi/ScriptableInstance.cpp b/plugins/npapi/ScriptableInstance.cpp
new file mode 100644
index 0000000..b171b32
--- /dev/null
+++ b/plugins/npapi/ScriptableInstance.cpp
@@ -0,0 +1,587 @@
+/*
+ * 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 "mozincludes.h"
+#include "scoped_ptr/scoped_ptr.h"
+#include "NPVariantWrapper.h"
+
+using std::string;
+using std::endl;
+
+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")),
+    toStringID(NPN_GetStringIdentifier("toString")),
+    connectedID(NPN_GetStringIdentifier("connected")),
+    statsID(NPN_GetStringIdentifier("stats")),
+    savedID(NPN_GetStringIdentifier("saved")),
+    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 || name == savedID;
+}
+
+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;
+  } else if (name == savedID) {
+    if (savedValueIdx >= 0) {
+      NPObject* npObj = localObjects.get(savedValueIdx);
+      OBJECT_TO_NPVARIANT(npObj, *variant);
+      NPN_RetainObject(npObj);
+    }
+    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; 
+  if (NPN_IdentifierIsString(name)) {
+    if (name == savedID && NPVariantProxy::isObject(*variant)) {
+      Debug::log(Debug::Debugging) << " set saved value" << Debug::flush;
+      savedValueIdx = localObjects.add(NPVariantProxy::getAsObject(*variant));
+      return true;
+    }
+    return false;
+  }
+  return false;
+}
+
+bool ScriptableInstance::hasMethod(NPIdentifier name) {
+  Debug::log(Debug::Debugging) << "ScriptableInstance::hasMethod(name=" << NPN_UTF8FromIdentifier(name) << ")"
+      << Debug::flush; 
+  if (name == _connectId || 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 == 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::connect(const NPVariant* args, unsigned argCount, NPVariant* result) {
+  if (argCount < 2 || argCount > 4 || !NPVariantProxy::isString(args[0])
+      || !NPVariantProxy::isString(args[1])
+      || (argCount == 3 && !NPVariantProxy::isObject(args[2]))) {
+    // 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 hostAddr = args[0].value.stringValue;
+  const NPString moduleName = args[1].value.stringValue;
+  if (argCount >= 3) {
+    if (window) {
+      NPN_ReleaseObject(window);
+    }
+    // replace our window object with that passed by the caller
+    window = NPVariantProxy::getAsObject(args[2]);
+    NPN_RetainObject(window);
+  }
+  Debug::log(Debug::Info) << "ScriptableInstance::connect(host=" << NPVariantProxy::toString(args[0])
+      << ",module=" << NPVariantProxy::toString(args[1]) << ")" << Debug::flush;
+  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)) {
+    Debug::log(Debug::Debugging) << "  connected, sending loadModule" << Debug::flush;
+    connected = LoadModuleMessage::send(*_channel, VERSION, GetNPStringUTF8Characters(moduleName),
+        GetNPStringUTF8Length(moduleName), NPN_UserAgent(getNPP()), this);
+  }
+  BOOLEAN_TO_NPVARIANT(connected, *result);
+  result->type = NPVariantType_Bool;
+}
+
+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;
+    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/ScriptableInstance.h b/plugins/npapi/ScriptableInstance.h
new file mode 100644
index 0000000..4b4d5c0
--- /dev/null
+++ b/plugins/npapi/ScriptableInstance.h
@@ -0,0 +1,131 @@
+#ifndef _H_ScriptableInstance
+#define _H_ScriptableInstance
+/*
+ * 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 <vector>
+#include <set>
+
+#include "Debug.h"
+
+#include "mozincludes.h"
+#include "HostChannel.h"
+#include "LoadModuleMessage.h"
+#include "LocalObjectTable.h"
+#include "SessionHandler.h"
+#include "HashMap.h"
+
+using std::vector;
+
+class JavaObject;
+class JavaClass;
+class Plugin;
+
+class ScriptableInstance : public NPObjectWrapper<ScriptableInstance>, SessionHandler {
+  friend class JavaObject;
+public:
+  ScriptableInstance(NPP npp);
+  ~ScriptableInstance();
+
+  void pluginDeath() {
+    // our local objects will get freed anyway when the plugin dies
+    localObjects.freeAll();
+    localObjects.setDontFree(true);
+    // TODO(jat): leaving this in causes SEGV upon plugin destruction in the
+    // NPN_ReleaseObject call.
+//    if (window) {
+//      NPN_ReleaseObject(window);
+//      window = 0;
+//    }
+  }
+  
+  // NPObjectWrapper methods
+  bool enumeration(NPIdentifier** values, uint32_t* count);
+  bool getProperty(NPIdentifier name, NPVariant* result);
+  bool setProperty(NPIdentifier name, const NPVariant* value);
+  bool invoke(NPIdentifier name, const NPVariant* args, unsigned argCount, NPVariant* result);
+  bool invokeDefault(const NPVariant* args, unsigned argCount, NPVariant* result);
+  bool hasMethod(NPIdentifier name);
+  bool hasProperty(NPIdentifier name);
+  
+  void dumpJSresult(const char* js);
+  
+  int getLocalObjectRef(NPObject* obj) { return localObjects.add(obj); }
+  NPObject* getLocalObject(int refid) { return localObjects.get(refid); }
+  
+  bool tryGetStringPrimitive(NPObject* obj, NPVariant& result);
+
+  JavaObject* createJavaWrapper(int objectId);
+  void destroyJavaWrapper(JavaObject*);
+
+  static const uint32_t VERSION = 1;
+private:  
+  // Map of object ID to JavaObject
+  hash_map<int, JavaObject*> javaObjects;
+  std::set<int> javaObjectsToFree;
+  
+  vector<JavaClass*> classes;
+  
+  Plugin& plugin;
+  HostChannel* _channel;
+  LocalObjectTable localObjects;
+
+  int savedValueIdx;
+
+  // Identifiers
+  const NPIdentifier _connectId;
+  const NPIdentifier toStringID;
+  
+  const NPIdentifier connectedID;
+  const NPIdentifier statsID;
+  const NPIdentifier savedID;
+
+  const NPIdentifier jsInvokeID;
+  const NPIdentifier jsResultID;
+  const NPIdentifier jsTearOffID;
+  const NPIdentifier jsValueOfID;
+  const NPIdentifier idx0;
+  const NPIdentifier idx1;
+  
+  NPObject* window;
+  void dupString(const char* str, NPString& npString);
+  void dumpObjectBytes(NPObject* obj);
+  bool makeResult(bool isException, const Value& value, NPVariant* result);
+  
+  // SessionHandler methods
+  virtual bool invoke(HostChannel& channel, const Value& thisObj,
+      const std::string& methodName, int numArgs, const Value* const args,
+      Value* returnValue);
+  virtual bool invokeSpecial(HostChannel& channel, SpecialMethodId dispatchId,
+      int numArgs, const Value* const args, Value* returnValue);
+  virtual void freeValue(HostChannel& channel, int idCount, const int* ids);
+  virtual void sendFreeValues(HostChannel& channel);
+  virtual void loadJsni(HostChannel& channel, const std::string& js);
+
+  void connect(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);
+  
+  void JavaObject_invalidate(int objectId);
+  bool JavaObject_invoke(int objectId, int dispId, const NPVariant* args,
+      uint32_t numArgs, NPVariant* result);
+  bool JavaObject_getProperty(int objectId, int dispId, NPVariant* result);
+  bool JavaObject_setProperty(int objectId, int dispId, const NPVariant* value);
+  bool JavaObject_getToStringTearOff(NPVariant* result);
+};
+
+#endif
diff --git a/plugins/npapi/SigningCommands.txt b/plugins/npapi/SigningCommands.txt
new file mode 100644
index 0000000..67869d4
--- /dev/null
+++ b/plugins/npapi/SigningCommands.txt
@@ -0,0 +1,9 @@
+# Create new certificate database
+certutil -N -d certdb
+
+# Create Object CA certificate
+certutil -d certdb -S -n 'GWT Plugin' -t u,u,Ccu -g 2048 -x -v 24 -5 -s 'CN=GWT Plugin,O=Google Inc,OU=Google Web Toolkit,ST=California,C=US,UID=jat,E=Google-Web-Toolkit-Contributors@googlegroups.com'
+#   add #3 & #7, then specify as critical extension
+
+# Export Object CA certificate in DER format, for import into browser
+certutil -d certdb -L -n 'GWT Plugin' -r >GwtPlugin.der
diff --git a/plugins/npapi/VisualStudio/firefox-plugin.sln b/plugins/npapi/VisualStudio/firefox-plugin.sln
new file mode 100755
index 0000000..a036212
--- /dev/null
+++ b/plugins/npapi/VisualStudio/firefox-plugin.sln
@@ -0,0 +1,26 @@
+

+Microsoft Visual Studio Solution File, Format Version 9.00

+# Visual C++ Express 2005

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "firefox-plugin", "firefox-plugin.vcproj", "{6BF0C2CE-CB0C-421B-A67C-1E448371D24A}"

+EndProject

+Global

+	GlobalSection(SolutionConfigurationPlatforms) = preSolution

+		Debug|Win32 = Debug|Win32

+		Debug|Win64 = Debug|Win64

+		Release|Win32 = Release|Win32

+		Release|Win64 = Release|Win64

+	EndGlobalSection

+	GlobalSection(ProjectConfigurationPlatforms) = postSolution

+		{6BF0C2CE-CB0C-421B-A67C-1E448371D24A}.Debug|Win32.ActiveCfg = Debug|Win32

+		{6BF0C2CE-CB0C-421B-A67C-1E448371D24A}.Debug|Win32.Build.0 = Debug|Win32

+		{6BF0C2CE-CB0C-421B-A67C-1E448371D24A}.Debug|Win64.ActiveCfg = Debug|Win32

+		{6BF0C2CE-CB0C-421B-A67C-1E448371D24A}.Debug|Win64.Build.0 = Debug|Win32

+		{6BF0C2CE-CB0C-421B-A67C-1E448371D24A}.Release|Win32.ActiveCfg = Release|Win32

+		{6BF0C2CE-CB0C-421B-A67C-1E448371D24A}.Release|Win32.Build.0 = Release|Win32

+		{6BF0C2CE-CB0C-421B-A67C-1E448371D24A}.Release|Win64.ActiveCfg = Release|Win32

+		{6BF0C2CE-CB0C-421B-A67C-1E448371D24A}.Release|Win64.Build.0 = Release|Win32

+	EndGlobalSection

+	GlobalSection(SolutionProperties) = preSolution

+		HideSolutionNode = FALSE

+	EndGlobalSection

+EndGlobal

diff --git a/plugins/npapi/VisualStudio/firefox-plugin.vcproj b/plugins/npapi/VisualStudio/firefox-plugin.vcproj
new file mode 100755
index 0000000..e24968f
--- /dev/null
+++ b/plugins/npapi/VisualStudio/firefox-plugin.vcproj
@@ -0,0 +1,409 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="8.00"

+	Name="firefox-plugin"

+	ProjectGUID="{6BF0C2CE-CB0C-421B-A67C-1E448371D24A}"

+	RootNamespace="firefox-plugin"

+	Keyword="Win32Proj"

+	>

+	<Platforms>

+		<Platform

+			Name="Win32"

+		/>

+	</Platforms>

+	<ToolFiles>

+	</ToolFiles>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="Debug"

+			IntermediateDirectory="Debug"

+			ConfigurationType="2"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\common&quot;"

+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FIREFOXPLUGIN_EXPORTS;GWT_DEBUGLEVEL=Warning"

+				MinimalRebuild="true"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="3"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="true"

+				DebugInformationFormat="3"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				ResourceOutputFileName="$(IntDir)/$(TargetName).res"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalDependencies="ws2_32.lib"

+				ShowProgress="2"

+				OutputFile="$(ProjectDir)\..\extension\platform\WINNT_x86-msvc\plugins\npOOPHM.dll"

+				LinkIncremental="1"

+				ModuleDefinitionFile="$(ProjectDir)\..\npOOPHM.def"

+				GenerateDebugInformation="true"

+				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"

+				SubSystem="2"

+				ImportLibrary="$(IntDir)\$(TargetName).lib"

+				TargetMachine="1"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCManifestTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCAppVerifierTool"

+			/>

+			<Tool

+				Name="VCWebDeploymentTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="Release"

+			IntermediateDirectory="Release"

+			ConfigurationType="2"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="3"

+				EnableIntrinsicFunctions="true"

+				AdditionalIncludeDirectories="&quot;..\..\common&quot;"

+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FIREFOXPLUGIN_EXPORTS;GWT_DEBUGLEVEL=Warning"

+				ExceptionHandling="1"

+				RuntimeLibrary="2"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="false"

+				DebugInformationFormat="3"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalDependencies="ws2_32.lib"

+				ShowProgress="2"

+				OutputFile="..\extension\platform\WINNT_x86-msvc\plugins\npOOPHM.dll"

+				LinkIncremental="0"

+				AdditionalLibraryDirectories=""

+				ModuleDefinitionFile="..\npOOPHM.def"

+				GenerateDebugInformation="true"

+				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"

+				SubSystem="2"

+				OptimizeReferences="2"

+				EnableCOMDATFolding="2"

+				ImportLibrary="$(IntDir)\$(TargetName).lib"

+				TargetMachine="1"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCManifestTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCAppVerifierTool"

+			/>

+			<Tool

+				Name="VCWebDeploymentTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+	</Configurations>

+	<References>

+	</References>

+	<Files>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"

+			>

+			<File

+				RelativePath="..\..\common\AllowedConnections.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\BrowserChannel.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\Debug.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\DebugLevel.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\FreeValueMessage.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\HashMap.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\HostChannel.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\InvokeMessage.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\InvokeSpecialMessage.h"

+				>

+			</File>

+			<File

+				RelativePath="..\JavaObject.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\LoadJsniMessage.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\LoadModuleMessage.h"

+				>

+			</File>

+			<File

+				RelativePath="..\LocalObjectTable.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\Message.h"

+				>

+			</File>

+			<File

+				RelativePath="..\mozincludes.h"

+				>

+			</File>

+			<File

+				RelativePath="..\npapi\npapi.h"

+				>

+			</File>

+			<File

+				RelativePath="..\npapi\nphostapi.h"

+				>

+			</File>

+			<File

+				RelativePath="..\NPObjectWrapper.h"

+				>

+			</File>

+			<File

+				RelativePath="..\npapi\npruntime.h"

+				>

+			</File>

+			<File

+				RelativePath="..\NPVariantWrapper.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\Platform.h"

+				>

+			</File>

+			<File

+				RelativePath="..\Plugin.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\QuitMessage.h"

+				>

+			</File>

+			<File

+				RelativePath="..\resource.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\ReturnMessage.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\scoped_ptr\scoped_ptr.h"

+				>

+			</File>

+			<File

+				RelativePath="..\ScriptableInstance.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\ServerMethods.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\SessionHandler.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\Socket.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\Value.h"

+				>

+			</File>

+		</Filter>

+		<Filter

+			Name="Resource Files"

+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"

+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"

+			>

+			<File

+				RelativePath="..\npOOPHM.rc"

+				>

+			</File>

+		</Filter>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"

+			>

+			<File

+				RelativePath="..\..\common\AllowedConnections.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\Debug.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\FreeValueMessage.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\HostChannel.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\InvokeMessage.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\InvokeSpecialMessage.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\JavaObject.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\LoadJsniMessage.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\LoadModuleMessage.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\LocalObjectTable.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\main.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\npn_bindings.cc"

+				>

+			</File>

+			<File

+				RelativePath="..\npOOPHM.def"

+				>

+			</File>

+			<File

+				RelativePath="..\Plugin.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\ReturnMessage.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\ScriptableInstance.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\ServerMethods.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\Socket.cpp"

+				>

+			</File>

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/plugins/npapi/arch b/plugins/npapi/arch
new file mode 100644
index 0000000..027cd25
--- /dev/null
+++ b/plugins/npapi/arch
@@ -0,0 +1 @@
+Linux_x86-gcc3
diff --git a/plugins/npapi/build.xml b/plugins/npapi/build.xml
new file mode 100755
index 0000000..0cf01ee
--- /dev/null
+++ b/plugins/npapi/build.xml
@@ -0,0 +1,18 @@
+<project name="firefox" default="build" basedir=".">
+	<property name="plugin.root" value="firefox" />
+	<import file="../common.ant.xml" />
+
+	<target name="build" description="Copy compiled plugin to the output folder">
+		<mkdir dir="${gwt.build.out}/plugins" />
+		<mkdir dir="${gwt.build.out}/plugins/firefox" />
+		<copy todir="${gwt.build.out}/plugins/firefox">
+			<fileset file="prebuilt/oophm.xpi" />
+		</copy>
+	</target>
+
+	<target name="test" description="Run any tests">
+	</target>
+
+	<target name="checkstyle" description="Static style analysis">
+	</target>
+</project>
diff --git a/plugins/npapi/computearch b/plugins/npapi/computearch
new file mode 100755
index 0000000..9d7c343
--- /dev/null
+++ b/plugins/npapi/computearch
@@ -0,0 +1,72 @@
+#!/bin/sh
+#
+# Compute the Firefox XPCOM-ABI string -- see
+#    http://developer.mozilla.org/en/docs/XPCOM_ABI
+# 
+
+# OS_TARGET portion should be one of:
+#   Linux
+#   Darwin - Mac OSX
+#   WINNT - Windows NT, 2000, XP and later
+#   SunOS - all Solaris versions
+#
+OS=`uname -s`
+
+# COMPILER should be one of:
+#    gcc2 - GNU C++ v2.x
+#    gcc3 - GNU C++ v3.x or v4.x
+#    msvc - MS Visual C++
+#    n32 - IRIX 6 C++ Compiler
+#    sunc - Sun C++ Compiler
+#    ibmc - IBM C++ Compiler
+#
+# TODO: figure out how to determine this in a better way
+case $OS in
+  SunOS)
+    COMPILER=sunc
+    ;;
+  WINNT)
+    COMPILER=msvc
+    ;;
+  *)
+    COMPILER=gcc3
+    ;;
+esac
+
+# TARGET_XPCOM_ABI consists of ARCH and COMPILER
+
+# Currently acceptable ARCH values are:
+#    x86 - i386 and up, 32-bit mode
+#    x86_64 - AMD64/EMT64 processors in 64-bit mode
+#    ppc
+#    alpha
+#    sparc
+#    ia64 - Itanium
+#
+ARCH=`uname -m`
+case "$ARCH" in
+  x86_64 | ppc | sparc | alpha | ia64)
+    # these don't need changing
+    ;;
+  athlon | i386 | i486 | i586 | i686 | i86pc)
+    ARCH=x86
+    ;;
+  *Macintosh*)
+    case `uname -p` in
+      powerpc)
+        ARCH=ppc
+        ;;
+      *)
+        echo "Unknown mac architecture '$ARCH'" >&2
+        exit 1
+        ;;
+    esac
+    ;;
+  *)
+    echo "Unknown architecture '$ARCH'" >&2
+    exit 1
+    ;;
+esac
+
+echo ${OS}_$ARCH-$COMPILER >$1
+exit 0
diff --git a/plugins/npapi/computeversion b/plugins/npapi/computeversion
new file mode 100755
index 0000000..7cf259c
--- /dev/null
+++ b/plugins/npapi/computeversion
@@ -0,0 +1,18 @@
+#!/bin/sh
+if [ -z "$1" ]
+then
+  F=version
+else
+  F=$1
+fi
+
+V=`svn info 2>/dev/null | fgrep Revision: | awk  '{ print $2; }'`
+if [ $? -gt 0 -o -z "$V" ]
+then
+  V='?'
+fi
+
+TS=`date +%Y%m%d%H%M%S`
+
+echo "0.0.$V.$TS" >$F
+exit 0
diff --git a/plugins/npapi/extension/chrome.manifest b/plugins/npapi/extension/chrome.manifest
new file mode 100644
index 0000000..38a0fdd
--- /dev/null
+++ b/plugins/npapi/extension/chrome.manifest
@@ -0,0 +1,2 @@
+content gwt-oophm content/
+skin gwt-oophm classic/1.0 skin/
diff --git a/plugins/npapi/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/Info.plist b/plugins/npapi/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/Info.plist
new file mode 100644
index 0000000..234ad6e
--- /dev/null
+++ b/plugins/npapi/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/Info.plist
@@ -0,0 +1,20 @@
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>liboophm</string>
+	<key>CFBundleIdentifier</key>
+	<string>com.google.gwt.oophm</string>
+	<key>CFBundleName</key>
+	<string>oophm</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundlePackageType</key>
+	<string>NSPL</string>
+	<key>CFBundleSignature</key>
+	<string>MOSS</string>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+</dict>
+</plist>
diff --git a/plugins/npapi/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/MacOS/liboophm b/plugins/npapi/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/MacOS/liboophm
new file mode 100755
index 0000000..49d5a1f
--- /dev/null
+++ b/plugins/npapi/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/MacOS/liboophm
Binary files differ
diff --git a/plugins/npapi/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/Resources/liboophm.rsrc b/plugins/npapi/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/Resources/liboophm.rsrc
new file mode 100644
index 0000000..c1cb961
--- /dev/null
+++ b/plugins/npapi/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/Resources/liboophm.rsrc
Binary files differ
diff --git a/plugins/npapi/extension/platform/WINNT_x86-msvc/plugins/npOOPHM.dll b/plugins/npapi/extension/platform/WINNT_x86-msvc/plugins/npOOPHM.dll
new file mode 100755
index 0000000..dfcdb9b
--- /dev/null
+++ b/plugins/npapi/extension/platform/WINNT_x86-msvc/plugins/npOOPHM.dll
Binary files differ
diff --git a/plugins/npapi/extension/skin/icon.png b/plugins/npapi/extension/skin/icon.png
new file mode 100644
index 0000000..7ba8270
--- /dev/null
+++ b/plugins/npapi/extension/skin/icon.png
Binary files differ
diff --git a/plugins/npapi/get32bitflag b/plugins/npapi/get32bitflag
new file mode 100755
index 0000000..ff62c6a
--- /dev/null
+++ b/plugins/npapi/get32bitflag
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+if [ ! -r "$1" ]
+then
+  echo "32"
+  exit 0
+fi
+
+read ARCH <$1
+
+case "$ARCH" in
+   *_64* | *sparc*)
+	echo "64"
+	;;
+   *)
+	echo "32"
+	;;
+esac
+exit 0
diff --git a/plugins/npapi/getarch b/plugins/npapi/getarch
new file mode 100755
index 0000000..fc69c11
--- /dev/null
+++ b/plugins/npapi/getarch
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+if [ -r $1 ]
+then
+  read k <$1
+  echo $k
+else 
+  echo "unknown"
+fi
+exit 0
diff --git a/plugins/npapi/install-template.rdf b/plugins/npapi/install-template.rdf
new file mode 100644
index 0000000..8f6120f
--- /dev/null
+++ b/plugins/npapi/install-template.rdf
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+
+  <Description about="urn:mozilla:install-manifest">
+    <em:id>oophm@gwt.google.com</em:id>
+    <em:name>GWT Hosted Mode Plugin</em:name>
+    <em:version>GWT_OOPHM_VERSION</em:version>
+    <em:type>2</em:type>
+    <em:targetApplication>
+      <Description>
+        <!-- Firefox 1.5-3.0 supported -->
+        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+        <em:minVersion>1.5</em:minVersion>
+        <em:maxVersion>3.0.*</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+
+    <!-- Front End MetaData -->
+    <em:name>GWT Hosted Mode Plugin</em:name>
+    <em:description>A plugin to support hosted-mode development of GWT applications</em:description>
+    <em:creator>Google, Inc.</em:creator>
+    <em:homepageURL>http://code.google.com/webtoolkit/</em:homepageURL>
+    <em:iconURL>chrome://gwt-oophm/skin/icon.png</em:iconURL>
+
+    <em:targetPlatform>Linux_x86-gcc3</em:targetPlatform>
+    <em:targetPlatform>Linux_x86_64-gcc3</em:targetPlatform>
+    <em:targetPlatform>WINNT_x86-msvc</em:targetPlatform>
+    <em:targetPlatform>Darwin_x86-gcc3</em:targetPlatform>
+    <em:targetPlatform>SunOS_x86-sunc</em:targetPlatform>
+
+    <!-- TODO
+    # prefs dialog
+
+    # replace default about dialog
+    <em:aboutURL>chrome://gwt-oophm/content/about.xul</em:aboutURL>
+
+    # updates, see http://developer.mozilla.org/en/docs/Extension_Versioning%2C_Update_and_Compatibility#Update_RDF_Format
+    <em:updateURL>https://xxx.google.com/.../update.rdf</em:updateURL>
+
+    # platforms - any others?
+    <em:targetPlatform>Darwin_ppc-gcc3</em:targetPlatform>
+    <em:targetPlatform>SunOS_sparc-sunc</em:targetPlatform>
+    -->
+
+  </Description>
+</RDF>
diff --git a/plugins/npapi/liboophm.r b/plugins/npapi/liboophm.r
new file mode 100644
index 0000000..251d5f4
--- /dev/null
+++ b/plugins/npapi/liboophm.r
@@ -0,0 +1,25 @@
+/*
+ * 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/main.cpp b/plugins/npapi/main.cpp
new file mode 100644
index 0000000..065c0c0
--- /dev/null
+++ b/plugins/npapi/main.cpp
@@ -0,0 +1,302 @@
+/*
+ *  main.cpp
+ *  gwt-hosted-mode
+ *
+ *  Created by Kelly Norton on 11/18/07.
+ *  Copyright 2007 Google Inc. All rights reserved.
+ *
+ */
+
+#ifndef _WINDOWS
+#include <unistd.h>
+#endif
+
+#include "Debug.h"
+
+#include "mozincludes.h"
+#include "Plugin.h"
+#include "ScriptableInstance.h"
+#include "scoped_ptr/scoped_ptr.h"
+
+#ifdef _WINDOWS
+#include <windows.h>
+
+BOOL APIENTRY DllMain(HMODULE hModule, DWORD ulReasonForCall, LPVOID lpReserved) {
+  switch (ulReasonForCall) {
+    case DLL_PROCESS_ATTACH:
+    case DLL_THREAD_ATTACH:
+    case DLL_THREAD_DETACH:
+    case DLL_PROCESS_DETACH:
+      break;
+  }
+  return TRUE;
+}
+#endif
+
+extern "C" {
+
+  static const NPNetscapeFuncs* browser;
+
+  NPError	NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode,
+	  int16 argc, char* argn[], char* argv[], NPSavedData* saved);
+  NPError	NPP_Destroy(NPP instance, NPSavedData** save);
+  NPError	NPP_SetWindow(NPP instance, NPWindow* window);
+  NPError	NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream,
+	  NPBool seekable, uint16* stype);
+  NPError	NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason);
+  int32		NPP_WriteReady(NPP instance, NPStream* stream);
+  int32		NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len,
+	  void* buffer);
+  void		NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname);
+  void		NPP_Print(NPP instance, NPPrint* platformPrint);
+  int16		NPP_HandleEvent(NPP instance, void* event);
+  void		NPP_URLNotify(NPP instance, const char* URL, NPReason reason,
+	  void* notifyData);
+  NPError NP_GetValue(void*, NPPVariable variable, void *value);
+  NPError	NPP_GetValue(NPP instance, NPPVariable variable, void *value);
+  NPError	NPP_SetValue(NPP instance, NPNVariable variable, void *value);
+
+  // necessary for Mac
+#ifdef __APPLE_CC__
+  #pragma export on
+  int main(NPNetscapeFuncs* browserFuncs, NPPluginFuncs* pluginFuncs, NPP_ShutdownUPP* shutdownUPP);
+#endif
+  NPError WINAPI NP_Initialize(NPNetscapeFuncs* browserFuncs NPINIT_ARG(pluginFuncs));
+  NPError WINAPI NP_GetEntryPoints(NPPluginFuncs* pluginFuncs);
+  const char *NP_GetMIMEDescription();
+  const char *NPP_GetMIMEDescription();
+  NP_SHUTDOWN_RETURN_TYPE WINAPI NP_Shutdown(void);
+#ifdef __APPLE_CC__
+  #pragma export off
+#endif
+
+  // Function pointer variables:
+
+  NPError WINAPI NP_Initialize(NPNetscapeFuncs* browserFuncs NPINIT_ARG(pluginFuncs)) {
+    Debug::log(Debug::Info) << "NP_Initialize (gwt-hosted-mode/c++)";
+#ifndef _WINDOWS
+    Debug::log(Debug::Info) << ", pid=" << (unsigned) getpid();
+#endif
+    Debug::log(Debug::Info) << Debug::flush;
+    SetNPNFuncs(browserFuncs);
+    browser = &GetNPNFuncs();
+#ifdef NPINIT_GETS_ENTRYPOINTS
+    NP_GetEntryPoints(pluginFuncs);
+#endif
+    return NPERR_NO_ERROR;
+  }
+
+#ifdef __APPLE_CC__
+  int main(NPNetscapeFuncs* browserFuncs, NPPluginFuncs* pluginFuncs, NPP_ShutdownUPP* shutdownUPP) {
+    printf("main (gwt-hosted-mode/c++)\n");
+    if (shutdownUPP == NULL) {
+      return NPERR_INVALID_FUNCTABLE_ERROR;
+    }
+    *shutdownUPP = NP_Shutdown;//NewNPP_ShutdownProc(NP_Shutdown);
+    NP_Initialize(browserFuncs);
+    NP_GetEntryPoints(pluginFuncs);
+    return NPERR_NO_ERROR;
+  }
+#endif
+
+  NPError WINAPI NP_GetEntryPoints(NPPluginFuncs* pluginFuncs) {
+    Debug::log(Debug::Debugging) << "NP_GetEntryPoints" << Debug::flush;
+#ifdef BROWSER_WEBKIT
+    pluginFuncs->size          = sizeof(NPPluginFuncs);
+#else
+    if (pluginFuncs->size < sizeof(NPPluginFuncs)) {
+      return NPERR_INVALID_FUNCTABLE_ERROR;
+    }
+#endif
+    pluginFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
+#if 1
+    pluginFuncs->newp          = NPP_New;
+    pluginFuncs->destroy       = NPP_Destroy;
+    pluginFuncs->setwindow     = NPP_SetWindow;
+    pluginFuncs->newstream     = NPP_NewStream;
+    pluginFuncs->destroystream = NPP_DestroyStream;
+    pluginFuncs->asfile        = NPP_StreamAsFile;
+    pluginFuncs->writeready    = NPP_WriteReady;
+#ifdef BROWSER_WEBKIT
+    pluginFuncs->write         = reinterpret_cast<NPP_WriteProcPtr>(NPP_Write);
+#else
+    pluginFuncs->write         = NPP_Write;
+#endif
+    pluginFuncs->print         = NPP_Print;
+    pluginFuncs->event         = NPP_HandleEvent;
+    pluginFuncs->urlnotify     = NPP_URLNotify;
+    pluginFuncs->getvalue      = NPP_GetValue;
+    pluginFuncs->setvalue      = NPP_SetValue;
+    pluginFuncs->javaClass     = NULL;
+#else
+    pluginFuncs->newp =          NewNPP_NewProc(NPP_New);
+    pluginFuncs->destroy =       NewNPP_DestroyProc(NPP_Destroy);
+    pluginFuncs->setwindow =     NewNPP_SetWindowProc(NPP_SetWindow);
+    pluginFuncs->newstream =     NewNPP_NewStreamProc(NPP_NewStream);
+    pluginFuncs->destroystream = NewNPP_DestroyStreamProc(NPP_DestroyStream);
+    pluginFuncs->asfile =        NewNPP_StreamAsFileProc(NPP_StreamAsFile);
+    pluginFuncs->writeready =    NewNPP_WriteReadyProc(NPP_WriteReady);
+    pluginFuncs->write =         NewNPP_WriteProc(NPP_Write);
+    pluginFuncs->print =         NewNPP_PrintProc(NPP_Print);
+    pluginFuncs->event =         NewNPP_HandleEventProc(NPP_HandleEvent);
+    pluginFuncs->urlnotify =     NewNPP_URLNotifyProc(NPP_URLNotify);
+    pluginFuncs->getvalue =      NewNPP_GetValueProc(NPP_GetValue);
+    pluginFuncs->setvalue =      NewNPP_SetValueProc(NPP_SetValue);
+#endif
+    return NPERR_NO_ERROR;
+  }
+
+  const char *NP_GetMIMEDescription() {
+    Debug::log(Debug::Info) << "NP_GetMIMEDescription: returned mime description" << Debug::flush;
+    return "application/x-gwt-hosted-mode::GWT Hosted-mode plugin";
+  }
+
+  const char *NPP_GetMIMEDescription() {
+    return NP_GetMIMEDescription();
+  }
+
+  NP_SHUTDOWN_RETURN_TYPE WINAPI NP_Shutdown(void) {
+    Debug::log(Debug::Debugging) << "NP_Shutdown" << Debug::flush;
+    return NP_SHUTDOWN_RETURN(NPERR_NO_ERROR);
+  }
+
+  NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[],
+      char* argv[], NPSavedData* saved) {
+    Debug::log(Debug::Info) << "NPP_New(instance=" << instance << ",mode=" << mode << ",argc="
+        << argc << ",args=[";
+    for (int i = 0; i < argc; ++i) {
+      Debug::log(Debug::Info) << (i ? "," : "") << argn[i] << "=" << argv[i];
+    }
+    Debug::log(Debug::Info) << "],saved=" << saved << "): version=" << browser->version
+        << Debug::flush;
+    // Version 14 provides browser->createobject, which we need for npruntime support.
+    if (browser->version < 14) {
+      return NPERR_INVALID_INSTANCE_ERROR;
+    }
+    if (instance == NULL) {
+      return NPERR_INVALID_INSTANCE_ERROR;
+    }
+    Plugin* obj;
+//    if (saved) {
+//      obj = new Plugin(instance, reinterpret_cast<ScriptableInstance*>(saved));
+//    } else {
+      obj = new Plugin(instance);
+//    }
+    instance->pdata = obj;
+
+    // Make this a windowless plugin.
+    return NPN_SetValue(instance, NPPVpluginWindowBool, NULL);
+  }
+
+  NPError NPP_Destroy(NPP instance, NPSavedData** save) {
+    Debug::log(Debug::Info) << "NPP_Destroy(instance=" << instance << ")" << Debug::flush;
+    if (instance == NULL) {
+      return NPERR_INVALID_INSTANCE_ERROR;
+    }
+    Plugin* plugin = static_cast<Plugin*>(instance->pdata);
+    if (plugin) {
+      delete plugin;
+      instance->pdata = 0;
+    }
+    return NPERR_NO_ERROR;
+  }
+
+  NPError NPP_SetWindow(NPP instance, NPWindow* window) {
+    Debug::log(Debug::Info) << "NPP_SetWindow(instance=" << instance << ",window=" << window
+        << ")" << Debug::flush;
+    return NPERR_NO_ERROR;
+  }
+   
+
+  NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype) {
+    Debug::log(Debug::Info) << "NPP_NewStream(instance=" << instance << ")" << Debug::flush;
+    *stype = NP_ASFILEONLY;
+    return NPERR_NO_ERROR;
+  }
+
+  NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason) {
+    Debug::log(Debug::Info) << "NPP_DestroyStream(instance=" << instance << ")" << Debug::flush;
+    return NPERR_NO_ERROR;
+  }
+
+  int32 NPP_WriteReady(NPP instance, NPStream* stream) {
+    Debug::log(Debug::Info) << "NPP_WriteReady(instance=" << instance << ")" << Debug::flush;
+    return 0;
+  }
+
+  int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer) {
+    Debug::log(Debug::Info) << "NPP_Write(instance=" << instance << ")" << Debug::flush;
+    return 0;
+  }
+
+  void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) {
+    Debug::log(Debug::Info) << "NPP_StreamAsFile(instance=" << instance << ")" << Debug::flush;
+  }
+
+  void NPP_Print(NPP instance, NPPrint* platformPrint) {
+    Debug::log(Debug::Info) << "NPP_Print(instance=" << instance << ")" << Debug::flush;
+  }
+
+  int16 NPP_HandleEvent(NPP instance, void* event) {
+    Debug::log(Debug::Info) << "NPP_HandleEvent(instance=" << instance << ")" << Debug::flush;
+    return 1 ;
+  }
+
+  void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData) {
+    Debug::log(Debug::Info) << "NPP_URLNotify(instance=" << instance << ")" << Debug::flush;
+  }
+
+  NPObject *NPP_GetScriptableInstance(NPP instance) {
+    Debug::log(Debug::Info) << "NPP_GetScriptableInstance(instance=" << instance << ")" << Debug::flush;
+    if (!instance) {
+      return 0;
+    }
+    Plugin* plugin = static_cast<Plugin*>(instance->pdata);
+    ScriptableInstance* scriptableInstance = plugin->getScriptableInstance();
+    NPN_RetainObject(scriptableInstance);  // caller expects it retained.
+    return scriptableInstance;
+  }
+  
+  NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) {
+    Debug::log(Debug::Info) << "NPP_GetValue(instance=" << instance << ",var=" << variable << ")"
+        << Debug::flush;
+    switch (variable) {
+      case NPPVpluginScriptableNPObject:
+        // here the plugin is asked by Mozilla to tell if it is scriptable
+        // we should return a valid interface id and a pointer to 
+        // nsScriptablePeer interface which we should have implemented
+        // and which should be defined in the corressponding *.xpt file
+        // in the bin/components folder
+        *static_cast<NPObject**>(value) = NPP_GetScriptableInstance(instance);
+        break;
+      default:
+        // pass other ones to the static version of GetValue
+        return NP_GetValue(0, variable, value);
+    }
+    return NPERR_NO_ERROR;
+  }
+
+  NPError NP_GetValue(void*, NPPVariable variable, void *value) {
+    Debug::log(Debug::Info) << "NP_GetValue(var=" << variable << ")" << Debug::flush;
+    switch (variable) {
+      case NPPVpluginNameString:
+        *static_cast<const char **>(value) = "GWT Hosted-mode Plugin";
+        break;
+      case NPPVpluginDescriptionString:
+        *static_cast<const char **>(value) = "Plugin to enable debugging of Google Web Toolkit "
+            "applications in hosted mode.";
+        break;
+      default:
+        Debug::log(Debug::Info) << "NPP_GetValue(var=" << variable
+            << ") -- unexpected variable type" << Debug::flush;
+        return NPERR_GENERIC_ERROR;
+    }
+    return NPERR_NO_ERROR;
+  }
+
+  NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) {
+    Debug::log(Debug::Info) << "NPP_SetValue(instance=" << instance << ",var=" << variable << ")"
+        << Debug::flush;
+    return NPERR_NO_ERROR;
+  }
+}
diff --git a/plugins/npapi/mozincludes.h b/plugins/npapi/mozincludes.h
new file mode 100644
index 0000000..3b455ff
--- /dev/null
+++ b/plugins/npapi/mozincludes.h
@@ -0,0 +1,63 @@
+#ifndef _H_mozincludes
+#define _H_mozincludes
+
+// Defines private prototypes for copy constructor and assigment operator. Do
+// not implement these methods.
+#define DISALLOW_EVIL_CONSTRUCTORS(CLASS) \
+ private:                                 \
+  CLASS(const CLASS&);                    \
+  CLASS& operator=(const CLASS&)
+
+#include "npapi/npapi.h"
+#include "npapi/nphostapi.h"
+#include "npapi/npruntime.h"
+
+void SetNPNFuncs(NPNetscapeFuncs* npnFuncs);
+const NPNetscapeFuncs& GetNPNFuncs();
+
+#include "NPObjectWrapper.h"
+
+inline const NPUTF8 *GetNPStringUTF8Characters(const NPString &npstr) {
+  return npstr.UTF8Characters;
+}
+
+inline uint32 GetNPStringUTF8Length(const NPString &npstr) {
+  return npstr.UTF8Length;
+}
+
+// Convenience wrappers to make an NPVariant from various string types.
+#define STDSTRING_TO_NPVARIANT(str, var) \
+  STRINGN_TO_NPVARIANT(str.data(), static_cast<uint32_t>(str.length()), var)
+
+#define NPSTRING_TO_NPVARIANT(npstr, var) \
+  STRINGN_TO_NPVARIANT(GetNPStringUTF8Characters(npstr), \
+                       GetNPStringUTF8Length(npstr), var)
+
+#ifdef LINUX
+#define OSCALL /**/
+#define WINAPI /**/
+#define DLLEXP /**/
+#define NPINIT_ARG(argname) , NPPluginFuncs* argname
+#define NPINIT_GETS_ENTRYPOINTS
+#define NP_SHUTDOWN_RETURN_TYPE NPError
+#define NP_SHUTDOWN_RETURN(val) (val)
+#endif
+
+#ifdef _WINDOWS
+#define DLLEXP __declspec(dllexport)
+#define NPINIT_ARG(argname) /**/
+#define NP_SHUTDOWN_RETURN_TYPE NPError
+#define NP_SHUTDOWN_RETURN(val) (val)
+#endif
+
+#ifdef __mac
+#define OSCALL /**/
+#define WINAPI /**/
+#define DLLEXP /**/
+#define NPINIT_ARG(argname) /**/
+#define NP_SHUTDOWN_RETURN_TYPE void
+#define NP_SHUTDOWN_RETURN(val) /**/
+typedef void (* NP_LOADDS NPP_ShutdownUPP)(void); // from npupp.h
+#endif
+
+#endif
diff --git a/plugins/npapi/npOOPHM.def b/plugins/npapi/npOOPHM.def
new file mode 100644
index 0000000..d581f53
--- /dev/null
+++ b/plugins/npapi/npOOPHM.def
@@ -0,0 +1,7 @@
+LIBRARY NPOOPHM
+
+EXPORTS
+  NP_GetEntryPoints			@1
+  NP_Initialize				@2
+  NP_Shutdown				@3
+  NP_GetMIMEDescription		@4
\ No newline at end of file
diff --git a/plugins/npapi/npOOPHM.rc b/plugins/npapi/npOOPHM.rc
new file mode 100644
index 0000000..5863b24
--- /dev/null
+++ b/plugins/npapi/npOOPHM.rc
@@ -0,0 +1,73 @@
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+#include "mfc/afxres.h"
+#undef APSTUDIO_READONLY_SYMBOLS
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif
+
+1 VERSIONINFO
+  FILEVERSION 0,1,1,0
+  PRODUCTVERSION 0,1,1,0
+  FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+  FILEFLAGS 0x1L
+#else
+  FILEFLAGS 0x0L
+#endif
+  FILEOS 0x40004L
+  FILETYPE 0x2L
+  FILESUBTYPE 0x0L
+BEGIN
+  BLOCK "StringFileInfo"
+  BEGIN
+  	BLOCK "040904e4"
+  	BEGIN
+  	  VALUE "CompanyName", 		"Google Inc"
+  	  VALUE "FileDescription",	"GWT OOPHM Plugin"
+#if 0
+  	  VALUE "FileExtents",		""
+#endif
+  	  VALUE "FileOpenName",		"Plugin to allow debugging of GWT applications in hosted mode."
+  	  VALUE "FileVersion",		"0.1a"
+  	  VALUE "InternalName",		"GWT OOPHM Plugin"
+  	  VALUE "LegalCopyright",	"Copyright © 2008 Google Inc.  All rights reserved."
+  	  VALUE "MIMEType",			"application/x-gwt-hosted-mode"
+  	  VALUE "OriginalFilename",	"npOOPHM.dll"
+  	  VALUE "ProductName",		"GWT OOPHM Plugin"
+  	  VALUE "ProductVersion",	"0.1a"
+  	END
+  END
+  BLOCK "VarFileInfo"
+  BEGIN
+    VALUE "Translation", 0x409, 1252
+  END
+END
+
+#ifdef APSTUDIO_INVOKED
+1 TEXTINCLUDE
+BEGIN
+  "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+  "#include ""mfc/afxres.h""\r\n"
+  "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+  "\r\n"
+  "\0"
+END
+
+#endif
+
+#else
+
+#endif
diff --git a/plugins/npapi/npapi/npapi.h b/plugins/npapi/npapi/npapi.h
new file mode 100644
index 0000000..dc37367
--- /dev/null
+++ b/plugins/npapi/npapi/npapi.h
@@ -0,0 +1,801 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+/*
+ *  npapi.h $Revision: 3.48 $
+ *  Netscape client plug-in API spec
+ */
+
+#ifndef _NPAPI_H_
+#define _NPAPI_H_
+
+
+// BEGIN GOOGLE GEARS MODIFICATIONS
+
+//#include "gears/base/common/int_types.h"
+// Signed integer types
+typedef signed char         int8;
+typedef short               int16;
+typedef int                 int32;
+#ifdef _MSC_VER  //_MSC_VER is defined iff the code is compiled by MSVC
+typedef __int64             int64;
+#else
+typedef long long           int64;
+#endif /* _MSC_VER */
+
+// Unsigned integer types
+typedef unsigned char      uint8;
+typedef unsigned short     uint16;
+typedef unsigned int       uint32;
+#ifdef _MSC_VER
+typedef unsigned __int64   uint64;
+#else
+typedef unsigned long long uint64;
+#endif /* _MSC_VER */
+
+// END GOOGLE GEARS MODIFICATIONS
+
+
+#ifdef __OS2__
+#pragma pack(1)
+#endif
+
+//#include "prtypes.h"
+/* Copied from xp_core.h */
+/* removed #ifdef for hpux defined in /usr/include/model.h */
+#ifndef _INT16
+#define _INT16
+#endif
+#ifndef _INT32
+#define _INT32
+#endif
+#ifndef _UINT16
+#define _UINT16
+#endif
+#ifndef _UINT32
+#define _UINT32
+#endif
+
+/* 
+ * NO_NSPR_10_SUPPORT disables the inclusion 
+ * of obsolete/protypes.h, whose int16, uint16, 
+ * int32, and uint32 typedefs conflict with those 
+ * in this file. 
+ */ 
+#ifndef NO_NSPR_10_SUPPORT
+#define NO_NSPR_10_SUPPORT
+#endif
+#ifdef OJI
+#include "jri.h"                /* Java Runtime Interface */
+#endif
+
+#if defined (__OS2__ ) || defined (OS2)
+#	ifndef XP_OS2
+#		define XP_OS2 1
+#	endif /* XP_OS2 */
+#endif /* __OS2__ */
+
+#ifdef _WINDOWS
+// BEGIN GOOGLE MODIFICATIONS
+//#ifdef XP_WIN
+typedef __int32 int32_t;
+typedef unsigned __int32 uint32_t; 
+//#include <windows.h>
+//#endif // XP_WIN
+// END GOOGLE MODIFICATIONS
+
+#	ifndef XP_WIN
+#		define XP_WIN 1
+#	endif /* XP_WIN */
+#endif /* _WINDOWS */
+
+#ifdef __MWERKS__
+#	define _declspec __declspec
+#	ifdef __INTEL__
+#		undef NULL
+#		ifndef XP_WIN
+#			define XP_WIN 1
+#		endif /* XP_WIN */
+#	endif /* __INTEL__ */
+#endif /* __MWERKS__ */
+
+#ifdef XP_MACOSX
+#include <Carbon/Carbon.h>
+#ifdef __LP64__
+#define NP_NO_QUICKDRAW
+#endif
+#endif
+
+#if defined(XP_UNIX) 
+#	include <stdio.h>
+#	if defined(MOZ_X11)
+#		include <X11/Xlib.h>
+#		include <X11/Xutil.h>
+#	endif
+#endif
+
+/*----------------------------------------------------------------------*/
+/*                        Plugin Version Constants                      */
+/*----------------------------------------------------------------------*/
+
+#define NP_VERSION_MAJOR 0
+#define NP_VERSION_MINOR 19
+
+
+/* The OS/2 version of Netscape uses RC_DATA to define the
+   mime types, file extensions, etc that are required.
+   Use a vertical bar to separate types, end types with \0.
+   FileVersion and ProductVersion are 32bit ints, all other
+   entries are strings the MUST be terminated wwith a \0.
+
+AN EXAMPLE:
+
+RCDATA NP_INFO_ProductVersion { 1,0,0,1,}
+
+RCDATA NP_INFO_MIMEType    { "video/x-video|",
+                             "video/x-flick\0" }
+RCDATA NP_INFO_FileExtents { "avi|",
+                             "flc\0" }
+RCDATA NP_INFO_FileOpenName{ "MMOS2 video player(*.avi)|",
+                             "MMOS2 Flc/Fli player(*.flc)\0" }
+
+RCDATA NP_INFO_FileVersion       { 1,0,0,1 }
+RCDATA NP_INFO_CompanyName       { "Netscape Communications\0" }
+RCDATA NP_INFO_FileDescription   { "NPAVI32 Extension DLL\0"
+RCDATA NP_INFO_InternalName      { "NPAVI32\0" )
+RCDATA NP_INFO_LegalCopyright    { "Copyright Netscape Communications \251 1996\0"
+RCDATA NP_INFO_OriginalFilename  { "NVAPI32.DLL" }
+RCDATA NP_INFO_ProductName       { "NPAVI32 Dynamic Link Library\0" }
+
+*/
+
+
+/* RC_DATA types for version info - required */
+#define NP_INFO_ProductVersion      1
+#define NP_INFO_MIMEType            2
+#define NP_INFO_FileOpenName        3
+#define NP_INFO_FileExtents         4
+
+/* RC_DATA types for version info - used if found */
+#define NP_INFO_FileDescription     5
+#define NP_INFO_ProductName         6
+
+/* RC_DATA types for version info - optional */
+#define NP_INFO_CompanyName         7
+#define NP_INFO_FileVersion         8
+#define NP_INFO_InternalName        9
+#define NP_INFO_LegalCopyright      10
+#define NP_INFO_OriginalFilename    11
+
+#ifndef RC_INVOKED
+
+
+
+/*----------------------------------------------------------------------*/
+/*                       Definition of Basic Types                      */
+/*----------------------------------------------------------------------*/
+
+#ifndef _UINT16
+typedef unsigned short uint16;
+#endif
+
+#ifndef _UINT32
+#    if defined(__alpha) || defined(__amd64__) || defined(__x86_64__)
+typedef unsigned int uint32;
+#    else  /* __alpha */
+typedef unsigned long uint32;
+#    endif /* __alpha */
+#endif
+
+/*
+ * AIX defines these in sys/inttypes.h included from sys/types.h
+ */
+#ifndef AIX
+#ifndef _INT16
+typedef short int16;
+#endif
+
+#ifndef _INT32
+#    if defined(__alpha) || defined(__amd64__) || defined(__x86_64__)
+typedef int int32;
+#    else  /* __alpha */
+typedef long int32;
+#    endif /* __alpha */
+#endif
+#endif
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+#ifndef TRUE
+#define TRUE (1)
+#endif
+#ifndef NULL
+#define NULL (0L)
+#endif
+
+#ifdef XP_MACOSX
+typedef enum {
+#ifndef NP_NO_QUICKDRAW
+  NPDrawingModelQuickDraw = 0,
+#endif
+  NPDrawingModelCoreGraphics = 1
+} NPDrawingModel;
+#endif
+
+typedef unsigned char	NPBool;
+typedef int16			NPError;
+typedef int16			NPReason;
+typedef char*			NPMIMEType;
+
+
+
+/*----------------------------------------------------------------------*/
+/*                       Structures and definitions                     */
+/*----------------------------------------------------------------------*/
+
+/*
+ *  NPP is a plug-in's opaque instance handle
+ */
+typedef struct _NPP
+{
+  void*	pdata;      /* plug-in private data */
+  void*	ndata;      /* netscape private data */
+} NPP_t;
+
+typedef NPP_t*  NPP;
+
+
+typedef struct _NPStream
+{
+  void*  pdata; /* plug-in private data */
+  void*  ndata; /* netscape private data */
+  const  char* url;
+  uint32 end;
+  uint32 lastmodified;
+  void*  notifyData;
+  const  char* headers; /* Response headers from host.
+                         * Exists only for >= NPVERS_HAS_RESPONSE_HEADERS.
+                         * Used for HTTP only; NULL for non-HTTP.
+                         * Available from NPP_NewStream onwards.
+                         * Plugin should copy this data before storing it.
+                         * Includes HTTP status line and all headers,
+                         * preferably verbatim as received from server,
+                         * headers formatted as in HTTP ("Header: Value"),
+                         * and newlines (\n, NOT \r\n) separating lines.
+                         * Terminated by \n\0 (NOT \n\n\0). */
+} NPStream;
+
+
+typedef struct _NPByteRange
+{
+  int32  offset; /* negative offset means from the end */
+  uint32 length;
+  struct _NPByteRange* next;
+} NPByteRange;
+
+
+typedef struct _NPSavedData
+{
+  int32	len;
+  void*	buf;
+} NPSavedData;
+
+
+typedef struct _NPRect
+{
+  uint16 top;
+  uint16 left;
+  uint16 bottom;
+  uint16 right;
+} NPRect;
+
+typedef struct _NPSize 
+{ 
+  int32 width; 
+  int32 height; 
+} NPSize; 
+
+#ifdef XP_UNIX
+/*
+ * Unix specific structures and definitions
+ */
+
+/*
+ * Callback Structures.
+ *
+ * These are used to pass additional platform specific information.
+ */
+enum {
+  NP_SETWINDOW = 1,
+  NP_PRINT
+};
+
+typedef struct
+{
+  int32 type;
+} NPAnyCallbackStruct;
+
+typedef struct
+{
+  int32        type;
+#ifdef MOZ_X11
+  Display*     display;
+  Visual*      visual;
+  Colormap     colormap;
+  unsigned int depth;
+#endif
+} NPSetWindowCallbackStruct;
+
+typedef struct
+{
+  int32 type;
+  FILE* fp;
+} NPPrintCallbackStruct;
+
+#endif /* XP_UNIX */
+
+
+/*
+ *   The following masks are applied on certain platforms to NPNV and 
+ *   NPPV selectors that pass around pointers to COM interfaces. Newer 
+ *   compilers on some platforms may generate vtables that are not 
+ *   compatible with older compilers. To prevent older plugins from 
+ *   not understanding a new browser's ABI, these masks change the 
+ *   values of those selectors on those platforms. To remain backwards
+ *   compatible with differenet versions of the browser, plugins can 
+ *   use these masks to dynamically determine and use the correct C++
+ *   ABI that the browser is expecting. This does not apply to Windows 
+ *   as Microsoft's COM ABI will likely not change.
+ */
+
+#define NP_ABI_GCC3_MASK  0x10000000
+/*
+ *   gcc 3.x generated vtables on UNIX and OSX are incompatible with 
+ *   previous compilers.
+ */
+#if (defined (XP_UNIX) && defined(__GNUC__) && (__GNUC__ >= 3))
+#define _NP_ABI_MIXIN_FOR_GCC3 NP_ABI_GCC3_MASK
+#else
+#define _NP_ABI_MIXIN_FOR_GCC3 0
+#endif
+
+
+#define NP_ABI_MACHO_MASK 0x01000000
+/*
+ *   On OSX, the Mach-O executable format is significantly
+ *   different than CFM. In addition to having a different
+ *   C++ ABI, it also has has different C calling convention.
+ *   You must use glue code when calling between CFM and
+ *   Mach-O C functions. 
+ */
+#if (defined(TARGET_RT_MAC_MACHO))
+#define _NP_ABI_MIXIN_FOR_MACHO NP_ABI_MACHO_MASK
+#else
+#define _NP_ABI_MIXIN_FOR_MACHO 0
+#endif
+
+
+#define NP_ABI_MASK (_NP_ABI_MIXIN_FOR_GCC3 | _NP_ABI_MIXIN_FOR_MACHO)
+
+/*
+ * List of variable names for which NPP_GetValue shall be implemented
+ */
+typedef enum {
+  NPPVpluginNameString = 1,
+  NPPVpluginDescriptionString,
+  NPPVpluginWindowBool,
+  NPPVpluginTransparentBool,
+  NPPVjavaClass,                /* Not implemented in Mozilla 1.0 */
+  NPPVpluginWindowSize,
+  NPPVpluginTimerInterval,
+
+  NPPVpluginScriptableInstance = (10 | NP_ABI_MASK),
+  NPPVpluginScriptableIID = 11,
+
+  /* Introduced in Mozilla 0.9.9 */
+  NPPVjavascriptPushCallerBool = 12,
+
+  /* Introduced in Mozilla 1.0 */
+  NPPVpluginKeepLibraryInMemory = 13,
+  NPPVpluginNeedsXEmbed         = 14,
+
+  /* Get the NPObject for scripting the plugin. Introduced in Firefox
+   * 1.0 (NPAPI minor version 14).
+   */
+  NPPVpluginScriptableNPObject  = 15,
+
+  /* Get the plugin value (as \0-terminated UTF-8 string data) for
+   * form submission if the plugin is part of a form. Use
+   * NPN_MemAlloc() to allocate memory for the string data. Introduced
+   * in Mozilla 1.8b2 (NPAPI minor version 15).
+   */
+  NPPVformValue = 16
+#ifdef XP_MACOSX
+  /* Used for negotiating drawing models */
+  , NPPVpluginDrawingModel = 1000
+#endif
+} NPPVariable;
+
+/*
+ * List of variable names for which NPN_GetValue is implemented by Mozilla
+ */
+typedef enum {
+  NPNVxDisplay = 1,
+  NPNVxtAppContext,
+  NPNVnetscapeWindow,
+  NPNVjavascriptEnabledBool,
+  NPNVasdEnabledBool,
+  NPNVisOfflineBool,
+
+  /* 10 and over are available on Mozilla builds starting with 0.9.4 */
+  NPNVserviceManager = (10 | NP_ABI_MASK),
+  NPNVDOMElement     = (11 | NP_ABI_MASK),   /* available in Mozilla 1.2 */
+  NPNVDOMWindow      = (12 | NP_ABI_MASK),
+  NPNVToolkit        = (13 | NP_ABI_MASK),
+  NPNVSupportsXEmbedBool = 14,
+
+  /* Get the NPObject wrapper for the browser window. */
+  NPNVWindowNPObject = 15,
+
+  /* Get the NPObject wrapper for the plugins DOM element. */
+  NPNVPluginElementNPObject = 16,
+
+  NPNVSupportsWindowless = 17
+
+#ifdef XP_MACOSX
+  /* Used for negotiating drawing models */
+  , NPNVpluginDrawingModel = 1000
+#ifndef NP_NO_QUICKDRAW
+  , NPNVsupportsQuickDrawBool = 2000
+#endif
+  , NPNVsupportsCoreGraphicsBool = 2001
+#endif
+} NPNVariable;
+
+/*
+ * The type of Tookkit the widgets use
+ */
+typedef enum {
+  NPNVGtk12 = 1,
+  NPNVGtk2
+} NPNToolkitType;
+
+/*
+ * The type of a NPWindow - it specifies the type of the data structure
+ * returned in the window field.
+ */
+typedef enum {
+  NPWindowTypeWindow = 1,
+  NPWindowTypeDrawable
+} NPWindowType;
+
+typedef struct _NPWindow
+{
+  void* window;  /* Platform specific window handle */
+                 /* OS/2: x - Position of bottom left corner  */
+                 /* OS/2: y - relative to visible netscape window */
+  int32 x;       /* Position of top left corner relative */
+  int32 y;       /* to a netscape page.					*/
+  uint32 width;  /* Maximum window size */
+  uint32 height;
+  NPRect clipRect; /* Clipping rectangle in port coordinates */
+                   /* Used by MAC only.			  */
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
+  void * ws_info; /* Platform-dependent additonal data */
+#endif /* XP_UNIX */
+  NPWindowType type; /* Is this a window or a drawable? */
+} NPWindow;
+
+
+typedef struct _NPFullPrint
+{
+  NPBool pluginPrinted;/* Set TRUE if plugin handled fullscreen printing */
+  NPBool printOne;		 /* TRUE if plugin should print one copy to default printer */
+  void* platformPrint; /* Platform-specific printing info */
+} NPFullPrint;
+
+typedef struct _NPEmbedPrint
+{
+  NPWindow window;
+  void* platformPrint; /* Platform-specific printing info */
+} NPEmbedPrint;
+
+typedef struct _NPPrint
+{
+  uint16 mode;               /* NP_FULL or NP_EMBED */
+  union
+  {
+    NPFullPrint fullPrint;   /* if mode is NP_FULL */
+    NPEmbedPrint embedPrint; /* if mode is NP_EMBED */
+  } print;
+} NPPrint;
+
+#ifdef XP_MACOSX
+typedef EventRecord	NPEvent;
+#elif defined(XP_WIN)
+typedef struct _NPEvent
+{
+  uint16 event;
+  uint32 wParam;
+  uint32 lParam;
+} NPEvent;
+#elif defined(XP_OS2)
+typedef struct _NPEvent
+{
+  uint32 event;
+  uint32 wParam;
+  uint32 lParam;
+} NPEvent;
+#elif defined (XP_UNIX) && defined(MOZ_X11)
+typedef XEvent NPEvent;
+#else
+typedef void*			NPEvent;
+#endif /* XP_MACOSX */
+
+#ifdef XP_MACOSX
+typedef void* NPRegion;
+#ifndef NP_NO_QUICKDRAW
+typedef RgnHandle NPQDRegion;
+#endif
+typedef CGPathRef NPCGRegion;
+#elif defined(XP_WIN)
+//typedef HRGN NPRegion;
+typedef int NPRegion;
+#elif defined(XP_UNIX) && defined(MOZ_X11)
+typedef Region NPRegion;
+#else
+typedef void *NPRegion;
+#endif /* XP_MACOSX */
+
+#ifdef XP_MACOSX
+/*
+ *  Mac-specific structures and definitions.
+ */
+
+typedef struct NP_Port
+{
+  CGrafPtr port; /* Grafport */
+  int32 portx;   /* position inside the topmost window */
+  int32 porty;
+} NP_Port;
+
+typedef struct NP_CGContext
+{
+  CGContextRef context;
+  WindowRef window;
+} NP_CGContext;
+
+/*
+ *  Non-standard event types that can be passed to HandleEvent
+ */
+
+enum NPEventType {
+  NPEventType_GetFocusEvent = (osEvt + 16),
+  NPEventType_LoseFocusEvent,
+  NPEventType_AdjustCursorEvent,
+  NPEventType_MenuCommandEvent,
+  NPEventType_ClippingChangedEvent,
+  NPEventType_ScrollingBeginsEvent = 1000,
+  NPEventType_ScrollingEndsEvent
+};
+
+#ifdef OBSOLETE
+#define getFocusEvent     (osEvt + 16)
+#define loseFocusEvent    (osEvt + 17)
+#define adjustCursorEvent (osEvt + 18)
+#endif
+#endif /* XP_MACOSX */
+
+/*
+ * Values for mode passed to NPP_New:
+ */
+#define NP_EMBED 1
+#define NP_FULL  2
+
+/*
+ * Values for stream type passed to NPP_NewStream:
+ */
+#define NP_NORMAL     1
+#define NP_SEEK       2
+#define NP_ASFILE     3
+#define NP_ASFILEONLY 4
+
+#define NP_MAXREADY	(((unsigned)(~0)<<1)>>1)
+
+
+/*----------------------------------------------------------------------*/
+/*		     Error and Reason Code definitions			*/
+/*----------------------------------------------------------------------*/
+
+/*
+ * Values of type NPError:
+ */
+#define NPERR_BASE                         0
+#define NPERR_NO_ERROR                    (NPERR_BASE + 0)
+#define NPERR_GENERIC_ERROR               (NPERR_BASE + 1)
+#define NPERR_INVALID_INSTANCE_ERROR      (NPERR_BASE + 2)
+#define NPERR_INVALID_FUNCTABLE_ERROR     (NPERR_BASE + 3)
+#define NPERR_MODULE_LOAD_FAILED_ERROR    (NPERR_BASE + 4)
+#define NPERR_OUT_OF_MEMORY_ERROR         (NPERR_BASE + 5)
+#define NPERR_INVALID_PLUGIN_ERROR        (NPERR_BASE + 6)
+#define NPERR_INVALID_PLUGIN_DIR_ERROR    (NPERR_BASE + 7)
+#define NPERR_INCOMPATIBLE_VERSION_ERROR  (NPERR_BASE + 8)
+#define NPERR_INVALID_PARAM               (NPERR_BASE + 9)
+#define NPERR_INVALID_URL                 (NPERR_BASE + 10)
+#define NPERR_FILE_NOT_FOUND              (NPERR_BASE + 11)
+#define NPERR_NO_DATA                     (NPERR_BASE + 12)
+#define NPERR_STREAM_NOT_SEEKABLE         (NPERR_BASE + 13)
+
+/*
+ * Values of type NPReason:
+ */
+#define NPRES_BASE          0
+#define NPRES_DONE         (NPRES_BASE + 0)
+#define NPRES_NETWORK_ERR  (NPRES_BASE + 1)
+#define NPRES_USER_BREAK   (NPRES_BASE + 2)
+
+/*
+ * Don't use these obsolete error codes any more.
+ */
+#define NP_NOERR  NP_NOERR_is_obsolete_use_NPERR_NO_ERROR
+#define NP_EINVAL NP_EINVAL_is_obsolete_use_NPERR_GENERIC_ERROR
+#define NP_EABORT NP_EABORT_is_obsolete_use_NPRES_USER_BREAK
+
+/*
+ * Version feature information
+ */
+#define NPVERS_HAS_STREAMOUTPUT             8
+#define NPVERS_HAS_NOTIFICATION             9
+#define NPVERS_HAS_LIVECONNECT              9
+#define NPVERS_WIN16_HAS_LIVECONNECT        9
+#define NPVERS_68K_HAS_LIVECONNECT          11
+#define NPVERS_HAS_WINDOWLESS               11
+#define NPVERS_HAS_XPCONNECT_SCRIPTING      13
+#define NPVERS_HAS_NPRUNTIME_SCRIPTING      14
+#define NPVERS_HAS_FORM_VALUES              15
+#define NPVERS_HAS_POPUPS_ENABLED_STATE     16
+#define NPVERS_HAS_RESPONSE_HEADERS         17
+#define NPVERS_HAS_NPOBJECT_ENUM            18
+#define NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL 19
+
+/*----------------------------------------------------------------------*/
+/*                        Function Prototypes                           */
+/*----------------------------------------------------------------------*/
+
+#if defined(_WINDOWS) && !defined(WIN32)
+#define NP_LOADDS  _loadds
+#else
+#if defined(__OS2__)
+#define NP_LOADDS _System
+#else
+#define NP_LOADDS
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * NPP_* functions are provided by the plugin and called by the navigator.
+ */
+
+#ifdef XP_UNIX
+const char* NPP_GetMIMEDescription(void);
+#endif /* XP_UNIX */
+
+NPError NP_LOADDS NPP_Initialize(void);
+void    NP_LOADDS NPP_Shutdown(void);
+NPError NP_LOADDS NPP_New(NPMIMEType pluginType, NPP instance,
+                          uint16 mode, int16 argc, char* argn[],
+                          char* argv[], NPSavedData* saved);
+NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** save);
+NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window);
+NPError NP_LOADDS NPP_NewStream(NPP instance, NPMIMEType type,
+                                NPStream* stream, NPBool seekable,
+                                uint16* stype);
+NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* stream,
+                                    NPReason reason);
+int32   NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream);
+int32   NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32 offset,
+                            int32 len, void* buffer);
+void    NP_LOADDS NPP_StreamAsFile(NPP instance, NPStream* stream,
+                                   const char* fname);
+void    NP_LOADDS NPP_Print(NPP instance, NPPrint* platformPrint);
+int16   NP_LOADDS NPP_HandleEvent(NPP instance, void* event);
+void    NP_LOADDS NPP_URLNotify(NPP instance, const char* url,
+                                NPReason reason, void* notifyData);
+#ifdef OJI
+jref    NP_LOADDS NPP_GetJavaClass(void);
+#endif
+NPError NP_LOADDS NPP_GetValue(NPP instance, NPPVariable variable, void *value);
+NPError NP_LOADDS NPP_SetValue(NPP instance, NPNVariable variable, void *value);
+
+/*
+ * NPN_* functions are provided by the navigator and called by the plugin.
+ */
+void    NP_LOADDS NPN_Version(int* plugin_major, int* plugin_minor,
+                              int* netscape_major, int* netscape_minor);
+NPError NP_LOADDS NPN_GetURLNotify(NPP instance, const char* url,
+                                   const char* target, void* notifyData);
+NPError NP_LOADDS NPN_GetURL(NPP instance, const char* url,
+                             const char* target);
+NPError NP_LOADDS NPN_PostURLNotify(NPP instance, const char* url,
+                                    const char* target, uint32 len,
+                                    const char* buf, NPBool file,
+                                    void* notifyData);
+NPError NP_LOADDS NPN_PostURL(NPP instance, const char* url,
+                              const char* target, uint32 len,
+                              const char* buf, NPBool file);
+NPError NP_LOADDS NPN_RequestRead(NPStream* stream, NPByteRange* rangeList);
+NPError NP_LOADDS NPN_NewStream(NPP instance, NPMIMEType type,
+                                const char* target, NPStream** stream);
+int32   NP_LOADDS NPN_Write(NPP instance, NPStream* stream, int32 len, void* buffer);
+NPError NP_LOADDS NPN_DestroyStream(NPP instance, NPStream* stream, NPReason reason);
+void    NP_LOADDS NPN_Status(NPP instance, const char* message);
+const char* NP_LOADDS	NPN_UserAgent(NPP instance);
+void*   NP_LOADDS NPN_MemAlloc(uint32 size);
+void    NP_LOADDS NPN_MemFree(void* ptr);
+uint32  NP_LOADDS NPN_MemFlush(uint32 size);
+void    NP_LOADDS NPN_ReloadPlugins(NPBool reloadPages);
+#ifdef OJI
+JRIEnv* NP_LOADDS NPN_GetJavaEnv(void);
+jref    NP_LOADDS NPN_GetJavaPeer(NPP instance);
+#endif
+NPError NP_LOADDS NPN_GetValue(NPP instance, NPNVariable variable, void *value);
+NPError NP_LOADDS NPN_SetValue(NPP instance, NPPVariable variable, void *value);
+void    NP_LOADDS NPN_InvalidateRect(NPP instance, NPRect *invalidRect);
+void    NP_LOADDS NPN_InvalidateRegion(NPP instance, NPRegion invalidRegion);
+void    NP_LOADDS NPN_ForceRedraw(NPP instance);
+void    NP_LOADDS NPN_PushPopupsEnabledState(NPP instance, NPBool enabled);
+void    NP_LOADDS NPN_PopPopupsEnabledState(NPP instance);
+void    NP_LOADDS NPN_PluginThreadAsyncCall(NPP instance,
+                                            void (*func) (void *),
+                                            void *userData);
+
+#ifdef __cplusplus
+}  /* end extern "C" */
+#endif
+
+#endif /* RC_INVOKED */
+#ifdef __OS2__
+#pragma pack()
+#endif
+
+#endif /* _NPAPI_H_ */
diff --git a/plugins/npapi/npapi/nphostapi.h b/plugins/npapi/npapi/nphostapi.h
new file mode 100644
index 0000000..2794dee
--- /dev/null
+++ b/plugins/npapi/npapi/nphostapi.h
@@ -0,0 +1,289 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+#ifndef _NPHOSTAPI_H_
+#define _NPHOSTAPI_H_
+
+#include "npapi.h"
+#include "npruntime.h"
+
+// BEGIN GOOGLE GEARS MODIFICATIONS
+
+#ifndef STDCALL
+#ifdef WIN32
+//#define STDCALL WINAPI
+#define STDCALL __stdcall
+#else
+#define STDCALL
+#endif // WIN32
+#endif // STDCALL
+
+// END GOOGLE GEARS MODIFICATIONS
+
+#ifdef __cplusplus
+extern "C" { 
+#endif
+
+//
+// NPAPI NPP Function Pointers
+//
+typedef NPError      (*NPP_NewProcPtr)(NPMIMEType pluginType,
+                         NPP instance,
+                         uint16 mode,
+                         int16 argc,
+                         char* argn[],
+                         char* argv[],
+                         NPSavedData* saved);
+typedef NPError      (*NPP_DestroyProcPtr)(NPP instance,
+                         NPSavedData** save);
+typedef NPError      (*NPP_SetWindowProcPtr)(NPP instance,
+                         NPWindow* window);
+typedef NPError      (*NPP_NewStreamProcPtr)(NPP instance,
+                         NPMIMEType type, 
+                         NPStream* stream,
+                         NPBool seekable,
+                         uint16* stype);
+typedef NPError      (*NPP_DestroyStreamProcPtr)(NPP instance,
+                         NPStream* stream,
+                         NPReason reason);
+typedef int32        (*NPP_WriteReadyProcPtr)(NPP instance,
+                         NPStream* stream);
+typedef int32        (*NPP_WriteProcPtr)(NPP instance,
+                         NPStream* stream, 
+                         int32 offset,
+                         int32 len,
+                         void* buffer);
+typedef void         (*NPP_StreamAsFileProcPtr)(NPP instance,
+                         NPStream* stream,
+                         const char* fname);
+typedef void         (*NPP_PrintProcPtr)(NPP instance,
+                         NPPrint* platformPrint);
+typedef int16        (*NPP_HandleEventProcPtr)(NPP instance,
+                         void* event);
+typedef void         (*NPP_URLNotifyProcPtr)(NPP instance,
+                         const char* url, 
+                         NPReason reason,
+                         void* notifyData);
+typedef void* JRIGlobalRef; //not using this right now
+typedef NPError      (*NPP_GetValueProcPtr)(NPP instance,
+                         NPPVariable variable,
+                         void *ret_alue);
+typedef NPError      (*NPP_SetValueProcPtr)(NPP instance,
+                         NPNVariable variable,
+                         void *ret_alue);
+
+//
+// NPAPI NPN Function Pointers
+//
+typedef NPError      (*NPN_GetURLProcPtr)(NPP instance,
+                         const char* URL,
+                         const char* window);
+typedef NPError      (*NPN_PostURLProcPtr)(NPP instance,
+                         const char* URL,
+                         const char* window,
+                         uint32 len,
+                         const char* buf,
+                         NPBool file);
+typedef NPError      (*NPN_RequestReadProcPtr)(NPStream* stream,
+                         NPByteRange* rangeList);
+typedef NPError      (*NPN_NewStreamProcPtr)(NPP instance,
+                         NPMIMEType type,
+                         const char* window,
+                         NPStream** stream);
+typedef int32        (*NPN_WriteProcPtr)(NPP instance,
+                         NPStream* stream,
+                         int32 len,
+                         void* buffer);
+typedef NPError      (*NPN_DestroyStreamProcPtr)(NPP instance,
+                         NPStream* stream,
+                         NPReason reason);
+typedef void         (*NPN_StatusProcPtr)(NPP instance,
+                         const char* message);
+typedef const char*  (*NPN_UserAgentProcPtr)(NPP instance);
+typedef void*        (*NPN_MemAllocProcPtr)(uint32 size);
+typedef void         (*NPN_MemFreeProcPtr)(void* ptr);
+typedef uint32       (*NPN_MemFlushProcPtr)(uint32 size);
+typedef void         (*NPN_ReloadPluginsProcPtr)(NPBool reloadPages);
+
+typedef void*        (*NPN_GetJavaEnvProcPtr)(void);
+typedef void*        (*NPN_GetJavaPeerProcPtr)(NPP instance);
+
+typedef NPError      (*NPN_GetURLNotifyProcPtr)(NPP instance,
+                         const char* URL,
+                         const char* window,
+                         void* notifyData);
+typedef NPError      (*NPN_PostURLNotifyProcPtr)(NPP instance,
+                         const char* URL,
+                         const char* window,
+                         uint32 len,
+                         const char* buf,
+                         NPBool file,
+                         void* notifyData);
+typedef NPError      (*NPN_GetValueProcPtr)(NPP instance,
+                         NPNVariable variable,
+                         void *ret_value);
+typedef NPError      (*NPN_SetValueProcPtr)(NPP instance,
+                         NPPVariable variable,
+                         void *value);
+typedef void         (*NPN_InvalidateRectProcPtr)(NPP instance,
+                         NPRect *rect);
+typedef void         (*NPN_InvalidateRegionProcPtr)(NPP instance,
+                         NPRegion region);
+typedef void         (*NPN_ForceRedrawProcPtr)(NPP instance);
+
+typedef void         (*NPN_ReleaseVariantValueProcPtr) (NPVariant *variant);
+
+typedef NPIdentifier (*NPN_GetStringIdentifierProcPtr) (const NPUTF8 *name);
+typedef void         (*NPN_GetStringIdentifiersProcPtr) (const NPUTF8 **names,
+                         int32_t nameCount,
+                         NPIdentifier *identifiers);
+typedef NPIdentifier (*NPN_GetIntIdentifierProcPtr) (int32_t intid);
+typedef int32_t      (*NPN_IntFromIdentifierProcPtr) (NPIdentifier identifier);
+typedef bool         (*NPN_IdentifierIsStringProcPtr) (NPIdentifier identifier);
+typedef NPUTF8 *     (*NPN_UTF8FromIdentifierProcPtr) (NPIdentifier identifier);
+
+typedef NPObject*    (*NPN_CreateObjectProcPtr) (NPP,
+                         NPClass *aClass);
+typedef NPObject*    (*NPN_RetainObjectProcPtr) (NPObject *obj);
+typedef void         (*NPN_ReleaseObjectProcPtr) (NPObject *obj);
+typedef bool         (*NPN_InvokeProcPtr) (NPP npp,
+                         NPObject *obj,
+                         NPIdentifier methodName,
+                         const NPVariant *args,
+                         unsigned argCount,
+                         NPVariant *result);
+typedef bool         (*NPN_InvokeDefaultProcPtr) (NPP npp,
+                         NPObject *obj,
+                         const NPVariant *args,
+                         unsigned argCount,
+                         NPVariant *result);
+typedef bool         (*NPN_EvaluateProcPtr) (NPP npp,
+                         NPObject *obj,
+                         NPString *script,
+                         NPVariant *result);
+typedef bool         (*NPN_GetPropertyProcPtr) (NPP npp,
+                         NPObject *obj,
+                         NPIdentifier propertyName,
+                         NPVariant *result);
+typedef bool         (*NPN_SetPropertyProcPtr) (NPP npp,
+                         NPObject *obj,
+                         NPIdentifier propertyName,
+                         const NPVariant *value);
+typedef bool         (*NPN_HasPropertyProcPtr) (NPP,
+                         NPObject *npobj,
+                         NPIdentifier propertyName);
+typedef bool         (*NPN_HasMethodProcPtr) (NPP npp,
+                         NPObject *npobj,
+                         NPIdentifier methodName);
+typedef bool         (*NPN_RemovePropertyProcPtr) (NPP npp,
+                         NPObject *obj,
+                         NPIdentifier propertyName);
+typedef void         (*NPN_SetExceptionProcPtr) (NPObject *obj,
+                         const NPUTF8 *message);
+typedef void         (*NPN_PushPopupsEnabledStateProcPtr)(NPP npp,
+                         NPBool enabled);
+typedef void         (*NPN_PopPopupsEnabledStateProcPtr)(NPP npp);
+typedef bool         (*NPN_EnumerateProcPtr)(NPP npp,
+                         NPObject *obj,
+                         NPIdentifier **identifier,
+                         uint32_t *count);
+typedef void         (*NPN_PluginThreadAsyncCallProcPtr)(NPP instance, 
+                         void (*func)(void *),
+                         void *userData);
+typedef bool         (*NPN_ConstructProcPtr)(NPP npp,
+                         NPObject* obj,
+                         const NPVariant *args,
+                         uint32_t argCount,
+                         NPVariant *result);
+
+//
+// NPAPI Function table of NPP functions (functions provided by plugin to host)
+//
+typedef struct _NPPluginFuncs {
+    unsigned short size;
+    unsigned short version;
+    NPP_NewProcPtr newp;
+    NPP_DestroyProcPtr destroy;
+    NPP_SetWindowProcPtr setwindow;
+    NPP_NewStreamProcPtr newstream;
+    NPP_DestroyStreamProcPtr destroystream;
+    NPP_StreamAsFileProcPtr asfile;
+    NPP_WriteReadyProcPtr writeready;
+    NPP_WriteProcPtr write;
+    NPP_PrintProcPtr print;
+    NPP_HandleEventProcPtr event;
+    NPP_URLNotifyProcPtr urlnotify;
+    JRIGlobalRef javaClass;
+    NPP_GetValueProcPtr getvalue;
+    NPP_SetValueProcPtr setvalue;
+} NPPluginFuncs;
+
+//
+// NPAPI Function table NPN functions (functions provided by host to plugin)
+//
+typedef struct _NPNetscapeFuncs {
+    uint16 size;
+    uint16 version;
+    NPN_GetURLProcPtr geturl;
+    NPN_PostURLProcPtr posturl;
+    NPN_RequestReadProcPtr requestread;
+    NPN_NewStreamProcPtr newstream;
+    NPN_WriteProcPtr write;
+    NPN_DestroyStreamProcPtr destroystream;
+    NPN_StatusProcPtr status;
+    NPN_UserAgentProcPtr uagent;
+    NPN_MemAllocProcPtr memalloc;
+    NPN_MemFreeProcPtr memfree;
+    NPN_MemFlushProcPtr memflush;
+    NPN_ReloadPluginsProcPtr reloadplugins;
+    NPN_GetJavaEnvProcPtr getJavaEnv;
+    NPN_GetJavaPeerProcPtr getJavaPeer;
+    NPN_GetURLNotifyProcPtr geturlnotify;
+    NPN_PostURLNotifyProcPtr posturlnotify;
+    NPN_GetValueProcPtr getvalue;
+    NPN_SetValueProcPtr setvalue;
+    NPN_InvalidateRectProcPtr invalidaterect;
+    NPN_InvalidateRegionProcPtr invalidateregion;
+    NPN_ForceRedrawProcPtr forceredraw;
+
+    NPN_GetStringIdentifierProcPtr getstringidentifier;
+    NPN_GetStringIdentifiersProcPtr getstringidentifiers;
+    NPN_GetIntIdentifierProcPtr getintidentifier;
+    NPN_IdentifierIsStringProcPtr identifierisstring;
+    NPN_UTF8FromIdentifierProcPtr utf8fromidentifier;
+    NPN_IntFromIdentifierProcPtr intfromidentifier;
+    NPN_CreateObjectProcPtr createobject;
+    NPN_RetainObjectProcPtr retainobject;
+    NPN_ReleaseObjectProcPtr releaseobject;
+    NPN_InvokeProcPtr invoke;
+    NPN_InvokeDefaultProcPtr invokeDefault;
+    NPN_EvaluateProcPtr evaluate;
+    NPN_GetPropertyProcPtr getproperty;
+    NPN_SetPropertyProcPtr setproperty;
+    NPN_RemovePropertyProcPtr removeproperty;
+    NPN_HasPropertyProcPtr hasproperty;
+    NPN_HasMethodProcPtr hasmethod;
+    NPN_ReleaseVariantValueProcPtr releasevariantvalue;
+    NPN_SetExceptionProcPtr setexception;
+    NPN_PushPopupsEnabledStateProcPtr pushpopupsenabledstate;
+    NPN_PopPopupsEnabledStateProcPtr poppopupsenabledstate;
+    // comment these out since they aren't provided by Firefox 1.5 and
+    // we don't currently use them anyway.
+//    NPN_EnumerateProcPtr enumerate;
+//    NPN_PluginThreadAsyncCallProcPtr pluginthreadasynccall;
+//    NPN_ConstructProcPtr construct;
+} NPNetscapeFuncs;
+
+//
+// NPAPI DLL entry points
+//
+
+typedef NPError (STDCALL * NP_InitializeFunc)(NPNetscapeFuncs* pFuncs);
+typedef NPError (STDCALL * NP_GetEntryPointsFunc)(NPPluginFuncs* pFuncs);
+typedef NPError (STDCALL * NP_ShutdownFunc)(void);
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _NPHOSTAPI_H_
diff --git a/plugins/npapi/npapi/npruntime.h b/plugins/npapi/npapi/npruntime.h
new file mode 100644
index 0000000..21b8089
--- /dev/null
+++ b/plugins/npapi/npapi/npruntime.h
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2004, Apple Computer, Inc. and The Mozilla Foundation. 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of Apple Computer, Inc. ("Apple") or The Mozilla
+ * Foundation ("Mozilla") nor the names of their contributors may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY APPLE, MOZILLA AND THEIR CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, MOZILLA OR
+ * THEIR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Revision 1 (March 4, 2004):
+ * Initial proposal.
+ *
+ * Revision 2 (March 10, 2004):
+ * All calls into script were made asynchronous.  Results are
+ * provided via the NPScriptResultFunctionPtr callback.
+ *
+ * Revision 3 (March 10, 2004):
+ * Corrected comments to not refer to class retain/release FunctionPtrs.
+ *
+ * Revision 4 (March 11, 2004):
+ * Added additional convenience NPN_SetExceptionWithUTF8().
+ * Changed NPHasPropertyFunctionPtr and NPHasMethodFunctionPtr to take NPClass
+ * pointers instead of NPObject pointers.
+ * Added NPIsValidIdentifier().
+ *
+ * Revision 5 (March 17, 2004):
+ * Added context parameter to result callbacks from ScriptObject functions.
+ *
+ * Revision 6 (March 29, 2004):
+ * Renamed functions implemented by user agent to NPN_*.  Removed _ from
+ * type names.
+ * Renamed "JavaScript" types to "Script".
+ *
+ * Revision 7 (April 21, 2004):
+ * NPIdentifier becomes a void*, was int32_t
+ * Remove NP_IsValidIdentifier, renamed NP_IdentifierFromUTF8 to NP_GetIdentifier
+ * Added NPVariant and modified functions to use this new type.
+ *
+ * Revision 8 (July 9, 2004):
+ * Updated to joint Apple-Mozilla license.
+ *
+ * Revision 9 (August 12, 2004):
+ * Changed NPVariantType enum values to form PVariantType_XXX
+ * Added NPP arguments to NPObject functions.
+ * Replaced NPVariant functions with macros.
+ */
+#ifndef _NP_RUNTIME_H_
+#define _NP_RUNTIME_H_
+
+
+// BEGIN GOOGLE GEARS MODIFICATIONS
+
+//#include "gears/base/common/int_types.h"
+#include "npapi.h"
+
+typedef uint32 uint32_t;
+typedef int32 int32_t;
+#ifndef sun
+typedef uint8 uint8_t;
+typedef int8 int8_t;
+typedef uint16 uint16_t;
+typedef int16 int16_t;
+// MODIFIED(jat)
+#ifndef __LP64__ 
+typedef int64 int64_t;
+typedef uint64 uint64_t;
+#endif
+#endif
+
+// END GOOGLE GEARS MODIFICATIONS
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+    This API is used to facilitate binding code written in C to script
+    objects.  The API in this header does not assume the presence of a
+    user agent.  That is, it can be used to bind C code to scripting
+    environments outside of the context of a user agent.
+    
+    However, the normal use of the this API is in the context of a
+    scripting environment running in a browser or other user agent.
+    In particular it is used to support the extended Netscape
+    script-ability API for plugins (NP-SAP).  NP-SAP is an extension
+    of the Netscape plugin API.  As such we have adopted the use of
+    the "NP" prefix for this API.
+
+    The following NP{N|P}Variables were added to the Netscape plugin
+    API (in npapi.h):
+
+    NPNVWindowNPObject
+    NPNVPluginElementNPObject
+    NPPVpluginScriptableNPObject
+
+    These variables are exposed through NPN_GetValue() and
+    NPP_GetValue() (respectively) and are used to establish the
+    initial binding between the user agent and native code.  The DOM
+    objects in the user agent can be examined and manipulated using
+    the NPN_ functions that operate on NPObjects described in this
+    header.
+
+    To the extent possible the assumptions about the scripting
+    language used by the scripting environment have been minimized.
+*/
+
+
+/*
+    Objects (non-primitive data) passed between 'C' and script is
+    always wrapped in an NPObject.  The 'interface' of an NPObject is
+    described by an NPClass.
+*/
+typedef struct NPObject NPObject;
+typedef struct NPClass NPClass;
+
+typedef char NPUTF8;
+typedef struct _NPString {
+    const NPUTF8 *UTF8Characters;
+    uint32_t UTF8Length;
+} NPString;
+  
+typedef enum {
+    NPVariantType_Void,
+    NPVariantType_Null,
+    NPVariantType_Bool,
+    NPVariantType_Int32,
+    NPVariantType_Double,
+    NPVariantType_String,
+    NPVariantType_Object
+} NPVariantType;
+
+typedef struct _NPVariant {
+    NPVariantType type;
+    union {
+        bool boolValue;
+        int32_t intValue;
+        double doubleValue;
+        NPString stringValue;
+        NPObject *objectValue;
+    } value;
+} NPVariant;
+
+/*
+    NPN_ReleaseVariantValue is called on all 'out' parameters references.
+    Specifically it is called on variants that are resultant out parameters
+    in NPGetPropertyFunctionPtr and NPInvokeFunctionPtr.  Resultant variants
+    from these two functions should be initialized using the
+    NPN_InitializeVariantXXX() functions.
+    
+    After calling NPReleaseVariantValue, the type of the variant will
+    be set to NPVariantUndefinedType.
+*/
+void NPN_ReleaseVariantValue (NPVariant *variant);
+
+#define NPVARIANT_IS_VOID(_v)    ((_v).type == NPVariantType_Void)
+#define NPVARIANT_IS_NULL(_v)    ((_v).type == NPVariantType_Null)
+#define NPVARIANT_IS_BOOLEAN(_v) ((_v).type == NPVariantType_Bool)
+#define NPVARIANT_IS_INT32(_v)   ((_v).type == NPVariantType_Int32)
+#define NPVARIANT_IS_DOUBLE(_v)  ((_v).type == NPVariantType_Double)
+#define NPVARIANT_IS_STRING(_v)  ((_v).type == NPVariantType_String)
+#define NPVARIANT_IS_OBJECT(_v)  ((_v).type == NPVariantType_Object)
+
+#define NPVARIANT_TO_BOOLEAN(_v) ((_v).value.boolValue)
+#define NPVARIANT_TO_INT32(_v)   ((_v).value.intValue)
+#define NPVARIANT_TO_DOUBLE(_v)  ((_v).value.doubleValue)
+#define NPVARIANT_TO_STRING(_v)  ((_v).value.stringValue)
+#define NPVARIANT_TO_OBJECT(_v)  ((_v).value.objectValue)
+
+#define NP_BEGIN_MACRO  do {
+#define NP_END_MACRO    } while (0)
+
+#define VOID_TO_NPVARIANT(_v)                NP_BEGIN_MACRO (_v).type = NPVariantType_Void; (_v).value.objectValue = NULL; NP_END_MACRO
+#define NULL_TO_NPVARIANT(_v)                NP_BEGIN_MACRO (_v).type = NPVariantType_Null; (_v).value.objectValue = NULL; NP_END_MACRO
+#define BOOLEAN_TO_NPVARIANT(_val, _v)       NP_BEGIN_MACRO (_v).type = NPVariantType_Bool; (_v).value.boolValue = !!(_val); NP_END_MACRO
+#define INT32_TO_NPVARIANT(_val, _v)         NP_BEGIN_MACRO (_v).type = NPVariantType_Int32; (_v).value.intValue = _val; NP_END_MACRO
+#define DOUBLE_TO_NPVARIANT(_val, _v)        NP_BEGIN_MACRO (_v).type = NPVariantType_Double; (_v).value.doubleValue = _val; NP_END_MACRO
+#define STRINGZ_TO_NPVARIANT(_val, _v)       NP_BEGIN_MACRO (_v).type = NPVariantType_String; NPString _str = { _val, strlen(_val) }; (_v).value.stringValue = _str; NP_END_MACRO
+#define STRINGN_TO_NPVARIANT(_val, _len, _v) NP_BEGIN_MACRO (_v).type = NPVariantType_String; NPString _str = { _val, _len }; (_v).value.stringValue = _str; NP_END_MACRO
+#define OBJECT_TO_NPVARIANT(_val, _v)        NP_BEGIN_MACRO (_v).type = NPVariantType_Object; (_v).value.objectValue = _val; NP_END_MACRO
+
+/*
+        Type mappings (JavaScript types have been used for illustration
+    purposes):
+
+        JavaScript       to             C (NPVariant with type:)
+        undefined                       NPVariantType_Void
+        null                            NPVariantType_Null
+        Boolean                         NPVariantType_Bool
+        Number                          NPVariantType_Double or NPVariantType_Int32
+        String                          NPVariantType_String
+        Object                          NPVariantType_Object
+
+        C (NPVariant with type:)   to   JavaScript
+        NPVariantType_Void              undefined
+        NPVariantType_Null              null
+        NPVariantType_Bool              Boolean 
+        NPVariantType_Int32             Number
+        NPVariantType_Double            Number
+        NPVariantType_String            String
+        NPVariantType_Object            Object
+*/
+
+typedef void *NPIdentifier;
+
+/*
+    NPObjects have methods and properties.  Methods and properties are
+    identified with NPIdentifiers.  These identifiers may be reflected
+    in script.  NPIdentifiers can be either strings or integers, IOW,
+    methods and properties can be identified by either strings or
+    integers (i.e. foo["bar"] vs foo[1]). NPIdentifiers can be
+    compared using ==.  In case of any errors, the requested
+    NPIdentifier(s) will be NULL.
+*/
+NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name);
+void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers);
+NPIdentifier NPN_GetIntIdentifier(int32_t intid);
+bool NPN_IdentifierIsString(NPIdentifier identifier);
+
+/*
+    The NPUTF8 returned from NPN_UTF8FromIdentifier SHOULD be freed.
+*/
+NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier);
+
+/*
+    Get the integer represented by identifier. If identifier is not an
+    integer identifier, the behaviour is undefined.
+*/
+int32_t NPN_IntFromIdentifier(NPIdentifier identifier);
+
+/*
+    NPObject behavior is implemented using the following set of
+    callback functions.
+
+    The NPVariant *result argument of these functions (where
+    applicable) should be released using NPN_ReleaseVariantValue().
+*/
+typedef NPObject *(*NPAllocateFunctionPtr)(NPP npp, NPClass *aClass);
+typedef void (*NPDeallocateFunctionPtr)(NPObject *obj);
+typedef void (*NPInvalidateFunctionPtr)(NPObject *obj);
+typedef bool (*NPHasMethodFunctionPtr)(NPObject *obj, NPIdentifier name);
+typedef bool (*NPInvokeFunctionPtr)(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);
+typedef bool (*NPInvokeDefaultFunctionPtr)(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);
+typedef bool (*NPHasPropertyFunctionPtr)(NPObject *obj, NPIdentifier name);
+typedef bool (*NPGetPropertyFunctionPtr)(NPObject *obj, NPIdentifier name, NPVariant *result);
+typedef bool (*NPSetPropertyFunctionPtr)(NPObject *obj, NPIdentifier name, const NPVariant *value);
+typedef bool (*NPRemovePropertyFunctionPtr)(NPObject *npobj, NPIdentifier name);
+typedef bool (*NPEnumerationFunctionPtr)(NPObject *npobj, NPIdentifier **value, uint32_t *count);
+
+/*
+    NPObjects returned by create have a reference count of one.  It is the caller's responsibility
+    to release the returned object.
+
+    NPInvokeFunctionPtr function may return false to indicate a the method could not be invoked.
+    
+    NPGetPropertyFunctionPtr and NPSetPropertyFunctionPtr may return false to indicate a property doesn't
+    exist.
+    
+    NPInvalidateFunctionPtr is called by the scripting environment when the native code is
+    shutdown.  Any attempt to message a NPObject instance after the invalidate
+    callback has been called will result in undefined behavior, even if the
+    native code is still retaining those NPObject instances.
+    (The runtime will typically return immediately, with 0 or NULL, from an attempt to
+    dispatch to a NPObject, but this behavior should not be depended upon.)
+    
+    The NPEnumerationFunctionPtr function may pass an array of                  
+    NPIdentifiers back to the caller. The callee allocs the memory of           
+    the array using NPN_MemAlloc(), and it's the caller's responsibility        
+    to release it using NPN_MemFree().           
+*/
+struct NPClass
+{
+    uint32_t structVersion;
+    NPAllocateFunctionPtr allocate;
+    NPDeallocateFunctionPtr deallocate;
+    NPInvalidateFunctionPtr invalidate;
+    NPHasMethodFunctionPtr hasMethod;
+    NPInvokeFunctionPtr invoke;
+    NPInvokeDefaultFunctionPtr invokeDefault;
+    NPHasPropertyFunctionPtr hasProperty;
+    NPGetPropertyFunctionPtr getProperty;
+    NPSetPropertyFunctionPtr setProperty;
+    NPRemovePropertyFunctionPtr removeProperty;
+    NPEnumerationFunctionPtr enumerate;
+};
+
+#define NP_CLASS_STRUCT_VERSION      2
+#define NP_CLASS_STRUCT_VERSION_ENUM 2                           
+#define NP_CLASS_STRUCT_VERSION_HAS_ENUM(npclass)   \
+    ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_ENUM)
+
+struct NPObject {
+    NPClass *_class;
+    uint32_t referenceCount;
+    // Additional space may be allocated here by types of NPObjects
+};
+
+/*
+    If the class has an allocate function, NPN_CreateObject invokes that function,
+    otherwise a NPObject is allocated and returned.  If a class has an allocate
+    function it is the responsibility of that implementation to set the initial retain
+    count to 1.
+*/
+NPObject *NPN_CreateObject(NPP npp, NPClass *aClass);
+
+/*
+    Increment the NPObject's reference count.
+*/
+NPObject *NPN_RetainObject (NPObject *obj);
+
+/*
+    Decremented the NPObject's reference count.  If the reference
+    count goes to zero, the class's destroy function is invoke if
+    specified, otherwise the object is freed directly.
+*/
+void NPN_ReleaseObject (NPObject *obj);
+
+/*
+    Functions to access script objects represented by NPObject.
+
+    Calls to script objects are synchronous.  If a function returns a
+    value, it will be supplied via the result NPVariant
+    argument. Successful calls will return true, false will be
+    returned in case of an error.
+    
+    Calls made from plugin code to script must be made from the thread
+    on which the plugin was initialized.
+*/
+bool NPN_Invoke(NPP npp, NPObject *npobj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result);
+bool NPN_InvokeDefault(NPP npp, NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);
+bool NPN_Evaluate(NPP npp, NPObject *npobj, NPString *script, NPVariant *result);
+bool NPN_GetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, NPVariant *result);
+bool NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, const NPVariant *value);
+bool NPN_RemoveProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
+bool NPN_HasProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
+bool NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName);
+bool NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier, uint32_t *count);
+
+// BEGIN GOOGLE MODIFICATIONS
+
+void* NPP_GetJavaClass(void);
+void* NPN_GetJavaEnv(void);
+void* NPN_GetJavaPeer(NPP instance);
+void NPN_PluginThreadAsyncCall(NPP id, void (*func)(void *), void *userData);
+bool NPN_Construct(NPP npp, NPObject* obj, const NPVariant *args, uint32_t argCount, NPVariant *result);
+
+// END GOOGLE MODIFICATIONS
+
+/*
+    NPN_SetException may be called to trigger a script exception upon return
+    from entry points into NPObjects.
+*/
+void NPN_SetException (NPObject *obj, const NPUTF8 *message);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/plugins/npapi/npn_bindings.cc b/plugins/npapi/npn_bindings.cc
new file mode 100644
index 0000000..b47b7af
--- /dev/null
+++ b/plugins/npapi/npn_bindings.cc
@@ -0,0 +1,381 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.1 (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.mozilla.org/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is 
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or 
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the NPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+////////////////////////////////////////////////////////////
+//
+// Implementation of Netscape entry points (NPN_*), which are the functions
+// the plugin calls to talk to the browser.
+//
+
+#include "Debug.h"
+
+// Sun's cstring doesn't declare memcpy
+#include <string.h>
+//#include <cstring>
+
+#include "mozincludes.h"
+//#include "gears/base/common/base_class.h"
+//#include "gears/base/common/thread_locals.h"
+//#include "gears/base/npapi/module.h"
+
+#ifndef HIBYTE
+#define HIBYTE(x) ((((uint32)(x)) & 0xff00) >> 8)
+#endif
+
+#ifndef LOBYTE
+#define LOBYTE(W) ((W) & 0xFF)
+#endif
+
+static NPNetscapeFuncs npn_funcs;
+
+void SetNPNFuncs(NPNetscapeFuncs* npnFuncs) {
+  // Since we can't rely on the pointer remaining valid, we need to
+  // copy the function pointers.
+  int size = sizeof(NPNetscapeFuncs);
+  if (size > npnFuncs->size) {
+    Debug::log(Debug::Warning) << "*** Warning: NPNetscapeFuncs supplied by "
+        "browser is smaller than expected: " << npnFuncs->size << " vs " << size
+        << Debug::flush;
+    size = npnFuncs->size;
+  }
+  memcpy(&npn_funcs, npnFuncs, size);
+}
+
+const NPNetscapeFuncs &GetNPNFuncs() {
+  return npn_funcs;
+}
+
+void NPN_Version(int* plugin_major, int* plugin_minor,
+                 int* netscape_major, int* netscape_minor)
+{
+  const NPNetscapeFuncs &funcs = GetNPNFuncs();
+  *plugin_major   = NP_VERSION_MAJOR;
+  *plugin_minor   = NP_VERSION_MINOR;
+  *netscape_major = HIBYTE(funcs.version);
+  *netscape_minor = LOBYTE(funcs.version);
+}
+
+NPError NPN_GetURLNotify(NPP instance, const char *url, const char *target,
+                         void* notifyData)
+{
+  const NPNetscapeFuncs &funcs = GetNPNFuncs();
+  int navMinorVers = funcs.version & 0xFF;
+  NPError rv = NPERR_NO_ERROR;
+
+  if (navMinorVers >= NPVERS_HAS_NOTIFICATION)
+    rv = funcs.geturlnotify(instance, url, target, notifyData);
+  else
+    rv = NPERR_INCOMPATIBLE_VERSION_ERROR;
+
+  return rv;
+}
+
+NPError NPN_GetURL(NPP instance, const char *url, const char *target)
+{
+  NPError rv = GetNPNFuncs().geturl(instance, url, target);
+  return rv;
+}
+
+NPError NPN_PostURLNotify(NPP instance, const char* url, const char* window,
+                          uint32 len, const char* buf, NPBool file,
+                          void* notifyData)
+{
+  const NPNetscapeFuncs &funcs = GetNPNFuncs();
+  int navMinorVers = funcs.version & 0xFF;
+  NPError rv = NPERR_NO_ERROR;
+
+  if (navMinorVers >= NPVERS_HAS_NOTIFICATION) {
+    rv = funcs.posturlnotify(instance, url, window, len, buf, file, notifyData);
+  } else {
+    rv = NPERR_INCOMPATIBLE_VERSION_ERROR;
+  }
+
+  return rv;
+}
+
+NPError NPN_PostURL(NPP instance, const char* url, const char* window,
+                    uint32 len, const char* buf, NPBool file)
+{
+  NPError rv = GetNPNFuncs().posturl(instance, url, window, len, buf, file);
+  return rv;
+} 
+
+NPError NPN_RequestRead(NPStream* stream, NPByteRange* rangeList)
+{
+  NPError rv = GetNPNFuncs().requestread(stream, rangeList);
+  return rv;
+}
+
+NPError NPN_NewStream(NPP instance, NPMIMEType type, const char* target,
+                      NPStream** stream)
+{
+  const NPNetscapeFuncs &funcs = GetNPNFuncs();
+  int navMinorVersion = funcs.version & 0xFF;
+
+  NPError rv = NPERR_NO_ERROR;
+
+  if ( navMinorVersion >= NPVERS_HAS_STREAMOUTPUT )
+    rv = funcs.newstream(instance, type, target, stream);
+  else
+    rv = NPERR_INCOMPATIBLE_VERSION_ERROR;
+
+  return rv;
+}
+
+int32 NPN_Write(NPP instance, NPStream *stream, int32 len, void *buffer)
+{
+  const NPNetscapeFuncs &funcs = GetNPNFuncs();
+  int navMinorVersion = funcs.version & 0xFF;
+  int32 rv = 0;
+
+  if ( navMinorVersion >= NPVERS_HAS_STREAMOUTPUT )
+    rv = funcs.write(instance, stream, len, buffer);
+  else
+    rv = -1;
+
+  return rv;
+}
+
+NPError NPN_DestroyStream(NPP instance, NPStream* stream, NPError reason)
+{
+  const NPNetscapeFuncs &funcs = GetNPNFuncs();
+  int navMinorVersion = funcs.version & 0xFF;
+  NPError rv = NPERR_NO_ERROR;
+
+  if ( navMinorVersion >= NPVERS_HAS_STREAMOUTPUT )
+    rv = funcs.destroystream(instance, stream, reason);
+  else
+    rv = NPERR_INCOMPATIBLE_VERSION_ERROR;
+
+  return rv;
+}
+
+void NPN_Status(NPP instance, const char *message)
+{
+  GetNPNFuncs().status(instance, message);
+}
+
+const char* NPN_UserAgent(NPP instance)
+{
+  const char * rv = NULL;
+  rv = GetNPNFuncs().uagent(instance);
+  return rv;
+}
+
+void* NPN_MemAlloc(uint32 size)
+{
+  void * rv = NULL;
+  rv = GetNPNFuncs().memalloc(size);
+  return rv;
+}
+
+void NPN_MemFree(void* ptr)
+{
+  GetNPNFuncs().memfree(ptr);
+}
+
+uint32 NPN_MemFlush(uint32 size)
+{
+  uint32 rv = GetNPNFuncs().memflush(size);
+  return rv;
+}
+
+void NPN_ReloadPlugins(NPBool reloadPages)
+{
+  GetNPNFuncs().reloadplugins(reloadPages);
+}
+
+NPError NPN_GetValue(NPP instance, NPNVariable variable, void *value)
+{
+  NPError rv = GetNPNFuncs().getvalue(instance, variable, value);
+  return rv;
+}
+
+NPError NPN_SetValue(NPP instance, NPPVariable variable, void *value)
+{
+  NPError rv = GetNPNFuncs().setvalue(instance, variable, value);
+  return rv;
+}
+
+void NPN_InvalidateRect(NPP instance, NPRect *invalidRect)
+{
+  GetNPNFuncs().invalidaterect(instance, invalidRect);
+}
+
+void NPN_InvalidateRegion(NPP instance, NPRegion invalidRegion)
+{
+  GetNPNFuncs().invalidateregion(instance, invalidRegion);
+}
+
+void NPN_ForceRedraw(NPP instance)
+{
+  GetNPNFuncs().forceredraw(instance);
+}
+
+NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name)
+{
+  return GetNPNFuncs().getstringidentifier(name);
+}
+
+void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount,
+                              NPIdentifier *identifiers)
+{
+  return GetNPNFuncs().getstringidentifiers(names, nameCount, identifiers);
+}
+
+NPIdentifier NPN_GetIntIdentifier(int32_t intid)
+{
+  return GetNPNFuncs().getintidentifier(intid);
+}
+
+bool NPN_IdentifierIsString(NPIdentifier identifier)
+{
+  return GetNPNFuncs().identifierisstring(identifier);
+}
+
+NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier)
+{
+  return GetNPNFuncs().utf8fromidentifier(identifier);
+}
+
+// On WebKit under OSX, the intfromidentifier field of the structure isn't
+// filled in (see WebNetscapePluginPackage.m#526 in WebKit source tree).
+// At this time this function isn't called from our code, so for now comment it
+// out.
+//
+int32_t NPN_IntFromIdentifier(NPIdentifier identifier)
+{
+  return GetNPNFuncs().intfromidentifier(identifier);
+}
+
+NPObject *NPN_CreateObject(NPP npp, NPClass *aClass)
+{
+  return GetNPNFuncs().createobject(npp, aClass);
+}
+
+NPObject *NPN_RetainObject(NPObject *obj)
+{
+  return GetNPNFuncs().retainobject(obj);
+}
+
+void NPN_ReleaseObject(NPObject *obj)
+{
+  return GetNPNFuncs().releaseobject(obj);
+}
+
+bool NPN_Invoke(NPP npp, NPObject* obj, NPIdentifier methodName,
+                const NPVariant *args, uint32_t argCount, NPVariant *result)
+{
+  return GetNPNFuncs().invoke(npp, obj, methodName, args, argCount, result);
+}
+
+bool NPN_InvokeDefault(NPP npp, NPObject* obj, const NPVariant *args,
+                       uint32_t argCount, NPVariant *result)
+{
+  return GetNPNFuncs().invokeDefault(npp, obj, args, argCount, result);
+}
+
+bool NPN_Evaluate(NPP npp, NPObject* obj, NPString *script,
+                  NPVariant *result)
+{
+  return GetNPNFuncs().evaluate(npp, obj, script, result);
+}
+
+bool NPN_GetProperty(NPP npp, NPObject* obj, NPIdentifier propertyName,
+                     NPVariant *result)
+{
+// Workaround for bug in WebKit: GetProperty() fails when attempting to
+// read a null value from an array, however it fills in the variant structure
+// correctly.
+// The workaround is to chek if GetProprety() touches the variant structure,
+// if so, we assume it succeeded.
+#ifdef BROWSER_WEBKIT
+  result->type = static_cast<NPVariantType>(-1);
+  
+  bool ret = GetNPNFuncs().getproperty(npp, obj, propertyName, result);
+  
+  if (result->type != -1 && !ret) {
+    ret = true;
+  }
+  return ret;
+#else
+  return GetNPNFuncs().getproperty(npp, obj, propertyName, result);
+#endif
+}
+
+bool NPN_SetProperty(NPP npp, NPObject* obj, NPIdentifier propertyName,
+                     const NPVariant *value)
+{
+  return GetNPNFuncs().setproperty(npp, obj, propertyName, value);
+}
+
+bool NPN_RemoveProperty(NPP npp, NPObject* obj, NPIdentifier propertyName)
+{
+  return GetNPNFuncs().removeproperty(npp, obj, propertyName);
+}
+
+#ifdef BROWSER_WEBKIT
+// This field of NPN functions isn't filled in by WebKit on OSX.
+#else
+bool NPN_HasProperty(NPP npp, NPObject* obj, NPIdentifier propertyName)
+{
+  return GetNPNFuncs().hasproperty(npp, obj, propertyName);
+}
+#endif
+
+#ifdef BROWSER_WEBKIT
+// This field of NPN functions isn't filled in by WebKit on OSX.
+#else
+bool NPN_HasMethod(NPP npp, NPObject* obj, NPIdentifier methodName)
+{
+  return GetNPNFuncs().hasmethod(npp, obj, methodName);
+}
+#endif
+
+void NPN_ReleaseVariantValue(NPVariant *variant)
+{
+  GetNPNFuncs().releasevariantvalue(variant);
+}
+
+#ifdef BROWSER_WEBKIT
+// This function is buggy in WebKit, see 
+// http://bugs.webkit.org/show_bug.cgi?id=16829
+#else
+void NPN_SetException(NPObject* obj, const NPUTF8 *message)
+{
+  GetNPNFuncs().setexception(obj, message);
+}
+#endif
diff --git a/plugins/npapi/oophm.xpi b/plugins/npapi/oophm.xpi
new file mode 100644
index 0000000..425cdba
--- /dev/null
+++ b/plugins/npapi/oophm.xpi
Binary files differ
diff --git a/plugins/npapi/prebuilt/LICENSE.txt b/plugins/npapi/prebuilt/LICENSE.txt
new file mode 100644
index 0000000..326366d
--- /dev/null
+++ b/plugins/npapi/prebuilt/LICENSE.txt
@@ -0,0 +1,13 @@
+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.
diff --git a/plugins/npapi/prebuilt/extension/chrome.manifest b/plugins/npapi/prebuilt/extension/chrome.manifest
new file mode 100644
index 0000000..38a0fdd
--- /dev/null
+++ b/plugins/npapi/prebuilt/extension/chrome.manifest
@@ -0,0 +1,2 @@
+content gwt-oophm content/
+skin gwt-oophm classic/1.0 skin/
diff --git a/plugins/npapi/prebuilt/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/Info.plist b/plugins/npapi/prebuilt/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/Info.plist
new file mode 100644
index 0000000..234ad6e
--- /dev/null
+++ b/plugins/npapi/prebuilt/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/Info.plist
@@ -0,0 +1,20 @@
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>liboophm</string>
+	<key>CFBundleIdentifier</key>
+	<string>com.google.gwt.oophm</string>
+	<key>CFBundleName</key>
+	<string>oophm</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundlePackageType</key>
+	<string>NSPL</string>
+	<key>CFBundleSignature</key>
+	<string>MOSS</string>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+</dict>
+</plist>
diff --git a/plugins/npapi/prebuilt/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/MacOS/liboophm b/plugins/npapi/prebuilt/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/MacOS/liboophm
new file mode 100755
index 0000000..49d5a1f
--- /dev/null
+++ b/plugins/npapi/prebuilt/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/MacOS/liboophm
Binary files differ
diff --git a/plugins/npapi/prebuilt/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/Resources/liboophm.rsrc b/plugins/npapi/prebuilt/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/Resources/liboophm.rsrc
new file mode 100644
index 0000000..c1cb961
--- /dev/null
+++ b/plugins/npapi/prebuilt/extension/platform/Darwin_x86-gcc3/plugins/oophm.plugin/Contents/Resources/liboophm.rsrc
Binary files differ
diff --git a/plugins/npapi/prebuilt/extension/platform/WINNT_x86-msvc/plugins/npOOPHM.dll b/plugins/npapi/prebuilt/extension/platform/WINNT_x86-msvc/plugins/npOOPHM.dll
new file mode 100755
index 0000000..dfcdb9b
--- /dev/null
+++ b/plugins/npapi/prebuilt/extension/platform/WINNT_x86-msvc/plugins/npOOPHM.dll
Binary files differ
diff --git a/plugins/npapi/prebuilt/extension/skin/icon.png b/plugins/npapi/prebuilt/extension/skin/icon.png
new file mode 100644
index 0000000..7ba8270
--- /dev/null
+++ b/plugins/npapi/prebuilt/extension/skin/icon.png
Binary files differ
diff --git a/plugins/npapi/prebuilt/oophm.xpi b/plugins/npapi/prebuilt/oophm.xpi
new file mode 100644
index 0000000..425cdba
--- /dev/null
+++ b/plugins/npapi/prebuilt/oophm.xpi
Binary files differ
diff --git a/plugins/npapi/resource.h b/plugins/npapi/resource.h
new file mode 100644
index 0000000..359695e
--- /dev/null
+++ b/plugins/npapi/resource.h
@@ -0,0 +1,20 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by npApuProto.rc
+//
+#define IDD_MAIN                        101
+#define IDC_BUTTON_GO                   1002
+#define IDC_STATIC_UA                   1003
+#define IDC_BUTTON1                     1005
+#define IDC_BUTTON_DONT                 1005
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        102
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1006
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/plugins/npapi/test.html b/plugins/npapi/test.html
new file mode 100644
index 0000000..e55d25e
--- /dev/null
+++ b/plugins/npapi/test.html
@@ -0,0 +1,110 @@
+<html>
+<head>
+<title>OOPHM test page</title>
+<script>
+var $wnd = window,$doc = document;
+var $moduleBase = 'file:///home/jat/s/gwt-oophm/plugins/firefox/';
+
+// fake property provider
+function __gwt_getProperty(prop) {
+  return "gecko1_8";
+}
+
+// wrapper to call JS methods, which we need both to be able to supply a
+// different this for method lookup and to get the exception back
+function __gwt_jsWrapper(method, methodlookup, thisref) {
+  try {
+    var args = Array.prototype.slice.call(arguments, 3);
+//    console.log("calling " + method + " on " + methodlookup + " (this=" + thisref + "), args are ",
+//        args);
+    var ret = methodlookup[method].apply(thisref, args);
+//    console.log("successful; returned ", ret);
+    return [0, ret];
+  } catch (e) {
+    try {
+//      console.log("methodlookup[method]=", methodlookup[method] ?
+//          methodlookup[method].toString() : methodlookup[method]);
+//      console.log("failed; exception ", e);
+    } catch (e2) {
+//      console.log("exception " + e2 + " logging original exception");
+    }
+    return [1, e];
+  }
+}
+
+function __gwt_initHandlers(resize, beforeunload, unload) {
+  console.log("initHandlers called", resize, beforeunload, unload);
+  var $wnd = window
+  , oldOnResize = $wnd.onresize
+  , oldOnBeforeUnload = $wnd.onbeforeunload
+  , oldOnUnload = $wnd.onunload
+  ;
+
+  $wnd.onresize = function(evt) {
+    try {
+      resize();
+    } finally {
+      oldOnResize && oldOnResize(evt);
+    }
+  };
+
+  $wnd.onbeforeunload = function(evt) {
+    var ret, oldRet;
+    try {
+      ret = beforeunload();
+    } finally {
+      oldRet = oldOnBeforeUnload && oldOnBeforeUnload(evt);
+    }
+    // Avoid returning null as IE6 will coerce it into a string.
+    // Ensure that "" gets returned properly.
+    if (ret != null) {
+      return ret;
+    }
+    if (oldRet != null) {
+      return oldRet;
+    }
+    // returns undefined.
+  };
+
+  $wnd.onunload = function(evt) {
+    try {
+      unload();
+    } finally {
+      oldOnUnload && oldOnUnload(evt);
+    }
+  };
+};
+
+// fire up plugin
+window.onload = function() {
+  var plugin = document.getElementById('plugin');
+  var connectTo = "localhost:9997";
+  var module = "com.google.gwt.sample.kitchensink.KitchenSink";
+  var idx = location.search.indexOf("gwt.hosted=");
+  if (idx >= 0) {
+    var amp = location.search.indexOf("&", idx);
+    if (amp >= 0) {
+      connectTo = location.search.substring(idx + 11, amp);
+    } else {
+      connectTo = location.search.substring(idx + 11);
+    }
+  }
+  var idx = location.search.indexOf("gwt.module=");
+  if (idx >= 0) {
+    var amp = location.search.indexOf("&", idx);
+    if (amp >= 0) {
+      module = location.search.substring(idx + 11, amp);
+    } else {
+      module = location.search.substring(idx + 11);
+    }
+  }
+  plugin.connect(connectTo, module)
+      || alert("failed to connect");
+};
+</script>
+</head>
+<body>
+<embed id="plugin" type="application/x-gwt-hosted-mode" width="10"
+        height="10"/>
+</body>
+</html>
diff --git a/plugins/npapi/version b/plugins/npapi/version
new file mode 100644
index 0000000..4c00d4e
--- /dev/null
+++ b/plugins/npapi/version
@@ -0,0 +1 @@
+0.0.0.20090326025214