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/Makefile b/plugins/Makefile
new file mode 100644
index 0000000..28babe1
--- /dev/null
+++ b/plugins/Makefile
@@ -0,0 +1,4 @@
+# Placeholder Makefile, to be replaced with ant build file
+
+xpcom::
+	cd xpcom; make
diff --git a/plugins/MissingBrowserPlugin.html b/plugins/MissingBrowserPlugin.html
new file mode 100644
index 0000000..553c27b
--- /dev/null
+++ b/plugins/MissingBrowserPlugin.html
@@ -0,0 +1,47 @@
+<html>
+<head>
+<title>Missing GWT Browser Plugin</title>
+<!-- TODO: add JS code to detect browser/platform and just show that link -->
+</head>
+<body>
+<h1>No GWT Browser Plugin Detected</h1>
+<!-- TODO: alter language for final naming decisions -->
+GWT Debug Mode needs a browser plugin to operate.  Please install the
+appropriate one for your browser.
+
+<ul>
+ <li><b font size="+1">Firefox</font></b>
+  <br>Install the appropriate Firefox plugin via the normal plugin install
+  process.
+ <ul>
+  <li><a href="http://google-web-toolkit.googlecode.com/svn/trunk/plugins/xpcom/prebuilt/oophm-xpcom-ff2.xpi">Version 1.5-2.0</a>
+  <li><a href="http://google-web-toolkit.googlecode.com/svn/trunk/plugins/xpcom/prebuilt/oophm-xpcom-ff3.xpi">Version 3.0</a> (see below if you have problems)
+  <li><a href="http://google-web-toolkit.googlecode.com/svn/trunk/plugins/xpcom/prebuilt/oophm-xpcom-ff3+.xpi">Version 3.0.11</a> (some platforms will use the one above)
+  <li><a href="http://google-web-toolkit.googlecode.com/svn/trunk/plugins/xpcom/prebuilt/oophm-xpcom-ff35.xpi">Version 3.5+</a>
+ </ul>
+ <br>
+ <li><b><font size="+1">Safari 3/4 on Mac/OSX</font></b>
+ <ul>
+  <li>Run the installer from this <a href="http://google-web-toolkit.googlecode.com/svn/trunk/plugins/webkit/prebuilt/oophm.dmg">disk image</a>.
+ </ul>
+ <br>
+ <li><b><font size="+1">Internet Explorer on Windows (32-bit IE)</font></b>
+ <ul>
+  <li>Download <a href="http://google-web-toolkit.googlecode.com/svn/trunk/plugins/ie/prebuilt/oophm.dll">oophm.dll</a> to local disk, then run regsvr32
+  oophm.dll and restart IE.
+ </ul>
+<!--
+ <br>
+ <li><b><font size="+1">Chrome on Windows</font></b>
+ <ul>
+  <li><i>Coming soon...</i>
+ </ul>
+ <br>
+-->
+</ul>
+
+<h2>Troubleshooting</h2>
+If you believe you have the plugin installed in your current browser (and
+profile, in the case of Firefox), see the <a href="http://code.google.com/p/google-web-toolkit/wiki/TroubleshootingOOPHM">TroubleshootingOOPHM</a> wiki page.
+</body>
+</html>
diff --git a/plugins/README.txt b/plugins/README.txt
new file mode 100644
index 0000000..447c0fc
--- /dev/null
+++ b/plugins/README.txt
@@ -0,0 +1,22 @@
+This directory contains the source for the OOPHM plugin which resides in
+the browser to allow hosted mode debugging.
+
+Subdirectories:
+ - common
+   Code that is shared between all platforms, and mostly deals with the wire
+   protocol and related tables.
+
+ - ie
+   Plugin for 32-bit Internet Explorer
+
+ - npapi
+   Obsolete NPAPI plugin for Firefox
+
+ - webkit
+   plugin for WebKit-based browsers that support its extension mechanism
+   (ie, no Safari/Windows support)
+
+ - xpcom
+   XPCOM-based Firefox plugin
+
+To build, see instructions in each directory.
diff --git a/plugins/common/AllowedConnections.cpp b/plugins/common/AllowedConnections.cpp
new file mode 100644
index 0000000..1f93f65
--- /dev/null
+++ b/plugins/common/AllowedConnections.cpp
@@ -0,0 +1,33 @@
+/*
+ * 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 "AllowedConnections.h"
+
+void AllowedConnections::init() {
+}
+
+bool AllowedConnections::isAllowed(const std::string& target) {
+  return true;
+}
+
+bool AllowedConnections::isAllowed(const char* host, int port) {
+  return true;
+}
+
+void AllowedConnections::parseRule(const std::string& rule) {
+};
diff --git a/plugins/common/AllowedConnections.h b/plugins/common/AllowedConnections.h
new file mode 100644
index 0000000..0dbed2e
--- /dev/null
+++ b/plugins/common/AllowedConnections.h
@@ -0,0 +1,55 @@
+#ifndef _H_AllowedConnections
+#define _H_AllowedConnections
+/*
+ * 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>
+
+/**
+ * Manages rules to control access to other sites.
+ */
+class AllowedConnections {
+public:
+  AllowedConnections() {
+    init();
+  }
+  
+  AllowedConnections(const std::string& rule) {
+    init();
+    parseRule(rule);
+  }
+
+  /**
+   * Returns true if a connection to the requested target is allowed.
+   * 
+   * @param target host or host:port to test
+   */
+  bool isAllowed(const std::string& target);
+
+  /**
+   * Returns true if a connection to the requested target is allowed.
+   * 
+   * @param host name or address to connect to
+   * @param port TCP port to connect to
+   */
+  bool isAllowed(const char* host, int port);
+
+private:
+  void init();
+  void parseRule(const std::string& rule);
+};
+
+#endif
diff --git a/plugins/common/BrowserChannel.h b/plugins/common/BrowserChannel.h
new file mode 100644
index 0000000..0a65c62
--- /dev/null
+++ b/plugins/common/BrowserChannel.h
@@ -0,0 +1,38 @@
+/*
+ * DO NOT EDIT
+ * Generated by com.google.gwt.util.tools.OophmHeaderFileGenerator
+ * TODO(jat): update generator to handle modifications
+ */
+
+/* from BrowserChannel.BROWSERCHANNEL_PROTOCOL_VERSION */
+#define BROWSERCHANNEL_PROTOCOL_VERSION 1
+
+/* from com.google.gwt.dev.shell.BrowserChannel.SpecialDispatchId */
+#define SPECIAL_HAS_METHOD 0
+#define SPECIAL_HAS_PROPERTY 1
+#define SPECIAL_GET_PROPERTY 2
+#define SPECIAL_SET_PROPERTY 3
+
+/* from com.google.gwt.dev.shell.BrowserChannel.MessageType */
+#define MESSAGE_TYPE_INVOKE 0
+#define MESSAGE_TYPE_RETURN 1
+#define MESSAGE_TYPE_LOAD_MODULE 2
+#define MESSAGE_TYPE_QUIT 3
+#define MESSAGE_TYPE_LOADJSNI 4
+#define MESSAGE_TYPE_INVOKESPECIAL 5
+#define MESSAGE_TYPE_FREEVALUE 6
+
+/* from com.google.gwt.dev.shell.BrowserChannel.Value.ValueType */
+#define VALUE_TYPE_NULL 0
+#define VALUE_TYPE_BOOLEAN 1
+#define VALUE_TYPE_BYTE 2
+#define VALUE_TYPE_CHAR 3
+#define VALUE_TYPE_SHORT 4
+#define VALUE_TYPE_INT 5
+#define VALUE_TYPE_LONG 6
+#define VALUE_TYPE_FLOAT 7
+#define VALUE_TYPE_DOUBLE 8
+#define VALUE_TYPE_STRING 9
+#define VALUE_TYPE_JAVA_OBJECT 10
+#define VALUE_TYPE_JS_OBJECT 11
+#define VALUE_TYPE_UNDEFINED 12
diff --git a/plugins/common/ByteOrder.h b/plugins/common/ByteOrder.h
new file mode 100644
index 0000000..7e6bd86
--- /dev/null
+++ b/plugins/common/ByteOrder.h
@@ -0,0 +1,141 @@
+#ifndef __H_ByteOrder
+#define __H_ByteOrder
+/*
+ * 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 "Platform.h"
+#include <cstring>
+
+class ByteOrder {
+private:
+  enum FloatByteOrder {
+    FLOAT_BIG_ENDIAN,
+    FLOAT_LITTLE_ENDIAN,
+    // TODO(jat): do we need to consider anything other than straight
+    // big-endian or little-endian?  PDP-11 (irrelevant), ARM (probably
+    // relevant for mobile devices), MIPS (probably not relevant, but maybe)
+    // and others have some intermediate endianess.  Also, FP-endianess is not
+    // necessarily the same as that for integers.
+  };
+#ifdef PLATFORM_FLOAT_ENDIANESS
+  static const FloatByteOrder floatByteOrder = PLATFORM_FLOAT_ENDIANESS;
+#else
+  FloatByteOrder floatByteOrder;
+#endif
+
+  typedef union {
+    float v;
+    char b[sizeof(float)];
+  } FloatUnion;
+
+  typedef union {
+    double v;
+    char b[sizeof(double)];
+  } DoubleUnion;
+
+  /**
+   * Copy src to dest, reversing the order of the bytes.
+   * Assumes src and dest do not overlap.
+   */
+  void memcpyrev(char* dest, const char* src, size_t n) {
+    src += n;
+    while (n-- > 0) {
+      *dest++ = *--src;
+    }
+  }
+public:
+  ByteOrder() {
+#ifndef PLATFORM_FLOAT_ENDIANESS
+    DoubleUnion u;
+    memset(u.b, 0, sizeof(u.b));
+    u.b[0] = (char) 0x80;
+    u.b[7] = (char) 0x02;
+    // TODO(jat): add more tests here if we support other endianess
+    floatByteOrder = u.v > 0 ? FLOAT_LITTLE_ENDIAN : FLOAT_BIG_ENDIAN;
+    if (Debug::level(Debug::Debugging)) {
+      std::string str = "Unknown";
+      switch (floatByteOrder) {
+         case FLOAT_LITTLE_ENDIAN:
+           str = "little-endian";
+           break;
+         case FLOAT_BIG_ENDIAN:
+           str = "big-endian";
+           break;
+      }
+      Debug::log(Debug::Debugging) << "Dynamically detected float byte order: "
+          << str << Debug::flush;
+    }
+#endif
+  }
+
+  void bytesFromDouble(double v, char* bytes) {
+    DoubleUnion u;
+    u.v = v;
+    switch (floatByteOrder) {
+      case FLOAT_LITTLE_ENDIAN:
+        memcpyrev(bytes, u.b, sizeof(u.b));
+        break;
+      case FLOAT_BIG_ENDIAN:
+        memcpy(bytes, u.b, sizeof(u.b));
+        break;
+    }
+  }
+
+  void bytesFromFloat(float v, char* bytes) {
+    FloatUnion u;
+    u.v = v;
+    switch (floatByteOrder) {
+      case FLOAT_LITTLE_ENDIAN:
+        memcpyrev(bytes, u.b, sizeof(u.b));
+        break;
+      case FLOAT_BIG_ENDIAN:
+        memcpy(bytes, u.b, sizeof(u.b));
+        break;
+    }
+  }
+
+  double doubleFromBytes(const char* bytes) {
+    DoubleUnion u;
+    switch (floatByteOrder) {
+      case FLOAT_LITTLE_ENDIAN:
+        memcpyrev(u.b, bytes, sizeof(u.b));
+        break;
+      case FLOAT_BIG_ENDIAN:
+        // TODO(jat): find a way to avoid the extra copy while keeping the
+        // compiler happy.
+        memcpy(u.b, bytes, sizeof(u.b));
+        break;
+    }
+    return u.v;
+  }
+
+  float floatFromBytes(const char* bytes) {
+    FloatUnion u;
+    switch (floatByteOrder) {
+      case FLOAT_LITTLE_ENDIAN:
+        memcpyrev(u.b, bytes, sizeof(u.b));
+        break;
+      case FLOAT_BIG_ENDIAN:
+        // TODO(jat): find a way to avoid the extra copy while keeping the
+        // compiler happy.
+        memcpy(u.b, bytes, sizeof(u.b));
+        break;
+    }
+    return u.v;
+  }
+};
+
+#endif
diff --git a/plugins/common/Debug.cpp b/plugins/common/Debug.cpp
new file mode 100644
index 0000000..66382bd
--- /dev/null
+++ b/plugins/common/Debug.cpp
@@ -0,0 +1,84 @@
+/*
+ * 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 <cstdio>
+
+#ifdef _WINDOWS
+#include <windows.h>
+#endif
+
+#include "Debug.h"
+
+#ifdef GWT_DEBUGDISABLE
+// Dummy implementations for when debugging has been disabled
+Debug::DebugStream& Debug::flush(Debug::DebugStream& dbg) {
+  return dbg;
+}
+
+void Debug::logFinish() {}
+
+void Debug::logString(const char* str) {}
+
+#else
+// Warning: this function is inlined in the manipulator output operator in DebugStream.
+// It only remains here because some compiler/linker combinations such as MSVC will
+// give unresolved symbol errors if it isn't -- GCC, for example, will completely remove
+// all traces of this method.
+Debug::DebugStream& Debug::flush(Debug::DebugStream& dbg) {
+  Debug::logFinish();
+  return dbg;
+}
+
+// These methods are implemented in an Objective-C++ file on OSX
+#if !defined(__APPLE_CC__) || defined(__mac)
+
+#ifdef _WINDOWS
+#define DEBUG_BUF_SIZE 2048
+
+static char buf[DEBUG_BUF_SIZE + 3]; // room for CR NL Null
+static char *bufPtr = buf;
+#endif
+
+void Debug::logFinish() {
+#ifdef _WINDOWS
+  logString("\r\n");
+  ::OutputDebugStringA(buf);
+  bufPtr = buf;
+#else
+  putchar('\n');
+#endif
+}
+
+// logStart may be called multiple times per logFinish
+void Debug::logStart(LogLevel level) {
+}
+
+void Debug::logString(const char* str) {
+#ifdef _WINDOWS
+  size_t len = strlen(str);
+  size_t buflen = DEBUG_BUF_SIZE - (bufPtr - buf);
+  if (len >= buflen) {
+    len = buflen - 1;
+  }
+  strncpy_s(bufPtr, buflen, str, len);
+  bufPtr += len;
+#else
+  printf("%s", str);
+#endif
+}
+#endif
+#endif
+
diff --git a/plugins/common/Debug.h b/plugins/common/Debug.h
new file mode 100644
index 0000000..c44e824
--- /dev/null
+++ b/plugins/common/Debug.h
@@ -0,0 +1,214 @@
+#ifndef _H_Debug
+#define _H_Debug
+/*
+ * 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.
+ */
+#ifndef _WINDOWS
+// TODO(jat): remove, for snprintf prototypes which should go away
+#include <stdio.h>
+#endif
+
+#include <ostream>
+#include <string>
+
+#include "Platform.h"
+
+// Get a default debug config if none supplied.
+#ifndef GWT_DEBUGLEVEL
+#include "DebugLevel.h"
+#endif
+
+/**
+ * Debugging class to get debugging output to a platform-specific location, with multiple
+ * levels supported.
+ * 
+ * To use:
+ *   #define GWT_DEBUGLEVEL level  // where level is in LogLevel
+ *   #include "Debug.h"
+ *   Debug::log(Debug::Warning) << ...
+ * 
+ * Zero overhead if GWT_DEBUGDISABLE is defined, other than the effort spent on side
+ * effects for stream object construction.  If that is expensive, use something like
+ * Debug::level(Debug::Warning) to conditionalize expensive logging computations.
+ */
+class Debug {
+public:
+  enum LogLevel {
+    None,
+    Error,
+    Warning,
+    Info,
+    Debugging,
+    Spam
+  };
+
+private:
+  static const LogLevel minLogLevel = GWT_DEBUGLEVEL;
+
+public:
+  /**
+   * Return true if the requested level would be logged.  Use to protect
+   * expensive computations for logging.
+   */
+  static bool level(LogLevel testLevel) {
+#ifdef GWT_DEBUGDISABLE
+    return false;
+#else
+    return testLevel <= minLogLevel;
+#endif
+  }
+
+private:
+  // complete the current log message
+  static void logFinish();
+  
+  // begin a new log message
+  static void logStart(LogLevel level);
+  
+  // add a string to the current log message
+  static void logString(const char* str);
+  static void logString(const std::string& str) {
+    logString(str.c_str());
+  }
+  
+public:
+  // Note that flush is special-cased in the manipulator output operator,
+  // and its implementation is inlined there.  If its implementation is
+  // modified, the implementation of the manipulator output operator will
+  // need to be modified as well.
+  class DebugStream;
+  static DebugStream& flush(DebugStream& dbg);
+
+  class DebugStream {
+
+    const bool shouldLog;
+
+    // TODO(jat): better implementations of output operators
+  public:
+    DebugStream(LogLevel level) : shouldLog(Debug::level(level)) {
+      if (shouldLog) {
+        Debug::logStart(level);
+      }
+    }
+
+    bool isActive() const {
+      return shouldLog;
+    }
+
+    DebugStream& operator<<(long v) {
+      if (shouldLog) {
+        char buf[20];
+        snprintf(buf, sizeof(buf), "%ld", v);
+        Debug::logString(buf);
+      }
+      return *this;
+    }
+
+    DebugStream& operator<<(unsigned long v) {
+      if (shouldLog) {
+        char buf[20];
+        snprintf(buf, sizeof(buf), "%lu", v);
+        Debug::logString(buf);
+      }
+      return *this;
+    }
+
+    DebugStream& operator<<(long long v) {
+      if (shouldLog) {
+        char buf[40];
+        snprintf(buf, sizeof(buf), "%lld", v);
+        Debug::logString(buf);
+      }
+      return *this;
+    }
+
+    DebugStream& operator<<(unsigned long long v) {
+      if (shouldLog) {
+        char buf[40];
+        snprintf(buf, sizeof(buf), "%llu", v);
+        Debug::logString(buf);
+      }
+      return *this;
+    }
+
+    DebugStream& operator<<(int v) {
+      if (shouldLog) {
+        char buf[20];
+        snprintf(buf, sizeof(buf), "%d", v);
+        Debug::logString(buf);
+      }
+      return *this;
+    }
+
+    DebugStream& operator<<(unsigned int v) {
+      if (shouldLog) {
+        char buf[20];
+        snprintf(buf, sizeof(buf), "%u", v);
+        Debug::logString(buf);
+      }
+      return *this;
+    }
+
+    DebugStream& operator<<(double v) {
+      if (shouldLog) {
+        char buf[20];
+        snprintf(buf, sizeof(buf), "%g", v);
+        Debug::logString(buf);
+      }
+      return *this;
+    }
+
+    DebugStream& operator<<(const std::string& str) {
+      if (shouldLog) {
+        Debug::logString(str);
+      }
+      return *this;
+    }
+
+    DebugStream& operator<<(const char* str) {
+      if (shouldLog) {
+        Debug::logString(str);
+      }
+      return *this;
+    }
+
+    DebugStream& operator<<(const void* v) {
+      if (shouldLog) {
+        char buf[20];
+        snprintf(buf, sizeof(buf), "%p", v);
+        Debug::logString(buf);
+      }
+      return *this;
+    }
+
+    DebugStream& operator<<(DebugStream& (*manip)(DebugStream&)) {
+      if (shouldLog) {
+        // Special-case flush for efficiency.
+        if (manip == Debug::flush) {
+          Debug::logFinish();
+        } else {
+          return manip(*this);
+        }
+      }
+      return *this;
+    }
+  };
+
+  static DebugStream log(LogLevel testLevel) {
+    return DebugStream(testLevel);
+  }
+};
+
+#endif
diff --git a/plugins/common/DebugLevel.h b/plugins/common/DebugLevel.h
new file mode 100644
index 0000000..d172e99
--- /dev/null
+++ b/plugins/common/DebugLevel.h
@@ -0,0 +1,25 @@
+#ifndef _H_DebugLevel
+#define _H_DebugLevel
+/*
+ * 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.
+ */
+
+// Defines the default debug level if not defined -- see Debug.h
+// Can also define GWT_DEBUGDISABLE to remove all traces of the debug code.
+//#define GWT_DEBUGLEVEL Debugging
+#define GWT_DEBUGLEVEL Spam
+//#define GWT_DEBUGDISABLE
+
+#endif
diff --git a/plugins/common/FreeValueMessage.cpp b/plugins/common/FreeValueMessage.cpp
new file mode 100644
index 0000000..b7f0bab
--- /dev/null
+++ b/plugins/common/FreeValueMessage.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 "FreeValueMessage.h"
+#include "HostChannel.h"
+#include "scoped_ptr/scoped_ptr.h"
+
+FreeValueMessage::~FreeValueMessage() {
+  delete[] ids;
+}
+
+FreeValueMessage* FreeValueMessage::receive(HostChannel& channel) {
+  int idCount;
+  if (!channel.readInt(idCount)) {
+    // TODO(jat): error handling
+    return 0;
+  }
+  // TODO: validate idCount
+  scoped_array<int> ids(new int[idCount]);
+
+  for (int i = 0; i < idCount; ++i) {
+    if (!channel.readInt(ids[i])) return 0;
+  }
+  return new FreeValueMessage(idCount, ids.release());
+}
+
+bool FreeValueMessage::send(HostChannel& channel, int idCount, const int* ids) {
+  if (!channel.sendByte(TYPE)) return false;
+  if (!channel.sendInt(idCount)) return false;
+  for (int i = 0; i < idCount; ++i) {
+    if (!channel.sendInt(ids[i])) return false;
+  }
+  return true;
+}
diff --git a/plugins/common/FreeValueMessage.h b/plugins/common/FreeValueMessage.h
new file mode 100644
index 0000000..a8b7a64
--- /dev/null
+++ b/plugins/common/FreeValueMessage.h
@@ -0,0 +1,51 @@
+#ifndef __H_FreeValueMessage
+#define __H_FreeValueMessage
+/*
+ * 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 "Message.h"
+#include "BrowserChannel.h"
+#include "HostChannel.h"
+
+class FreeValueMessage : public Message {
+public:  
+  static const char TYPE = MESSAGE_TYPE_FREEVALUE;
+private:
+  int idCount;
+  const int* ids;
+  
+  FreeValueMessage(int idCount, const int* ids) : idCount(idCount), ids(ids) {}
+  
+public:
+  ~FreeValueMessage();
+
+  virtual char getType() const {
+    return TYPE;
+  }
+  
+  int getIdCount() const {
+    return idCount;
+  }
+  
+  const int* const getIds() const {
+    return ids;
+  }
+
+  static FreeValueMessage* receive(HostChannel& channel);
+  static bool send(HostChannel& channel, int idCount, const int* ids);
+};
+#endif
diff --git a/plugins/common/HashMap.h b/plugins/common/HashMap.h
new file mode 100644
index 0000000..c76b220
--- /dev/null
+++ b/plugins/common/HashMap.h
@@ -0,0 +1,58 @@
+#ifndef _H_HashMap
+#define _H_HashMap
+/*
+ * 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.
+ */
+
+// Portability wrapper for hash maps, since they aren't part of the standard C++ library
+
+#ifdef __GNUC__
+#if 0
+// future support
+#include <unordered_map>
+#define hash_map unordered_map
+
+namespace HashFunctions = std;
+#else
+#include <ext/hash_map>
+using __gnu_cxx::hash_map;
+
+// TODO(jat): surely this exists somewhere already?
+// TODO(jat): portability issues
+namespace __gnu_cxx {
+  using std::size_t;
+
+  template<> struct hash<std::string> {
+    size_t operator()(const std::string& str) const {
+      return hash<const char*>()(str.c_str());
+    }
+  };
+};
+namespace HashFunctions = __gnu_cxx;
+#endif
+#elif sun
+// TODO(jat): find a hash_map implementation for Solaris
+#include <map>
+namespace HashFunctions = std;
+#define hash_map map
+using std::map;
+#else
+// Try something reasonably standard, which works in Windows
+#include <hash_map>
+using stdext::hash_map;
+namespace HashFunctions = stdext;
+#endif
+
+#endif
diff --git a/plugins/common/HostChannel.cpp b/plugins/common/HostChannel.cpp
new file mode 100644
index 0000000..896667e
--- /dev/null
+++ b/plugins/common/HostChannel.cpp
@@ -0,0 +1,393 @@
+/*
+ * 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 <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+
+#include "Debug.h"
+
+#ifdef _WINDOWS
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <sys/time.h>
+#endif
+#include <time.h>
+
+#include "Platform.h"
+#include "ByteOrder.h"
+
+#include "FreeValueMessage.h"
+#include "HostChannel.h"
+#include "LoadJsniMessage.h"
+#include "InvokeMessage.h"
+#include "InvokeSpecialMessage.h"
+#include "QuitMessage.h"
+#include "ReturnMessage.h"
+#include "Value.h"
+#include "scoped_ptr/scoped_ptr.h"
+
+using namespace std;
+
+ByteOrder HostChannel::byteOrder;
+
+bool HostChannel::connectToHost(const char* host, unsigned port) {
+  Debug::log(Debug::Info) << "Initiating GWT hosted mode connection to host "
+      << host << ", port " << port << Debug::flush;
+  if (!port) {
+    port = 9997;
+  }
+  if (!whitelist.isAllowed(host, port)) {
+    Debug::log(Debug::Error) << "Permission to connect to " << host << ":" << port
+        << " denied" << Debug::flush;
+    return false;
+  }
+  return sock.connect(host, port);
+}
+
+bool HostChannel::disconnectFromHost() {
+  Debug::log(Debug::Debugging) << "Disconnecting channel" << Debug::flush;
+  if (!isConnected()) {
+    Debug::log(Debug::Error) << "Disconnecting already disconnected channel" << Debug::flush;
+    return false;
+  }
+  QuitMessage::send(*this);
+  flush();
+  sock.disconnect();
+  return true;
+}
+
+bool HostChannel::readInt(int32_t& data) {
+  int32_t d;
+  if (!readBytes(&d, sizeof(d))) return false;
+  data = ntohl(d);
+  return true;
+}
+
+bool HostChannel::sendInt(int32_t data) {
+  uint32_t d = htonl(data);
+  return sendBytes(&d, sizeof(d));
+}
+
+bool HostChannel::readShort(short& data) {
+  int16_t d;
+  if (!readBytes(&d, sizeof(d))) return false;
+  data = ntohs(d);
+  return true;
+}
+
+bool HostChannel::sendShort(const short data) {
+  uint16_t d = htons(data);
+  return sendBytes(&d, sizeof(d));
+}
+
+bool HostChannel::readLong(int64_t& data) {
+  // network is big-endian
+  int32_t d[2];
+  if (!readInt(d[0])) return false;
+  if (!readInt(d[1])) return false;
+  data = (static_cast<int64_t>(d[0]) << 32) | ntohl(d[1]);
+  return true;
+}
+
+bool HostChannel::sendLong(const int64_t data) {
+  if (!sendInt(static_cast<int32_t>(data >> 32))) {
+    return false;
+  }
+  return sendInt(static_cast<int32_t>(data));
+}
+
+bool HostChannel::readFloat(float& data) {
+  char bytes[sizeof(data)];
+  if (!readBytes(bytes, sizeof(bytes))) {
+    return false;
+  }
+  data = byteOrder.floatFromBytes(bytes);
+  return true;
+}
+
+bool HostChannel::sendFloat(const float data) {
+  char bytes[sizeof(data)];
+  byteOrder.bytesFromFloat(data, bytes);
+  return sendBytes(bytes, sizeof(bytes));
+}
+
+bool HostChannel::readDouble(double& data) {
+  char bytes[sizeof(data)];
+  if (!readBytes(bytes, sizeof(bytes))) {
+    return false;
+  }
+  data = byteOrder.doubleFromBytes(bytes);
+  return true;
+}
+
+bool HostChannel::sendDouble(const double data) {
+  char bytes[sizeof(data)];
+  byteOrder.bytesFromDouble(data, bytes);
+  return sendBytes(bytes, sizeof(bytes));
+}
+
+bool HostChannel::readStringLength(uint32_t& data) {
+  int32_t val;
+  if (!readInt(val)) return false;
+  // TODO: assert positive?
+  data = val;
+  return true;
+}
+
+bool HostChannel::readStringBytes(char* data, const uint32_t len) {
+  return readBytes(data, len);
+}
+
+bool HostChannel::readString(std::string& strRef) {
+  uint32_t len;
+  if (!readStringLength(len)) {
+    Debug::log(Debug::Error) << "readString: failed to read length"
+        << Debug::flush;
+    return false;
+  }
+  // Allocating variable-length arrays on the stack is a GCC feature,
+  // and is vulnerable to stack overflow attacks, so we allocate on the heap.
+  scoped_array<char> buf(new char[len]);
+  if (!readStringBytes(buf.get(), len)) {
+    Debug::log(Debug::Error) << "readString: failed to read " << len
+        << " bytes" << Debug::flush;
+    return false;
+  }
+  strRef.assign(buf.get(), len);
+  return true;
+}
+
+static inline double operator-(const struct timeval& end,
+    const struct timeval& begin) {
+  double us = end.tv_sec * 1000000.0 + end.tv_usec - begin.tv_sec * 1000000.0
+      - begin.tv_usec;
+  return us;
+}
+
+ReturnMessage* HostChannel::reactToMessages(SessionHandler* handler, bool expectReturn) {
+  char type;
+  while (true) {
+    flush();
+     Debug::log(Debug::Spam) << "Waiting for response, flushed output" << Debug::flush;
+    if (!readByte(type)) {
+      Debug::log(Debug::Error) << "Failed to receive message type" << Debug::flush;
+      return 0;
+    }
+    switch (type) {
+      case MESSAGE_TYPE_INVOKE:
+        {
+          scoped_ptr<InvokeMessage> imsg(InvokeMessage::receive(*this));
+          if (!imsg.get()) {
+            Debug::log(Debug::Error) << "Failed to receive invoke message" << Debug::flush;
+            return 0;
+          }
+          Value returnValue;
+          bool exception = handler->invoke(*this, imsg->getThis(), imsg->getMethodName(),
+              imsg->getNumArgs(), imsg->getArgs(), &returnValue);
+          handler->sendFreeValues(*this);
+          ReturnMessage::send(*this, exception, returnValue);
+        }
+        break;
+      case MESSAGE_TYPE_INVOKESPECIAL:
+        {
+          // scottb: I think this is never used; I think server never sends invokeSpecial
+          scoped_ptr<InvokeSpecialMessage> imsg(InvokeSpecialMessage::receive(*this));
+          if (!imsg.get()) {
+            Debug::log(Debug::Error) << "Failed to receive invoke special message" << Debug::flush;
+            return 0;
+          }
+          Value returnValue;
+          bool exception = handler->invokeSpecial(*this, imsg->getDispatchId(),
+              imsg->getNumArgs(), imsg->getArgs(), &returnValue);
+          handler->sendFreeValues(*this);
+          ReturnMessage::send(*this, exception, returnValue);
+        }
+        break;
+      case MESSAGE_TYPE_FREEVALUE:
+        {
+          scoped_ptr<FreeValueMessage> freeMsg(FreeValueMessage::receive(*this));
+          if (!freeMsg.get()) {
+            Debug::log(Debug::Error) << "Failed to receive free value message" << Debug::flush;
+            return 0;
+          }
+          handler->freeValue(*this, freeMsg->getIdCount(), freeMsg->getIds());
+        }
+        // do not send a response
+        break;
+      case MESSAGE_TYPE_LOADJSNI:
+        {
+          scoped_ptr<LoadJsniMessage> loadMsg(LoadJsniMessage::receive(*this));
+          if (!loadMsg.get()) {
+            Debug::log(Debug::Error) << "Failed to receive load JSNI message" << Debug::flush;
+            return 0;
+          }
+          handler->loadJsni(*this, loadMsg->getJs());
+        }
+        // do not send a response
+        break;
+      case MESSAGE_TYPE_RETURN:
+        if (!expectReturn) {
+          Debug::log(Debug::Error) << "Received unexpected RETURN" << Debug::flush;
+        }
+        return ReturnMessage::receive(*this);
+      case MESSAGE_TYPE_QUIT:
+        if (expectReturn) {
+          Debug::log(Debug::Error) << "Received QUIT while waiting for return" << Debug::flush;
+        }
+    	  disconnectFromHost();
+        return 0;
+      default:
+        // TODO(jat): error handling
+        Debug::log(Debug::Error) << "Unexpected message type " << type
+            << ", expectReturn=" << expectReturn << Debug::flush;
+        disconnectFromHost();
+        return 0;
+    }
+  }
+}
+
+bool HostChannel::readValue(Value& valueRef) {
+  char typeBuf;
+  if (!readByte(typeBuf)) return false;
+  Value::ValueType type = Value::ValueType(typeBuf);
+  switch (type) {
+    case Value::NULL_TYPE:
+      valueRef.setNull();
+      return true;
+    case Value::UNDEFINED:
+      valueRef.setUndefined();
+      return true;
+    case Value::BOOLEAN:
+      {
+        char val;
+        if (!readByte(val)) return false;
+        valueRef.setBoolean(val != 0);
+      }
+      return true;
+    case Value::BYTE:
+      {
+        char val;
+        if (!readByte(val)) return false;
+        valueRef.setByte(val);
+      }
+      return true;
+    case Value::CHAR:
+      {
+        short val;
+        if (!readShort(val)) return false;
+        valueRef.setChar(val);
+      }
+      return true;
+    case Value::SHORT:
+      {
+        short val;
+        if (!readShort(val)) return false;
+        valueRef.setShort(val);
+      }
+      return true;
+    case Value::STRING:
+      {
+        std::string val;
+        if (!readString(val)) return false;
+        valueRef.setString(val);
+      }
+      return true;
+    case Value::INT:
+      {
+        int val;
+        if (!readInt(val)) return false;
+        valueRef.setInt(val);
+      }
+      return true;
+    case Value::LONG:
+      {
+        int64_t val;
+        if (!readLong(val)) return false;
+        valueRef.setLong(val);
+      }
+      return true;
+    case Value::DOUBLE:
+      {
+        double val;
+        if (!readDouble(val)) return false;
+        valueRef.setDouble(val);
+      }
+      return true;
+    case Value::JAVA_OBJECT:
+      {
+        int objId;
+        if (!readInt(objId)) return false;
+        valueRef.setJavaObject(objId);
+      }
+      return true;
+    case Value::JS_OBJECT:
+      {
+        int val;
+        if (!readInt(val)) return false;
+        valueRef.setJsObjectId(val);
+      }
+      return true;
+    default:
+      Debug::log(Debug::Error) << "Unhandled value type sent from server: " << type << Debug::flush;
+      break;
+  }
+  return false;
+}
+
+bool HostChannel::sendValue(const Value& value) {
+  Value::ValueType type = value.getType();
+  if (!sendByte(type)) return false;
+  switch (type) {
+    case Value::NULL_TYPE:
+    case Value::UNDEFINED:
+      // Null and Undefined only have the tag byte, no data
+      return true;
+    case Value::BOOLEAN:
+      return sendByte(value.getBoolean() ? 1 : 0);
+    case Value::BYTE:
+      return sendByte(value.getByte());
+    case Value::CHAR:
+      return sendShort(short(value.getChar()));
+    case Value::SHORT:
+      return sendShort(value.getShort());
+    case Value::INT:
+      return sendInt(value.getInt());
+    case Value::LONG:
+      return sendLong(value.getLong());
+    case Value::STRING:
+      return sendString(value.getString());
+    case Value::DOUBLE:
+      return sendDouble(value.getDouble());
+    case Value::FLOAT:
+      return sendFloat(value.getFloat());
+    case Value::JS_OBJECT:
+      return sendInt(value.getJsObjectId());
+    case Value::JAVA_OBJECT:
+      return sendInt(value.getJavaObjectId());
+    default:
+      Debug::log(Debug::Error) << "Unhandled value type sent to server: " << type << Debug::flush;
+      break;
+  }
+  return false;
+}
diff --git a/plugins/common/HostChannel.h b/plugins/common/HostChannel.h
new file mode 100644
index 0000000..0097b6d
--- /dev/null
+++ b/plugins/common/HostChannel.h
@@ -0,0 +1,139 @@
+#ifndef __H_HostChannel
+#define __H_HostChannel
+/*
+ * 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"
+
+// Sun's cstdio doesn't define a bunch of stuff
+#include <stdio.h>
+#include <string>
+
+#include "ByteOrder.h"
+#include "Socket.h"
+#include "AllowedConnections.h"
+#include "Platform.h"
+#include "Message.h"
+#include "ReturnMessage.h"
+#include "Value.h"
+#include "SessionHandler.h"
+
+class HostChannel {
+  Socket sock;
+  AllowedConnections whitelist;
+  static ByteOrder byteOrder;
+
+public:
+  ~HostChannel() {
+    if (isConnected()) {
+      disconnectFromHost();
+    }
+    Debug::log(Debug::Debugging) << "HostChannel destroyed" << Debug::flush;
+  }
+
+  bool connectToHost(const char* host, unsigned port);
+  bool disconnectFromHost();
+  
+  bool isConnected() const {
+    return sock.isConnected();
+  }
+
+  bool readBytes(void* data, size_t dataLen) {
+    char* ptr = static_cast<char*>(data);
+    while(dataLen > 0) {
+      if (!readByte(*ptr++)) {
+        return false;
+      }
+      --dataLen;
+    }
+    return true;
+  }
+
+  bool sendBytes(const void* data, size_t dataLen) {
+    const char* ptr = static_cast<const char*>(data);
+    while(dataLen > 0) {
+      if (!sendByte(*ptr++)) {
+        return false;
+      }
+      --dataLen;
+    }
+    return true;
+  }
+
+  // TODO: don't pass out-params by reference as it makes the call site misleading
+  bool readInt(int32_t& data);
+  bool sendInt(const int32_t data);
+
+  bool readShort(short& data);
+  bool sendShort(const short data);
+
+  bool readLong(int64_t& data);
+  bool sendLong(const int64_t data);
+
+  bool readFloat(float& data);
+  bool sendFloat(const float data);
+
+  bool readDouble(double& doubleRef);
+  bool sendDouble(const double data);
+
+  bool readByte(char& data) {
+    if (!isConnected()) {
+      return false;
+    }
+    int c = sock.readByte();
+    if (c < 0) {
+      return false;
+    }
+    data = static_cast<char>(c);
+    return true;
+  }
+
+  bool sendByte(const char data) {
+    if (!isConnected()) {
+      return false;
+    }
+    return sock.writeByte(data);
+  }
+
+  bool readStringLength(uint32_t& data);
+  bool readStringBytes(char* data, const uint32_t len);
+  bool readString(std::string& strRef);
+  bool sendString(const char* data, const uint32_t len) {
+    return sendInt(len) && sendBytes(data, len);
+  }
+
+  bool sendString(const std::string& str) {
+    return sendString(str.c_str(), static_cast<uint32_t>(str.length()));
+  }
+
+  bool readValue(Value& valueRef);
+  bool sendValue(const Value& value);
+
+  ReturnMessage* reactToMessages(SessionHandler* handler, bool expectReturn);
+
+  bool reactToMessages(SessionHandler* handler) {
+    return !reactToMessages(handler, false);
+  }
+
+  bool flush() {
+    return sock.flush();
+  }
+
+  ReturnMessage* reactToMessagesWhileWaitingForReturn(SessionHandler* handler) {
+    return reactToMessages(handler, true);
+  }
+};
+#endif
diff --git a/plugins/common/InvokeMessage.cpp b/plugins/common/InvokeMessage.cpp
new file mode 100644
index 0000000..90fc790
--- /dev/null
+++ b/plugins/common/InvokeMessage.cpp
@@ -0,0 +1,79 @@
+/*
+ * 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 "InvokeMessage.h"
+#include "HostChannel.h"
+#include "scoped_ptr/scoped_ptr.h"
+
+InvokeMessage::~InvokeMessage() {
+  delete[] args;
+}
+
+char InvokeMessage::getType() const {
+  return TYPE;
+}
+
+/**
+ * Receive an Invoke message from the channel (note that the message
+ * type has already been read).  Caller is responsible for destroying
+ * returned message.  Returns null on error.
+ */
+InvokeMessage* InvokeMessage::receive(HostChannel& channel) {
+  std::string methodName;
+  if (!channel.readString(methodName)) {
+    // TODO(jat): error handling
+    printf("Failed to read method name\n");
+    return 0;
+  }
+  Value thisRef;
+  if (!channel.readValue(thisRef)) {
+    // TODO(jat): error handling
+    printf("Failed to read thisRef\n");
+    return 0;
+  }
+  int numArgs;
+  if (!channel.readInt(numArgs)) {
+    // TODO(jat): error handling
+    printf("Failed to read #args\n");
+    return 0;
+  }
+  scoped_array<Value> args(new Value[numArgs]);
+  for (int i = 0; i < numArgs; ++i) {
+    if (!channel.readValue(args[i])) {
+      // TODO(jat): error handling
+      printf("Failed to read arg[%d]\n", i);
+      return 0;
+    }
+  }
+  return new InvokeMessage(thisRef, methodName, numArgs, args.release());
+}
+
+/**
+ * Request the server invoke a method on an object and return the result.
+ * 
+ * Note that the method to be invoked is sent as an integer (a dispatch id) to the server.
+ */
+bool InvokeMessage::send(HostChannel& channel, const Value& thisRef, int methodDispatchId,
+    int numArgs, const Value* args) {
+  if (!channel.sendByte(TYPE)) return false;
+  if (!channel.sendInt(methodDispatchId)) return false;
+  if (!channel.sendValue(thisRef)) return false;
+  if (!channel.sendInt(numArgs)) return false;
+  for (int i = 0; i < numArgs; ++i) {
+    if (!channel.sendValue(args[i])) return false;
+  }
+  return true;
+}
diff --git a/plugins/common/InvokeMessage.h b/plugins/common/InvokeMessage.h
new file mode 100644
index 0000000..7d57e30
--- /dev/null
+++ b/plugins/common/InvokeMessage.h
@@ -0,0 +1,67 @@
+#ifndef __INVOKEMESSAGE_H
+#define __INVOKEMESSAGE_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 "Message.h"
+#include "BrowserChannel.h"
+#include "Value.h"
+
+class HostChannel;
+
+/**
+ * Class representing an InvokeMessage received from the server, and a way
+ * to send an invoke message to the server.
+ *
+ * Note that the wire protocol is different in the two directions, as the
+ * server sends a string for the method name and the client send an integer
+ * dispatchID.
+ */
+class InvokeMessage : public Message {
+public:
+  static const char TYPE = MESSAGE_TYPE_INVOKE;
+  static const int TOSTRING_DISP_ID = 0;
+private:
+  Value thisRef;
+  std::string methodName;
+  int methodDispatchId;
+  int numArgs;
+  const Value* args;
+
+protected:
+  /**
+   * @param args array of arguments -- InvokeMessage takes ownership and will
+   *     destroy when it is destroyed.
+   */
+  InvokeMessage(const Value& thisRef, const std::string& methodName,
+      int numArgs, const Value* args) : thisRef(thisRef), methodName(methodName),
+      numArgs(numArgs), args(args) {}
+
+public:
+  ~InvokeMessage();
+  virtual char getType() const;
+
+  Value getThis() const { return thisRef; }
+  const std::string& getMethodName() const { return methodName; }
+  int getNumArgs() const { return numArgs; }
+  const Value* const getArgs() const { return args; }
+
+  static InvokeMessage* receive(HostChannel& channel);
+  static bool send(HostChannel& channel, const Value& thisRef, int methodDispatchId,
+      int numArgs, const Value* args);
+};
+#endif
diff --git a/plugins/common/InvokeSpecialMessage.cpp b/plugins/common/InvokeSpecialMessage.cpp
new file mode 100644
index 0000000..5fd1540
--- /dev/null
+++ b/plugins/common/InvokeSpecialMessage.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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 "InvokeSpecialMessage.h"
+#include "HostChannel.h"
+#include "SessionHandler.h"
+#include "scoped_ptr/scoped_ptr.h"
+
+InvokeSpecialMessage::~InvokeSpecialMessage() {
+  delete[] args;
+}
+
+char InvokeSpecialMessage::getType() const {
+  return TYPE;
+}
+
+/**
+ * Receive an InvokeSpecial message from the channel (note that the message
+ * type has already been read).  Caller is responsible for destroying
+ * returned message.  Returns null on error.
+ */
+InvokeSpecialMessage* InvokeSpecialMessage::receive(HostChannel& channel) {
+  char dispatchId;
+  if (!channel.readByte(dispatchId)) {
+    // TODO(jat): error handling
+    printf("Failed to read method name\n");
+    return 0;
+  }
+  int numArgs;
+  if (!channel.readInt(numArgs)) {
+    // TODO(jat): error handling
+    printf("Failed to read #args\n");
+    return 0;
+  }
+  scoped_array<Value> args(new Value[numArgs]);
+  for (int i = 0; i < numArgs; ++i) {
+    if (!channel.readValue(args[i])) {
+      // TODO(jat): error handling
+      printf("Failed to read arg[%d]\n", i);
+      return 0;
+    }
+  }
+  
+  SessionHandler::SpecialMethodId id =
+    static_cast<SessionHandler::SpecialMethodId>(dispatchId);
+  return new InvokeSpecialMessage(id, numArgs, args.release());
+}
+
+/**
+ * Request the server perform a special method and return the result.
+ */
+bool InvokeSpecialMessage::send(HostChannel& channel, int dispatchId,
+    int numArgs, const Value* args) {
+  if (!channel.sendByte(TYPE)) return false;
+  if (!channel.sendByte(dispatchId)) return false;
+  if (!channel.sendInt(numArgs)) return false;
+  for (int i = 0; i < numArgs; ++i) {
+    if (!channel.sendValue(args[i])) return false;
+  }
+  return true;
+}
diff --git a/plugins/common/InvokeSpecialMessage.h b/plugins/common/InvokeSpecialMessage.h
new file mode 100644
index 0000000..196baa5
--- /dev/null
+++ b/plugins/common/InvokeSpecialMessage.h
@@ -0,0 +1,59 @@
+#ifndef __INVOKESPECIALMESSAGE_H
+#define __INVOKESPECIALMESSAGE_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 "Message.h"
+#include "BrowserChannel.h"
+#include "SessionHandler.h"
+#include "Value.h"
+
+class HostChannel;
+
+/**
+ * Class representing an InvokeSpecialMessage received from the server, and a way
+ * to send an invoke message to the server.
+ */
+class InvokeSpecialMessage : public Message {
+public:
+  static const char TYPE = MESSAGE_TYPE_INVOKESPECIAL;
+private:
+  SessionHandler::SpecialMethodId dispatchId;
+  int numArgs;
+  const Value* args;
+
+protected:
+  /**
+   * @param args array of arguments -- InvokeMessage takes ownership and will
+   *     destroy when it is destroyed.
+   */
+  InvokeSpecialMessage(SessionHandler::SpecialMethodId dispatchId, int numArgs, const Value* args) : dispatchId(dispatchId),
+      numArgs(numArgs), args(args) {}
+
+public:
+  ~InvokeSpecialMessage();
+  virtual char getType() const;
+
+  SessionHandler::SpecialMethodId getDispatchId() const { return dispatchId; }
+  int getNumArgs() const { return numArgs; }
+  const Value* const getArgs() const { return args; }
+
+  static InvokeSpecialMessage* receive(HostChannel& channel);
+  static bool send(HostChannel& channel, int dispatchId, int numArgs,
+      const Value* args);
+};
+#endif
diff --git a/plugins/common/LoadJsniMessage.cpp b/plugins/common/LoadJsniMessage.cpp
new file mode 100644
index 0000000..db8b943
--- /dev/null
+++ b/plugins/common/LoadJsniMessage.cpp
@@ -0,0 +1,26 @@
+/*
+ * 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 "LoadJsniMessage.h"
+
+LoadJsniMessage* LoadJsniMessage::receive(HostChannel& channel) {
+  std::string js;
+  if (!channel.readString(js)) {
+    // TODO(jat): error handling
+    return 0;
+  }
+  return new LoadJsniMessage(js);
+}
diff --git a/plugins/common/LoadJsniMessage.h b/plugins/common/LoadJsniMessage.h
new file mode 100644
index 0000000..5b1f8d9
--- /dev/null
+++ b/plugins/common/LoadJsniMessage.h
@@ -0,0 +1,43 @@
+#ifndef __H_LoadJsniMessage
+#define __H_LoadJsniMessage
+/*
+ * 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 "Message.h"
+#include "BrowserChannel.h"
+#include "HostChannel.h"
+
+class LoadJsniMessage : public Message {
+public:  
+  static const char TYPE = MESSAGE_TYPE_LOADJSNI;
+private:
+  const std::string js;
+  
+  LoadJsniMessage(const std::string& js) : js(js) {}
+  
+public:  
+  virtual char getType() const {
+    return TYPE;
+  }
+  
+  std::string getJs() const {
+    return js;
+  }
+
+  static LoadJsniMessage* receive(HostChannel& channel);
+};
+#endif
diff --git a/plugins/common/LoadModuleMessage.cpp b/plugins/common/LoadModuleMessage.cpp
new file mode 100644
index 0000000..a436961
--- /dev/null
+++ b/plugins/common/LoadModuleMessage.cpp
@@ -0,0 +1,44 @@
+/*
+ * 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 <cstring>
+#include <string>
+
+#include "LoadModuleMessage.h"
+#include "scoped_ptr/scoped_ptr.h"
+
+char LoadModuleMessage::getType() const {
+  return LoadModuleMessage::TYPE;
+}
+
+bool LoadModuleMessage::send(HostChannel& channel, uint32_t version, const char* moduleName,
+    const uint32_t moduleNameLen, const char* userAgent, SessionHandler* handler) {
+  Debug::log(Debug::Spam) << "LoadModule(module=\"" << moduleName << "\",vers="
+      << version << ")" << Debug::flush;
+  if (!channel.sendByte(TYPE) || !channel.sendInt(version)
+      || !channel.sendString(moduleName, moduleNameLen)
+      || !channel.sendString(userAgent, static_cast<uint32_t>(strlen(userAgent)))) {
+    return false;
+  }
+  scoped_ptr<ReturnMessage> ret(channel.reactToMessagesWhileWaitingForReturn(handler));
+  if (!ret.get()) {
+    return false;
+  }
+
+  return !ret.get()->isException();
+}
diff --git a/plugins/common/LoadModuleMessage.h b/plugins/common/LoadModuleMessage.h
new file mode 100644
index 0000000..3091c46
--- /dev/null
+++ b/plugins/common/LoadModuleMessage.h
@@ -0,0 +1,47 @@
+#ifndef __LOADMODULEMESSAGE_H
+#define __LOADMODULEMESSAGE_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 "Message.h"
+#include "BrowserChannel.h"
+#include "HostChannel.h"
+#include "SessionHandler.h"
+
+class HostChannel;
+
+class LoadModuleMessage : public Message {
+  static const char TYPE = MESSAGE_TYPE_LOAD_MODULE;
+
+public:  
+  LoadModuleMessage(int version, std::string& moduleName, std::string& userAgent) :
+    version(version), moduleName(moduleName), userAgent(userAgent) { }
+
+  int getVersion() const { return version; }
+  const std::string& getModuleName() const { return moduleName; }
+  const std::string& getUserAgent() const { return userAgent; }
+  virtual char getType() const;
+  
+  static bool send(HostChannel& channel, uint32_t version, const char* moduleName,
+      uint32_t moduleNameLen, const char* userAgent, SessionHandler* handler);
+private:
+  int version;
+  std::string moduleName;
+  std::string userAgent;
+};
+#endif
diff --git a/plugins/common/Makefile b/plugins/common/Makefile
new file mode 100644
index 0000000..b22fd27
--- /dev/null
+++ b/plugins/common/Makefile
@@ -0,0 +1,93 @@
+# Copyright 2009 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 ../config.mk
+
+HDRS= HostChannel.h InvokeMessage.h LoadModuleMessage.h Message.h \
+      ReturnMessage.h Value.h BrowserChannel.h Debug.h DebugLevel.h \
+      SessionHandler.h ServerMethods.h Socket.h AllowedConnections.h \
+      LoadJsniMessage.h InvokeSpecialMessage.h FreeValueMessage.h \
+      ByteOrder.h
+
+SRCS=	HostChannel.cpp LoadModuleMessage.cpp InvokeMessage.cpp \
+	ReturnMessage.cpp ServerMethods.cpp Debug.cpp Socket.cpp \
+	AllowedConnections.cpp LoadJsniMessage.cpp InvokeSpecialMessage.cpp \
+	FreeValueMessage.cpp
+
+LIBCOMMON= libcommon$(FLAG32BIT).a
+OBJDIR= obj$(FLAG32BIT)
+OBJS= $(patsubst %.cpp,$(OBJDIR)/%.o,$(SRCS))
+
+all:: $(OBJDIR) $(LIBCOMMON)
+
+$(OBJDIR):
+	-mkdir $@
+
+$(LIBCOMMON): $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+$(OBJDIR)/%.o: %.cpp
+	$(CXX) $(CXXFLAGS) -c $< -o $@
+
+.PHONY: clean depend testdebug
+
+testdebug:
+	(cd testing; CXX=$(CXX) CXXFLAGS="$(CFLAGS) -m32" ./testdebug)
+	(cd testing; CXX=$(CXX) CXXFLAGS="$(CFLAGS) -m64" ./testdebug)
+
+clean:
+	rm -rf obj32 obj64 libcommon32.a libcommon64.a
+
+depend:
+	g++ -MM $(CFLAGS) $(SRCS) >>Makefile
+#	makedepend -- $(CFLAGS) -- $(SRCS)
+
+# DO NOT DELETE
+HostChannel.o: HostChannel.cpp Debug.h Platform.h DebugLevel.h \
+  ByteOrder.h FreeValueMessage.h Message.h BrowserChannel.h HostChannel.h \
+  Socket.h AllowedConnections.h ReturnMessage.h Value.h SessionHandler.h \
+  LoadJsniMessage.h InvokeMessage.h InvokeSpecialMessage.h QuitMessage.h \
+  scoped_ptr/scoped_ptr.h
+LoadModuleMessage.o: LoadModuleMessage.cpp Debug.h Platform.h \
+  DebugLevel.h LoadModuleMessage.h Message.h BrowserChannel.h \
+  HostChannel.h ByteOrder.h Socket.h AllowedConnections.h ReturnMessage.h \
+  Value.h SessionHandler.h scoped_ptr/scoped_ptr.h
+InvokeMessage.o: InvokeMessage.cpp InvokeMessage.h Message.h \
+  BrowserChannel.h Value.h Debug.h Platform.h DebugLevel.h HostChannel.h \
+  ByteOrder.h Socket.h AllowedConnections.h ReturnMessage.h \
+  SessionHandler.h scoped_ptr/scoped_ptr.h
+ReturnMessage.o: ReturnMessage.cpp ReturnMessage.h Message.h \
+  BrowserChannel.h Value.h Debug.h Platform.h DebugLevel.h HostChannel.h \
+  ByteOrder.h Socket.h AllowedConnections.h SessionHandler.h
+ServerMethods.o: ServerMethods.cpp Debug.h Platform.h DebugLevel.h \
+  FreeValueMessage.h Message.h BrowserChannel.h HostChannel.h ByteOrder.h \
+  Socket.h AllowedConnections.h ReturnMessage.h Value.h SessionHandler.h \
+  InvokeMessage.h InvokeSpecialMessage.h ServerMethods.h \
+  scoped_ptr/scoped_ptr.h
+Debug.o: Debug.cpp Debug.h Platform.h DebugLevel.h
+Socket.o: Socket.cpp Platform.h Socket.h Debug.h DebugLevel.h
+AllowedConnections.o: AllowedConnections.cpp Debug.h Platform.h \
+  DebugLevel.h AllowedConnections.h
+LoadJsniMessage.o: LoadJsniMessage.cpp LoadJsniMessage.h Message.h \
+  BrowserChannel.h HostChannel.h Debug.h Platform.h DebugLevel.h \
+  ByteOrder.h Socket.h AllowedConnections.h ReturnMessage.h Value.h \
+  SessionHandler.h
+InvokeSpecialMessage.o: InvokeSpecialMessage.cpp InvokeSpecialMessage.h \
+  Message.h BrowserChannel.h SessionHandler.h Value.h Debug.h Platform.h \
+  DebugLevel.h HostChannel.h ByteOrder.h Socket.h AllowedConnections.h \
+  ReturnMessage.h scoped_ptr/scoped_ptr.h
+FreeValueMessage.o: FreeValueMessage.cpp FreeValueMessage.h Message.h \
+  BrowserChannel.h HostChannel.h Debug.h Platform.h DebugLevel.h \
+  ByteOrder.h Socket.h AllowedConnections.h ReturnMessage.h Value.h \
+  SessionHandler.h scoped_ptr/scoped_ptr.h
diff --git a/plugins/common/Makefile.sun b/plugins/common/Makefile.sun
new file mode 100644
index 0000000..2043187
--- /dev/null
+++ b/plugins/common/Makefile.sun
@@ -0,0 +1,115 @@
+# Set to classpath value to get GWT classes from
+#GWTDEV=../build/staging/gwt-linux-0.0.0/gwt-dev-linux.jar
+GWTDEV=../eclipse/dev/linux/bin
+
+INC=-I..
+#CFLAGS=-fast -g0 -Kpic $(INC) -Bdynamic -noex
+# SunC appears to miscompile Socket::writeByte by not incrementing the
+# buffer pointer, so no optimization for now
+#CFLAGS=-g -Kpic $(INC) -Bdynamic -noex
+CFLAGS=-g0 -Kpic -noex -xO1 -xlibmil -xlibmopt -features=tmplife -xbuiltin=%all -mt $(INC)
+CXXFLAGS=$(CFLAGS)
+CXX=CC
+
+HDRS= HostChannel.h InvokeMessage.h LoadModuleMessage.h Message.h \
+      ReturnMessage.h Value.h BrowserChannel.h Debug.h DebugLevel.h \
+      SessionHandler.h ServerMethods.h Socket.h AllowedConnections.h \
+      LoadJsniMessage.h InvokeSpecialMessage.h FreeValueMessage.h
+
+OBJS=	HostChannel.o LoadModuleMessage.o InvokeMessage.o \
+	ReturnMessage.o ServerMethods.o Debug.o Socket.o \
+	AllowedConnections.o LoadJsniMessage.o InvokeSpecialMessage.o \
+	FreeValueMessage.o
+
+SRCS=	HostChannel.cpp LoadModuleMessage.cpp InvokeMessage.cpp \
+	ReturnMessage.cpp ServerMethods.cpp Debug.cpp Socket.cpp \
+	AllowedConnections.cpp LoadJsniMessage.cpp InvokeSpecialMessage.cpp \
+	FreeValueMessage.cpp
+
+OBJ32= $(patsubst %.cpp,obj32/%.o,$(SRCS))
+OBJ64= $(patsubst %.cpp,obj64/%.o,$(SRCS))
+
+all:: libcommon32.a libcommon64.a
+
+libcommon32.a: $(OBJ32) obj32.dir
+	ar -rv $@ $(OBJ32)
+
+libcommon64.a: $(OBJ64) obj64.dir
+	ar -rv $@ $(OBJ64)
+
+obj32.dir:
+	-mkdir obj32
+	touch obj32.dir
+
+obj64.dir:
+	-mkdir obj64
+	touch obj64.dir
+
+obj32/%.o: %.cpp obj32.dir
+	$(CXX) $(CXXFLAGS) -m32 -c $< -o $@
+
+obj64/%.o: %.cpp obj64.dir
+	$(CXX) $(CXXFLAGS) -m64 -c $< -o $@
+
+.PHONY: all clean depend
+
+clean:
+	-rm $(OBJ32) $(OBJ64) libcommon32.a libcommon64.a
+
+depend:
+	$(CXX) -xMMF $(CFLAGS) $(SRCS) >>Makefile.sun
+#	makedepend -- $(CFLAGS) -- $(SRCS)
+
+# DO NOT DELETE
+obj32/HostChannel.o obj64/HostChannel.o: Makefile.sun \
+  HostChannel.cpp HostChannel.h Platform.h Message.h \
+  ReturnMessage.h BrowserChannel.h Value.h SessionHandler.h \
+  InvokeMessage.h QuitMessage.h scoped_ptr/scoped_ptr.h
+obj32/LoadModuleMessage.o obj64/LoadModuleMessage.o: Makefile.sun \
+  LoadModuleMessage.cpp LoadModuleMessage.h Message.h \
+  BrowserChannel.h HostChannel.h Platform.h ReturnMessage.h Value.h \
+  SessionHandler.h scoped_ptr/scoped_ptr.h
+obj32/InvokeMessage.o obj64/InvokeMessage.o: Makefile.sun \
+  InvokeMessage.cpp InvokeMessage.h Message.h \
+  BrowserChannel.h Value.h HostChannel.h Platform.h ReturnMessage.h \
+  SessionHandler.h
+obj32/ReturnMessage.o obj64/ReturnMessage.o: Makefile.sun \
+  ReturnMessage.cpp ReturnMessage.h Message.h \
+  BrowserChannel.h Value.h HostChannel.h Platform.h SessionHandler.h
+obj32/ServerMethods.o obj64/ServerMethods.o: Makefile.sun \
+  ServerMethods.cpp ServerMethods.h Value.h \
+  BrowserChannel.h HostChannel.h Platform.h Message.h ReturnMessage.h \
+  SessionHandler.h InvokeMessage.h scoped_ptr/scoped_ptr.h
+obj32/HostChannel.o obj64/HostChannel.o: Makefile.sun \
+  HostChannel.cpp HostChannel.h Platform.h Message.h \
+  ReturnMessage.h BrowserChannel.h Value.h SessionHandler.h \
+  InvokeMessage.h QuitMessage.h scoped_ptr/scoped_ptr.h
+obj32/LoadModuleMessage.o obj64/LoadModuleMessage.o: Makefile.sun \
+  LoadModuleMessage.cpp LoadModuleMessage.h Message.h \
+  BrowserChannel.h HostChannel.h Platform.h ReturnMessage.h Value.h \
+  SessionHandler.h scoped_ptr/scoped_ptr.h
+obj32/InvokeMessage.o obj64/InvokeMessage.o: Makefile.sun \
+  InvokeMessage.cpp InvokeMessage.h Message.h \
+  BrowserChannel.h Value.h HostChannel.h Platform.h ReturnMessage.h \
+  SessionHandler.h
+obj32/InvokeSpecialMessage.o obj64/InvokeSpecialMessage.o: Makefile.sun \
+  InvokeSpecialMessage.cpp InvokeSpecialMessage.h Message.h \
+  BrowserChannel.h Value.h HostChannel.h Platform.h ReturnMessage.h \
+  SessionHandler.h
+obj32/FreeValueMesssage.o obj64/FreeValueMesssage.o: Makefile.sun \
+  FreeValueMesssage.cpp FreeValueMesssage.h Message.h \
+  BrowserChannel.h Value.h HostChannel.h Platform.h ReturnMessage.h \
+  SessionHandler.h
+obj32/ReturnMessage.o obj64/ReturnMessage.o: Makefile.sun \
+  ReturnMessage.cpp ReturnMessage.h Message.h \
+  BrowserChannel.h Value.h HostChannel.h Platform.h SessionHandler.h
+obj32/ServerMethods.o obj64/ServerMethods.o: Makefile.sun \
+  ServerMethods.cpp ServerMethods.h Value.h \
+  BrowserChannel.h HostChannel.h Platform.h Message.h ReturnMessage.h \
+  SessionHandler.h InvokeMessage.h scoped_ptr/scoped_ptr.h
+obj32/Debug.o obj64/Debug.o: Makefile.sun \
+  Debug.cpp Debug.h DebugLevel.h
+obj32/Socket.o obj64/Socket.o: Makefile.sun \
+  Socket.cpp Socket.h Debug.h DebugLevel.h
+obj32/AllowedConnections.o obj64/AllowedConnections.o: Makefile.sun \
+  AllowedConnections.cpp AllowedConnections.h Debug.h DebugLevel.h
diff --git a/plugins/common/Message.h b/plugins/common/Message.h
new file mode 100644
index 0000000..a244e0b
--- /dev/null
+++ b/plugins/common/Message.h
@@ -0,0 +1,28 @@
+#ifndef __MESSAGE_H
+#define __MESSAGE_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.
+ */
+
+class Message {
+public:
+  virtual char getType() const = 0;
+  virtual bool isAsynchronous() const {
+    return false;
+  }
+  virtual ~Message() {}
+};
+
+#endif
diff --git a/plugins/common/Platform.h b/plugins/common/Platform.h
new file mode 100644
index 0000000..bbc0334
--- /dev/null
+++ b/plugins/common/Platform.h
@@ -0,0 +1,46 @@
+#ifndef _H_Platform
+#define _H_Platform
+/*
+ * 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.
+ */
+
+// Platform-specific hacks to enable more shared code elsewhere
+#ifdef _WINDOWS
+typedef __int32 int32_t;
+typedef unsigned __int32 uint32_t; 
+typedef __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+typedef long ssize_t;
+
+#define snprintf sprintf_s
+#define SOCKETTYPE SOCKET
+// Bogus conversion from size_t -> unsigned int warnings.
+#pragma warning(disable:4267)
+#else
+#define SOCKETTYPE int
+#endif
+
+// Set the float byte-order if we know it -- see ByteOrder.h FloatByteOrder
+#if defined(i386) || defined(i586) || defined(i686) || defined(_x86)
+#define PLATFORM_FLOAT_ENDIANESS FLOAT_LITTLE_ENDIAN
+#endif
+
+#if defined(__sparc)
+#define PLATFORM_FLOAT_ENDIANESS FLOAT_BIG_ENDIAN
+#endif
+
+#endif
diff --git a/plugins/common/QuitMessage.h b/plugins/common/QuitMessage.h
new file mode 100644
index 0000000..344612f
--- /dev/null
+++ b/plugins/common/QuitMessage.h
@@ -0,0 +1,38 @@
+#ifndef __H_QuitMessage
+#define __H_QuitMessage
+/*
+ * 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 "Message.h"
+#include "BrowserChannel.h"
+
+class QuitMessage : public Message {
+public:  
+  static const char TYPE = MESSAGE_TYPE_QUIT;
+private:
+  QuitMessage() {}
+  
+public:  
+  virtual char getType() const {
+    return TYPE;
+  }
+  
+  static bool send(HostChannel& channel) {
+    return channel.sendByte(TYPE);
+  }
+};
+#endif
diff --git a/plugins/common/ReturnMessage.cpp b/plugins/common/ReturnMessage.cpp
new file mode 100644
index 0000000..0149c1f
--- /dev/null
+++ b/plugins/common/ReturnMessage.cpp
@@ -0,0 +1,42 @@
+/*
+ * 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 "ReturnMessage.h"
+#include "HostChannel.h"
+
+char ReturnMessage::getType() const {
+  return TYPE;
+}
+  
+ReturnMessage* ReturnMessage::receive(HostChannel& channel) {
+  char isException;
+  if (!channel.readByte(isException)) {
+    // TODO(jat): error handling
+    return 0;
+  }
+  Value retval;
+  if (!channel.readValue(retval)) {
+    // TODO(jat): error handling
+    return 0;
+  }
+  return new ReturnMessage(isException != 0, retval);
+}
+
+bool ReturnMessage::send(HostChannel& channel, bool isException, const Value& retval) {
+  if (!channel.sendByte(TYPE)) return false;
+  if (!channel.sendByte(isException ? 1 : 0)) return false;
+  return channel.sendValue(retval);
+}
diff --git a/plugins/common/ReturnMessage.h b/plugins/common/ReturnMessage.h
new file mode 100644
index 0000000..fddf9ec
--- /dev/null
+++ b/plugins/common/ReturnMessage.h
@@ -0,0 +1,43 @@
+#ifndef __RETURNMESSAGE_H
+#define __RETURNMESSAGE_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 "Message.h"
+#include "BrowserChannel.h"
+#include "Value.h"
+
+class HostChannel;
+
+class ReturnMessage : public Message {
+  static const char TYPE = MESSAGE_TYPE_RETURN;
+private:
+  bool bisException;
+  Value retval;
+  
+public:  
+  ReturnMessage(bool isException, const Value& retValue) : bisException(isException),
+      retval(retValue) {}
+
+  bool isException() const { return bisException; }
+  const Value& getReturnValue() const { return retval; }
+  virtual char getType() const;
+  
+  static ReturnMessage* receive(HostChannel& channel);
+  static bool send(HostChannel& channel, bool isException, const Value& retValue);
+};
+#endif
diff --git a/plugins/common/ServerMethods.cpp b/plugins/common/ServerMethods.cpp
new file mode 100644
index 0000000..5a18bcb
--- /dev/null
+++ b/plugins/common/ServerMethods.cpp
@@ -0,0 +1,129 @@
+/*
+ * 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 "Debug.h"
+#include "FreeValueMessage.h"
+#include "HostChannel.h"
+#include "InvokeMessage.h"
+#include "InvokeSpecialMessage.h"
+#include "ReturnMessage.h"
+#include "ServerMethods.h"
+#include "scoped_ptr/scoped_ptr.h"
+
+using std::string;
+
+Value ServerMethods::getProperty(HostChannel& channel, SessionHandler* handler, int objectRef,
+    int dispatchId) {
+  Value args[2];
+  args[0].setInt(objectRef);
+  args[1].setInt(dispatchId);
+  if (!InvokeSpecialMessage::send(channel, SPECIAL_GET_PROPERTY, 2, args)) {
+    Debug::log(Debug::Error) << "  failed to send invoke of GetProperty(disp=" << dispatchId
+        << ", obj=" << objectRef << ")" << Debug::flush;
+    return Value();
+  }
+  scoped_ptr<ReturnMessage> retMsg(channel.reactToMessagesWhileWaitingForReturn(handler));
+  if (!retMsg.get()) {
+    Debug::log(Debug::Error) << "getProperty: get return value failed for GetProperty(disp="
+        << dispatchId << ", obj=" << objectRef << ")" << Debug::flush;
+    return Value();
+  }
+  return retMsg->getReturnValue();
+}
+
+int ServerMethods::hasMethod(HostChannel& channel, SessionHandler* handler, int classId,
+    const std::string& name) {
+  if (name != "toString" && name.find("::") == string::npos) {
+    // only JSNI-style names and toString are valid
+    return -1;
+  }
+  Value arg;
+  arg.setString(name);
+  if (!InvokeSpecialMessage::send(channel, SPECIAL_HAS_METHOD, 1, &arg)) {
+    Debug::log(Debug::Error) << "hasMethod: invoke(hasMethod) failed" << Debug::flush;
+    return -2;
+  }
+  scoped_ptr<ReturnMessage> retMsg(channel.reactToMessagesWhileWaitingForReturn(handler));
+  if (!retMsg.get()) {
+    Debug::log(Debug::Error) << "hasMethod: get return value failed" << Debug::flush;
+    return -2;
+  }
+  Value retval = retMsg->getReturnValue();
+  // TODO(jat): better error handling?
+  return retval.isInt() ? retval.getInt() : -2;
+}
+
+int ServerMethods::hasProperty(HostChannel& channel, SessionHandler* handler, int classId,
+    const std::string& name) {
+  if (name != "toString" && name.find("::") == string::npos) {
+    // only JSNI-style names and toString are valid
+    return -1;
+  }
+  Value arg;
+  arg.setString(name);
+  if (!InvokeSpecialMessage::send(channel, SPECIAL_HAS_PROPERTY, 1, &arg)) {
+    Debug::log(Debug::Error) << "hasProperty: invoke(hasProperty) failed" << Debug::flush;
+    return -2;
+  }
+  scoped_ptr<ReturnMessage> retMsg(channel.reactToMessagesWhileWaitingForReturn(handler));
+  if (!retMsg.get()) {
+    Debug::log(Debug::Error) << "hasProperty: get return value failed" << Debug::flush;
+    return -2;
+  }
+  Value retval = retMsg->getReturnValue();
+  // TODO(jat): better error handling?
+  return retval.isInt() ? retval.getInt() : -2;
+}
+
+bool ServerMethods::setProperty(HostChannel& channel, SessionHandler* handler, int objectRef,
+    int dispatchId, const Value& value) {
+  // TODO(jat): error handling?
+  Value args[3];
+  args[0].setInt(objectRef);
+  args[1].setInt(dispatchId);
+  args[2] = value;
+  if (!InvokeSpecialMessage::send(channel, SPECIAL_SET_PROPERTY, 3, args)) {
+    Debug::log(Debug::Error) << "  failed to send invoke of SetProperty(disp=" << dispatchId
+        << ", obj=" << objectRef << ")" << Debug::flush;
+    return false;
+  }
+  scoped_ptr<ReturnMessage> retMsg(channel.reactToMessagesWhileWaitingForReturn(handler));
+  if (!retMsg.get()) {
+    Debug::log(Debug::Error) << "setProperty: get return value failed for SetProperty(disp="
+        << dispatchId << ", obj=" << objectRef << ")" << Debug::flush;
+    return false;
+  }
+  // TODO: use the returned exception?
+  return !retMsg.get()->isException();
+}
+
+bool ServerMethods::freeJava(HostChannel& channel, SessionHandler* handler, int idCount,
+      const int* ids) {
+  // If we are disconnected, assume the server will free all of these anyway.
+  // This deals with the problem of getting finalizers called after the channel is dropped.
+  if (!channel.isConnected()) {
+    Debug::log(Debug::Debugging) << "Ignoring freeJava after disconnect"
+        << Debug::flush;
+    return true;
+  }
+  if (!FreeValueMessage::send(channel, idCount, ids)) {
+    Debug::log(Debug::Error) << "  failed to send FreeValues message" << Debug::flush;
+    return false;
+  }
+  return true;
+}
diff --git a/plugins/common/ServerMethods.h b/plugins/common/ServerMethods.h
new file mode 100644
index 0000000..3ff0134
--- /dev/null
+++ b/plugins/common/ServerMethods.h
@@ -0,0 +1,78 @@
+#ifndef _H_ServerMethods
+#define _H_ServerMethods
+/*
+ * 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 "Value.h"
+
+class HostChannel;
+class SessionHandler;
+
+/**
+ * Encapsulates the methods defined on the special server object.
+ */
+class ServerMethods {
+public:
+  /**
+   * Get the value of a property on an object.
+   * 
+   * @param objectRef ID of object to fetch field on
+   * @param dispatchID dispatch ID of field
+   * @return the value of the property, undef if none (or on error)
+   */
+  static Value getProperty(HostChannel& channel, SessionHandler* handler, int objectRef,
+      int dispatchId);
+  
+  /**
+   * Lookup the named method on the specified class.
+   * 
+   * @return the dispatch ID (non-negative) of the method if present, or -1 if not.
+   * If an error is encountered, -2 is returned.
+   */
+  static int hasMethod(HostChannel& channel, SessionHandler* handler, int classId,
+      const std::string& name);
+  
+  /**
+   * Lookup the named property on the specified class.
+   * 
+   * @return the dispatch ID (non-negative) of the property if present, or -1 if not.
+   * If an error is encountered, -2 is returned.
+   */
+  static int hasProperty(HostChannel& channel, SessionHandler* handler, int classId,
+      const std::string& name);
+
+  /**
+   * Set the value of a property on an object.
+   * 
+   * @param objectRef ID of object to fetch field on
+   * @param dispatchID dispatch ID of field
+   * @param value value to store in the property
+   * @return false if an error occurred
+   */
+  static bool setProperty(HostChannel& channel, SessionHandler* handler, int objectRef,
+      int dispatchId, const Value& value);
+  
+  /**
+   * Tell the server that the client no longer has any references to the specified
+   * Java object.
+   * 
+   * @param objcetRef ID of object to free
+   * @return false if an error occurred
+   */ 
+  static bool freeJava(HostChannel& channel, SessionHandler* handler, int idCount, const int* ids);
+};
+
+#endif
diff --git a/plugins/common/SessionHandler.h b/plugins/common/SessionHandler.h
new file mode 100644
index 0000000..217dce4
--- /dev/null
+++ b/plugins/common/SessionHandler.h
@@ -0,0 +1,82 @@
+#ifndef _H_SessionHandler
+#define _H_SessionHandler
+/*
+ * 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 "BrowserChannel.h"
+#include "Value.h"
+
+class HostChannel;
+
+/**
+ * Interface for session-handling needs.
+ * 
+ * Note that if this is being "added" onto a class which extends a C structure, the inheritance
+ * chain leading to the plain C object must be first in the inheritance list.
+ * 
+ * For example:
+ * 
+ * extern "C" {
+ *   typedef struct PlainCstruct {
+ *      ... data only members here
+ *   } PlainCstruct;
+ * };
+ * 
+ * class MyWrapper: public PlainCstruct, SessionHandler {
+ *    ... virtual functions ok here
+ * };
+ */
+class SessionHandler {
+  friend class HostChannel;
+public:
+  enum SpecialMethodId {
+    HasMethod = SPECIAL_HAS_METHOD,
+    HasProperty = SPECIAL_HAS_PROPERTY,
+    GetProperty = SPECIAL_GET_PROPERTY,
+    SetProperty = SPECIAL_SET_PROPERTY
+  };
+protected:
+  virtual void freeValue(HostChannel& channel, int idCount, const int* ids) = 0;
+
+  virtual void loadJsni(HostChannel& channel, const std::string& js) = 0;
+
+  /**
+   * Does not own any of its args -- must copy them if it wants them and should not free the
+   * ones passed in.
+   * 
+   * Returns true if an exception occurred.
+   */
+  virtual bool invoke(HostChannel& channel, const Value& thisObj, const std::string& methodName,
+      int numArgs, const Value* const args, Value* returnValue)=0;
+  
+  /**
+   * Invoke a plugin-provided method with the given args.  As above, this method does not own
+   * any of its args.
+   * 
+   * Returns true if an exception occurred.
+   */
+  virtual bool invokeSpecial(HostChannel& channel, SpecialMethodId method, int numArgs,
+      const Value* const args, Value* returnValue) = 0;
+
+  /**
+   * Send any queued up free values back to the server.
+   */
+  virtual void sendFreeValues(HostChannel& channel) = 0;
+
+  virtual ~SessionHandler() {}
+};
+
+#endif
diff --git a/plugins/common/Socket.cpp b/plugins/common/Socket.cpp
new file mode 100644
index 0000000..0d6fae5
--- /dev/null
+++ b/plugins/common/Socket.cpp
@@ -0,0 +1,172 @@
+/*
+ * 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 "Platform.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+
+#include "Socket.h"
+
+void Socket::init() {
+#ifdef _WINDOWS
+  // version 2.2 supported on Win95OSR2/WinNT4 and up
+  WORD winsockVers = MAKEWORD(2, 2);
+  WSADATA wsaData;
+  int err = WSAStartup(winsockVers, &wsaData);
+  if (err) {
+    // TODO(jat): report error
+    Debug::log(Debug::Error) << "WSAStartup(vers=2.2): err=" << err << Debug::flush;
+  }
+#endif
+}
+
+bool Socket::connect(const char* host, int port) {
+  Debug::log(Debug::Debugging) << "Socket::connect(host=" << host << ",port=" << port << ")"
+      << Debug::flush;
+  if (isConnected()) {
+    Debug::log(Debug::Error) << "Socket::connect - already connected" << Debug::flush;
+    return false;
+  }
+
+  SOCKETTYPE fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+  if (fd < 0) {
+    Debug::log(Debug::Error) << "Socket::connect - can't get socket" << Debug::flush;
+    return false;
+  }
+#ifdef SO_NOSIGPIPE
+  // On BSD, we need to suppress the SIGPIPE if the remote end disconnects.
+  int option_value = 1;
+  if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &option_value, sizeof(int))) {
+    Debug::log(Debug::Error) << "Socket::connect - can't set NOSIGPIPE option" << Debug::flush;
+    return false;
+  }
+#endif
+
+  struct sockaddr_in sockAddr;
+  memset(&sockAddr, 0, static_cast<int>(sizeof(sockAddr)));
+  // check for numeric IP4 addresses first
+  // TODO(jat): handle IPv6 addresses
+  unsigned long numericAddr = inet_addr(host);
+  if (numericAddr != 0xFFFFFFFF) {
+    sockAddr.sin_addr.s_addr = numericAddr;
+    sockAddr.sin_family = AF_INET;
+  } else {
+    struct hostent* hent = gethostbyname(host);
+    if (!hent || !hent->h_addr_list[0]) {
+      Debug::log(Debug::Error) << "Unable to get address for " << host << Debug::flush;
+      return false;
+    }
+    memcpy(&(sockAddr.sin_addr), hent->h_addr_list[0], hent->h_length);
+    sockAddr.sin_family = hent->h_addrtype;
+  }
+  sockAddr.sin_port = htons(port);
+
+  if (::connect(fd, (struct sockaddr*) &sockAddr, sizeof(sockAddr)) < 0) {
+#ifdef _WINDOWS
+    char buf[256];
+    strerror_s(buf, sizeof(buf), errno);
+    Debug::log(Debug::Error) << "Can't connect to " << host << ":" << port << " -- "
+        << buf << Debug::flush;
+    closesocket(fd);
+#else
+    Debug::log(Debug::Error) << "Can't connect to " << host << ":" << port << " -- "
+        << strerror(errno) << Debug::flush;
+    close(fd);
+#endif
+    return false;
+  }
+  sock = fd;
+  connected = true;
+  readBufPtr = readValid = readBuf;
+  writeBufPtr = writeBuf;
+#ifdef _WINDOWS
+  Debug::log(Debug::Spam) << "  connected" << Debug::flush;
+#else
+  Debug::log(Debug::Spam) << "  connected, fd=" << fd << Debug::flush;
+#endif
+  return true;
+}
+
+bool Socket::disconnect(bool doFlush) {
+  if (connected) {
+    Debug::log(Debug::Debugging) << "Disconnecting socket" << Debug::flush;
+    if (doFlush) {
+      flush();
+    }
+    connected = false;
+#ifdef _WINDOWS
+    closesocket(sock);
+#else
+    shutdown(sock, SHUT_RDWR);
+    close(sock);
+#endif
+  }
+  return true;
+}
+  
+bool Socket::emptyWriteBuf() {
+  size_t len = writeBufPtr - writeBuf;
+  Debug::log(Debug::Spam) << "Socket::emptyWriteBuf: len=" << len << Debug::flush;
+  ++numWrites;
+  totWriteBytes += len;
+  if (len > maxWriteBytes) {
+    maxWriteBytes = len;
+  }
+  for (char* ptr = writeBuf; len > 0; ) {
+    ssize_t n = send(sock, ptr, len, 0);
+    if (n <= 0) {
+      if (errno == EPIPE) {
+        Debug::log(Debug::Warning) << "Other end of socket disconnected" << Debug::flush;
+        disconnect(false);
+        return false;
+      }
+      Debug::log(Debug::Error) << "Error " << errno << " writing " << len << " bytes to socket"
+          << Debug::flush;
+      return false;
+    }
+    ptr += n;
+    len -= n;
+  }
+  writeBufPtr = writeBuf;
+  return true;
+}
+  
+bool Socket::fillReadBuf() {
+  readBufPtr = readBuf;
+  errno = 0;
+  ssize_t n = recv(sock, readBuf, BUF_SIZE, 0);
+  if (n <= 0) {
+    // EOF results in no error
+    if (!errno || errno == EPIPE) {
+      Debug::log(Debug::Warning) << "Other end of socket disconnected" << Debug::flush;
+      disconnect(false);
+      return false;
+    }
+    Debug::log(Debug::Error) << "Error " << errno << " reading " << BUF_SIZE << " bytes from socket"
+        << Debug::flush;
+    return false;
+  }
+  ++numReads;
+  totReadBytes += n;
+  if (static_cast<size_t>(n) > maxReadBytes) {
+    maxReadBytes = n;
+  }
+  readValid = readBuf + n;
+  return true;
+}
diff --git a/plugins/common/Socket.h b/plugins/common/Socket.h
new file mode 100644
index 0000000..90298f6
--- /dev/null
+++ b/plugins/common/Socket.h
@@ -0,0 +1,170 @@
+#ifndef _H_Socket
+#define _H_Socket
+/*
+ * 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 "Platform.h"
+#include "Debug.h"
+
+#include <string>
+
+#ifdef _WINDOWS
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <sys/time.h>
+#endif
+
+/**
+ * Encapsulates platform dependencies regarding buffered sockets.
+ */
+class Socket {
+private:
+  // Buffer size, chosen to fit in a single packet after TCP/IP overhead.
+  static const int BUF_SIZE = 1400;
+  
+  // Can't rely on a sentinel value for the socket descriptor
+  bool connected;
+  
+  SOCKETTYPE sock;
+  
+  // Read buffer
+  char* readBuf;
+  
+  // One bye past end of valid data in readBuf
+  char* readValid;
+  
+  // Current read pointer
+  char* readBufPtr;
+
+  // Write buffer
+  char* writeBuf;
+  
+  // Current write pointer
+  char* writeBufPtr;
+
+  // Stats
+  unsigned long numReads;
+  unsigned long long totReadBytes;
+  size_t maxReadBytes;
+
+  unsigned long numWrites;
+  unsigned long long totWriteBytes;
+  size_t maxWriteBytes;
+
+private:
+  void init();
+  bool fillReadBuf();
+  bool emptyWriteBuf();
+
+public:
+  Socket() : connected(false), readBuf(new char[BUF_SIZE]), writeBuf(new char[BUF_SIZE]) {
+    readBufPtr = readValid = readBuf;
+    writeBufPtr = writeBuf;
+    numReads = numWrites = 0;
+    maxReadBytes = maxWriteBytes = 0;
+    totReadBytes = totWriteBytes = 0;
+    init();
+  }
+  
+  ~Socket() {
+    disconnect();
+#ifdef _WINDOWS
+    if (0) WSACleanup();
+#endif
+    // TODO(jat): LEAK LEAK LEAK
+    // delete[] readBuf;
+    // delete[] writeBuf;
+    Debug::log(Debug::Debugging) << "Socket: #r=" << numReads << ", bytes/read="
+        << (numReads ? totReadBytes / numReads : 0) << ", maxr=" << maxReadBytes << "; #w="
+        << numWrites << ", bytes/write=" << (numWrites ? totWriteBytes / numWrites : 0) << ", maxw="
+        << maxWriteBytes << Debug::flush;
+  }
+
+  /**
+   * Connects this socket to a specified port on a host.
+   * 
+   * @param host host name or IP address to connect to
+   * @param port TCP port to connect to
+   * @return true if the connection succeeds
+   */ 
+  bool connect(const char* host, int port);
+  
+  /**
+   * Returns true if the socket is connected.
+   */
+  bool isConnected() const {
+    return connected;
+  }
+  
+  /**
+   * Disconnect this socket.
+   * 
+   * @param doFlush true (the default value) if the socket should be flushed.
+   * @return true if disconnect succeeds
+   */
+  bool disconnect(bool doFlush = true);
+  
+  /**
+   * Read a single byte from the socket.
+   *
+   * @return -1 on error, otherwise unsigned byte read.
+   */
+  int readByte() {
+    if (readBufPtr >= readValid) {
+      if (!fillReadBuf()) {
+        return -1;
+      }
+    }
+    return static_cast<unsigned char>(*readBufPtr++);
+  }
+  
+  /**
+   * Write a single byte to the socket.
+   * 
+   * @return true on success.
+   */
+  bool writeByte(char c) {
+    if (writeBufPtr >= writeBuf + BUF_SIZE) {
+      if (!emptyWriteBuf()) {
+        return false;
+      }
+    }
+    *writeBufPtr++ = c;
+    return true;
+  }
+  
+  /**
+   * Flush any pending writes on the socket.
+   *
+   * @return true on success
+   */
+  bool flush() {
+    if (writeBufPtr > writeBuf) {
+      if (!emptyWriteBuf()) {
+        return false;
+      }
+    }
+    return true;
+  }
+};
+
+#endif
diff --git a/plugins/common/Value.h b/plugins/common/Value.h
new file mode 100644
index 0000000..4401893
--- /dev/null
+++ b/plugins/common/Value.h
@@ -0,0 +1,387 @@
+#ifndef _H_Value
+#define _H_Value
+/*
+ * 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.
+ */
+
+#ifndef _WINDOWS
+// TODO(jat): remove; for abort() which should probably go away
+#include <stdlib.h>
+#endif
+
+#include <string>
+
+#include "Debug.h"
+
+#include "BrowserChannel.h"
+
+class Value {
+public:
+  enum ValueType {
+    NULL_TYPE = VALUE_TYPE_NULL,
+    BOOLEAN = VALUE_TYPE_BOOLEAN,
+    BYTE = VALUE_TYPE_BYTE,
+    CHAR = VALUE_TYPE_CHAR,
+    SHORT = VALUE_TYPE_SHORT,
+    INT = VALUE_TYPE_INT,
+    LONG = VALUE_TYPE_LONG,
+    FLOAT = VALUE_TYPE_FLOAT,
+    DOUBLE = VALUE_TYPE_DOUBLE,
+    STRING = VALUE_TYPE_STRING,
+    JAVA_OBJECT = VALUE_TYPE_JAVA_OBJECT,
+    JS_OBJECT = VALUE_TYPE_JS_OBJECT,
+    UNDEFINED = VALUE_TYPE_UNDEFINED
+  };
+
+private:
+  ValueType type;
+  union {
+    bool  boolValue;
+    unsigned char byteValue;
+    unsigned short charValue;
+    double doubleValue;
+    float floatValue;
+    int32_t intValue;
+    int64_t longValue;
+    short shortValue;
+    std::string* stringValue;
+  } value;
+
+public:
+  Value() {
+    type = UNDEFINED;
+  }
+
+  Value(const Value& other) {
+    copyValue(other);
+  }
+
+  Value& operator=(const Value& other) {
+    clearOldValue();
+    copyValue(other);
+    return *this;
+  }
+
+  ~Value() {
+    clearOldValue();
+  }
+
+  bool getBoolean() const {
+    assertType(BOOLEAN);
+    return value.boolValue;
+  }
+
+  unsigned char getByte() const {
+    assertType(BYTE);
+    return value.byteValue;
+  }
+
+  unsigned short getChar() const {
+    assertType(CHAR);
+    return value.charValue;
+  }
+
+  double getDouble() const {
+    assertType(DOUBLE);
+    return value.doubleValue;
+  }
+
+  float getFloat() const {
+    assertType(FLOAT);
+    return value.floatValue;
+  }
+
+  int getInt() const {
+    assertType(INT);
+    return value.intValue;
+  }
+
+  int getJavaObjectId() const {
+    assertType(JAVA_OBJECT);
+    return value.intValue;
+  }
+
+  int getJsObjectId() const {
+    assertType(JS_OBJECT);
+    return value.intValue;
+  }
+
+  int64_t getLong() const {
+    assertType(LONG);
+    return value.longValue;
+  }
+
+  short getShort() const {
+    assertType(SHORT);
+    return value.shortValue;
+  }
+
+  const std::string getString() const {
+    assertType(STRING);
+    return std::string(*value.stringValue);
+  }
+
+  ValueType getType() const {
+    return type;
+  }
+
+  bool isBoolean() const {
+    return type == BOOLEAN;
+  }
+
+  bool isByte() const {
+    return type == BYTE;
+  }
+
+  bool isChar() const {
+    return type == CHAR;
+  }
+
+  bool isDouble() const {
+    return type == DOUBLE;
+  }
+
+  bool isFloat() const {
+    return type == FLOAT;
+  }
+
+  bool isInt() const {
+    return type == INT;
+  }
+
+  bool isJavaObject() const {
+    return type == JAVA_OBJECT;
+  }
+
+  bool isJsObject() const {
+    return type == JS_OBJECT;
+  }
+
+  bool isLong() const {
+    return type == LONG;
+  }
+
+  bool isNull() const {
+    return type == NULL_TYPE;
+  }
+
+  bool isNumber() const {
+    switch (type) {
+      case BYTE:
+      case CHAR:
+      case DOUBLE:
+      case FLOAT:
+      case INT:
+      case LONG:
+      case SHORT:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  bool isPrimitive() const {
+    switch (type) {
+      case BOOLEAN:
+      case BYTE:
+      case CHAR:
+      case DOUBLE:
+      case FLOAT:
+      case INT:
+      case LONG:
+      case SHORT:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  bool isShort() const {
+    return type == SHORT;
+  }
+
+  bool isString() const {
+    return type == STRING;
+  }
+
+  bool isUndefined() const {
+    return type == UNDEFINED;
+  }
+
+  void setBoolean(bool val) {
+    clearOldValue();
+    type = BOOLEAN;
+    value.boolValue = val;
+  }
+
+  void setByte(unsigned char val) {
+    clearOldValue();
+    type = BYTE;
+    value.byteValue = val;
+  }
+
+  void setChar(unsigned short val) {
+    clearOldValue();
+    type = CHAR;
+    value.charValue = val;
+  }
+
+  void setDouble(double val) {
+    clearOldValue();
+    type = DOUBLE;
+    value.doubleValue = val;
+  }
+
+  void setFloat(float val) {
+    clearOldValue();
+    type = FLOAT;
+    value.floatValue = val;
+  }
+
+  void setInt(int val) {
+    clearOldValue();
+    type = INT;
+    value.intValue = val;
+  }
+
+  void setJavaObject(int objectId) {
+    clearOldValue();
+    type = JAVA_OBJECT;
+    value.intValue = objectId;
+  }
+
+  void setJsObjectId(int val) {
+    clearOldValue();
+    type = JS_OBJECT;
+    value.intValue = val;
+  }
+
+  void setLong(int64_t val) {
+    clearOldValue();
+    type = LONG;
+    value.longValue = val;
+  }
+
+  void setNull() {
+    clearOldValue();
+    type = NULL_TYPE;
+  }
+
+  void setShort(short val) {
+    clearOldValue();
+    type = SHORT;
+    value.shortValue = val;
+  }
+
+  void setString(const char* chars, int len) {
+    setString(std::string(chars, len));
+  }
+
+  void setString(const std::string& val) {
+    clearOldValue();
+    type = STRING;
+    value.stringValue = new std::string(val);
+  }
+
+  void setUndefined() {
+    clearOldValue();
+    type = UNDEFINED;
+  }
+
+  std::string toString() const {
+    char buf[30];
+    switch (type) {
+      case NULL_TYPE:
+        return "null";
+      case BOOLEAN:
+        snprintf(buf, sizeof(buf), "boolean(%s)", getBoolean() ? "true"
+            : "false");
+        return std::string(buf);
+      case BYTE:
+        snprintf(buf, sizeof(buf), "byte(%d)", getByte());
+        return std::string(buf);
+      case CHAR:
+        snprintf(buf, sizeof(buf), "char(%d)", getChar());
+        return std::string(buf);
+      case SHORT:
+        snprintf(buf, sizeof(buf), "short(%d)", getShort());
+        return std::string(buf);
+      case INT:
+        snprintf(buf, sizeof(buf), "int(%d)", getInt());
+        return std::string(buf);
+      case LONG:
+        snprintf(buf, sizeof(buf), "long(%lld)",
+            static_cast<long long>(getLong()));
+        return std::string(buf);
+      case FLOAT:
+        snprintf(buf, sizeof(buf), "float(%f)", getFloat());
+        return std::string(buf);
+      case DOUBLE:
+        snprintf(buf, sizeof(buf), "double(%lf)", getDouble());
+        return std::string(buf);
+      case STRING:
+        snprintf(buf, sizeof(buf), "string(%.20s)", getString().c_str());
+        return std::string(buf);
+      case JAVA_OBJECT:
+        snprintf(buf, sizeof(buf), "JavaObj(%d)", getJavaObjectId());
+        return std::string(buf);
+      case JS_OBJECT:
+        snprintf(buf, sizeof(buf), "JsObj(%d)", getJsObjectId());
+        return std::string(buf);
+      case UNDEFINED:
+        return "undefined";
+      default:
+        return "Unknown type";
+    }
+  }
+
+private:
+  void assertType(ValueType reqType) const {
+    if (type != reqType) {
+      Debug::log(Debug::Error) << "Value::assertType - expecting type "
+          << int(reqType) << ", was " << int(type) << Debug::flush;
+      // TODO(jat): is this portable?  Should we do something else here?
+      abort();
+    }
+  }
+
+  void clearOldValue() {
+    if (type == STRING) {
+      delete value.stringValue;
+      type = UNDEFINED;
+    }
+  }
+
+  // Precondition: existing value, if any, has been cleared
+  void copyValue(const Value& other) {
+    type = other.type;
+    value = other.value;
+    // handle deep copies of value types that need it
+    switch (type) {
+      case STRING:
+        value.stringValue = new std::string(*value.stringValue);
+        break;
+      default:
+        // no other values need deep copies
+        break;
+    }
+  }
+};
+
+inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, const Value& val) {
+  return dbg << val.toString();
+}
+
+#endif
diff --git a/plugins/common/scoped_ptr/README.google b/plugins/common/scoped_ptr/README.google
new file mode 100644
index 0000000..d513e21
--- /dev/null
+++ b/plugins/common/scoped_ptr/README.google
@@ -0,0 +1,27 @@
+Description
+===========
+
+This is the scoped_ptr from Boost with some additions by Google.
+
+Homepage
+========
+
+http://www.boost.org/
+http://www.boost.org/libs/smart_ptr/scoped_ptr.htm
+
+License
+=======
+
+http://boost.org/LICENSE_1_0.txt
+
+Source files and modifications
+==============================
+
+scoped_ptr_malloc added in by Ray Sidney of Google.  When one of these goes
+out of scope, instead of doing a delete or delete[], it calls free().
+scoped_ptr_malloc<char> is likely to see much more use than any other
+specializations.
+
+release() added in by Spencer Kimball of Google. Use this to conditionally
+transfer ownership of a heap-allocated object to the caller, usually on
+method success.
diff --git a/plugins/common/scoped_ptr/scoped_ptr.h b/plugins/common/scoped_ptr/scoped_ptr.h
new file mode 100644
index 0000000..1ae1b96
--- /dev/null
+++ b/plugins/common/scoped_ptr/scoped_ptr.h
@@ -0,0 +1,364 @@
+#ifndef SCOPED_PTR_H
+#define SCOPED_PTR_H
+
+// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+// Copyright (c) 2001, 2002 Peter Dimov
+// 
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+//  See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation.
+//
+//
+//  scoped_ptr mimics a built-in pointer except that it guarantees deletion
+//  of the object pointed to, either on destruction of the scoped_ptr or via
+//  an explicit reset(). scoped_ptr is a simple solution for simple needs;
+//  use shared_ptr if your needs are more complex.
+//
+//  *** NOTE ***
+//  If your scoped_ptr is a class member of class FOO pointing to a 
+//  forward declared type BAR (as shown below), then at creation (and 
+//  destruction) of an object of type FOO, BAR must be complete.  You can do
+//  this by either:
+//   - Making all FOO constructors and destructors non-inlined to FOO's class
+//     definition, instead placing them in foo.cc below an include of bar.h
+//   - Including bar.h before any creation or destruction of any object of
+//     type FOO
+//  The former is probably the less error-prone method, as shown below.
+//
+//  Example:
+//
+//  -- foo.h --
+//  class BAR;
+//
+//  class FOO {
+//   public:
+//    FOO();   // Required for sources that instantiate class FOO to compile!
+//    ~FOO();  // Required for sources that instantiate class FOO to compile!
+//    
+//   private:
+//    scoped_ptr<BAR> bar_;
+//  };
+//
+//  -- foo.cc --
+//  #include "bar.h"
+//  #include "foo.h"
+//  FOO::FOO() {}  // Empty, but must be non-inlined to FOO's class definition.
+//  FOO::~FOO() {} // Empty, but must be non-inlined to FOO's class definition.
+//
+//  scoped_ptr_malloc added in by Ray Sidney of Google.  When one of
+//  these goes out of scope, instead of doing a delete or delete[], it
+//  calls free().  scoped_ptr_malloc<char> is likely to see much more
+//  use than any other specializations.
+//
+//  release() added in by Spencer Kimball of Google. Use this to conditionally
+//  transfer ownership of a heap-allocated object to the caller, usually on
+//  method success.
+
+#include <cstddef>            // for std::ptrdiff_t
+#include <assert.h>           // for assert
+#include <stdlib.h>           // for free() decl
+
+template <typename T>
+class scoped_ptr;
+
+template <typename T>
+class scoped_ptr {
+ private:
+
+  T* ptr;
+
+  // scoped_ptr's must not be copied.  We make sure of that by making the
+  // copy constructor prototype private.  At the same time, there is no body
+  // for this constructor.  Thus, if anything that has access to private
+  // members of scoped_ptr ever (inadvertently) copies a scoped_ptr, the
+  // linker will complain about missing symbols.  This is a good thing!
+  scoped_ptr(scoped_ptr const &);
+  scoped_ptr & operator=(scoped_ptr const &);
+
+ public:
+
+  typedef T element_type;
+
+  explicit scoped_ptr(T* p = 0): ptr(p) {}
+
+  ~scoped_ptr() {
+    typedef char type_must_be_complete[sizeof(T)];
+    delete ptr;
+  }
+
+  void reset(T* p = 0) {
+    typedef char type_must_be_complete[sizeof(T)];
+
+    if (ptr != p) {
+      delete ptr;
+      ptr = p;
+    }
+  }
+
+  T& operator*() const {
+    assert(ptr != 0);
+    return *ptr;
+  }
+
+  T* operator->() const  {
+    assert(ptr != 0);
+    return ptr;
+  }
+
+  bool operator==(T* p) const {
+    return ptr == p;
+  }
+
+  bool operator!=(T* p) const {
+    return ptr != p;
+  }
+
+  T* get() const  {
+    return ptr;
+  }
+
+  void swap(scoped_ptr & b) {
+    T* tmp = b.ptr;
+    b.ptr = ptr;
+    ptr = tmp;
+  }
+
+  T* release() {
+    T* tmp = ptr;
+    ptr = 0;
+    return tmp;
+  }
+
+ private:
+
+  // no reason to use these: each scoped_ptr should have its own object
+  template <typename U> bool operator==(scoped_ptr<U> const& p) const;
+  template <typename U> bool operator!=(scoped_ptr<U> const& p) const;
+};
+
+template<typename T> inline
+void swap(scoped_ptr<T>& a, scoped_ptr<T>& b) {
+  a.swap(b);
+}
+
+template<typename T> inline
+bool operator==(T* p, const scoped_ptr<T>& b) {
+  return p == b.get();
+}
+
+template<typename T> inline
+bool operator!=(T* p, const scoped_ptr<T>& b) {
+  return p != b.get();
+}
+
+//  scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
+//  is guaranteed, either on destruction of the scoped_array or via an explicit
+//  reset(). Use shared_array or std::vector if your needs are more complex.
+
+template<typename T>
+class scoped_array {
+ private:
+
+  T* ptr;
+
+  scoped_array(scoped_array const &);
+  scoped_array & operator=(scoped_array const &);
+
+ public:
+
+  typedef T element_type;
+
+  explicit scoped_array(T* p = 0) : ptr(p) {}
+
+  ~scoped_array() {
+    typedef char type_must_be_complete[sizeof(T)];
+    delete[] ptr;
+  }
+
+  void reset(T* p = 0) {
+    typedef char type_must_be_complete[sizeof(T)];
+
+    if (ptr != p) {
+      delete [] ptr;
+      ptr = p;
+    }
+  }
+
+  T& operator[](std::ptrdiff_t i) const {
+    assert(ptr != 0);
+    assert(i >= 0);
+    return ptr[i];
+  }
+
+  bool operator==(T* p) const {
+    return ptr == p;
+  }
+
+  bool operator!=(T* p) const {
+    return ptr != p;
+  }
+
+  T* get() const {
+    return ptr;
+  }
+
+  void swap(scoped_array & b) {
+    T* tmp = b.ptr;
+    b.ptr = ptr;
+    ptr = tmp;
+  }
+
+  T* release() {
+    T* tmp = ptr;
+    ptr = 0;
+    return tmp;
+  }
+
+ private:
+
+  // no reason to use these: each scoped_array should have its own object
+  template <typename U> bool operator==(scoped_array<U> const& p) const;
+  template <typename U> bool operator!=(scoped_array<U> const& p) const;
+};
+
+template<class T> inline
+void swap(scoped_array<T>& a, scoped_array<T>& b) {
+  a.swap(b);
+}
+
+template<typename T> inline
+bool operator==(T* p, const scoped_array<T>& b) {
+  return p == b.get();
+}
+
+template<typename T> inline
+bool operator!=(T* p, const scoped_array<T>& b) {
+  return p != b.get();
+}
+
+
+// This class wraps the c library function free() in a class that can be
+// passed as a template argument to scoped_ptr_malloc below.
+class ScopedPtrMallocFree {
+ public:
+  inline void operator()(void* x) const {
+    free(x);
+  }
+};
+
+// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
+// second template argument, the functor used to free the object.
+
+template<typename T, typename FreeProc = ScopedPtrMallocFree>
+class scoped_ptr_malloc {
+ private:
+
+  T* ptr;
+
+  scoped_ptr_malloc(scoped_ptr_malloc const &);
+  scoped_ptr_malloc & operator=(scoped_ptr_malloc const &);
+
+ public:
+
+  typedef T element_type;
+
+  explicit scoped_ptr_malloc(T* p = 0): ptr(p) {}
+
+  ~scoped_ptr_malloc() {
+    typedef char type_must_be_complete[sizeof(T)];
+    free_((void*) ptr);
+  }
+
+  void reset(T* p = 0) {
+    typedef char type_must_be_complete[sizeof(T)];
+
+    if (ptr != p) {
+      free_((void*) ptr);
+      ptr = p;
+    }
+  }
+
+  T& operator*() const {
+    assert(ptr != 0);
+    return *ptr;
+  }
+
+  T* operator->() const {
+    assert(ptr != 0);
+    return ptr;
+  }
+
+  bool operator==(T* p) const {
+    return ptr == p;
+  }
+
+  bool operator!=(T* p) const {
+    return ptr != p;
+  }
+
+  T* get() const {
+    return ptr;
+  }
+
+  void swap(scoped_ptr_malloc & b) {
+    T* tmp = b.ptr;
+    b.ptr = ptr;
+    ptr = tmp;
+  }
+
+  T* release() {
+    T* tmp = ptr;
+    ptr = 0;
+    return tmp;
+  }
+
+ private:
+
+  // no reason to use these: each scoped_ptr_malloc should have its own object
+  template <typename U, typename GP>
+  bool operator==(scoped_ptr_malloc<U, GP> const& p) const;
+  template <typename U, typename GP>
+  bool operator!=(scoped_ptr_malloc<U, GP> const& p) const;
+
+  static FreeProc const free_;
+};
+
+template<typename T, typename FP>
+FP const scoped_ptr_malloc<T,FP>::free_ = FP();
+
+template<typename T, typename FP> inline
+void swap(scoped_ptr_malloc<T,FP>& a, scoped_ptr_malloc<T,FP>& b) {
+  a.swap(b);
+}
+
+template<typename T, typename FP> inline
+bool operator==(T* p, const scoped_ptr_malloc<T,FP>& b) {
+  return p == b.get();
+}
+
+template<typename T, typename FP> inline
+bool operator!=(T* p, const scoped_ptr_malloc<T,FP>& b) {
+  return p != b.get();
+}
+
+#endif  // #ifndef SCOPED_PTR_H
diff --git a/plugins/common/testing/DebugTest.cpp b/plugins/common/testing/DebugTest.cpp
new file mode 100644
index 0000000..add1357
--- /dev/null
+++ b/plugins/common/testing/DebugTest.cpp
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+// This file exists to verify that the debugging code leaves nothing
+// behind when disabled or at an appropriate level.
+//
+// Compile with, for example, g++ -O3 -D* -S DebugTest.cpp and inspect the DebugTest.s file.
+//   where * is GWT_DEBUGDISABLE or GWT_DEBUGLEVEL=Spam (etc)
+//
+// testdebug is a shell script to automate this test
+
+// #define GWT_DEBUGDISABLE
+// #define GWT_DEBUGLEVEL Info
+
+#include "../Debug.h"
+
+void foo(int i) {
+  Debug::log(Debug::Error) << "Error GarbalDeGook" << i << Debug::flush;
+  Debug::log(Debug::Warning) << "Warning GarbalDeGook" << i << Debug::flush;
+  Debug::log(Debug::Info) << "Info GarbalDeGook" << i << Debug::flush;
+  Debug::log(Debug::Debugging) << "Debugging GarbalDeGook" << i << Debug::flush;
+  Debug::log(Debug::Spam) << "Spam GarbalDeGook" << i << Debug::flush;
+  if (Debug::level(Debug::Spam)) {
+    extern int ExpensiveCall();
+    Debug::log(Debug::Spam) << "Filtered spam GarbalDeGook" << ExpensiveCall() << Debug::flush;
+  }
+}
diff --git a/plugins/common/testing/testdebug b/plugins/common/testing/testdebug
new file mode 100755
index 0000000..e2e8ea4
--- /dev/null
+++ b/plugins/common/testing/testdebug
@@ -0,0 +1,61 @@
+#!/bin/sh
+# 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.
+
+# this verifies that debug code is elided if it is not needed
+
+# The C++ compiler is specified in CXX, and its flags in CXXFLAGS
+# Defaults for GCC are used if not supplied.  Note that CXXFLAGS should
+# include optimizations intended to be used.  It is assumed that the
+# compiler uses -S to produce assembly output and -o - works to get that
+# output on stdout, and -Dsym=val is used to define preprocessor symbols.
+#
+# Note that debugging symbols should not be included as generally the
+# debugging info contains references to elided calls etc.
+if [ "x$CXX" == "x" ]
+then
+  CXX=g++
+fi
+
+if [ "x$CXXFLAGS" == "x" ]
+then
+  CXXFLAGS=-O3
+else
+  # remove -g if supplied
+  CXXFLAGS=`echo $CXXFLAGS | sed 's/-g\S*//'`
+fi
+
+CMD="$CXX $CXXFLAGS -S -o -"
+
+err=0
+$CMD -DGWT_DEBUGDISABLE DebugTest.cpp | egrep '(GarbalDeGook|ExpensiveCall)' >/dev/null
+if [ $? -eq 0 ]
+then
+  echo "Debug disabled leaves debug code around"
+  err=1
+fi
+$CMD -DGWT_DEBUGLEVEL=Error DebugTest.cpp | egrep '(Warning|ExpensiveCall)' >/dev/null
+if [ $? -eq 0 ]
+then
+  echo "Debug level Error leaves lower-level debug code around"
+  err=1
+fi
+$CMD -DGWT_DEBUGLEVEL=Spam DebugTest.cpp | grep 'ExpensiveCall' >/dev/null
+if [ $? -eq 1 ]
+then
+  echo "Debug level Spam does not include code that should be included"
+  err=1
+fi
+
+exit $err
diff --git a/plugins/config.mk b/plugins/config.mk
new file mode 100644
index 0000000..2f1fcb9
--- /dev/null
+++ b/plugins/config.mk
@@ -0,0 +1,81 @@
+# Copyright 2009 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.
+
+# This Makefile fragment sets the following make variables according to the
+# current platform:
+#   ARCH - the Mozilla architecture name, such as x86, x86_64, ppc, etc
+#   FLAG32BIT - 32 or 64
+#   MARCH - the Mac architecture, such as i386 or ppc
+#   OS - linux, mac, or sun
+#   CFLAGS - appropriate C compiler flags for this platform
+#   CXXFLAGS - appropriate C++ compiler flags for this platform
+# Also, various stanard make variables are overridden if necessary, such as AR
+#
+# If ARCH is already set, that is used instead of uname -m to get the
+# architecture to build.  This can be used to build a 32-bit plugin on a 64-bit
+# platform, for example: make ARCH=x86
+
+ARCH ?= $(shell uname -m)
+
+# default is 32 bits
+FLAG32BIT=32
+
+# Figure out 64-bit platforms, canonicalize ARCH and MARCH
+ifeq ($(ARCH),x86_64)
+FLAG32BIT=64
+else ifeq ($(ARCH),sparc)
+FLAG32BIT=64
+else ifeq ($(ARCH),alpha)
+FLAG32BIT=64
+else ifeq ($(ARCH),ia64)
+FLAG32BIT=64
+else ifeq ($(ARCH),athlon)
+ARCH=x86
+else ifeq ($(ARCH),i386)
+ARCH=x86
+else ifeq ($(ARCH),i486)
+ARCH=x86
+else ifeq ($(ARCH),i586)
+ARCH=x86
+else ifeq ($(ARCH),i686)
+ARCH=x86
+else ifeq ($(ARCH),i86pc)
+ARCH=x86
+else ifeq ($(ARCH),Macintosh)
+ARCH=ppc
+endif
+MARCH=$(ARCH)
+ifeq ($(ARCH),x86)
+MARCH=i386
+endif
+
+# Set OS as well as CFLAGS, CXX, and other common make variables
+ifeq ($(shell uname),Linux)
+OS=linux
+CFLAGS= -g -O2 -fPIC $(INC) -rdynamic -m$(FLAG32BIT)
+else ifeq ($(shell uname),Darwin)
+OS=mac
+CFLAGS= -g -O2 -fPIC $(INC) -D__mac -arch $(MARCH)
+AR=libtool
+ARFLAGS=-static -o
+else ifeq ($(shell uname),SunOS)
+OS=sun
+#CFLAGS=-fast -g0 -Kpic $(INC) -Bdynamic -noex
+# SunC appears to miscompile Socket::writeByte by not incrementing the
+# buffer pointer, so no optimization for now
+#CFLAGS=-g -Kpic $(INC) -Bdynamic -noex
+CFLAGS= -g0 -Kpic -noex -xO1 -xlibmil -xlibmopt -features=tmplife -xbuiltin=%all -mt $(INC)
+CXX= CC
+endif
+CXXFLAGS = $(CFLAGS)
diff --git a/plugins/ie/build.xml b/plugins/ie/build.xml
new file mode 100755
index 0000000..4c8a99d
--- /dev/null
+++ b/plugins/ie/build.xml
@@ -0,0 +1,18 @@
+<project name="ie" default="build" basedir=".">
+	<property name="plugin.root" value="ie" />
+	<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/ie" />
+		<copy todir="${gwt.build.out}/plugins/ie">
+			<fileset file="prebuilt/oophm.dll" />
+		</copy>
+	</target>
+
+	<target name="test" description="Run any tests">
+	</target>
+
+	<target name="checkstyle" description="Static style analysis">
+	</target>
+</project>
diff --git a/plugins/ie/oophm/oophm.sln b/plugins/ie/oophm/oophm.sln
new file mode 100644
index 0000000..e5d9fea
--- /dev/null
+++ b/plugins/ie/oophm/oophm.sln
@@ -0,0 +1,20 @@
+

+Microsoft Visual Studio Solution File, Format Version 10.00

+# Visual Studio 2008

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "oophm", "oophm\oophm.vcproj", "{EB69BDFE-9380-4C51-99E8-C3EB25AE36A2}"

+EndProject

+Global

+	GlobalSection(SolutionConfigurationPlatforms) = preSolution

+		Debug|Win32 = Debug|Win32

+		Release|Win32 = Release|Win32

+	EndGlobalSection

+	GlobalSection(ProjectConfigurationPlatforms) = postSolution

+		{EB69BDFE-9380-4C51-99E8-C3EB25AE36A2}.Debug|Win32.ActiveCfg = Debug|Win32

+		{EB69BDFE-9380-4C51-99E8-C3EB25AE36A2}.Debug|Win32.Build.0 = Debug|Win32

+		{EB69BDFE-9380-4C51-99E8-C3EB25AE36A2}.Release|Win32.ActiveCfg = Release|Win32

+		{EB69BDFE-9380-4C51-99E8-C3EB25AE36A2}.Release|Win32.Build.0 = Release|Win32

+	EndGlobalSection

+	GlobalSection(SolutionProperties) = preSolution

+		HideSolutionNode = FALSE

+	EndGlobalSection

+EndGlobal

diff --git a/plugins/ie/oophm/oophm/ExceptionCatcher.cpp b/plugins/ie/oophm/oophm/ExceptionCatcher.cpp
new file mode 100644
index 0000000..44d9ff9
--- /dev/null
+++ b/plugins/ie/oophm/oophm/ExceptionCatcher.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+// ExceptionCatcher.cpp : Implementation of CExceptionCatcher
+
+#include "stdafx.h"
+#include "Debug.h"
+#include "ExceptionCatcher.h"
+
+// CExceptionCatcher
+
+
+STDMETHODIMP CExceptionCatcher::getException(VARIANT* retVal)
+{
+  *retVal = caughtException.GetVARIANT();
+  return S_OK;
+}
+
+STDMETHODIMP CExceptionCatcher::hasSeenException(BOOL* retVal) {
+  *retVal = hasCaughtException;
+  return S_OK;
+}
+
+STDMETHODIMP CExceptionCatcher::CanHandleException(EXCEPINFO* exInfo, VARIANT* value) {
+  Debug::log(Debug::Debugging) << "Caught an exception from JS function" << Debug::flush;
+  if (hasCaughtException) {
+    Debug::log(Debug::Spam) << "Double-catching exception" << Debug::flush;
+    // We see this if a COM object that called a JavaObject doesn't recognize the
+    // throwing-exception return code; just keep the first exception that we've
+    // seen.
+    return S_OK;
+  }
+  caughtException = value;
+  hasCaughtException = true;
+  return S_OK;
+}
+
+STDMETHODIMP CExceptionCatcher::QueryService(const GUID& guidService, const IID& riid, void** ret) {
+  Debug::log(Debug::Spam) << "QueryService not supported by ExceptionCatcher" << Debug::flush;
+  return E_NOTIMPL;
+}
diff --git a/plugins/ie/oophm/oophm/ExceptionCatcher.h b/plugins/ie/oophm/oophm/ExceptionCatcher.h
new file mode 100644
index 0000000..c1a091c
--- /dev/null
+++ b/plugins/ie/oophm/oophm/ExceptionCatcher.h
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+// ExceptionCatcher.h : Declaration of the CExceptionCatcher
+
+#pragma once
+#include "resource.h"       // main symbols
+#include "comutil.h"
+#include "dispex.h"
+#include "oophm_i.h"
+
+
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
+#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
+#endif
+
+
+
+// CExceptionCatcher
+
+class ATL_NO_VTABLE CExceptionCatcher :
+	public CComObjectRootEx<CComSingleThreadModel>,
+	public CComCoClass<CExceptionCatcher, &CLSID_ExceptionCatcher>,
+  public ICanHandleException,
+  public IServiceProvider,
+	public IDispatchImpl<IExceptionCatcher, &IID_IExceptionCatcher, &LIBID_oophmLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
+{
+public:
+	CExceptionCatcher()
+	{
+	}
+
+DECLARE_REGISTRY_RESOURCEID(IDR_EXCEPTIONCATCHER)
+
+
+BEGIN_COM_MAP(CExceptionCatcher)
+  COM_INTERFACE_ENTRY(ICanHandleException)
+  COM_INTERFACE_ENTRY(IServiceProvider)
+	COM_INTERFACE_ENTRY(IExceptionCatcher)
+	COM_INTERFACE_ENTRY(IDispatch)
+END_COM_MAP()
+
+
+
+	DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+	HRESULT FinalConstruct()
+	{
+    hasCaughtException = false;
+		return S_OK;
+	}
+
+	void FinalRelease()
+	{
+	}
+
+public:
+  STDMETHOD(getException)(VARIANT* retVal);
+  STDMETHOD(hasSeenException)(BOOL* ret);
+  STDMETHOD(CanHandleException)(EXCEPINFO* exInfo, VARIANT* value);
+  STDMETHOD(QueryService)(const GUID& guidService, const IID& riid, void** ret);
+private:
+  _variant_t caughtException;
+  bool hasCaughtException;
+};
+
+OBJECT_ENTRY_AUTO(__uuidof(ExceptionCatcher), CExceptionCatcher)
diff --git a/plugins/ie/oophm/oophm/ExceptionCatcher.rgs b/plugins/ie/oophm/oophm/ExceptionCatcher.rgs
new file mode 100644
index 0000000..a2b759f
--- /dev/null
+++ b/plugins/ie/oophm/oophm/ExceptionCatcher.rgs
@@ -0,0 +1,26 @@
+HKCR

+{

+	oophm.ExceptionCatcher.1 = s 'ExceptionCatcher Class'

+	{

+		CLSID = s '{1A2A78F4-B5A4-4208-B520-BDDA0A7EC5CB}'

+	}

+	oophm.ExceptionCatcher = s 'ExceptionCatcher Class'

+	{

+		CLSID = s '{1A2A78F4-B5A4-4208-B520-BDDA0A7EC5CB}'

+		CurVer = s 'oophm.ExceptionCatcher.1'

+	}

+	NoRemove CLSID

+	{

+		ForceRemove {1A2A78F4-B5A4-4208-B520-BDDA0A7EC5CB} = s 'ExceptionCatcher Class'

+		{

+			ProgID = s 'oophm.ExceptionCatcher.1'

+			VersionIndependentProgID = s 'oophm.ExceptionCatcher'

+			ForceRemove 'Programmable'

+			InprocServer32 = s '%MODULE%'

+			{

+				val ThreadingModel = s 'Apartment'

+			}

+			'TypeLib' = s '{9259F105-BE55-4BF6-B7CE-D0AA878C1BA6}'

+		}

+	}

+}

diff --git a/plugins/ie/oophm/oophm/IESessionHandler.cpp b/plugins/ie/oophm/oophm/IESessionHandler.cpp
new file mode 100644
index 0000000..9c08363
--- /dev/null
+++ b/plugins/ie/oophm/oophm/IESessionHandler.cpp
@@ -0,0 +1,438 @@
+/*
+ * 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 "stdafx.h"
+#include "comutil.h"
+#include "dispex.h"
+#include "ExceptionCatcher.h"
+#include "IESessionHandler.h"
+#include "ServerMethods.h"
+#include "scoped_ptr/scoped_ptr.h"
+
+IESessionHandler::IESessionHandler(HostChannel* channel,
+                                   IHTMLWindow2* window) : SessionData(channel, window, this), jsObjectId(1)
+{
+  window->put_defaultStatus(L"GWT OOPHM Plugin active");
+}
+
+IESessionHandler::~IESessionHandler(void) {
+  Debug::log(Debug::Debugging) << "Destroying session handler" << Debug::flush;
+
+  Debug::log(Debug::Spam) << jsObjectsById.size() << " active JS object referances" << Debug::flush;
+
+  // Put any remaining JavaObject references into zombie-mode in case
+  // of lingering references
+  Debug::log(Debug::Spam) << javaObjectsById.size() << " active Java object referances" << Debug::flush;
+  std::map<int, IUnknown*>::iterator it = javaObjectsById.begin();
+  while (it != javaObjectsById.end()) {
+    ((CJavaObject*)it->second)->shutdown();
+    it++;
+  }
+
+  channel->disconnectFromHost();
+}
+void IESessionHandler::freeJavaObject(unsigned int objId) {
+  // Remove the now-defunt object from the lookup table
+  javaObjectsById.erase(objId);
+
+  // and add it to the set of objects to free on the server
+  javaObjectsToFree.insert(objId);
+}
+
+void IESessionHandler::freeJavaObjects() {
+  int idCount = javaObjectsToFree.size();
+  if (idCount == 0) {
+    return;
+  }
+
+  Debug::log(Debug::Debugging) << "Freeing " << idCount << " Java objects on server" << Debug::flush;
+  scoped_array<int> ids(new int[idCount]);
+
+  std::set<int>::iterator it = javaObjectsToFree.begin();
+  for (int i = 0; it != javaObjectsToFree.end(); it++) {
+    ids[i++] = *it;
+  }
+
+  if (!ServerMethods::freeJava(*channel, this, idCount, ids.get())) {
+    Debug::log(Debug::Error) << "Unable to free Java ids on server" << Debug::flush;
+  }
+  javaObjectsToFree.clear();
+}
+
+void IESessionHandler::freeValue(HostChannel& channel, int idCount, const int* ids) {
+  for (int i = 0; i < idCount; i++) {
+    int jsId = ids[i];
+    std::map<int, CComPtr<IUnknown>>::iterator it = jsObjectsById.find(jsId);
+    if (it == jsObjectsById.end()) {
+      Debug::log(Debug::Error) << "Trying to free unknown js id " << jsId << Debug::flush;
+      continue;
+    }
+    jsIdsByObject.erase(it->second);
+    jsObjectsById.erase(it);
+  }
+  Debug::log(Debug::Debugging) << "Freed " << idCount << " JS objects" << Debug::flush;
+}
+
+bool IESessionHandler::invoke(HostChannel& channel, const Value& thisObj,
+                               const std::string& methodName, int numArgs,
+                               const Value* const args, Value* returnValue)
+{
+  Debug::log(Debug::Debugging) << "Executing method " << methodName << " on object " << thisObj.toString() << Debug::flush;
+
+  HRESULT res;
+
+  // Get the function off of the window
+  DISPID methodDispId;
+  _bstr_t methodNameBstr = UTF8ToBSTR(methodName.length(), methodName.c_str());
+  res = window->GetIDsOfNames(IID_NULL, &methodNameBstr.GetBSTR(), 1,
+    LOCALE_SYSTEM_DEFAULT, &methodDispId);
+  if (res) {
+    Debug::log(Debug::Error) << "Unable to find method " << methodName << " on the window object" <<Debug::flush;
+    makeExceptionValue(*returnValue, "Unable to find named method on window");
+    return true;
+  }
+
+  // Get the JS Function object as an IDispatch
+  // TODO try PROPERTYGET|EXECUTE instead?
+  _variant_t functionObject;
+  DISPPARAMS disparamsNoArgs = {NULL, NULL, 0, 0};
+  res = window->Invoke(methodDispId, IID_NULL, LOCALE_SYSTEM_DEFAULT,
+    DISPATCH_PROPERTYGET, &disparamsNoArgs, functionObject.GetAddress(), NULL, NULL);
+  if (res) {
+    Debug::log(Debug::Error) << "Unable to get method " << methodName << Debug::flush;
+    makeExceptionValue(*returnValue, "Unable to get method from window");
+    return true;
+  } else if (functionObject.vt != VT_DISPATCH) {
+    Debug::log(Debug::Error) << "Did not get a VT_DISPATCH, got " << functionObject.vt << Debug::flush;
+    makeExceptionValue(*returnValue, "Did not get a VT_DISPATCH");
+    return true;
+  }
+
+  // See if it's an IDispatchEx
+  CComPtr<IDispatchEx> ex;
+  if (functionObject.pdispVal->QueryInterface(&ex)) {
+    // Probably not a function
+    Debug::log(Debug::Error) << "Failed to invoke " << methodName << " which is not an IDispatchEx" << Debug::flush;
+    makeExceptionValue(*returnValue, "Unable to invoke method");
+    return true;
+  }
+
+  // Convert the function arguments
+  // The parameters in the DISPARAMS are backwards
+  // Named parameters are first
+  int jsArgsLen = numArgs + 1;
+  scoped_array<_variant_t> jsargs(new _variant_t[jsArgsLen]);
+  DISPID thisId[] = {DISPID_THIS};
+  makeValueRef(jsargs[0], thisObj);
+  for (int i = 0; i < numArgs; i++) {
+    makeValueRef(jsargs[jsArgsLen - 1 - i], args[i]);
+  }
+  DISPPARAMS callDispParams = {jsargs.get(), thisId, numArgs + 1, 1};
+  EXCEPINFO excepInfo;
+  _variant_t retVal;
+  CComPtr<IExceptionCatcher> catcher;
+  CExceptionCatcher::CreateInstance(&catcher);
+
+  CComPtr<IServiceProvider> serviceProvider;
+  catcher->QueryInterface(&serviceProvider);
+  res = ex->InvokeEx(DISPID_VALUE, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,
+    &callDispParams, retVal.GetAddress(), &excepInfo, serviceProvider);
+
+  // There are cases where an exception was thrown and we've caught it, but
+  // the return value from InvokeEx is still S_OK.  Thus, we check our
+  // ExceptionCatcher before using the res value to determine failure.
+  BOOL exceptionFlag = false;
+  catcher->hasSeenException(&exceptionFlag);
+  if (exceptionFlag) {
+    VARIANT exceptionVariant;
+    catcher->getException(&exceptionVariant);
+    _variant_t exception(exceptionVariant);
+
+    makeValue(*returnValue, exception);
+    exceptionFlag = true;
+
+  } else if (!SUCCEEDED(res)) {
+    makeExceptionValue(*returnValue, "Unknown failure");
+    exceptionFlag = true;
+
+  } else {
+    // Success
+    makeValue(*returnValue, retVal);
+  }
+
+  // Free previously-collected Java ids on the server to enable re-use
+  freeJavaObjects();
+  return exceptionFlag != 0;
+}
+
+bool IESessionHandler::invokeSpecial(HostChannel& channel, SpecialMethodId method, int numArgs,
+                                     const Value* const args, Value* returnValue)
+{
+  Debug::log(Debug::Error) << "InvokeSpecial is currently unimplemented" << Debug::flush;
+  makeExceptionValue(*returnValue, "InvokeSpecial is currently unimplemented");
+  return true;
+}
+
+void IESessionHandler::loadJsni(HostChannel& channel, const std::string& js) {
+  Debug::log(Debug::Spam) << "loadJsni " << js << Debug::flush;
+
+  _bstr_t code = UTF8ToBSTR(js.length(), js.c_str());
+  _bstr_t language = UTF8ToBSTR(10, "JavaScript");
+  _variant_t retVal;
+  Value toReturn;
+
+  HRESULT res = window->execScript(code, language, retVal.GetAddress());
+  if (!SUCCEEDED(res)) {
+    Debug::log(Debug::Error) << "Unable to evaluate JSNI code" << Debug::flush;
+  }
+}
+
+void IESessionHandler::makeException(_variant_t& in, const char* message) {
+  Debug::log(Debug::Debugging) << "Creating exception variant " << std::string(message) << Debug::flush;
+  HRESULT res;
+  DISPID dispId;
+  LPOLESTR error = L"Error";
+  res = window->GetIDsOfNames(IID_NULL, &error, 1, LOCALE_SYSTEM_DEFAULT, &dispId);
+
+  DISPPARAMS emptyParams = {NULL, NULL, 0, 0};
+  _variant_t errorConstructor;
+  res = window->Invoke(dispId, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET,
+    &emptyParams, errorConstructor.GetAddress(), NULL, NULL);
+  if (res) {
+    Debug::log(Debug::Error) << "Unable to get Error constructor" << Debug::flush;
+    in.SetString("Unable to get Error constructor");
+  }
+
+  CComPtr<IDispatchEx> ex;
+  res = errorConstructor.pdispVal->QueryInterface(&ex);
+  if (res) {
+    Debug::log(Debug::Error) << "Error constructor not IDispatchEx" << Debug::flush;
+    in.SetString("Error constructor not IDispatchEx");
+  }
+
+  _variant_t param = _variant_t(message);
+  DISPPARAMS dispParams = {&param, NULL, 1, 0};
+
+  res = ex->InvokeEx(DISPID_VALUE, LOCALE_SYSTEM_DEFAULT, DISPATCH_CONSTRUCT,
+    &dispParams, in.GetAddress(), NULL, NULL);
+
+  if (res) {
+    Debug::log(Debug::Error) << "Unable to invoke Error constructor" << Debug::flush;
+    in.SetString("Unable to invoke Error constructor");
+  }
+}
+
+void IESessionHandler::makeExceptionValue(Value& in, const char* message) {
+  Debug::log(Debug::Debugging) << "Creating exception value " << std::string(message) << Debug::flush;
+  _variant_t exception;
+  makeException(exception, message);
+  makeValue(in, exception);
+}
+
+void IESessionHandler::makeValue(Value& retVal, const _variant_t& value) {
+  CComPtr<IDispatch> dispObj;
+  CComPtr<IJavaObject> javaObject;
+
+  switch (value.vt) {
+    case VT_EMPTY:
+      retVal.setUndefined();
+      break;
+
+    case VT_NULL:
+      retVal.setNull();
+      break;
+
+    case VT_BOOL:
+      retVal.setBoolean(VARIANT_TRUE == value.boolVal);
+      break;
+
+    case VT_BSTR:
+      retVal.setString(BSTRToUTF8(value.bstrVal));
+      break;
+
+    case VT_I4:
+      retVal.setInt(value.lVal);
+      break;
+
+    case VT_I8:
+      retVal.setLong(value.llVal);
+      break;
+
+    case VT_R4:
+      retVal.setFloat(value.fltVal);
+      break;
+
+    case VT_R8:
+      retVal.setDouble(value.dblVal);
+      break;
+
+    case VT_DISPATCH:
+      dispObj = value.pdispVal;
+
+      if (!dispObj) {
+        // XXX Determine if this is normal operation
+        retVal.setUndefined();
+
+      } else if (!dispObj->QueryInterface(&javaObject)) {
+        // It's one of our Java Object proxies
+        // XXX This casting is a hack
+        retVal.setJavaObject(((CJavaObject*)javaObject.p)->getObjectId());
+
+      } else {
+        _variant_t stringValue;
+        DISPPARAMS emptyParams = {NULL, NULL, 0, 0};
+        DISPID valueOfDispId = -1;
+        LPOLESTR valueOfString = L"valueOf";
+
+        dispObj->GetIDsOfNames(IID_NULL, &valueOfString, 1, LOCALE_SYSTEM_DEFAULT, &valueOfDispId);
+        // See if it's a wrapped String object by invoking valueOf()
+        if ((valueOfDispId != -1) &&
+            SUCCEEDED(dispObj->Invoke(valueOfDispId, IID_NULL, LOCALE_SYSTEM_DEFAULT,
+              DISPATCH_METHOD, &emptyParams, stringValue.GetAddress(),
+              NULL, NULL)) &&
+            stringValue.vt == VT_BSTR) {
+          retVal.setString(BSTRToUTF8(stringValue.bstrVal));
+
+        } else {
+          // It's a plain-old JavaScript Object
+
+          // We ask for the IUnknown interface since that's the only
+          // COM interface guaranteed to have object-identity semantics
+          CComPtr<IUnknown> asUnknown;
+          dispObj->QueryInterface(&asUnknown);
+
+          // See if we already know about this object
+          std::map<IUnknown*, int>::iterator it = jsIdsByObject.find(asUnknown);
+          if (it != jsIdsByObject.end()) {
+            retVal.setJsObjectId(it->second);
+
+          } else {
+            // Allocate a new id
+            int objId = ++jsObjectId;
+            jsObjectsById[objId] = asUnknown;
+            jsIdsByObject[asUnknown] = objId;
+            retVal.setJsObjectId(objId);
+          }
+        }
+      }
+      break;
+
+    default:
+      Debug::log(Debug::Error) << "Unhandled variant type " << value.vt << Debug::flush;
+      retVal.setString("Unhandled variant type");
+  }
+}
+
+void IESessionHandler::makeValueRef(_variant_t& retVal, const Value& value) {
+  switch (value.getType()) {
+    case Value::NULL_TYPE:
+      retVal.ChangeType(VT_NULL);
+      break;
+
+    case Value::BOOLEAN:
+      retVal = value.getBoolean();
+      break;
+
+    case Value::BYTE:
+      retVal = value.getByte();
+      break;
+
+    case Value::CHAR:
+      retVal = value.getChar();
+      break;
+
+    case Value::SHORT:
+      retVal = value.getShort();
+      break;
+
+    case Value::INT:
+      retVal = value.getInt();
+      break;
+
+    case Value::LONG:
+      retVal = value.getLong();
+      break;
+
+    case Value::FLOAT:
+      retVal = value.getFloat();
+      break;
+
+    case Value::DOUBLE:
+      retVal = value.getDouble();
+      break;
+
+    case Value::STRING:
+      // The copy-constructor does not correctly handle embedded nulls
+      retVal.bstrVal = UTF8ToBSTR(value.getString().length(), 
+        value.getString().c_str()).Detach();
+      retVal.vt = VT_BSTR;
+      break;
+
+    case Value::JAVA_OBJECT:
+      {
+        int javaId = value.getJavaObjectId();
+
+        std::map<int, IUnknown*>::iterator i = javaObjectsById.find(javaId);
+        if (i == javaObjectsById.end()) {
+          CComPtr<IUnknown> target;
+
+          // Create a new instance of the Java object proxy type
+          CJavaObject::CreateInstance(&target);
+
+          // Because we used CreateInstance, we can cast it back to the concrete type
+          // which allows us to pass pointers around, since we're guaranteed that
+          // it is in the same process space
+          ((CJavaObject*)target.p)->initialize(javaId, this);
+          target->QueryInterface(&retVal.pdispVal);
+
+          // Don't artificially increase the lifetime of a Java object proxy by
+          // calling Detach; we want Release to be called.
+          javaObjectsById[javaId] = target;
+
+          // 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);
+
+        } else {
+          i->second->QueryInterface(&retVal.pdispVal);
+        }
+        retVal.vt = VT_DISPATCH;
+      }
+      break;
+
+    case Value::JS_OBJECT:
+      {
+        int jsId = value.getJsObjectId();
+
+        std::map<int, CComPtr<IUnknown>>::iterator i = jsObjectsById.find(jsId);
+        if (i == jsObjectsById.end()) {
+          Debug::log(Debug::Error) << "Missing jsObject with id " << jsId << Debug::flush;
+
+        } else {
+          i->second->QueryInterface(&retVal.pdispVal);
+          retVal.vt = VT_DISPATCH;
+        }
+      }
+      break;
+
+    case Value::UNDEFINED:
+      retVal.ChangeType(VT_EMPTY);
+      break;
+
+    default:
+      Debug::log(Debug::Error) << "Unknown Value type " << value.toString() << Debug::flush;
+  }
+}
diff --git a/plugins/ie/oophm/oophm/IESessionHandler.h b/plugins/ie/oophm/oophm/IESessionHandler.h
new file mode 100644
index 0000000..e8cdf92
--- /dev/null
+++ b/plugins/ie/oophm/oophm/IESessionHandler.h
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+#pragma once
+#include <map>
+#include <set>
+#include "HostChannel.h"
+#include "JavaObject.h"
+#include "mshtml.h"
+#include "oophm_i.h"
+#include "SessionData.h"
+#include "SessionHandler.h"
+
+class IESessionHandler :
+  public SessionData,
+  public SessionHandler
+{
+public:
+  IESessionHandler(HostChannel* channel, IHTMLWindow2* window);
+  ~IESessionHandler(void);
+  virtual void freeJavaObject(unsigned int objId);
+  virtual void makeValue(Value& value, const _variant_t& in);
+  virtual void makeValueRef(_variant_t& value, const Value& in);
+
+protected:
+  virtual void freeValue(HostChannel& channel, int idCount, const int* ids);
+  virtual void loadJsni(HostChannel& channel, const std::string& js);
+  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 method, int numArgs,
+      const Value* const args, Value* returnValue);
+
+private:
+  int jsObjectId;
+
+  /*
+  * This must be IUnknown and not IDispatch because the IUnknown
+  * interface is the only COM interface guaranteed to be stable for
+  * any particular instance of an object.  It appears as though
+  * Event objects exhibit the multiple-interface behavior.
+  *
+  * Furthermore, this map is not a CComPtr map because we don't
+  * to artificially add to the retain count of the Java objects.
+  */
+  std::map<int, IUnknown*> javaObjectsById;
+  std::set<int> javaObjectsToFree;
+
+  // Same as above; only one map needs to increment reference count.
+  std::map<int, CComPtr<IUnknown>> jsObjectsById;
+  std::map<IUnknown*, int> jsIdsByObject;
+
+  /*
+  * Send freed Java ids back to the server.
+  */
+  void IESessionHandler::freeJavaObjects();
+
+  /*
+  * Create a JavaScript Error object with the given message.
+  */
+  void makeException(_variant_t& value, const char* message);
+
+  /*
+  * Create a exception Value that contains the given message.
+  */
+  void makeExceptionValue(Value& value, const char* message);
+};
diff --git a/plugins/ie/oophm/oophm/JavaObject.cpp b/plugins/ie/oophm/oophm/JavaObject.cpp
new file mode 100644
index 0000000..cba4d71
--- /dev/null
+++ b/plugins/ie/oophm/oophm/JavaObject.cpp
@@ -0,0 +1,269 @@
+/*
+ * 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.
+ */
+
+// JavaObject.cpp : Implementation of CJavaObject
+
+#include "stdafx.h"
+#include "InvokeMessage.h"
+#include "JavaObject.h"
+#include "ReturnMessage.h"
+#include "ServerMethods.h"
+#include "scoped_ptr/scoped_ptr.h"
+//#include "activscp.h"
+
+static const DISPID DISPID_TOSTRING = 1;
+
+// CJavaObject
+STDMETHODIMP CJavaObject::GetDispID(BSTR name, DWORD options, DISPID* dispId){
+  std::string nameString = BSTRToUTF8(name);
+
+  // toString is the only non-numeric dispid we recognize
+  if (nameString == "toString") {
+    *dispId = DISPID_TOSTRING;
+    return S_OK;
+  }
+
+  char* lastChar;
+  int d = strtol(nameString.c_str(), &lastChar, 10);
+
+  if (*lastChar != '\0' || d < 0) {
+    Debug::log(Debug::Error) << "Unable to get dispatch id for " << nameString << Debug::flush;
+    // Set to unknown name in the case of an error
+    *dispId = DISPID_UNKNOWN;
+    return DISP_E_UNKNOWNNAME;
+  }
+  *dispId = d;
+  return S_OK;
+}
+
+STDMETHODIMP CJavaObject::DeleteMemberByName(BSTR,DWORD){
+  return S_FALSE;
+}
+
+STDMETHODIMP CJavaObject::DeleteMemberByDispID(DISPID){
+  return S_FALSE;
+}
+
+STDMETHODIMP CJavaObject::GetMemberProperties(DISPID dispId, DWORD options, DWORD* retVal){
+  Debug::log(Debug::Error) << "Hit unimplemented GetMemberProperties" << Debug::flush;
+  return DISP_E_UNKNOWNNAME;
+}
+
+STDMETHODIMP CJavaObject::GetMemberName(DISPID,BSTR *){
+  Debug::log(Debug::Error) << "Hit unimplemented GetMemberName" << Debug::flush;
+  return DISP_E_UNKNOWNNAME;
+}
+
+STDMETHODIMP CJavaObject::GetNextDispID(DWORD,DISPID,DISPID *){
+  Debug::log(Debug::Error) << "Hit unimplemented GetNextDispID" << Debug::flush;
+  return DISP_E_UNKNOWNNAME;
+}
+
+STDMETHODIMP CJavaObject::GetNameSpaceParent(IUnknown **unk){
+  sessionData->getWindow()->QueryInterface(unk);
+  return S_OK;
+}
+
+STDMETHODIMP CJavaObject::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
+                                        UINT cNames, LCID lcid, DISPID* rgdispid)
+{
+  USES_CONVERSION;
+  // Stack-allocated
+  return GetDispID(OLE2BSTR(*rgszNames), 0, rgdispid);
+}
+
+STDMETHODIMP CJavaObject::Invoke(DISPID dispidMember, REFIID riid,
+                                 LCID lcid, WORD wFlags, DISPPARAMS* pdispparams,
+                                 VARIANT* pvarResult, EXCEPINFO* pexcepinfo,
+                                 UINT* puArgErr)
+{
+  return InvokeEx(dispidMember, lcid, wFlags, pdispparams, pvarResult,
+    pexcepinfo, NULL);
+}
+
+STDMETHODIMP CJavaObject::InvokeEx(DISPID dispidMember, LCID lcid, WORD wFlags,
+                                   DISPPARAMS* pdispparams, VARIANT* pvarResult,
+                                   EXCEPINFO* pexcepinfo,
+                                   IServiceProvider* pspCaller)
+{
+  Debug::log(Debug::Debugging) << "Invoking " << dispidMember << " on Java object " << objId << Debug::flush;
+
+  if (!sessionData) {
+    // Prevent errors if the object is retained post-disconnect
+    Debug::log(Debug::Warning) << "JavaObject retained beyound session shutdown" << Debug::flush;
+    return DISP_E_MEMBERNOTFOUND;
+  }
+
+  HostChannel* channel = sessionData->getHostChannel();
+  Value thisRef = Value();
+  thisRef.setJavaObject(objId);
+
+  if ((wFlags & DISPATCH_PROPERTYGET) && dispidMember == DISPID_VALUE &&
+    pdispparams->cArgs - pdispparams->cNamedArgs == 0) {
+      // This is an expression like ('' + obj)
+      // raw toString();
+      wFlags = DISPATCH_METHOD;
+      dispidMember = DISPID_TOSTRING;
+  }
+
+  if (wFlags & DISPATCH_METHOD) {
+    Debug::log(Debug::Spam) << "Dispatching method " << dispidMember << " on " << objId << Debug::flush;
+
+    if (!(dispidMember == DISPID_VALUE || dispidMember == DISPID_TOSTRING)) {
+      Debug::log(Debug::Error) << "Cannot dispatch for non-default id: " << dispidMember << Debug::flush;
+      return E_FAIL;
+    }
+    scoped_array<Value> args;
+    Value javaDispatchId;
+    int numArgs;
+
+    if (dispidMember == DISPID_VALUE) {
+      numArgs = pdispparams->cArgs - pdispparams->cNamedArgs - 2;
+      if (numArgs < 0) {
+        // Indicates an error in JSNI rewriting or dispatch code
+        Debug::log(Debug::Error) << "Insufficient number of arguments" << Debug::flush;
+        return E_FAIL;
+      }
+      args.reset(new Value[numArgs]);
+      // The dispatch parameters are backwards
+      sessionData->makeValue(javaDispatchId, pdispparams->rgvarg[pdispparams->cArgs - 1]);
+      sessionData->makeValue(thisRef, pdispparams->rgvarg[pdispparams->cArgs - 2]);
+      for (int i = 0; i < numArgs; i++) {
+        int index = pdispparams->cArgs - 3 - i;
+        VARIANTARG element = pdispparams->rgvarg[index];
+        sessionData->makeValue(args[i], element);
+      }
+    } else if (dispidMember == DISPID_TOSTRING) {
+      // raw toString();
+      numArgs = 0;
+      javaDispatchId.setInt(0);
+    }
+
+    if (!InvokeMessage::send(*channel, thisRef, javaDispatchId.getInt(), numArgs, args.get())) {
+      Debug::log(Debug::Error) << "Unable to send method invocation" << Debug::flush;
+      return E_FAIL;
+    }
+
+    scoped_ptr<ReturnMessage> m(channel->reactToMessagesWhileWaitingForReturn(
+      sessionData->getSessionHandler()));
+
+    if (!m.get()) {
+      Debug::log(Debug::Error) << "Did not receive ReturnMessage" << Debug::flush;
+      if (pvarResult) {
+        VariantClear(pvarResult);
+      }
+      // XXX better error handling
+      return E_FAIL;
+    }
+
+    if (dispidMember == DISPID_TOSTRING) {
+      // raw toString();
+      if (pvarResult) {
+        // This will be NULL when the caller doesn't care about the return value
+        _variant_t returnVariant;
+        sessionData->makeValueRef(returnVariant, m->getReturnValue());
+        *pvarResult = returnVariant.Detach();
+      }
+      return m->isException() ? E_FAIL : S_OK;
+    }
+
+    DISPID dispId;
+    LPOLESTR makeResultName = L"__gwt_makeResult";
+    if (!SUCCEEDED(sessionData->getWindow()->GetIDsOfNames(IID_NULL, &makeResultName, 1,
+      LOCALE_SYSTEM_DEFAULT, &dispId))) {
+        Debug::log(Debug::Error) << "Unable to get dispId for __gwt_makeResult" << Debug::flush;
+        return E_FAIL;
+    }
+
+    // Call __gwt_makeResult(isException, returnValue)
+    scoped_array<_variant_t> varArgs(new _variant_t[2]);
+    // Args go backwards.
+    varArgs[1] = (m->isException() ? 1 : 0);
+    sessionData->makeValueRef(varArgs[0], m->getReturnValue());
+    DISPPARAMS dispParams = {varArgs.get(), NULL, 2, 0};
+    CComPtr<IDispatchEx> dispEx;
+    sessionData->getWindow()->QueryInterface(&dispEx);
+    return dispEx->InvokeEx(dispId, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,
+      &dispParams, pvarResult, pexcepinfo, pspCaller);
+
+  } else if (wFlags & DISPATCH_PROPERTYGET) {
+    Debug::log(Debug::Spam) << "Getting property " << dispidMember << " on " << objId << Debug::flush;
+
+    if (dispidMember == DISPID_VALUE) {
+      this->QueryInterface(IID_IDispatch, (void**)&pvarResult->pdispVal);
+      pvarResult->vt = VT_DISPATCH;
+
+    } else if (dispidMember == DISPID_TOSTRING) {
+      // Asking for a tear-off of the .toString function
+      Debug::log(Debug::Spam) << "Making .toString tearoff" << Debug::flush;
+      HRESULT res;
+
+      // Get a reference to __gwt_makeTearOff
+      DISPID tearOffDispid;
+      LPOLESTR tearOffName = L"__gwt_makeTearOff";
+      res = sessionData->getWindow()->GetIDsOfNames(IID_NULL,
+        &tearOffName, 1, LOCALE_SYSTEM_DEFAULT, &tearOffDispid);
+      if (FAILED(res)) {
+        Debug::log(Debug::Error) << "Unable to find __gwt_makeTearOff" << Debug::flush;
+        return E_FAIL;
+      }
+
+      scoped_array<_variant_t> tearOffArgs(new _variant_t[3]);
+      // Parameters are backwards:
+      // __gwt_makeTearOff(proxy, dispId, argCount);
+      tearOffArgs[2] = this; // proxy
+      tearOffArgs[1] = 0; // dispId
+      tearOffArgs[0] = 0; // argCount
+      DISPPARAMS tearOffParams = {tearOffArgs.get(), NULL, 3, 0};
+
+      // Invoke __gwt_makeTearOff
+      res = sessionData->getWindow()->Invoke(tearOffDispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
+        DISPATCH_METHOD, &tearOffParams, pvarResult, NULL, 0);
+      if (FAILED(res)) {
+        Debug::log(Debug::Error) << "Unable to invoke __gwt_makeTearOff" << Debug::flush;
+        return E_FAIL;
+      }
+
+    } else {
+      Value ret = ServerMethods::getProperty(*channel,
+        sessionData->getSessionHandler(), objId, dispidMember);
+
+      if (ret.isUndefined()) {
+        Debug::log(Debug::Error) << "Undefined get from Java object" << Debug::flush;
+        return E_FAIL;
+      }
+
+      _variant_t returnVariant;
+      sessionData->makeValueRef(returnVariant, ret);
+      *pvarResult = returnVariant.Detach();
+    }
+
+  } else if (wFlags & (DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF)) {
+    Debug::log(Debug::Spam) << "Setting property " << dispidMember << " on " << objId << Debug::flush;
+
+    Value value;
+    sessionData->makeValue(value, pdispparams->rgvarg[0]);
+
+    ServerMethods::setProperty(*channel, sessionData->getSessionHandler(),
+      objId, dispidMember, value);
+
+  } else {
+    Debug::log(Debug::Error) << "Unsupported invocation " << wFlags << Debug::flush;
+    return DISP_E_MEMBERNOTFOUND;
+  }
+
+  return S_OK;
+}
diff --git a/plugins/ie/oophm/oophm/JavaObject.h b/plugins/ie/oophm/oophm/JavaObject.h
new file mode 100644
index 0000000..cf56fa2
--- /dev/null
+++ b/plugins/ie/oophm/oophm/JavaObject.h
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+// JavaObject.h : Declaration of the CJavaObject
+
+#pragma once
+#include "resource.h"       // main symbols
+#include "SessionData.h"
+
+#include "oophm_i.h"
+
+
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
+#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
+#endif
+
+
+
+// CJavaObject
+
+class ATL_NO_VTABLE CJavaObject :
+	public CComObjectRootEx<CComSingleThreadModel>,
+	public CComCoClass<CJavaObject, &CLSID_JavaObject>,
+	public IDispatchImpl<IJavaObject, &IID_IJavaObject, &LIBID_oophmLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
+{
+public:
+  // TODO How can the default constructor be gotten rid of?
+  CJavaObject() : objId(-1) {
+  }
+
+	STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
+		LCID lcid, DISPID* rgdispid);
+
+	STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid,
+		LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
+		EXCEPINFO* pexcepinfo, UINT* puArgErr);
+
+DECLARE_REGISTRY_RESOURCEID(IDR_JAVAOBJECT)
+
+
+BEGIN_COM_MAP(CJavaObject)
+	COM_INTERFACE_ENTRY(IJavaObject)
+  COM_INTERFACE_ENTRY(IDispatchEx)
+  COM_INTERFACE_ENTRY(IDispatch)
+END_COM_MAP()
+
+
+
+	DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+	HRESULT FinalConstruct()
+	{
+		return S_OK;
+	}
+
+	void FinalRelease()
+	{
+    Debug::log(Debug::Debugging) << "JavaObject " << objId << " released" << Debug::flush;
+    if (sessionData) {
+      // After shutdown, the session data will have been torn down
+      sessionData->freeJavaObject(objId);
+    }
+	}
+
+  unsigned int getObjectId() const {
+    return objId;
+  }
+
+  STDMETHOD(GetDispID)(BSTR,DWORD,DISPID *);
+  STDMETHOD(InvokeEx)(DISPID,LCID,WORD,DISPPARAMS *,VARIANT *,EXCEPINFO *,IServiceProvider *);
+  STDMETHOD(DeleteMemberByName)(BSTR,DWORD);
+  STDMETHOD(DeleteMemberByDispID)(DISPID);
+  STDMETHOD(GetMemberProperties)(DISPID,DWORD,DWORD *);
+  STDMETHOD(GetMemberName)(DISPID,BSTR *);
+  STDMETHOD(GetNextDispID)(DWORD,DISPID,DISPID *);
+  STDMETHOD(GetNameSpaceParent)(IUnknown **);
+
+  void initialize(unsigned int objId, SessionDataRef sessionData) {
+    this->objId = objId;
+    this->sessionData = sessionData;
+  }
+
+  void shutdown() {
+    sessionData = NULL;
+  }
+
+private:
+  unsigned int objId;
+  SessionDataRef sessionData;
+};
+
+OBJECT_ENTRY_AUTO(__uuidof(JavaObject), CJavaObject)
diff --git a/plugins/ie/oophm/oophm/JavaObject.rgs b/plugins/ie/oophm/oophm/JavaObject.rgs
new file mode 100644
index 0000000..00d6719
--- /dev/null
+++ b/plugins/ie/oophm/oophm/JavaObject.rgs
@@ -0,0 +1,26 @@
+HKCR

+{

+	oophm.JavaObject.1 = s 'JavaObject Class'

+	{

+		CLSID = s '{644FD769-8B9D-4AC4-A79E-AAAF5CD751C1}'

+	}

+	oophm.JavaObject = s 'JavaObject Class'

+	{

+		CLSID = s '{644FD769-8B9D-4AC4-A79E-AAAF5CD751C1}'

+		CurVer = s 'oophm.JavaObject.1'

+	}

+	NoRemove CLSID

+	{

+		ForceRemove {644FD769-8B9D-4AC4-A79E-AAAF5CD751C1} = s 'JavaObject Class'

+		{

+			ProgID = s 'oophm.JavaObject.1'

+			VersionIndependentProgID = s 'oophm.JavaObject'

+			ForceRemove 'Programmable'

+			InprocServer32 = s '%MODULE%'

+			{

+				val ThreadingModel = s 'Apartment'

+			}

+			'TypeLib' = s '{9259F105-BE55-4BF6-B7CE-D0AA878C1BA6}'

+		}

+	}

+}

diff --git a/plugins/ie/oophm/oophm/ReadMe.txt b/plugins/ie/oophm/oophm/ReadMe.txt
new file mode 100644
index 0000000..2e7a437
--- /dev/null
+++ b/plugins/ie/oophm/oophm/ReadMe.txt
@@ -0,0 +1,56 @@
+========================================================================
+    ACTIVE TEMPLATE LIBRARY : oophm Project Overview
+========================================================================
+
+AppWizard has created this oophm project for you to use as the starting point for
+writing your Dynamic Link Library (DLL).
+
+This file contains a summary of what you will find in each of the files that
+make up your project.
+
+oophm.vcproj
+    This is the main project file for VC++ projects generated using an Application Wizard.
+    It contains information about the version of Visual C++ that generated the file, and
+    information about the platforms, configurations, and project features selected with the
+    Application Wizard.
+
+oophm.idl
+    This file contains the IDL definitions of the type library, the interfaces
+    and co-classes defined in your project.
+    This file will be processed by the MIDL compiler to generate:
+        C++ interface definitions and GUID declarations (oophm.h)
+        GUID definitions                                (oophm_i.c)
+        A type library                                  (oophm.tlb)
+        Marshaling code                                 (oophm_p.c and dlldata.c)
+
+oophm.h
+    This file contains the C++ interface definitions and GUID declarations of the
+    items defined in oophm.idl. It will be regenerated by MIDL during compilation.
+
+oophm.cpp
+    This file contains the object map and the implementation of your DLL's exports.
+
+oophm.rc
+    This is a listing of all of the Microsoft Windows resources that the
+    program uses.
+
+oophm.def
+    This module-definition file provides the linker with information about the exports
+    required by your DLL. It contains exports for:
+        DllGetClassObject
+        DllCanUnloadNow
+        DllRegisterServer
+        DllUnregisterServer
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+    These files are used to build a precompiled header (PCH) file
+    named oophm.pch and a precompiled types file named StdAfx.obj.
+
+Resource.h
+    This is the standard header file that defines resource IDs.
+
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/plugins/ie/oophm/oophm/Resource.h b/plugins/ie/oophm/oophm/Resource.h
new file mode 100644
index 0000000..d53c63f
--- /dev/null
+++ b/plugins/ie/oophm/oophm/Resource.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by oophm.rc
+//
+#define IDS_PROJNAME                    100
+#define IDR_OOPHM                       101
+#define IDB_PLUGIN                      102
+#define IDR_PLUGIN                      103
+#define IDH_PLUGIN                      104
+#define IDR_JAVAOBJECT                  105
+#define IDR_EXCEPTIONCATCHER            106
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        201
+#define _APS_NEXT_COMMAND_VALUE         32768
+#define _APS_NEXT_CONTROL_VALUE         201
+#define _APS_NEXT_SYMED_VALUE           107
+#endif
+#endif
diff --git a/plugins/ie/oophm/oophm/SessionData.h b/plugins/ie/oophm/oophm/SessionData.h
new file mode 100644
index 0000000..8585a44
--- /dev/null
+++ b/plugins/ie/oophm/oophm/SessionData.h
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+#pragma once
+#include "stdafx.h"
+#include "comutil.h"
+#include "HostChannel.h"
+#include "Mshtml.h"
+#include "SessionHandler.h"
+#include "scoped_ptr/scoped_ptr.h"
+
+/*
+* Encapsules per-OOPHM-session data.
+*/
+class SessionData {
+public:
+  SessionData(HostChannel* channel,
+    IHTMLWindow2* window,
+    SessionHandler* sessionHandler) : channel(channel),
+    window(window),
+    sessionHandler(sessionHandler) {
+  }
+
+  virtual void freeJavaObject(unsigned int objId)=0;
+
+  HostChannel* getHostChannel() const {
+    return channel.get();
+  }
+
+  SessionHandler* getSessionHandler() const {
+    return sessionHandler;
+  }
+
+  IHTMLWindow2* getWindow() const {
+    return window;
+  }
+
+  /*
+  * Convert a value from the JavaScript into something that can be sent back
+  * to the OOPHM host.
+  */
+  virtual void makeValue(Value& value, const _variant_t& in)=0;
+
+  /*
+  * Convert a value from the OOPHM host into something that can be passed into
+  * the JavaScript execution environment.
+  */
+  virtual void makeValueRef(_variant_t& value, const Value& in)=0;
+
+protected:
+  /*
+  * The communication channel used for the OOPHM session.
+  */
+  scoped_ptr<HostChannel> const channel;
+
+  /*
+  * A reference to the SessionHandler being used in the OOPHM session.
+  */
+  SessionHandler* const sessionHandler;
+
+  CComPtr<IHTMLWindow2> const window;
+};
+typedef SessionData* SessionDataRef;
+
+// TODO move these to a utility header
+
+static std::string BSTRToUTF8(BSTR bstr) {
+  // Need an explict length due to the possibility of embedded nulls
+  int length = SysStringLen(bstr);
+  int numChars = WideCharToMultiByte(CP_UTF8, 0, bstr, length, NULL, 0, NULL, NULL);
+  char* buffer = new char[numChars];
+  int res = WideCharToMultiByte(CP_UTF8, 0, bstr, length, buffer, numChars, NULL, NULL);
+  // TODO assert res == numChars?
+  std::string toReturn = std::string(buffer, res);
+  delete[] buffer;
+  return toReturn;
+}
+
+/*
+ * Convert a utf8-encoded string into a BSTR.  The length is explicitly
+ * specified because the incoming string may have embedded null charachers.
+ */
+static _bstr_t UTF8ToBSTR(int length, const char* utf8) {
+  // We explicitly use MultiByteToWideChar to handle embedded nulls
+  int numChars = MultiByteToWideChar(CP_UTF8, 0, utf8, length, NULL, 0);
+  OLECHAR* buffer = new OLECHAR[numChars];
+  int res = MultiByteToWideChar(CP_UTF8, 0, utf8, length, buffer, numChars);
+  // Manually allocate the BSTR to set the length; _bstr_t assumes C-strings
+  _bstr_t toReturn = _bstr_t(SysAllocStringLen(buffer, res), false);
+  delete[] buffer;
+  return toReturn;
+}
diff --git a/plugins/ie/oophm/oophm/dlldata.c b/plugins/ie/oophm/oophm/dlldata.c
new file mode 100644
index 0000000..7b86f60
--- /dev/null
+++ b/plugins/ie/oophm/oophm/dlldata.c
@@ -0,0 +1,38 @@
+/*********************************************************
+   DllData file -- generated by MIDL compiler 
+
+        DO NOT ALTER THIS FILE
+
+   This file is regenerated by MIDL on every IDL file compile.
+
+   To completely reconstruct this file, delete it and rerun MIDL
+   on all the IDL files in this DLL, specifying this file for the
+   /dlldata command line option
+
+*********************************************************/
+
+#define PROXY_DELEGATION
+
+#include <rpcproxy.h>
+
+#ifdef __cplusplus
+extern "C"   {
+#endif
+
+EXTERN_PROXY_FILE( oophm )
+
+
+PROXYFILE_LIST_START
+/* Start of list */
+  REFERENCE_PROXY_FILE( oophm ),
+/* End of list */
+PROXYFILE_LIST_END
+
+
+DLLDATA_ROUTINES( aProxyFileList, GET_DLL_CLSID )
+
+#ifdef __cplusplus
+}  /*extern "C" */
+#endif
+
+/* end of generated dlldata file */
diff --git a/plugins/ie/oophm/oophm/dlldatax.c b/plugins/ie/oophm/oophm/dlldatax.c
new file mode 100644
index 0000000..8979369
--- /dev/null
+++ b/plugins/ie/oophm/oophm/dlldatax.c
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+// wrapper for dlldata.c
+
+#ifdef _MERGE_PROXYSTUB // merge proxy stub DLL
+
+#define REGISTER_PROXY_DLL //DllRegisterServer, etc.
+
+#define _WIN32_WINNT 0x0500	//for WinNT 4.0 or Win95 with DCOM
+#define USE_STUBLESS_PROXY	//defined only with MIDL switch /Oicf
+
+#pragma comment(lib, "rpcns4.lib")
+#pragma comment(lib, "rpcrt4.lib")
+
+#define ENTRY_PREFIX	Prx
+
+#include "dlldata.c"
+#include "oophm_p.c"
+
+#endif //_MERGE_PROXYSTUB
diff --git a/plugins/ie/oophm/oophm/dlldatax.h b/plugins/ie/oophm/oophm/dlldatax.h
new file mode 100644
index 0000000..4ce5f66
--- /dev/null
+++ b/plugins/ie/oophm/oophm/dlldatax.h
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#ifdef _MERGE_PROXYSTUB
+
+extern "C" 
+{
+BOOL WINAPI PrxDllMain(HINSTANCE hInstance, DWORD dwReason, 
+	LPVOID lpReserved);
+STDAPI PrxDllCanUnloadNow(void);
+STDAPI PrxDllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv);
+STDAPI PrxDllRegisterServer(void);
+STDAPI PrxDllUnregisterServer(void);
+}
+
+#endif
diff --git a/plugins/ie/oophm/oophm/dllmain.cpp b/plugins/ie/oophm/oophm/dllmain.cpp
new file mode 100644
index 0000000..57790ba
--- /dev/null
+++ b/plugins/ie/oophm/oophm/dllmain.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+// dllmain.cpp : Implementation of DllMain.
+
+#include "stdafx.h"
+#include "resource.h"
+#include "oophm_i.h"
+#include "dllmain.h"
+#include "dlldatax.h"
+
+CoophmModule _AtlModule;
+
+// DLL Entry Point
+extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
+{
+#ifdef _MERGE_PROXYSTUB
+	if (!PrxDllMain(hInstance, dwReason, lpReserved))
+		return FALSE;
+#endif
+	hInstance;
+	return _AtlModule.DllMain(dwReason, lpReserved); 
+}
diff --git a/plugins/ie/oophm/oophm/dllmain.h b/plugins/ie/oophm/oophm/dllmain.h
new file mode 100644
index 0000000..6965209
--- /dev/null
+++ b/plugins/ie/oophm/oophm/dllmain.h
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+// dllmain.h : Declaration of module class.
+
+class CoophmModule : public CAtlDllModuleT< CoophmModule >
+{
+public :
+	DECLARE_LIBID(LIBID_oophmLib)
+	DECLARE_REGISTRY_APPID_RESOURCEID(IDR_OOPHM, "{F9365E53-5A14-47F3-BF1D-10CAAB815309}")
+};
+
+extern class CoophmModule _AtlModule;
diff --git a/plugins/ie/oophm/oophm/oophm.aps b/plugins/ie/oophm/oophm/oophm.aps
new file mode 100644
index 0000000..74623ca
--- /dev/null
+++ b/plugins/ie/oophm/oophm/oophm.aps
Binary files differ
diff --git a/plugins/ie/oophm/oophm/oophm.cpp b/plugins/ie/oophm/oophm/oophm.cpp
new file mode 100644
index 0000000..5435c62
--- /dev/null
+++ b/plugins/ie/oophm/oophm/oophm.cpp
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+// oophm.cpp : Implementation of DLL Exports.
+
+
+#include "stdafx.h"
+#include "resource.h"
+#include "oophm_i.h"
+#include "dllmain.h"
+#include "dlldatax.h"
+
+// Used to determine whether the DLL can be unloaded by OLE
+STDAPI DllCanUnloadNow(void)
+{
+#ifdef _MERGE_PROXYSTUB
+    HRESULT hr = PrxDllCanUnloadNow();
+    if (hr != S_OK)
+        return hr;
+#endif
+    return _AtlModule.DllCanUnloadNow();
+}
+
+
+// Returns a class factory to create an object of the requested type
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
+{
+#ifdef _MERGE_PROXYSTUB
+    if (PrxDllGetClassObject(rclsid, riid, ppv) == S_OK)
+        return S_OK;
+#endif
+    return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
+}
+
+
+// DllRegisterServer - Adds entries to the system registry
+STDAPI DllRegisterServer(void)
+{
+    // registers object, typelib and all interfaces in typelib
+    HRESULT hr = _AtlModule.DllRegisterServer();
+#ifdef _MERGE_PROXYSTUB
+    if (FAILED(hr))
+        return hr;
+    hr = PrxDllRegisterServer();
+#endif
+	return hr;
+}
+
+
+// DllUnregisterServer - Removes entries from the system registry
+STDAPI DllUnregisterServer(void)
+{
+	HRESULT hr = _AtlModule.DllUnregisterServer();
+#ifdef _MERGE_PROXYSTUB
+    if (FAILED(hr))
+        return hr;
+    hr = PrxDllRegisterServer();
+    if (FAILED(hr))
+        return hr;
+    hr = PrxDllUnregisterServer();
+#endif
+	return hr;
+}
+
+// DllInstall - Adds/Removes entries to the system registry per user
+//              per machine.	
+STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine)
+{
+    HRESULT hr = E_FAIL;
+    static const wchar_t szUserSwitch[] = _T("user");
+
+    if (pszCmdLine != NULL)
+    {
+    	if (_wcsnicmp(pszCmdLine, szUserSwitch, _countof(szUserSwitch)) == 0)
+    	{
+    		AtlSetPerUserRegistration(true);
+    	}
+    }
+
+    if (bInstall)
+    {	
+    	hr = DllRegisterServer();
+    	if (FAILED(hr))
+    	{	
+    		DllUnregisterServer();
+    	}
+    }
+    else
+    {
+    	hr = DllUnregisterServer();
+    }
+
+    return hr;
+}
+
+
diff --git a/plugins/ie/oophm/oophm/oophm.def b/plugins/ie/oophm/oophm/oophm.def
new file mode 100644
index 0000000..bbb6f99
--- /dev/null
+++ b/plugins/ie/oophm/oophm/oophm.def
@@ -0,0 +1,24 @@
+; 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.
+
+; oophm.def : Declares the module parameters.
+
+LIBRARY      "oophm.DLL"
+
+EXPORTS
+	DllCanUnloadNow		PRIVATE
+	DllGetClassObject	PRIVATE
+	DllRegisterServer	PRIVATE
+	DllUnregisterServer	PRIVATE
+	DllInstall		PRIVATE
diff --git a/plugins/ie/oophm/oophm/oophm.idl b/plugins/ie/oophm/oophm/oophm.idl
new file mode 100644
index 0000000..3b64a60
--- /dev/null
+++ b/plugins/ie/oophm/oophm/oophm.idl
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+// oophm.idl : IDL source for oophm
+//
+
+// This file will be processed by the MIDL tool to
+// produce the type library (oophm.tlb) and marshalling code.
+
+#include "olectl.h"
+import "oaidl.idl";
+import "ocidl.idl";
+import "dispex.idl";
+
+// This interface is something of a hack to work around the lack
+// of ICanHandleException being defined by default in the dispex headers
+[
+	object,
+	uuid(c5598e60-b307-11d1-b27d-006008c3fbfb),
+	pointer_default(unique)
+]
+interface ICanHandleException : IUnknown
+{
+	HRESULT CanHandleException([in] EXCEPINFO *pExcepInfo, [in] VARIANT *pvar);
+};
+
+[
+	object,
+	uuid(73607C2E-369B-4055-8020-D7643A59F521),
+	dual,
+	nonextensible,
+	helpstring("Iplugin Interface"),
+	pointer_default(unique)
+]
+interface Iplugin : IDispatch{
+	[id(1), helpstring("OOPHM connect")] HRESULT connect([in] BSTR url, [in] BSTR moduleName, [in] IDispatch* jsniContext, [out,retval] VARIANT_BOOL* ret);
+	[id(2), helpstring("method testObject")] HRESULT testObject([out,retval] IDispatch** ret);
+};
+
+[
+	object, 
+	dual,
+	nonextensible,
+	uuid(AB9B16A0-03E9-481E-ADF5-B00B860A8C3A),
+	helpstring("IpluginUI Interface"),
+	pointer_default(unique)
+]
+interface IpluginUI : IDispatch
+{
+	// Example method that will be called by the HTML
+	HRESULT OnClick([in]IDispatch* pdispBody, [in]VARIANT varColor);
+};
+[
+	object,
+	uuid(58276E45-1F24-4B71-88AC-2A7D0C26CDFF),
+	dual,
+	nonextensible,
+	helpstring("IJavaObject Interface"),
+	pointer_default(unique)
+]
+interface IJavaObject : IDispatchEx{
+};
+[
+	object,
+	uuid(1C3FBB2D-58C2-426C-A461-E6002F9EE294),
+	dual,
+	nonextensible,
+	helpstring("IExceptionCatcher Interface"),
+	pointer_default(unique)
+]
+interface IExceptionCatcher : IDispatch{
+  [id(1), helpstring("method getException")] HRESULT getException([out,retval] VARIANT* retVal);
+  [id(2), helpstring("method hasSeenException")] HRESULT hasSeenException([out,retval] BOOL* retVal);
+};
+[
+	uuid(9259F105-BE55-4BF6-B7CE-D0AA878C1BA6),
+	version(1.0),
+	helpstring("oophm 1.0 Type Library")
+]
+library oophmLib
+{
+	importlib("stdole2.tlb");
+	[
+		uuid(1D6156B6-002B-49E7-B5CA-C138FB843B4E),
+		control,
+		helpstring("plugin Class")
+	]
+	coclass plugin
+	{
+		[default] interface Iplugin;
+		interface IpluginUI;
+	};
+	[
+		uuid(644FD769-8B9D-4AC4-A79E-AAAF5CD751C1),
+		helpstring("JavaObject Class")
+	]
+	coclass JavaObject
+	{
+		[default] interface IJavaObject;
+	};
+	[
+		uuid(1A2A78F4-B5A4-4208-B520-BDDA0A7EC5CB),
+		helpstring("ExceptionCatcher Class")
+	]
+	coclass ExceptionCatcher
+	{
+		[default] interface IExceptionCatcher;
+    interface ICanHandleException;
+	};
+};
diff --git a/plugins/ie/oophm/oophm/oophm.rc b/plugins/ie/oophm/oophm/oophm.rc
new file mode 100644
index 0000000..92a62dc
--- /dev/null
+++ b/plugins/ie/oophm/oophm/oophm.rc
@@ -0,0 +1,143 @@
+// Microsoft Visual C++ generated resource script.

+//

+#include "resource.h"

+

+#define APSTUDIO_READONLY_SYMBOLS

+/////////////////////////////////////////////////////////////////////////////

+//

+// Generated from the TEXTINCLUDE 2 resource.

+//

+#ifndef APSTUDIO_INVOKED

+#include "targetver.h"

+#endif

+#include "winres.h"

+

+/////////////////////////////////////////////////////////////////////////////

+#undef APSTUDIO_READONLY_SYMBOLS

+

+/////////////////////////////////////////////////////////////////////////////

+// English (U.S.) resources

+

+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)

+#ifdef _WIN32

+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

+#pragma code_page(1252)

+#endif //_WIN32

+

+#ifdef APSTUDIO_INVOKED

+/////////////////////////////////////////////////////////////////////////////

+//

+// TEXTINCLUDE

+//

+

+1 TEXTINCLUDE 

+BEGIN

+    "resource.h\0"

+END

+

+2 TEXTINCLUDE 

+BEGIN

+    "#ifndef APSTUDIO_INVOKED\r\n"

+    "#include ""targetver.h""\r\n"

+    "#endif\r\n"

+    "#include ""winres.h""\r\n"

+    "\0"

+END

+

+3 TEXTINCLUDE 

+BEGIN

+    "1 TYPELIB ""oophm.tlb""\r\n"

+    "\0"

+END

+

+#endif    // APSTUDIO_INVOKED

+

+

+/////////////////////////////////////////////////////////////////////////////

+//

+// Version

+//

+

+VS_VERSION_INFO VERSIONINFO

+ FILEVERSION 1,0,0,1

+ PRODUCTVERSION 1,0,0,1

+ FILEFLAGSMASK 0x3fL

+#ifdef _DEBUG

+ FILEFLAGS 0x1L

+#else

+ FILEFLAGS 0x0L

+#endif

+ FILEOS 0x4L

+ FILETYPE 0x2L

+ FILESUBTYPE 0x0L

+BEGIN

+    BLOCK "StringFileInfo"

+    BEGIN

+        BLOCK "040904e4"

+        BEGIN

+            VALUE "CompanyName", "Google Inc."

+            VALUE "FileDescription", "Google Web Toolkit Out-of-Process Hosted Mode Plugin"

+            VALUE "FileVersion", "1.0.0.1"

+            VALUE "InternalName", "oophm.dll"

+            VALUE "LegalCopyright", "Copyright 2008 Google Inc. Licensed under the Apache 2.0 license."

+            VALUE "OriginalFilename", "oophm.dll"

+            VALUE "ProductName", "Google Web Toolkit"

+            VALUE "ProductVersion", "1.0.0.1"

+        END

+    END

+    BLOCK "VarFileInfo"

+    BEGIN

+        VALUE "Translation", 0x409, 1252

+    END

+END

+

+

+/////////////////////////////////////////////////////////////////////////////

+//

+// REGISTRY

+//

+

+IDR_OOPHM               REGISTRY                "oophm.rgs"

+IDR_PLUGIN              REGISTRY                "plugin.rgs"

+IDR_JAVAOBJECT          REGISTRY                "JavaObject.rgs"

+IDR_EXCEPTIONCATCHER    REGISTRY                "ExceptionCatcher.rgs"

+

+/////////////////////////////////////////////////////////////////////////////

+//

+// Bitmap

+//

+

+IDB_PLUGIN              BITMAP                  "plugin.bmp"

+

+/////////////////////////////////////////////////////////////////////////////

+//

+// HTML

+//

+

+IDH_PLUGIN              HTML                    "pluginUI.htm"

+

+/////////////////////////////////////////////////////////////////////////////

+//

+// String Table

+//

+

+STRINGTABLE 

+BEGIN

+    IDS_PROJNAME            "oophm"

+END

+

+#endif    // English (U.S.) resources

+/////////////////////////////////////////////////////////////////////////////

+

+

+

+#ifndef APSTUDIO_INVOKED

+/////////////////////////////////////////////////////////////////////////////

+//

+// Generated from the TEXTINCLUDE 3 resource.

+//

+1 TYPELIB "oophm.tlb"

+

+/////////////////////////////////////////////////////////////////////////////

+#endif    // not APSTUDIO_INVOKED

+

diff --git a/plugins/ie/oophm/oophm/oophm.rgs b/plugins/ie/oophm/oophm/oophm.rgs
new file mode 100644
index 0000000..928d936
--- /dev/null
+++ b/plugins/ie/oophm/oophm/oophm.rgs
@@ -0,0 +1,11 @@
+HKCR

+{

+	NoRemove AppID

+	{

+		'%APPID%' = s 'oophm'

+		'oophm.DLL'

+		{

+			val AppID = s '%APPID%'

+		}

+	}

+}

diff --git a/plugins/ie/oophm/oophm/oophm.vcproj b/plugins/ie/oophm/oophm/oophm.vcproj
new file mode 100644
index 0000000..33e662b
--- /dev/null
+++ b/plugins/ie/oophm/oophm/oophm.vcproj
@@ -0,0 +1,557 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="9.00"

+	Name="oophm"

+	ProjectGUID="{EB69BDFE-9380-4C51-99E8-C3EB25AE36A2}"

+	RootNamespace="oophm"

+	Keyword="AtlProj"

+	TargetFrameworkVersion="196613"

+	>

+	<Platforms>

+		<Platform

+			Name="Win32"

+		/>

+	</Platforms>

+	<ToolFiles>

+	</ToolFiles>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(ConfigurationName)"

+			IntermediateDirectory="$(ConfigurationName)"

+			ConfigurationType="2"

+			UseOfMFC="1"

+			UseOfATL="1"

+			ATLMinimizesCRunTimeLibraryUsage="false"

+			CharacterSet="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+				PreprocessorDefinitions="_DEBUG"

+				MkTypLibCompatible="false"

+				TargetEnvironment="1"

+				GenerateStublessProxies="true"

+				TypeLibraryName="$(IntDir)/oophm.tlb"

+				HeaderFileName="oophm_i.h"

+				DLLDataFileName=""

+				InterfaceIdentifierFileName="oophm_i.c"

+				ProxyFileName="oophm_p.c"

+				ValidateParameters="true"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				AdditionalIncludeDirectories="../../../common"

+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;GWT_DEBUGLEVEL=Spam"

+				MinimalRebuild="true"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="1"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				DebugInformationFormat="4"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				PreprocessorDefinitions="_DEBUG"

+				Culture="1033"

+				AdditionalIncludeDirectories="$(IntDir)"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				RegisterOutput="true"

+				IgnoreImportLibrary="true"

+				AdditionalDependencies="comsuppw.lib ws2_32.lib"

+				LinkIncremental="2"

+				ModuleDefinitionFile=".\oophm.def"

+				GenerateDebugInformation="true"

+				SubSystem="2"

+				TargetMachine="1"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCManifestTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCAppVerifierTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(ConfigurationName)"

+			IntermediateDirectory="$(ConfigurationName)"

+			ConfigurationType="2"

+			UseOfMFC="1"

+			UseOfATL="1"

+			ATLMinimizesCRunTimeLibraryUsage="false"

+			CharacterSet="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+				PreprocessorDefinitions="NDEBUG"

+				MkTypLibCompatible="false"

+				TargetEnvironment="1"

+				GenerateStublessProxies="true"

+				TypeLibraryName="$(IntDir)/oophm.tlb"

+				HeaderFileName="oophm_i.h"

+				DLLDataFileName=""

+				InterfaceIdentifierFileName="oophm_i.c"

+				ProxyFileName="oophm_p.c"

+				ValidateParameters="true"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="2"

+				AdditionalIncludeDirectories="../../../common"

+				PreprocessorDefinitions="_WINDOWS;GWT_DEBUGDISABLE"

+				RuntimeLibrary="0"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				DebugInformationFormat="3"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				PreprocessorDefinitions="NDEBUG"

+				Culture="1033"

+				AdditionalIncludeDirectories="$(IntDir)"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLinkerTool"

+				RegisterOutput="true"

+				IgnoreImportLibrary="true"

+				AdditionalDependencies="comsuppw.lib ws2_32.lib"

+				LinkIncremental="1"

+				ModuleDefinitionFile=".\oophm.def"

+				GenerateDebugInformation="true"

+				SubSystem="2"

+				OptimizeReferences="2"

+				EnableCOMDATFolding="2"

+				TargetMachine="1"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCManifestTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCAppVerifierTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+	</Configurations>

+	<References>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

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

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

+			>

+			<File

+				RelativePath=".\dlldatax.c"

+				>

+				<FileConfiguration

+					Name="Debug|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						UsePrecompiledHeader="0"

+						CompileAsManaged="0"

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						UsePrecompiledHeader="0"

+						CompileAsManaged="0"

+					/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath=".\dllmain.cpp"

+				>

+				<FileConfiguration

+					Name="Debug|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						UsePrecompiledHeader="0"

+						CompileAsManaged="0"

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						UsePrecompiledHeader="0"

+						CompileAsManaged="0"

+					/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath=".\ExceptionCatcher.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\IESessionHandler.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\JavaObject.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\oophm.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\oophm.def"

+				>

+			</File>

+			<File

+				RelativePath=".\oophm.idl"

+				>

+			</File>

+			<File

+				RelativePath=".\plugin.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\stdafx.cpp"

+				>

+				<FileConfiguration

+					Name="Debug|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						UsePrecompiledHeader="1"

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						UsePrecompiledHeader="1"

+					/>

+				</FileConfiguration>

+			</File>

+			<Filter

+				Name="common"

+				>

+				<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="..\..\..\common\LoadJsniMessage.cpp"

+					>

+				</File>

+				<File

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

+					>

+				</File>

+				<File

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

+					>

+				</File>

+				<File

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

+					>

+				</File>

+				<File

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

+					>

+				</File>

+			</Filter>

+		</Filter>

+		<Filter

+			Name="Header Files"

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

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

+			>

+			<File

+				RelativePath=".\dlldatax.h"

+				>

+			</File>

+			<File

+				RelativePath=".\dllmain.h"

+				>

+			</File>

+			<File

+				RelativePath=".\ExceptionCatcher.h"

+				>

+			</File>

+			<File

+				RelativePath=".\IESessionHandler.h"

+				>

+			</File>

+			<File

+				RelativePath=".\JavaObject.h"

+				>

+			</File>

+			<File

+				RelativePath=".\plugin.h"

+				>

+			</File>

+			<File

+				RelativePath=".\Resource.h"

+				>

+			</File>

+			<File

+				RelativePath=".\SessionData.h"

+				>

+			</File>

+			<File

+				RelativePath=".\stdafx.h"

+				>

+			</File>

+			<File

+				RelativePath=".\targetver.h"

+				>

+			</File>

+			<Filter

+				Name="common"

+				>

+				<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="..\..\..\common\LoadJsniMessage.h"

+					>

+				</File>

+				<File

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

+					>

+				</File>

+				<File

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

+					>

+				</File>

+				<File

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

+					>

+				</File>

+				<File

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

+					>

+				</File>

+				<File

+					RelativePath="..\..\..\common\ReturnMessage.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>

+		<Filter

+			Name="Resource Files"

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

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

+			>

+			<File

+				RelativePath=".\ExceptionCatcher.rgs"

+				>

+			</File>

+			<File

+				RelativePath=".\JavaObject.rgs"

+				>

+			</File>

+			<File

+				RelativePath=".\oophm.rc"

+				>

+			</File>

+			<File

+				RelativePath=".\oophm.rgs"

+				>

+			</File>

+			<File

+				RelativePath=".\plugin.bmp"

+				>

+			</File>

+			<File

+				RelativePath=".\plugin.rgs"

+				>

+			</File>

+		</Filter>

+		<Filter

+			Name="Generated Files"

+			SourceControlFiles="false"

+			>

+			<File

+				RelativePath=".\oophm_i.c"

+				>

+				<FileConfiguration

+					Name="Debug|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						UsePrecompiledHeader="0"

+						CompileAsManaged="0"

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						UsePrecompiledHeader="0"

+						CompileAsManaged="0"

+					/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath=".\oophm_i.h"

+				>

+			</File>

+		</Filter>

+		<File

+			RelativePath=".\plugin.htm"

+			DeploymentContent="true"

+			>

+		</File>

+		<File

+			RelativePath=".\pluginUI.htm"

+			DeploymentContent="true"

+			>

+		</File>

+		<File

+			RelativePath=".\ReadMe.txt"

+			>

+		</File>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/plugins/ie/oophm/oophm/plugin.bmp b/plugins/ie/oophm/oophm/plugin.bmp
new file mode 100644
index 0000000..1229764
--- /dev/null
+++ b/plugins/ie/oophm/oophm/plugin.bmp
Binary files differ
diff --git a/plugins/ie/oophm/oophm/plugin.cpp b/plugins/ie/oophm/oophm/plugin.cpp
new file mode 100644
index 0000000..cf8b7f2
--- /dev/null
+++ b/plugins/ie/oophm/oophm/plugin.cpp
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+// plugin.cpp : Implementation of Cplugin
+#include "stdafx.h"
+#include "comutil.h"
+#include "plugin.h"
+#include "JavaObject.h"
+#include "HostChannel.h"
+#include "IESessionHandler.h"
+#include "LoadModuleMessage.h"
+#include "ServerMethods.h"
+
+// Cplugin
+
+STDMETHODIMP Cplugin::connect(BSTR burl, BSTR bmoduleName, IDispatch* jsniContext, VARIANT_BOOL* ret)
+{
+  // TODO: Add your implementation code here
+  LPOLECLIENTSITE site;
+  IOleContainer* container = NULL;
+  IHTMLDocument2* doc = NULL;
+  IHTMLWindow2* window = NULL;
+
+  this->GetClientSite(&site);
+  site->GetContainer(&container);
+  container->QueryInterface(IID_IHTMLDocument2, (void**)&doc);
+  container->Release();
+
+  doc->get_parentWindow(&window);
+  doc->Release();
+
+  std::string url = BSTRToUTF8(burl);
+  size_t index = url.find(':');
+  if (index == std::string::npos) {
+    *ret = false;
+    return S_OK;
+  }
+  std::string hostPart = url.substr(0, index);
+  std::string portPart = url.substr(index + 1);
+
+  HostChannel* channel = new HostChannel();
+
+  // TODO : Update HostChannel to take a const char*
+  if (!channel->connectToHost(
+      const_cast<char*>(hostPart.c_str()),
+      atoi(portPart.c_str()))) {
+    *ret = false;
+    return S_OK;
+  }
+
+  sessionHandler.reset(new IESessionHandler(channel, window));
+  std::string moduleName = BSTRToUTF8(bmoduleName);
+  IOmNavigator* navigator;
+  _bstr_t userAgent;
+
+  window->get_navigator(&navigator);
+  navigator->get_userAgent(userAgent.GetAddress());
+
+  LoadModuleMessage::send(*channel, 1,
+    moduleName.c_str(), moduleName.length(),
+    BSTRToUTF8(userAgent).c_str(),
+    sessionHandler.get());
+
+  navigator->Release();
+
+  *ret = true;
+  return S_OK;
+}
+
+STDMETHODIMP Cplugin::testObject(IDispatch** ret)
+{
+  IJavaObject* toRet;
+  CJavaObject::CreateInstance(&toRet);
+  *ret = toRet;
+  // TODO: Add your implementation code here
+
+  return S_OK;
+}
diff --git a/plugins/ie/oophm/oophm/plugin.h b/plugins/ie/oophm/oophm/plugin.h
new file mode 100644
index 0000000..ea91ab0
--- /dev/null
+++ b/plugins/ie/oophm/oophm/plugin.h
@@ -0,0 +1,222 @@
+/*
+ * 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.
+ */
+
+// plugin.h : Declaration of the Cplugin
+#pragma once
+#include "resource.h"       // main symbols
+#include <atlctl.h>
+#include "oophm_i.h"
+#include "Debug.h"
+#include "IESessionHandler.h"
+
+#ifdef _WIN32_WCE
+#error "ATL does not support HTML controls for Windows CE."
+#endif
+class ATL_NO_VTABLE CpluginUI :
+	public IDispatchImpl<IpluginUI, &IID_IpluginUI, &LIBID_oophmLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
+	public CComObjectRootEx<CComSingleThreadModel>
+{
+BEGIN_COM_MAP(CpluginUI)
+	COM_INTERFACE_ENTRY(IpluginUI)
+	COM_INTERFACE_ENTRY(IDispatch)
+END_COM_MAP()
+// Iplugin
+public:
+	DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+	HRESULT FinalConstruct()
+	{
+		return S_OK;
+	}
+
+	void FinalRelease()
+	{
+	}
+
+	// Example method called by the HTML to change the <BODY> background color
+	STDMETHOD(OnClick)(IDispatch* pdispBody, VARIANT varColor)
+	{
+		CComQIPtr<IHTMLBodyElement> spBody(pdispBody);
+		if (spBody != NULL)
+			spBody->put_bgColor(varColor);
+		return S_OK;
+	}
+};
+
+
+
+// Cplugin
+class ATL_NO_VTABLE Cplugin :
+	public CComObjectRootEx<CComSingleThreadModel>,
+	public IDispatchImpl<Iplugin, &IID_Iplugin, &LIBID_oophmLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
+	public IPersistStreamInitImpl<Cplugin>,
+	public IOleControlImpl<Cplugin>,
+	public IOleObjectImpl<Cplugin>,
+	public IOleInPlaceActiveObjectImpl<Cplugin>,
+	public IViewObjectExImpl<Cplugin>,
+	public IOleInPlaceObjectWindowlessImpl<Cplugin>,
+	public ISupportErrorInfo,
+	public IPersistStorageImpl<Cplugin>,
+	public ISpecifyPropertyPagesImpl<Cplugin>,
+	public IQuickActivateImpl<Cplugin>,
+	public IObjectSafetyImpl<Cplugin, INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA>,
+#ifndef _WIN32_WCE
+	public IDataObjectImpl<Cplugin>,
+#endif
+	public IProvideClassInfo2Impl<&CLSID_plugin, NULL, &LIBID_oophmLib>,
+#ifdef _WIN32_WCE // IObjectSafety is required on Windows CE for the control to be loaded correctly
+	public IObjectSafetyImpl<Cplugin, INTERFACESAFE_FOR_UNTRUSTED_CALLER>,
+#endif
+	public CComCoClass<Cplugin, &CLSID_plugin>,
+	public CComControl<Cplugin>
+{
+public:
+
+
+	Cplugin()
+	{
+		m_bWindowOnly = TRUE;
+	}
+
+DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE |
+	OLEMISC_CANTLINKINSIDE |
+	OLEMISC_INSIDEOUT |
+	OLEMISC_ACTIVATEWHENVISIBLE |
+	OLEMISC_SETCLIENTSITEFIRST
+)
+
+DECLARE_REGISTRY_RESOURCEID(IDR_PLUGIN)
+
+
+BEGIN_COM_MAP(Cplugin)
+	COM_INTERFACE_ENTRY(Iplugin)
+	COM_INTERFACE_ENTRY(IDispatch)
+	COM_INTERFACE_ENTRY(IViewObjectEx)
+	COM_INTERFACE_ENTRY(IViewObject2)
+	COM_INTERFACE_ENTRY(IViewObject)
+	COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
+	COM_INTERFACE_ENTRY(IOleInPlaceObject)
+	COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
+	COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
+	COM_INTERFACE_ENTRY(IOleControl)
+	COM_INTERFACE_ENTRY(IOleObject)
+	COM_INTERFACE_ENTRY(IPersistStreamInit)
+	COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)
+	COM_INTERFACE_ENTRY(ISupportErrorInfo)
+	COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
+	COM_INTERFACE_ENTRY(IQuickActivate)
+	COM_INTERFACE_ENTRY(IPersistStorage)
+	COM_INTERFACE_ENTRY(IObjectSafety)
+#ifndef _WIN32_WCE
+	COM_INTERFACE_ENTRY(IDataObject)
+#endif
+	COM_INTERFACE_ENTRY(IProvideClassInfo)
+	COM_INTERFACE_ENTRY(IProvideClassInfo2)
+#ifdef _WIN32_WCE // IObjectSafety is required on Windows CE for the control to be loaded correctly
+	COM_INTERFACE_ENTRY_IID(IID_IObjectSafety, IObjectSafety)
+#endif
+END_COM_MAP()
+
+BEGIN_PROP_MAP(Cplugin)
+	PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
+	PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
+	// Example entries
+	// PROP_ENTRY_TYPE("Property Name", dispid, clsid, vtType)
+	// PROP_PAGE(CLSID_StockColorPage)
+END_PROP_MAP()
+
+
+BEGIN_MSG_MAP(Cplugin)
+	MESSAGE_HANDLER(WM_CREATE, OnCreate)
+	CHAIN_MSG_MAP(CComControl<Cplugin>)
+	DEFAULT_REFLECTION_HANDLER()
+END_MSG_MAP()
+// Handler prototypes:
+//  LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+//  LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+//  LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
+
+// ISupportsErrorInfo
+	STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
+	{
+		static const IID* arr[] =
+		{
+			&IID_Iplugin,
+		};
+
+		for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
+		{
+			if (InlineIsEqualGUID(*arr[i], riid))
+				return S_OK;
+		}
+		return S_FALSE;
+	}
+
+// IViewObjectEx
+	DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)
+
+// Iplugin
+
+	LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+	{
+		CAxWindow wnd(m_hWnd);
+		wnd.ModifyStyle(0, WS_HSCROLL | WS_VSCROLL);
+		HRESULT hr = wnd.CreateControl(IDH_PLUGIN);
+		if (SUCCEEDED(hr))
+		{
+			CComObject<CpluginUI> *pObject = NULL;
+			hr = CComObject<CpluginUI>::CreateInstance(&pObject);
+			if (SUCCEEDED(hr) && pObject != NULL)
+				hr = wnd.SetExternalDispatch(static_cast<IpluginUI*>(pObject));
+		}
+		if (SUCCEEDED(hr))
+			hr = wnd.QueryControl(IID_IWebBrowser2, (void**)&m_spBrowser);
+		return SUCCEEDED(hr) ? 0 : -1;
+	}
+
+	STDMETHOD(TranslateAccelerator)(LPMSG pMsg)
+	{
+		CComPtr<IOleInPlaceActiveObject> spIOleInPlaceActiveObject;
+
+		HRESULT hr = m_spBrowser->QueryInterface(&spIOleInPlaceActiveObject);
+		if (SUCCEEDED(hr))
+			hr = spIOleInPlaceActiveObject->TranslateAccelerator(pMsg);
+		if (hr != S_OK)
+			hr = IOleInPlaceActiveObjectImpl<Cplugin>::TranslateAccelerator(pMsg);
+
+		return hr;
+	}
+	CComPtr<IWebBrowser2> m_spBrowser;
+
+	DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+	HRESULT FinalConstruct()
+	{
+		return S_OK;
+	}
+
+	void FinalRelease()
+	{
+    Debug::log(Debug::Debugging) << "OOPHM plugin FinalRelease" << Debug::flush;
+	}
+
+	STDMETHOD(connect)(BSTR url, BSTR moduleName, IDispatch* jsniContext, VARIANT_BOOL* ret);
+	STDMETHOD(testObject)(IDispatch** ret);
+private:
+  scoped_ptr<IESessionHandler> sessionHandler;
+};
+
+OBJECT_ENTRY_AUTO(__uuidof(plugin), Cplugin)
diff --git a/plugins/ie/oophm/oophm/plugin.htm b/plugins/ie/oophm/oophm/plugin.htm
new file mode 100644
index 0000000..b3d8a77
--- /dev/null
+++ b/plugins/ie/oophm/oophm/plugin.htm
@@ -0,0 +1,19 @@
+<HTML>
+<HEAD>
+<TITLE>ATL 8.0 test page for object plugin</TITLE>
+</HEAD>
+<BODY>
+
+
+<OBJECT ID="plugin" CLASSID="CLSID:1D6156B6-002B-49E7-B5CA-C138FB843B4E"></OBJECT>
+
+<script>
+var p = document.getElementById("plugin");
+var b = p.connect("this", "sucks");
+var o = p.testObject();
+o.doSomething(42);
+
+
+</script>
+</BODY>
+</HTML>
diff --git a/plugins/ie/oophm/oophm/plugin.rgs b/plugins/ie/oophm/oophm/plugin.rgs
new file mode 100644
index 0000000..33e8062
--- /dev/null
+++ b/plugins/ie/oophm/oophm/plugin.rgs
@@ -0,0 +1,34 @@
+HKCR

+{

+	oophm.plugin.1 = s 'plugin Class'

+	{

+		CLSID = s '{1D6156B6-002B-49E7-B5CA-C138FB843B4E}'

+	}

+	oophm.plugin = s 'plugin Class'

+	{

+		CLSID = s '{1D6156B6-002B-49E7-B5CA-C138FB843B4E}'

+		CurVer = s 'oophm.plugin.1'

+	}

+	NoRemove CLSID

+	{

+		ForceRemove {1D6156B6-002B-49E7-B5CA-C138FB843B4E} = s 'plugin Class'

+		{

+			ProgID = s 'oophm.plugin.1'

+			VersionIndependentProgID = s 'oophm.plugin'

+			ForceRemove 'Programmable'

+			InprocServer32 = s '%MODULE%'

+			{

+				val ThreadingModel = s 'Apartment'

+			}

+			val AppID = s '%APPID%'

+			ForceRemove 'Control'

+			ForceRemove 'ToolboxBitmap32' = s '%MODULE%, 102'

+			'MiscStatus' = s '0'

+			{

+			    '1' = s '%OLEMISC%'

+			}

+			'TypeLib' = s '{9259F105-BE55-4BF6-B7CE-D0AA878C1BA6}'

+			'Version' = s '1.0'

+		}

+	}

+}

diff --git a/plugins/ie/oophm/oophm/pluginUI.htm b/plugins/ie/oophm/oophm/pluginUI.htm
new file mode 100644
index 0000000..7a017d7
--- /dev/null
+++ b/plugins/ie/oophm/oophm/pluginUI.htm
@@ -0,0 +1,11 @@
+<HTML>
+<BODY id=theBody>
+<BUTTON onclick='window.external.OnClick(theBody, "red");'>Red</BUTTON>
+<BR>
+<BR>
+<BUTTON onclick='window.external.OnClick(theBody, "green");'>Green</BUTTON>
+<BR>
+<BR>
+<BUTTON onclick='window.external.OnClick(theBody, "blue");'>Blue</BUTTON>
+</BODY>
+</HTML>
diff --git a/plugins/ie/oophm/oophm/stdafx.cpp b/plugins/ie/oophm/oophm/stdafx.cpp
new file mode 100644
index 0000000..39ac1a3
--- /dev/null
+++ b/plugins/ie/oophm/oophm/stdafx.cpp
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+// stdafx.cpp : source file that includes just the standard includes
+// oophm.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
diff --git a/plugins/ie/oophm/oophm/stdafx.h b/plugins/ie/oophm/oophm/stdafx.h
new file mode 100644
index 0000000..c397df1
--- /dev/null
+++ b/plugins/ie/oophm/oophm/stdafx.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#pragma once
+
+#ifndef STRICT
+#define STRICT
+#endif
+
+#include "targetver.h"
+
+#define _ATL_APARTMENT_THREADED
+#define _ATL_NO_AUTOMATIC_NAMESPACE
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS	// some CString constructors will be explicit
+
+#include "resource.h"
+#include <atlbase.h>
+#include <atlcom.h>
+#include <atlctl.h>
+
+// We want to bake GUID defs into the app
+#include "initguid.h"
+
+using namespace ATL;
diff --git a/plugins/ie/oophm/oophm/targetver.h b/plugins/ie/oophm/oophm/targetver.h
new file mode 100644
index 0000000..e33be6a
--- /dev/null
+++ b/plugins/ie/oophm/oophm/targetver.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+// The following macros define the minimum required platform.  The minimum required platform
+// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run 
+// your application.  The macros work by enabling all features available on platform versions up to and 
+// including the version specified.
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef WINVER                          // Specifies that the minimum required platform is Windows Vista.
+#define WINVER 0x0501           // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINNT            // Specifies that the minimum required platform is Windows Vista.
+#define _WIN32_WINNT 0x0501     // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINDOWS          // Specifies that the minimum required platform is Windows 98.
+#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
+#endif
+
+#ifndef _WIN32_IE                       // Specifies that the minimum required platform is Internet Explorer 7.0.
+#define _WIN32_IE 0x0600        // Change this to the appropriate value to target other versions of IE.
+#endif
+
diff --git a/plugins/ie/prebuilt/oophm.dll b/plugins/ie/prebuilt/oophm.dll
new file mode 100644
index 0000000..1ae8067
--- /dev/null
+++ b/plugins/ie/prebuilt/oophm.dll
Binary files differ
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
diff --git a/plugins/webkit/Browser/AppController.h b/plugins/webkit/Browser/AppController.h
new file mode 100644
index 0000000..2d4747f
--- /dev/null
+++ b/plugins/webkit/Browser/AppController.h
@@ -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.
+ */
+
+#import <Cocoa/Cocoa.h>
+#import <WebKit/WebKit.h>
+
+@interface AppController : NSObject
+{
+    IBOutlet WebView *webview;
+}
+- (IBAction)newWindow:(id)sender;
+@end
diff --git a/plugins/webkit/Browser/AppController.m b/plugins/webkit/Browser/AppController.m
new file mode 100644
index 0000000..046a507
--- /dev/null
+++ b/plugins/webkit/Browser/AppController.m
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#import "AppController.h"
+#import "BrowserWindow.h"
+
+@implementation AppController
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
+  NSLog(@"%s", __PRETTY_FUNCTION__);
+  
+  if (![WebView canShowMIMEType:@"application/x-gwt-hosted-mode"]) {
+    NSLog(@"plugin not available");
+    exit(-1);
+  }
+  NSString* str = @"http://localhost:8888/com.google.gwt.dev.jjs.CompilerSuite.JUnit/junit.html?gwt.hosted=localhost:9997";
+//  NSString* str = @"http://localhost:8888/com.google.gwt.user.RPCSuite.JUnit/junit.html?gwt.hosted=localhost:9997";
+//  NSString* str = @"http://localhost:8888/com.google.gwt.user.User.JUnit/junit.html?gwt.hosted=localhost:9997";
+  [webview setUIDelegate:self];
+  [webview setShouldCloseWithWindow: YES];
+  [[webview mainFrame] loadRequest: [NSURLRequest requestWithURL:[NSURL URLWithString:str]]];
+}
+
+- (IBAction)newWindow:(id)sender {
+  NSLog(@"Action received");
+  NSRect r;
+  r.origin.x = 100;
+  r.origin.y = 100;
+  r.size.height = 500;
+  r.size.width = 500;
+  
+  WebView* webView = [[WebView alloc] initWithFrame:r];
+  NSString* str = @"http://localhost:8888/com.google.gwt.sample.kitchensink.KitchenSink/KitchenSink.html?gwt.hosted=localhost:9997";
+  [webView setUIDelegate:self];
+  [webView setShouldCloseWithWindow: YES];
+  [[webView mainFrame] loadRequest: [NSURLRequest requestWithURL:[NSURL URLWithString:str]]];
+  
+  NSWindow* wnd = [[BrowserWindow alloc] initWithContentRect:r styleMask:NSResizableWindowMask|NSClosableWindowMask backing:NSBackingStoreBuffered defer:NO];
+  [wnd setContentView:webView];
+  [wnd makeKeyAndOrderFront:self];
+}
+
+- (void)webView:(WebView *)sender windowScriptObjectAvailable:(WebScriptObject *)windowScriptObject {
+  NSLog(@"%s", __PRETTY_FUNCTION__);
+}
+
+@end
diff --git a/plugins/webkit/Browser/Browser-Info.plist b/plugins/webkit/Browser/Browser-Info.plist
new file mode 100644
index 0000000..c597e30
--- /dev/null
+++ b/plugins/webkit/Browser/Browser-Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIconFile</key>
+	<string>gwtlogo</string>
+	<key>CFBundleIdentifier</key>
+	<string>com.google.gwt.oophm.browser</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+	<key>NSMainNibFile</key>
+	<string>browser.nib</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+</dict>
+</plist>
diff --git a/plugins/webkit/Browser/BrowserWindow.h b/plugins/webkit/Browser/BrowserWindow.h
new file mode 100644
index 0000000..18664ed
--- /dev/null
+++ b/plugins/webkit/Browser/BrowserWindow.h
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+@interface BrowserWindow : NSWindow {
+
+}
+
+@end
diff --git a/plugins/webkit/Browser/BrowserWindow.m b/plugins/webkit/Browser/BrowserWindow.m
new file mode 100644
index 0000000..c822886
--- /dev/null
+++ b/plugins/webkit/Browser/BrowserWindow.m
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#import "BrowserWindow.h"
+
+@implementation BrowserWindow
+
+@end
diff --git a/plugins/webkit/Browser/browser.nib/classes.nib b/plugins/webkit/Browser/browser.nib/classes.nib
new file mode 100644
index 0000000..af71aad
--- /dev/null
+++ b/plugins/webkit/Browser/browser.nib/classes.nib
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBClasses</key>
+	<array>
+		<dict>
+			<key>CLASS</key>
+			<string>BrowserWindow</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>SUPERCLASS</key>
+			<string>NSWindow</string>
+		</dict>
+		<dict>
+			<key>ACTIONS</key>
+			<dict>
+				<key>toggleAutomaticLinkDetection</key>
+				<string>id</string>
+				<key>toggleAutomaticQuoteSubstitution</key>
+				<string>id</string>
+				<key>toggleGrammarChecking</key>
+				<string>id</string>
+				<key>toggleSmartInsertDelete</key>
+				<string>id</string>
+			</dict>
+			<key>CLASS</key>
+			<string>FirstResponder</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>SUPERCLASS</key>
+			<string>NSObject</string>
+		</dict>
+		<dict>
+			<key>ACTIONS</key>
+			<dict>
+				<key>newWindow</key>
+				<string>id</string>
+			</dict>
+			<key>CLASS</key>
+			<string>AppController</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>OUTLETS</key>
+			<dict>
+				<key>webview</key>
+				<string>WebView</string>
+			</dict>
+			<key>SUPERCLASS</key>
+			<string>NSObject</string>
+		</dict>
+	</array>
+	<key>IBVersion</key>
+	<string>1</string>
+</dict>
+</plist>
diff --git a/plugins/webkit/Browser/browser.nib/info.nib b/plugins/webkit/Browser/browser.nib/info.nib
new file mode 100644
index 0000000..6271e8e
--- /dev/null
+++ b/plugins/webkit/Browser/browser.nib/info.nib
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBFramework Version</key>
+	<string>629</string>
+	<key>IBLastKnownRelativeProjectPath</key>
+	<string>../../oophm.xcodeproj</string>
+	<key>IBOldestOS</key>
+	<integer>5</integer>
+	<key>IBOpenObjects</key>
+	<array/>
+	<key>IBSystem Version</key>
+	<string>9C7010</string>
+	<key>targetFramework</key>
+	<string>IBCocoaFramework</string>
+</dict>
+</plist>
diff --git a/plugins/webkit/Browser/browser.nib/keyedobjects.nib b/plugins/webkit/Browser/browser.nib/keyedobjects.nib
new file mode 100644
index 0000000..7691b0d
--- /dev/null
+++ b/plugins/webkit/Browser/browser.nib/keyedobjects.nib
Binary files differ
diff --git a/plugins/webkit/Browser/main.m b/plugins/webkit/Browser/main.m
new file mode 100644
index 0000000..f1a7cba
--- /dev/null
+++ b/plugins/webkit/Browser/main.m
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, char *argv[])
+{
+    return NSApplicationMain(argc,  (const char **) argv);
+}
diff --git a/plugins/webkit/Core/ObjectFunctions.cpp b/plugins/webkit/Core/ObjectFunctions.cpp
new file mode 100644
index 0000000..a0a4a73
--- /dev/null
+++ b/plugins/webkit/Core/ObjectFunctions.cpp
@@ -0,0 +1,100 @@
+/*
+ * 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 "ObjectFunctions.h"
+#include "WebScriptSessionHandler.h"
+#include "scoped_ptr.h"
+
+JSValueRef JavaObjectCallAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
+                                            size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) {
+  TrackingDataRef tracker = static_cast<TrackingDataRef>(JSObjectGetPrivate(function));
+  WebScriptSessionHandler* sessionHandler = static_cast<WebScriptSessionHandler*>(tracker->getSessionData());
+  
+  *exception = NULL;
+  int dispatchId = JSValueToNumber(ctx, arguments[0], exception);
+  if (*exception) {
+    return JSValueMakeUndefined(ctx);
+  }
+  
+  bool explicitThis = JSValueToBoolean(ctx, arguments[1]);
+  if (explicitThis) {
+    thisObject = JSValueToObject(ctx, arguments[1], exception);
+    if (*exception) {
+      return JSValueMakeUndefined(ctx);
+    }
+  } else {
+    thisObject = function;
+  }
+  
+  return sessionHandler->javaFunctionCallbackImpl(dispatchId, thisObject,
+                                                  argumentCount - 2, &arguments[2], exception);  
+}
+
+/*
+ * Static-dispatch function to clean up a Java object proxy.  This will
+ * deallocate the TrackingData as well as remove the objectId mapping.  This
+ * function is called from JavaScriptCore as well as ~WebScriptSessionHandler.
+ *
+ * The JavaScriptCore documentation indicates that finalizers may be called
+ * from any thread, so we can't see javaFree messages directly from this
+ * method.  Instead, we'll accumulate a list of ids to free. 
+ */
+void JavaObjectFinalize (JSObjectRef object) {
+  TrackingDataRef tracker = static_cast<TrackingDataRef>(JSObjectGetPrivate(object));
+  if (!tracker) {
+    // The tracker may have already been deleted in ~WebScriptSessionHandler()
+    return;
+  }
+  Debug::log(Debug::Spam) << "Finalizing Java object " << tracker->getObjectId() << Debug::flush;
+  JSObjectSetPrivate(object, NULL);
+  int id = tracker->getObjectId();  
+  WebScriptSessionHandler* sessionHandler = static_cast<WebScriptSessionHandler*>(tracker->getSessionData());
+  delete tracker;
+  sessionHandler->javaObjectFinalizeImpl(id);
+}
+
+/*
+ * Static-dispatch function to check for the presence of a property on a Java
+ * object proxy.
+ */
+bool JavaObjectHasProperty (JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) {
+  TrackingDataRef tracker = static_cast<TrackingDataRef>(JSObjectGetPrivate(object));
+  WebScriptSessionHandler* sessionHandler = static_cast<WebScriptSessionHandler*>(tracker->getSessionData());
+  return sessionHandler->javaObjectHasPropertyImpl(tracker, object, propertyName);
+}
+
+/*
+ * Static-dispatch function to retrieve the value of a property on a Java
+ * object proxy.
+ */
+JSValueRef JavaObjectGetProperty (JSContextRef ctx, JSObjectRef object,
+                                         JSStringRef propertyName, JSValueRef* exception) {
+  TrackingDataRef tracker = static_cast<TrackingDataRef>(JSObjectGetPrivate(object));
+  WebScriptSessionHandler* sessionHandler = static_cast<WebScriptSessionHandler*>(tracker->getSessionData());
+  return sessionHandler->javaObjectGetPropertyImpl(tracker, object, propertyName, exception);
+}
+
+/*
+ * Static-dispatch function to set the value of a property an a Java object
+ * proxy.
+ */
+bool JavaObjectSetProperty (JSContextRef ctx, JSObjectRef object,
+                                   JSStringRef propertyName, JSValueRef value,
+                                   JSValueRef* exception) {
+  TrackingDataRef tracker = static_cast<TrackingDataRef>(JSObjectGetPrivate(object));
+  WebScriptSessionHandler* sessionHandler = static_cast<WebScriptSessionHandler*>(tracker->getSessionData());
+  return sessionHandler->javaObjectSetPropertyImpl(tracker, object, propertyName, value, exception);
+}
diff --git a/plugins/webkit/Core/ObjectFunctions.h b/plugins/webkit/Core/ObjectFunctions.h
new file mode 100644
index 0000000..176218e
--- /dev/null
+++ b/plugins/webkit/Core/ObjectFunctions.h
@@ -0,0 +1,55 @@
+/*
+ * 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 "JavaScriptCore/JavaScriptCore.h"
+
+/*
+ * Handle JSNI function invocations.
+ */
+JSValueRef JavaObjectCallAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
+                                    size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+/*
+ * Static-dispatch function to clean up a Java object proxy.  This will
+ * deallocate the TrackingData as well as remove the objectId mapping.  This
+ * function is called from JavaScriptCore as well as ~WebScriptSessionHandler.
+ *
+ * The JavaScriptCore documentation indicates that finalizers may be called
+ * from any thread, so we can't see javaFree messages directly from this
+ * method.  Instead, we'll accumulate a list of ids to free. 
+ */
+void JavaObjectFinalize (JSObjectRef object);
+
+/*
+ * Static-dispatch function to check for the presence of a property on a Java
+ * object proxy.
+ */
+bool JavaObjectHasProperty (JSContextRef ctx, JSObjectRef object, JSStringRef propertyName);
+
+/*
+ * Static-dispatch function to retrieve the value of a property on a Java
+ * object proxy.
+ */
+JSValueRef JavaObjectGetProperty (JSContextRef ctx, JSObjectRef object,
+                                         JSStringRef propertyName, JSValueRef* exception);
+
+/*
+ * Static-dispatch function to set the value of a property an a Java object
+ * proxy.
+ */
+bool JavaObjectSetProperty (JSContextRef ctx, JSObjectRef object,
+                                   JSStringRef propertyName, JSValueRef value,
+                                   JSValueRef* exception);
\ No newline at end of file
diff --git a/plugins/webkit/Core/SessionData.h b/plugins/webkit/Core/SessionData.h
new file mode 100644
index 0000000..9f60ddf
--- /dev/null
+++ b/plugins/webkit/Core/SessionData.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#import "HostChannel.h"
+#import "JavaScriptCore/JavaScriptCore.h"
+#import "SessionHandler.h"
+
+/*
+ * Encapsules per-OOPHM-session data.
+ */
+class SessionData {
+public:
+  SessionData(HostChannel* channel, JSGlobalContextRef contextRef, 
+              SessionHandler* sessionHandler) : channel(channel),
+                                                contextRef(contextRef),
+                                                sessionHandler(sessionHandler) {
+  }
+  
+  JSGlobalContextRef getContext() const {
+    return contextRef;
+  }
+  
+  HostChannel* getHostChannel() const {
+    return channel;
+  }
+  
+  SessionHandler* getSessionHandler() const {
+    return sessionHandler;
+  }
+
+protected:
+  /*
+   * The communication channel used for the OOPHM session.
+   */
+  HostChannel* const channel;
+  
+  /*
+   * The JavaScriptCore interpreter instance.
+   */
+  JSGlobalContextRef const contextRef;
+  
+  /*
+   * A reference to the SessionHandler being used in the OOPHM session.
+   */
+  SessionHandler* const sessionHandler;
+};
+typedef SessionData* SessionDataRef;
\ No newline at end of file
diff --git a/plugins/webkit/Core/TrackingData.h b/plugins/webkit/Core/TrackingData.h
new file mode 100644
index 0000000..de19f00
--- /dev/null
+++ b/plugins/webkit/Core/TrackingData.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+#import "SessionData.h"
+
+/*
+ * This class encapsulates per-object information to determine how to dispatch
+ * a given JSObjectRef that is a Java object proxy. Instances of
+ * this class are intended to be stored in the private data area provided
+ * by JSObjectRef.
+ */
+class TrackingData {
+public:
+  /*
+   * Constructor for Java object proxies.
+   */
+  TrackingData(const SessionDataRef sessionData, const unsigned objId) :
+  objId(objId), sessionData(sessionData) {
+  }
+  
+  const unsigned getObjectId() const {
+    return objId;
+  }
+  
+  SessionDataRef getSessionData() const {
+    return sessionData;
+  }
+  
+private:
+  /*
+   * The tracking number assigned to the object.
+   */
+  const unsigned objId;
+  
+  /*
+   * A reference to the per-OOPHM-session data.
+   */
+  SessionDataRef const sessionData;  
+};
+typedef const TrackingData* TrackingDataRef;
diff --git a/plugins/webkit/Core/WebScriptSessionHandler.cpp b/plugins/webkit/Core/WebScriptSessionHandler.cpp
new file mode 100644
index 0000000..95caff5
--- /dev/null
+++ b/plugins/webkit/Core/WebScriptSessionHandler.cpp
@@ -0,0 +1,696 @@
+/*
+ * 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.
+ */
+
+#import "WebScriptSessionHandler.h"
+#import "InvokeMessage.h"
+#import "ObjectFunctions.h"
+#import "ServerMethods.h"
+#import "TrackingData.h"
+#import "scoped_ptr.h"
+
+
+WebScriptSessionHandler::WebScriptSessionHandler(HostChannel* channel,
+                                                 JSGlobalContextRef contextRef,
+                                                 CrashHandlerRef crashHandler) : 
+SessionData(channel, contextRef, this), jsObjectId(1), crashHandler(crashHandler) {
+
+  JSClassDefinition def = kJSClassDefinitionEmpty;
+  def.className = "JavaObject";
+  def.hasProperty = JavaObjectHasProperty;
+  def.callAsFunction = JavaObjectCallAsFunction;
+  def.finalize = JavaObjectFinalize;
+  def.getProperty = JavaObjectGetProperty;
+  def.setProperty = JavaObjectSetProperty;
+  javaObjectWrapperClass = JSClassCreate(&def);
+  JSClassRetain(javaObjectWrapperClass);
+  
+  // Get the String constructor function to tell Strings from other Objects
+  JSStringRef stringString = JSStringCreateWithUTF8CString("String");
+  JSValueRef stringConstructorValue = JSObjectGetProperty(contextRef,
+                                                          JSContextGetGlobalObject(contextRef),
+                                                          stringString, NULL);
+  stringConstructor = JSValueToObject(contextRef, stringConstructorValue, NULL);
+  JSValueProtect(contextRef, stringConstructor);
+  JSStringRelease(stringString);
+  
+  // Call out to the utility __gwt_makeResult function to create the return array
+  JSStringRef makeResultString = JSStringCreateWithUTF8CString("__gwt_makeResult");
+  JSValueRef makeResultValue = JSObjectGetProperty(contextRef, JSContextGetGlobalObject(contextRef), makeResultString, NULL);
+  JSStringRelease(makeResultString);
+  
+  if (!JSValueIsObject(contextRef, makeResultValue)) {
+    crashHandler->crash(__PRETTY_FUNCTION__, "Could not find __gwt_makeResult");
+  } else {
+    makeResultFunction = JSValueToObject(contextRef, makeResultValue, NULL);
+    JSValueProtect(contextRef, makeResultFunction);
+  }
+  
+  pthread_mutexattr_t mutexAttrs;
+  pthread_mutexattr_init(&mutexAttrs);
+  // This behaves basically like the Java synchronized keyword
+  pthread_mutexattr_settype(&mutexAttrs, PTHREAD_MUTEX_RECURSIVE);
+  pthread_mutex_init(&javaObjectsLock, &mutexAttrs);
+  pthread_mutexattr_destroy(&mutexAttrs);
+}
+
+WebScriptSessionHandler::~WebScriptSessionHandler() {
+  std::map<int, JSObjectRef>::iterator i;
+  
+  pthread_mutex_lock(&javaObjectsLock);
+  while ((i = javaObjectsById.begin()) != javaObjectsById.end()) {
+    JavaObjectFinalize(i->second);
+  }
+  pthread_mutex_unlock(&javaObjectsLock);
+  
+  for (i = jsObjectsById.begin(); i != jsObjectsById.end(); i++) {
+    JSObjectRef ref = i->second;
+    delete static_cast<TrackingDataRef>(JSObjectGetPrivate(ref));
+    JSObjectSetPrivate(ref, NULL);
+    JSValueUnprotect(contextRef, i->second);
+  }
+  
+  JSClassRelease(javaObjectWrapperClass);
+  
+  JSValueUnprotect(contextRef, stringConstructor);
+  JSValueUnprotect(contextRef, makeResultFunction);
+  
+  JSGarbageCollect(contextRef);
+  pthread_mutex_destroy(&javaObjectsLock);
+}
+
+void WebScriptSessionHandler::freeJavaObjects() {
+  pthread_mutex_lock(&javaObjectsLock);
+  int idCount = javaObjectsToFree.size();
+  if (idCount == 0) {
+    pthread_mutex_unlock(&javaObjectsLock);
+    return;
+  }
+  
+  int ids[idCount];
+  std::set<int>::iterator it = javaObjectsToFree.begin();
+  for (int i = 0; i < idCount; it++) {
+    ids[i++] = *it;
+  }
+  if (!ServerMethods::freeJava(*channel, this, idCount, ids)) {
+    Debug::log(Debug::Error) << "Unable to free Java ids" << Debug::flush;
+  } else {
+    Debug::log(Debug::Debugging) << "Freed " << idCount << " Java ids" << Debug::flush;
+  }
+  javaObjectsToFree.clear();
+  pthread_mutex_unlock(&javaObjectsLock);
+}
+
+void WebScriptSessionHandler::freeValue(HostChannel& channel, int idCount, const int* ids) {
+  Debug::log(Debug::Spam) << "freeValue freeing " << idCount << " js objects" << Debug::flush;
+  if (idCount == 0) {
+    return;
+  }
+  
+  for (int i = 0; i < idCount; i++) {
+    int objId = ids[i];
+    
+    std::map<int, JSObjectRef>::iterator i = jsObjectsById.find(objId);
+    if (i == jsObjectsById.end()) {
+      Debug::log(Debug::Error) << "Unknown object id " << objId << Debug::flush;
+      continue;
+    }
+    
+    JSObjectRef ref = i->second;
+    jsObjectsById.erase(objId);
+    jsIdsByObject.erase(ref);
+    JSValueUnprotect(contextRef, ref);
+  }
+  Debug::log(Debug::Debugging) << "Freed " << idCount << " JS objects" << Debug::flush;
+}
+
+void WebScriptSessionHandler::initiateAutodestructSequence(const char* functionName, const char* message) {
+  crashHandler->crash(functionName, message);
+}
+
+bool WebScriptSessionHandler::invoke(HostChannel& channel, const Value& thisObj,
+                                    const std::string& methodName,
+                                    int numArgs, const Value* args, Value* returnValue) {
+  Debug::log(Debug::Spam) << "invoke " << methodName << Debug::flush;
+
+  JSValueRef argsJS[numArgs];
+  JSValueRef localException = NULL;
+  JSStringRef methodNameJS = JSStringCreateWithUTF8CString(methodName.c_str());    
+  JSObjectRef thisObjJs;
+  
+  if (thisObj.isNull()) {
+    thisObjJs = JSContextGetGlobalObject(contextRef);
+  } else {
+    thisObjJs = (JSObjectRef) makeValueRef(thisObj);
+  }
+  
+  JSValueRef functionValueJS = JSObjectGetProperty(contextRef, JSContextGetGlobalObject(contextRef),
+                                                   methodNameJS, &localException);
+  JSStringRelease(methodNameJS);
+  
+  if (!JSValueIsObject(contextRef, functionValueJS)) {
+    char message[512];
+    snprintf(message, sizeof(message), "Could not find method for property name %s on %s", methodName.c_str(), thisObj.toString().c_str());
+    makeExceptionValue(*returnValue, message);
+    return true;
+  }
+  
+  JSObjectRef functionJS = JSValueToObject(contextRef, functionValueJS,
+                                           &localException);
+  if (localException) {
+    makeValue(*returnValue, localException);
+    return true;
+  }
+  
+  // Convert the arguments
+  for (int i = 0; i < numArgs; i++) {
+    argsJS[i] = makeValueRef(args[i]);
+  }
+  
+  JSValueRef retVal = JSObjectCallAsFunction(contextRef, functionJS,
+                                             thisObjJs, numArgs, argsJS,
+                                             &localException);
+  
+  // It's safe to free remote objects before sending an Invoke or a Return message
+  freeJavaObjects();
+  
+  if (localException) {
+    Debug::log(Debug::Spam) << "Returning exception to server" << Debug::flush;
+    makeValue(*returnValue, localException);
+    return true;
+  } else {
+    makeValue(*returnValue, retVal);
+    return false;
+  }
+}
+
+bool WebScriptSessionHandler::invokeSpecial(HostChannel& channel, SpecialMethodId method, int numArgs,
+                                            const Value* const args, Value* returnValue) {
+  Debug::log(Debug::Spam) << "invokeSpecial " << method << Debug::flush;
+  switch (method) {
+    case GetProperty:
+    {
+      int objId = args[0].getInt();
+      std::map<int, JSObjectRef>::iterator i = jsObjectsById.find(objId);
+      if (i == jsObjectsById.end()) {
+        char message[50];
+        snprintf(message, sizeof(message), "Unknown object id %i", objId);
+        makeExceptionValue(*returnValue, message);
+        return true;
+      }
+      
+      JSObjectRef jsObj = i->second;
+      if (args[1].isString()) {
+        JSStringRef asString = JSValueToStringCopy(contextRef, jsObj, NULL);
+        int maxLength = JSStringGetMaximumUTF8CStringSize(asString);
+        scoped_array<char> asChars(new char[maxLength]);
+        JSStringGetUTF8CString(asString, asChars.get(), maxLength);
+        
+        JSValueRef localException = NULL;
+        JSStringRef str = JSStringCreateWithUTF8CString(args[1].getString().c_str());
+        JSValueRef value = JSObjectGetProperty(contextRef, jsObj, str, &localException);
+        JSStringRelease(str);
+        if (localException) {
+          makeValue(*returnValue, localException);
+          return true;
+        } else {
+          makeValue(*returnValue, value);
+          return false;
+        }
+      } else if (args[1].isInt()) {
+        JSValueRef localException = NULL;
+        JSValueRef value = JSObjectGetPropertyAtIndex(contextRef, jsObj, args[1].getInt(), &localException);
+        
+        if (localException) {
+          makeValue(*returnValue, localException);
+          return true;
+        } else {
+          makeValue(*returnValue, value);
+          return false;
+        }
+      } else {
+        char message[50];
+        snprintf(message, sizeof(message), "Unhandled argument type %s for getProperty", args[1].toString().c_str());
+        makeExceptionValue(*returnValue, message);
+        return true;
+      }
+    }
+    default:
+      Debug::log(Debug::Error) << "Unhandled invokeSpecial " << method << Debug::flush;
+      makeExceptionValue(*returnValue, "Unhandled invokeSpecial");
+      return true;
+  }  
+}
+
+JSValueRef WebScriptSessionHandler::javaFunctionCallbackImpl (int dispatchId,
+                                                              JSObjectRef thisObject,
+                                                              size_t argumentCount,
+                                                              const JSValueRef arguments[],
+                                                              JSValueRef* exception){
+  /*
+   * NB: Because throwing exceptions in JavaScriptCore is trivial, we don't rely
+   * on any special return values to indicate that an exception is thrown, we'll simply
+   * throw the exception.
+   */
+  Debug::log(Debug::Debugging) << "Java method " << dispatchId << " invoked" << Debug::flush;
+  
+  /*
+   * If a JS function is evaluated without an meaningful this object or the global
+   * object is implicitly used as the this object, we'll assume that the
+   * Java-derived method is static, and send a null this object to the server
+   */
+  Value thisValue;
+  if (JSValueIsEqual(contextRef, thisObject, JSContextGetGlobalObject(contextRef), NULL)) {
+    thisValue = Value();
+    thisValue.setNull();
+  } else {
+    makeValue(thisValue, thisObject);
+  }
+  
+  // Argument conversion is straightforward
+  Value args[argumentCount];
+  for (int i = 0; i < argumentCount; i++) {
+    makeValue(args[i], arguments[i]);
+  }
+  
+  if (!InvokeMessage::send(*channel, thisValue, dispatchId,
+                           argumentCount, args)) {
+    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Unable to send invocation message");
+    *exception = makeException("Unable to send invocation message");
+    return JSValueMakeUndefined(contextRef);
+  }
+  
+  scoped_ptr<ReturnMessage> ret(channel->reactToMessagesWhileWaitingForReturn(sessionHandler));
+  
+  if (!ret.get()) {
+    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Unable to receive return message");
+    *exception = makeException("Unable to receive return message");
+    return JSValueMakeUndefined(contextRef);
+  }
+  
+  Value v = ret->getReturnValue();
+  
+  JSValueRef toReturn;
+  if (ret->isException()) {
+    *exception = makeValueRef(v);
+    toReturn = JSValueMakeUndefined(contextRef);
+  } else {
+    toReturn = makeValueRef(v);
+  }
+  
+  JSValueRef makeResultArguments[] = {JSValueMakeBoolean(contextRef, false), toReturn};
+  return JSObjectCallAsFunction(contextRef, makeResultFunction, NULL, 2, makeResultArguments, exception);
+}
+
+void WebScriptSessionHandler::javaObjectFinalizeImpl(int objId) {
+  if (pthread_mutex_lock(&javaObjectsLock)) {
+    Debug::log(Debug::Error) << "Unable to acquire javaObjectsLock in thread " << pthread_self() << " " << __PRETTY_FUNCTION__ << Debug::flush;
+    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Unable to acquire javaObjectsLock");
+    return;
+  }
+  javaObjectsById.erase(objId);
+  javaObjectsToFree.insert(objId);
+  if (pthread_mutex_unlock(&javaObjectsLock)) {
+    Debug::log(Debug::Error) << "Unable to release javaObjectsLock in thread " << pthread_self() << " " << __PRETTY_FUNCTION__ << Debug::flush;
+    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Unable to release javaObjectsLock");
+  }
+}
+
+JSValueRef WebScriptSessionHandler::javaObjectGetPropertyImpl (TrackingDataRef tracker, JSObjectRef object,
+                                                               JSStringRef propertyName, JSValueRef* exception) {
+  *exception = NULL;
+  
+  // Convert the name
+  int maxLength = JSStringGetMaximumUTF8CStringSize(propertyName);
+  scoped_array<char> propertyNameChars(new char[maxLength]);
+  JSStringGetUTF8CString(propertyName, propertyNameChars.get(), maxLength);
+  JSValueRef toReturn;  
+  
+  if (!strcmp(propertyNameChars.get(), "toString")) {
+    // We'll call out to the JSNI tear-off support function
+    JSStringRef tearOffName =JSStringCreateWithUTF8CString("__gwt_makeTearOff");
+    JSValueRef makeTearOffValue = JSObjectGetProperty(contextRef, JSContextGetGlobalObject(contextRef), tearOffName, exception);
+    JSStringRelease(tearOffName);
+    if (*exception) {
+      return JSValueMakeUndefined(contextRef);
+    }    
+    
+    JSObjectRef makeTearOff = JSValueToObject(contextRef, makeTearOffValue, exception);
+    if (*exception) {
+      return JSValueMakeUndefined(contextRef);
+    }
+    
+    JSValueRef arguments[3];
+    arguments[0] = object;
+    arguments[1] = JSValueMakeNumber(contextRef, 0);
+    arguments[2] = JSValueMakeNumber(contextRef, 0);
+    toReturn = JSObjectCallAsFunction(contextRef, makeTearOff, JSContextGetGlobalObject(contextRef), 3, arguments, exception);
+  } else {
+    char* endptr;
+    int dispatchId = strtol(propertyNameChars.get(), &endptr, 10);
+    
+    if (*endptr != '\0') {
+      Debug::log(Debug::Error) << "Unable to parse dispatch id " << propertyNameChars.get() << Debug::flush;
+      *exception = makeException("Unable to parse dispatch id");
+    } else if (dispatchId < 0) {
+      Debug::log(Debug::Error) << "Dispatch ids may not be negative" << Debug::flush;
+      *exception = makeException("Dispatch ids may not be negative");
+    } else {
+      Value v = ServerMethods::getProperty(*channel, this, tracker->getObjectId(), dispatchId);
+      toReturn = makeValueRef(v);
+    }
+  }
+  
+  return toReturn;
+}
+
+bool WebScriptSessionHandler::javaObjectHasPropertyImpl (TrackingDataRef tracker, JSObjectRef object, JSStringRef propertyName) {
+  // The property name must either be "toString" or a number
+  int maxLength = JSStringGetMaximumUTF8CStringSize(propertyName);
+  scoped_array<char> propertyNameChars(new char[maxLength]);
+  JSStringGetUTF8CString(propertyName, propertyNameChars.get(), maxLength);
+  if (!strcmp(propertyNameChars.get(), "toString")) {
+    return true;
+  }
+  
+  char* endptr;
+  int dispatchId = strtol(propertyNameChars.get(), &endptr, 10);
+  
+  if (*endptr != '\0') {
+    return false;
+  } else if (dispatchId < 0) {
+    return false;
+  } else {
+    return true;
+  }
+}
+
+bool WebScriptSessionHandler::javaObjectSetPropertyImpl (TrackingDataRef tracker, JSObjectRef object,
+                                                         JSStringRef propertyName, JSValueRef jsValue,
+                                                         JSValueRef* exception) {
+  int maxLength = JSStringGetMaximumUTF8CStringSize(propertyName);
+  scoped_array<char> propertyNameChars(new char[maxLength]);
+  JSStringGetUTF8CString(propertyName, propertyNameChars.get(), maxLength);
+  Value value;
+  
+  char* endptr;
+  int dispatchId = strtol(propertyNameChars.get(), &endptr, 10);
+  
+  if (*endptr != '\0') {
+    // TODO Figure out the right policy here; when we throw a Java object, JSCore wants to
+    // add expandos to record stack information.  It would be possible to map the limited
+    // number of properties into a synthetic causal exception in the exception being thrown.
+  } else if (dispatchId < 0) {
+    // Do nothing.
+    Debug::log(Debug::Error) << "Dispatch ids may not be negative" << Debug::flush;
+    *exception = makeException("Dispatch ids may not be negative");
+  } else {
+  
+    makeValue(value, jsValue);
+    
+    if (!ServerMethods::setProperty(*channel, this, tracker->getObjectId(), dispatchId, value)) {
+      char message[50];
+      snprintf(message, sizeof(message), "Unable to set value object %i dispatchId %i", tracker->getObjectId(), dispatchId);
+      *exception = makeException(message);
+    }
+  }
+  
+  // true means to not try to follow the prototype chain; not an indication of success
+  return true;
+}
+
+void WebScriptSessionHandler::loadJsni(HostChannel& channel, const std::string& js) {
+  Debug::log(Debug::Spam) << "loadJsni " << js << Debug::flush;
+  JSValueRef localException = NULL;
+  
+  JSStringRef script = JSStringCreateWithUTF8CString(js.c_str());
+  JSEvaluateScript(contextRef, script, NULL, NULL, NULL, &localException);
+  JSStringRelease(script);
+  
+  if (localException) {
+    // TODO Exception handling
+    Debug::log(Debug::Error) << "Exception thrown during loadJsni" << Debug::flush;
+  } else {
+    Debug::log(Debug::Spam) << "Success" << Debug::flush;
+  }
+}
+
+JSValueRef WebScriptSessionHandler::makeException(const char* message) {
+  JSValueRef localException = NULL;
+  JSObjectRef global = JSContextGetGlobalObject(contextRef);
+  
+  JSStringRef errorName = JSStringCreateWithUTF8CString("Error");
+  JSValueRef errorValue = JSObjectGetProperty(contextRef, global, errorName, &localException);
+  JSStringRelease(errorName);
+  
+  if (!JSValueIsObject(contextRef, errorValue)) {
+    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Could not get reference to Error");
+    return JSValueMakeUndefined(contextRef);
+  }
+  
+  JSObjectRef errorObject = (JSObjectRef) errorValue;
+  
+  if (!JSObjectIsFunction(contextRef, errorObject)) {
+    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Error was not a function");
+    return JSValueMakeUndefined(contextRef);
+  }
+  
+  JSValueRef args[1];
+  JSStringRef messageJs = JSStringCreateWithUTF8CString(message);
+  args[0] = JSValueMakeString(contextRef, messageJs);
+  JSStringRelease(messageJs);
+  
+  return JSObjectCallAsConstructor(contextRef, errorObject, 1, args, &localException);
+}
+
+void WebScriptSessionHandler::makeExceptionValue(Value& value, const char* message) {
+  makeValue(value, makeException(message));
+}
+
+JSObjectRef WebScriptSessionHandler::makeJavaWrapper(int objId) {
+  Debug::log(Debug::Spam) << "Creating wrapper for Java object " << objId << Debug::flush;
+  
+  TrackingDataRef data = new TrackingData(this, objId);
+  return JSObjectMake(contextRef, javaObjectWrapperClass,
+                      const_cast<TrackingData*>(data));
+}
+
+JSValueRef WebScriptSessionHandler::makeValueRef(const Value& v) {
+  std::map<int, JSObjectRef>::iterator i;
+  switch (v.getType()) {
+    case Value::NULL_TYPE:
+      return JSValueMakeNull(contextRef);
+      
+    case Value::BOOLEAN:
+      return JSValueMakeBoolean(contextRef, v.getBoolean());
+      
+    case Value::BYTE:
+      return JSValueMakeNumber(contextRef, v.getByte());
+      
+    case Value::CHAR:
+      return JSValueMakeNumber(contextRef, v.getChar());
+      
+    case Value::SHORT:
+      return JSValueMakeNumber(contextRef, v.getShort());
+      
+    case Value::INT:
+      return JSValueMakeNumber(contextRef, v.getInt());
+      
+    case Value::LONG:
+      return JSValueMakeNumber(contextRef, v.getLong());
+      
+    case Value::FLOAT:
+      return JSValueMakeNumber(contextRef, v.getFloat());
+      
+    case Value::DOUBLE:
+      return JSValueMakeNumber(contextRef, v.getDouble());
+      
+    case Value::STRING:
+    {
+      std::string stringValue = v.getString();
+      
+      // We need to handle the conversion ourselves to be able to get both
+      // UTF8 encoding as well as explicit control over the length of the string
+      // due to the possibility of null characters being part of the data
+      CFStringRef cfString = CFStringCreateWithBytesNoCopy(NULL, (UInt8*)stringValue.data(),
+                                                           stringValue.length(), kCFStringEncodingUTF8,
+                                                           false, kCFAllocatorNull);
+      JSStringRef stringRef = JSStringCreateWithCFString(cfString);
+      JSValueRef toReturn = JSValueMakeString(contextRef, stringRef);
+      JSStringRelease(stringRef);
+      CFRelease(cfString);
+      return toReturn;
+    }
+      
+    case Value::JAVA_OBJECT:
+      unsigned javaId = v.getJavaObjectId();
+      JSObjectRef ref;
+      
+      pthread_mutex_lock(&javaObjectsLock);
+      i = javaObjectsById.find(javaId);
+      
+      /*
+       * It's possible that we've already finalized the JsObjectRef that
+       * represented the object with the given id.  If so, we must remove it
+       * from the list of finalized object ids to avoid prematurely freeing
+       * the object on the server.
+       */
+      javaObjectsToFree.erase(javaId);
+      
+      if (i == javaObjectsById.end()) {
+        /*
+         * We don't call JSValueProtect so that the JavaObject peer can be
+         * garbage-collected during the lifetime of the program.  Object
+         * identity is maintained as long as the object hasn't been finalized.
+         * If it had been finalized, then there wouldn't be an object to use
+         * as a basis for identity comparison.
+         *
+         * NB: The act of creating the wrapper may trigger a GC.
+         */
+        ref = makeJavaWrapper(javaId);
+        
+        javaObjectsById[javaId] = ref;
+        
+      } else {
+        ref = i->second;
+      }
+      pthread_mutex_unlock(&javaObjectsLock);
+      
+      
+      return ref;
+      
+      case Value::JS_OBJECT:
+      int jsId = v.getJsObjectId();
+      
+      i = jsObjectsById.find(jsId);
+      if (i == jsObjectsById.end()) {
+        char errMsg[50];
+        snprintf(errMsg, sizeof(errMsg), "Missing JsObject with id %i", jsId);
+        return makeException(errMsg);
+        
+      } else {
+        return i->second;
+      }
+      
+      case Value::UNDEFINED:
+      return JSValueMakeUndefined(contextRef);
+      
+      default:
+      char message[50];
+      snprintf(message, sizeof(message), "Could not convert %s", v.toString().c_str());
+      initiateAutodestructSequence(__PRETTY_FUNCTION__, message);
+      return makeException(message);
+  }
+}
+
+bool WebScriptSessionHandler::makeValue(Value& ret, JSValueRef v) {
+  JSValueRef localException = NULL;
+  
+  if (JSValueIsNull(contextRef, v)) {
+    ret.setNull();
+    
+  } else if (JSValueIsUndefined(contextRef, v)) {
+    ret.setUndefined();
+    
+  } else if (JSValueIsBoolean(contextRef, v)) {
+    ret.setBoolean(JSValueToBoolean(contextRef, v));
+    
+  } else if (JSValueIsNumber(contextRef, v)) {
+    double d = JSValueToNumber(contextRef, v, &localException);
+    int i = round(d);
+    if (i == d) {
+      ret.setInt(i);
+    } else {
+      ret.setDouble(d);
+    }
+    
+  } else if (JSValueIsString(contextRef, v) ||
+             JSValueIsInstanceOfConstructor(contextRef, v, stringConstructor, &localException)) {
+    return makeValueFromString(ret, v);
+    
+  } else if (JSValueIsObjectOfClass(contextRef, v, javaObjectWrapperClass)) {
+    // It's one of our Java object proxies
+    JSObjectRef objectRef = JSValueToObject(contextRef, v, &localException);
+    
+    if (!localException) {
+      TrackingDataRef tracker = (TrackingDataRef) JSObjectGetPrivate(objectRef);
+      int objId = tracker->getObjectId();
+      ret.setJavaObject(objId);
+      Debug::log(Debug::Spam) << "Made a Java object Value " << objId << Debug::flush;
+    }
+    
+  } else if (JSValueIsObject(contextRef, v)) {
+    JSObjectRef objectRef = JSValueToObject(contextRef, v, &localException);
+    if (!localException) {
+      /*
+       * Then this is just a plain-old JavaScript Object.  Because JSCore
+       * doesn't retain private data for objects derived from the built-in
+       * Object type, we'll simply revert to using a pair of maps to provide
+       * a 1:1 mapping of JSObjectRefs and ints.
+       */
+      std::map<JSObjectRef, int>::iterator i = jsIdsByObject.find(objectRef);
+      if (i != jsIdsByObject.end()) {
+        // We've seen the object before
+        ret.setJsObjectId(i->second);
+      } else {
+        // Allocate a new id
+        int objId = ++jsObjectId;
+        JSValueProtect(contextRef, objectRef);
+        
+        jsObjectsById[objId] = objectRef;
+        jsIdsByObject[objectRef] = objId;
+        
+        ret.setJsObjectId(objId);
+        Debug::log(Debug::Spam) << "Made JS Value " << objId << Debug::flush;
+      }
+    }
+  } else {
+    Debug::log(Debug::Error) << "Unhandled JSValueRef -> Value conversion in plugin" << Debug::flush;
+    ret.setString("Unhandled JSValueRef -> Value conversion in plugin");
+  }
+  
+  if (localException) {
+    makeValue(ret, localException);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+bool WebScriptSessionHandler::makeValueFromString(Value& ret, JSValueRef value) {
+  JSValueRef localException = NULL;
+  
+  JSStringRef jsString = JSValueToStringCopy(contextRef, value, &localException);
+  if (localException) {
+    makeValue(ret, localException);
+    return true;
+  }
+  
+  CFStringRef cfString = JSStringCopyCFString(NULL, jsString);
+  JSStringRelease(jsString);
+  
+  CFIndex cfLength = CFStringGetLength(cfString);
+  CFIndex maxLength = CFStringGetMaximumSizeForEncoding(cfLength, kCFStringEncodingUTF8);
+  scoped_array<char> utf8(new char[maxLength]);
+  
+  CFIndex numBytes;
+  CFStringGetBytes(cfString, CFRangeMake(0, cfLength), kCFStringEncodingUTF8,
+                   0, false, (UInt8*) utf8.get(), maxLength, &numBytes);    
+  CFRelease(cfString);
+  
+  ret.setString(utf8.get(), numBytes);
+  Debug::log(Debug::Spam) << "Made a string Value " << ret.getString() << Debug::flush;
+  return false;
+}
diff --git a/plugins/webkit/Core/WebScriptSessionHandler.h b/plugins/webkit/Core/WebScriptSessionHandler.h
new file mode 100644
index 0000000..fc9795d
--- /dev/null
+++ b/plugins/webkit/Core/WebScriptSessionHandler.h
@@ -0,0 +1,153 @@
+/*
+ * 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 <map>
+#include <set>
+#import "Debug.h"
+#import "HostChannel.h"
+#import "JavaScriptCore/JavaScriptCore.h"
+#import "pthread.h"
+#import "TrackingData.h"
+
+class CrashHandler {
+public:
+  virtual void crash(const char* functionName, const char* message) = 0;
+};
+typedef CrashHandler* CrashHandlerRef;
+
+/*
+ * This comprises the guts of the JavaScriptCore-specific code and is
+ * responsible for message dispatch and value conversion.  This class should
+ * be portable to any runtime that uses JavaScriptCore.
+ */
+class WebScriptSessionHandler : public SessionHandler, public SessionData  {
+public:
+  WebScriptSessionHandler(HostChannel* channel, JSGlobalContextRef contextRef,
+                          CrashHandler* crashHandler);
+  
+  /*
+   * Invoking the destructor will perform a clean shutdown of the OOPHM session.
+   */
+  ~WebScriptSessionHandler();
+  
+  /*
+   * This is a panic method for shutting down the OOPHM debugging session due
+   * to unrecoverable errors.
+   */
+  void initiateAutodestructSequence(const char* functionName, const char* message);
+
+  /*
+   * Invoke a Java method.
+   */
+  JSValueRef javaFunctionCallbackImpl(int dispatchId,
+                                      JSObjectRef thisObject,
+                                      size_t argumentCount,
+                                      const JSValueRef arguments[],
+                                      JSValueRef* exception);
+  
+  /*
+   * Finalize a Javo object proxy.
+   */
+  void javaObjectFinalizeImpl(int objId);
+  
+  /*
+   * Determine if a Java class has a named property.
+   */
+  bool javaObjectHasPropertyImpl(TrackingDataRef tracker, JSObjectRef object,
+                                JSStringRef propertyName);
+  
+  /*
+   * Obtain the value of named property of an object.
+   */
+  JSValueRef javaObjectGetPropertyImpl(TrackingDataRef tracker, JSObjectRef object,
+                                       JSStringRef propertyName, JSValueRef* exception);
+  
+  /*
+   * Set the value of a named property on a Java object.
+   */
+  bool javaObjectSetPropertyImpl(TrackingDataRef tracker, JSObjectRef object,
+                                 JSStringRef propertyName, JSValueRef value,
+                                 JSValueRef* exception);
+  
+  /*
+   * Create a JavaScript Error object with the given message.
+   */
+  JSValueRef makeException(const char* message);
+  
+protected:
+  virtual void freeValue(HostChannel& channel, int idCount, const int* ids);
+  virtual void loadJsni(HostChannel& channel, const std::string& js);
+  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 method, int numArgs,
+                             const Value* const args, Value* returnValue);
+  
+private:
+  CrashHandlerRef const crashHandler;
+  int jsObjectId;
+  std::map<int, JSObjectRef> javaObjectsById;
+  std::set<int> javaObjectsToFree;
+  pthread_mutex_t javaObjectsLock;
+  std::map<int, JSObjectRef> jsObjectsById;
+  std::map<JSObjectRef, int> jsIdsByObject;
+  JSClassRef javaObjectWrapperClass;
+  
+  /* A reference to __gwt_makeResult, which we use constantly */
+  JSObjectRef makeResultFunction;
+  
+  /* The String() function */
+  JSObjectRef stringConstructor;
+   
+  /*
+   * Free server-side references.
+   */
+  void freeJavaObjects();
+  
+  /*
+   * Create a exception Value that contains the given message.
+   */
+  void makeExceptionValue(Value& value, const char* message);
+  
+  /*
+   * Create a Java object proxy to be passed into the JavaScript execution
+   * environment.
+   */
+  JSObjectRef makeJavaWrapper(int objId);
+  
+  /*
+   * Convert a value from the JavaScript into something that can be sent back
+   * to the OOPHM host.
+   *
+   * Returns true if an exception was encountered.
+   */
+  bool makeValue(Value& ret, JSValueRef value);
+  
+  /*
+   * Convert a string-like object to something that can be sent back to the OOPHM
+   * host.
+   *
+   * Returns true if an exception was encountered.
+   */
+  bool makeValueFromString(Value& ret, JSValueRef value);
+  
+  /*
+   * Convert a value from the OOPHM host into something that can be passed into
+   * the JavaScript execution environment.
+   */
+  JSValueRef makeValueRef(const Value& value);
+};
+typedef WebScriptSessionHandler* WebScriptSessionHandlerRef;
+
diff --git a/plugins/webkit/English.lproj/InfoPlist.strings b/plugins/webkit/English.lproj/InfoPlist.strings
new file mode 100644
index 0000000..6260754
--- /dev/null
+++ b/plugins/webkit/English.lproj/InfoPlist.strings
Binary files differ
diff --git a/plugins/webkit/Info.plist b/plugins/webkit/Info.plist
new file mode 100644
index 0000000..7b8e8a0
--- /dev/null
+++ b/plugins/webkit/Info.plist
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIconFile</key>
+	<string>gwtlogo</string>
+	<key>CFBundleIdentifier</key>
+	<string>com.google.gwt.oophm</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>WBPL</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>0.1</string>
+	<key>NSPrincipalClass</key>
+	<string>OophmPlugin</string>
+	<key>WebPluginDescription</key>
+	<string>Google Web Toolkit Out-Of-Process Hosted Mode plugin</string>
+	<key>WebPluginMIMETypes</key>
+	<dict>
+		<key>application/x-gwt-hosted-mode</key>
+		<dict>
+			<key>WebPluginTypeDescription</key>
+			<string>Google Web Toolkit Out-of-Process hosted mode.</string>
+		</dict>
+	</dict>
+	<key>WebPluginName</key>
+	<string>GWT OOPHM</string>
+</dict>
+</plist>
diff --git a/plugins/webkit/Plugin/Debug.mm b/plugins/webkit/Plugin/Debug.mm
new file mode 100644
index 0000000..6cc8edf
--- /dev/null
+++ b/plugins/webkit/Plugin/Debug.mm
@@ -0,0 +1,36 @@
+/*
+ * 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>
+
+static NSMutableString* const buffer = [[NSMutableString alloc] initWithCapacity:1024];
+
+Debug::DebugStream& Debug::flush(Debug::DebugStream& dbg) {
+  Debug::logFinish();
+  return dbg;
+}
+
+void Debug::logStart(Debug::LogLevel level) {
+}
+
+void Debug::logFinish() {
+  NSLog(buffer);
+  [buffer setString:@""];
+}
+
+void Debug::logString(const char* str) {
+  [buffer appendString:[NSString stringWithUTF8String:str]];
+}
diff --git a/plugins/webkit/Plugin/English.lproj/crash.html b/plugins/webkit/Plugin/English.lproj/crash.html
new file mode 100644
index 0000000..040d2f0
--- /dev/null
+++ b/plugins/webkit/Plugin/English.lproj/crash.html
@@ -0,0 +1,27 @@
+<html>
+<head>
+<title>Hosted Mode failure</title>
+<style>
+* {font-family: monospace;}
+h1 {background: blue; color: white;}
+#r {border: thin solid silver; width:100%; height: 50em; white-space: pre; overflow: scroll;}
+</style>
+</head>
+<body>
+<h1>STOP</h1>
+<p>The hosted mode plugin encountered a fatal error and was unable to continue.  Ensure
+that the hosted mode server is running.  You can attempt to restart the module
+by reloading the current page.</p>
+<textarea id="r" wrap="off">
+__MESSAGE__
+
+System version: __SYSTEM_VERSION__
+
+__USER_AGENT__
+
+Compilation time: __DATE__ __TIME__
+
+__BACKTRACE__
+</textarea>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/webkit/Plugin/NSMutableString+HtmlReplacement.h b/plugins/webkit/Plugin/NSMutableString+HtmlReplacement.h
new file mode 100644
index 0000000..57da6e3
--- /dev/null
+++ b/plugins/webkit/Plugin/NSMutableString+HtmlReplacement.h
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#import <Cocoa/Cocoa.h>
+#import "GTMNSString+HTML.h"
+
+/*
+ * This adds a convenience method to add HTML-escaped text to an NSMutableString.
+ */
+@interface NSMutableString (NSMutableStringWithHtmlReplacement)
+- (void)replacePattern:(NSString*)pattern
+     withStringLiteral:(NSString*)replacement;
+@end
diff --git a/plugins/webkit/Plugin/NSMutableString+HtmlReplacement.m b/plugins/webkit/Plugin/NSMutableString+HtmlReplacement.m
new file mode 100644
index 0000000..ed0f62b
--- /dev/null
+++ b/plugins/webkit/Plugin/NSMutableString+HtmlReplacement.m
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+#import "NSMutableString+HtmlReplacement.h"
+
+@implementation NSMutableString (NSMutableStringWithHtmlReplacement)
+- (void)replacePattern:(NSString*)pattern
+     withStringLiteral:(NSString*)replacement {
+  [self replaceOccurrencesOfString:pattern
+                        withString:[replacement gtm_stringByEscapingForHTML]
+                           options:NSLiteralSearch
+                             range:NSMakeRange(0, [self length])];
+}
+@end
diff --git a/plugins/webkit/Plugin/OophmPlugin.h b/plugins/webkit/Plugin/OophmPlugin.h
new file mode 100644
index 0000000..96d0ed3
--- /dev/null
+++ b/plugins/webkit/Plugin/OophmPlugin.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#import <Cocoa/Cocoa.h>
+#import <WebKit/WebKit.h>
+#import <WebKit/WebPlugin.h>
+#import "Debug.h"
+#import "OophmWebScriptObject.h"
+#import "SlowScriptProxy.h"
+#import "WebFrameNonTigerHeaders.h"
+
+/*
+ * This provides the entrypoint for the WebKit plugin.  This class performs
+ * any necessary environmental configuration and provides the scripting object
+ * that represents the plugin in the JavaScript environment.
+ */
+@interface OophmPlugin : NSView <WebPlugInViewFactory> {
+@private
+  OophmWebScriptObject* _scriptObject;
+  id _slowScriptProxy;
+}
+
+/*
+ * Defined by the WebPlugInViewFactory protocol to construct an instance of
+ * the plugin.
+ */
++ (NSView *)plugInViewWithArguments:(NSDictionary *)arguments;
+- (void)dealloc;
+
+/*
+ * Called by plugInViewWithArguments to initialize the instance of the plugin.
+ */
+- (id)initWithArguments:(NSDictionary *)arguments;
+
+/*
+ * Specified by the WebPlugIn informal protocol to obtain an object whose
+ * methods will be exposed to the scripting environment.
+ */
+- (id)objectForWebScript;
+
+/*
+ * Defined by WebPlugIn and called when the plugin should shut down.
+ */
+- (void)webPlugInDestroy;
+@end
diff --git a/plugins/webkit/Plugin/OophmPlugin.mm b/plugins/webkit/Plugin/OophmPlugin.mm
new file mode 100644
index 0000000..02552d1
--- /dev/null
+++ b/plugins/webkit/Plugin/OophmPlugin.mm
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+#import "OophmPlugin.h"
+#import "OophmWebScriptObject.h"
+#import "SlowScriptProxy.h"
+
+@implementation OophmPlugin
++ (NSView *)plugInViewWithArguments:(NSDictionary *)arguments {
+  return [[[OophmPlugin alloc] initWithArguments: arguments] autorelease];
+}
+
+- (void)dealloc {
+  Debug::log(Debug::Info) << "Plugin deallocated" << Debug::flush;
+  [super dealloc];
+}
+
+- (id)initWithArguments:(NSDictionary *)arguments {
+  Debug::log(Debug::Info) << "Plugin starting" << Debug::flush;
+  self = [super initWithFrame: NSZeroRect];
+  if (!self) {
+    return nil;
+  }
+
+  id container = [[arguments objectForKey:WebPlugInContainerKey] retain];
+  WebFrame* frame = [container webFrame];
+  JSGlobalContextRef contextRef = [frame globalContext];
+  _scriptObject = [[OophmWebScriptObject scriptObjectWithContext:contextRef withWebView:[frame webView]] retain];
+
+  /*
+   * Install a proxy to prevent slow script warnings from being shown by hijacking
+   * the message sent to the original UIDelegate.  We could also use this to prevent
+   * window.alert and window.prompt from blocking test code.
+   */
+  WebView* view = [frame webView];
+  _slowScriptProxy = [[SlowScriptProxy alloc] initWithWebView: view];
+  if ([_slowScriptProxy respondsToSelector:@selector(webView:setStatusText:)]) {
+    [_slowScriptProxy webView:view setStatusText:@"GWT OOPHM Plugin Active"];
+  }
+  
+  return self;
+}
+
+- (id)objectForWebScript {
+  return _scriptObject;
+}
+
+- (void)webPlugInDestroy {
+  Debug::log(Debug::Info) << "Destroying plugin" << Debug::flush;
+  [_scriptObject release];
+  _scriptObject = nil;
+  
+  if ([_slowScriptProxy respondsToSelector:@selector(webView:setStatusText:)]) {
+    [_slowScriptProxy webView:[_slowScriptProxy webView] 
+                      setStatusText:@"GWT OOPHM Session Ended"];
+  }
+  [_slowScriptProxy release];
+  _slowScriptProxy = nil;
+}
+@end
diff --git a/plugins/webkit/Plugin/OophmWebScriptObject.h b/plugins/webkit/Plugin/OophmWebScriptObject.h
new file mode 100644
index 0000000..28f52ce
--- /dev/null
+++ b/plugins/webkit/Plugin/OophmWebScriptObject.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#import <JavaScriptCore/JavaScriptCore.h>
+#import "HostChannel.h"
+#import "WebScriptSessionHandler.h"
+
+@interface OophmWebScriptObject : NSObject {
+@private
+  JSGlobalContextRef _contextRef;
+  CrashHandlerRef _crashHandler;
+  HostChannel* _hostChannel;
+  WebScriptSessionHandlerRef _sessionHandler;
+  WebView* _webView;
+}
++ (void)initialize;
++ (BOOL)isSelectorExcludedFromWebScript: (SEL)selector;
++ (OophmWebScriptObject*)scriptObjectWithContext: (JSGlobalContextRef)context
+                                     withWebView: (WebView*) webView;
++ (NSString*)webScriptNameForSelector: (SEL)selector;
+- (BOOL)connectWithHost: (NSString*) host
+         withModuleName: (NSString*) moduleName
+        withJsniContext: (WebScriptObject*) jsniContext;
+- (void)crashWithMessage: (NSString*)message;
+- (void)dealloc;
+- (void)finalizeForWebScript;
+@end
+
diff --git a/plugins/webkit/Plugin/OophmWebScriptObject.mm b/plugins/webkit/Plugin/OophmWebScriptObject.mm
new file mode 100644
index 0000000..f737fd8
--- /dev/null
+++ b/plugins/webkit/Plugin/OophmWebScriptObject.mm
@@ -0,0 +1,302 @@
+/*
+ * 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 <map>
+#import <JavaScriptCore/JavaScriptCore.h>
+#import <WebKit/WebKit.h>
+#import "BrowserChannel.h"
+#import "Debug.h"
+#import "GTMStackTrace.h"
+#import "GTMSystemVersion.h"
+#import "NSMutableString+HtmlReplacement.h"
+#import "LoadModuleMessage.h"
+#import "OophmWebScriptObject.h"
+#import "SessionHandler.h"
+
+/*
+ * This is a helper shim to bridge crash events from the core cpp code to the
+ * objc plugin and UI layer.
+ */
+class PluginCrashHandler : public CrashHandler {
+public:
+  PluginCrashHandler(OophmWebScriptObject* obj) : obj(obj) {
+  }
+  
+  virtual void crash(const char* functionName, const char* message) {
+    Debug::log(Debug::Error) << "Crashing with message: "<< message << Debug::flush;
+    NSString* str = [NSString stringWithFormat:@"%s\n\n%s", message, functionName];
+    [obj crashWithMessage:str];
+  }
+private:
+  OophmWebScriptObject* const obj;
+};
+
+@interface OophmWebScriptObject (Private)
++ (void)logAndThrowString: (NSString*)message;
+- (void)addAllowedHost: (NSString*)host;
+- (void)connectAlertDidEnd: (NSAlert*)alert
+                returnCode: (int)returnCode
+               contextInfo: (void*)contextInfo;
+- (BOOL)doConnectWithHost: (NSString*) host
+               withModule: (NSString*) moduleName;
+@end
+
+@implementation OophmWebScriptObject
++ (void)initialize {
+  // Add the plugin's bundle name to the user defaults search path
+  NSBundle* pluginBundle = [NSBundle bundleForClass:[OophmWebScriptObject class]];
+  NSString* bundleIdentifier = [pluginBundle bundleIdentifier];
+  NSUserDefaults* shared = [NSUserDefaults standardUserDefaults];
+  [shared addSuiteNamed:bundleIdentifier];
+}
+
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)selector {
+  if (selector == @selector(connectWithHost:withModuleName:withJsniContext:)) {
+    return NO;
+  } else if (selector == @selector(crashWithMessage:)) {
+    return NO;
+  }
+
+  return YES;
+}
+
++ (OophmWebScriptObject*)scriptObjectWithContext: (JSGlobalContextRef) context
+                                     withWebView: (WebView*) webView {
+  JSGlobalContextRetain(context);
+  OophmWebScriptObject* obj = [[[OophmWebScriptObject alloc] init] autorelease];
+  obj->_contextRef = context;
+  obj->_webView = [webView retain];
+  return obj;
+}
+
++ (NSString*)webScriptNameForSelector: (SEL)selector {
+  if (selector == @selector(connectWithHost:withModuleName:withJsniContext:)) {
+    return @"connect";
+  } else if (selector == @selector(crashWithMessage:)) {
+    return @"crash";
+  }
+  return nil;
+}
+
+- (BOOL)connectWithHost: (NSString*) host
+         withModuleName: (NSString*) moduleName
+        withJsniContext: (WebScriptObject*) jsniContext {
+  
+  // TODO remove this for production builds
+  Debug::log(Debug::Warning) << "ACLs are currently disabled" << Debug::flush;
+  return [self doConnectWithHost:host withModule:moduleName];
+
+  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+
+  // See if authentication has been bypassed
+  if ([defaults boolForKey:@"allowAll"]) {
+    return [self doConnectWithHost:host withModule:moduleName];
+  }
+  
+  // Otherwise, check for an explicit entry
+  NSArray* allowedHosts = [defaults arrayForKey:@"allowedHosts"];
+  if (allowedHosts != nil) {
+    NSArray* hostParts = [host componentsSeparatedByString:@":"];
+    if ([allowedHosts containsObject:[hostParts objectAtIndex:0]]) {
+      return [self doConnectWithHost:host withModule:moduleName];
+    }
+  }
+  
+  // Otherwise, bring up an alert dialog
+  NSAlert* alert = [NSAlert alertWithMessageText:@"Initiate hosted-mode session"
+                                   defaultButton:@"Deny"
+                                 alternateButton:nil
+                                     otherButton:@"Allow"
+                       informativeTextWithFormat:@"The current web-page would like to initiate a hosted-mode connection to %@", host];
+  
+  if ([alert respondsToSelector:@selector(setShowsSuppressionButton:)]) {
+    [alert setShowsSuppressionButton:YES];
+    [[alert suppressionButton] setTitle:@"Always allow connections to this host"];
+  } else {
+    [[alert addButtonWithTitle:@"Always allow"] setTag:NSAlertAlternateReturn];
+  }
+  
+  NSBundle* bundle = [NSBundle bundleForClass:[OophmWebScriptObject class]];
+  NSArray* contextArray = [[NSArray arrayWithObjects:[host retain],
+                            [moduleName retain], nil] retain];
+  NSString* imagePath = [bundle pathForImageResource:@"gwtlogo"];
+  if (imagePath != nil) {
+    NSImage* img = [[[NSImage alloc] initByReferencingFile:imagePath] autorelease];
+    [alert setIcon:img];
+  }
+  
+  [alert beginSheetModalForWindow:[_webView hostWindow]
+                    modalDelegate:self
+                   didEndSelector:@selector(connectAlertDidEnd:returnCode:contextInfo:)
+                      contextInfo:contextArray];
+  return YES;
+}
+
+- (void)crashWithMessage: (NSString*)message {
+  NSBundle* oophmBundle = [NSBundle bundleForClass:[self class]];
+  NSString* path = [oophmBundle pathForResource:@"crash" ofType:@"html"];
+  NSMutableString* crashPage = [NSMutableString stringWithContentsOfFile:path];
+  [crashPage replacePattern:@"__MESSAGE__" withStringLiteral:message];
+  
+  long major, minor, bugFix;
+  [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix];
+  NSString* systemVersion = [NSString stringWithFormat:@"%i.%i.%i", major, minor, bugFix];
+  [crashPage replacePattern:@"__SYSTEM_VERSION__" withStringLiteral:systemVersion];
+  
+  NSString* ua = [_webView userAgentForURL:[NSURL URLWithString:@"about:blank"]];
+  [crashPage replacePattern:@"__USER_AGENT__" withStringLiteral:ua];
+  
+  [crashPage replacePattern:@"__DATE__"
+          withStringLiteral:[NSString stringWithUTF8String:__DATE__]];
+  [crashPage replacePattern:@"__TIME__"
+          withStringLiteral:[NSString stringWithUTF8String:__TIME__]];  
+  
+  NSString* trace = GTMStackTrace();
+  [crashPage replacePattern:@"__BACKTRACE__" withStringLiteral:trace];
+  
+
+  NSURL* currentUrl = [[[[_webView mainFrame] dataSource] response] URL];
+  
+  [[_webView mainFrame] loadAlternateHTMLString:crashPage
+                                        baseURL:[NSURL fileURLWithPath:path]
+                              forUnreachableURL:currentUrl];
+}
+
+- (void)dealloc {
+  [_webView release];  
+  delete _crashHandler;
+  [super dealloc];
+}
+
+- (void)finalizeForWebScript {
+  Debug::log(Debug::Info) << "Finalizing OophmWebScriptObject" << Debug::flush;
+  
+  // Free memory
+  delete _sessionHandler;
+  
+  if (_hostChannel) {
+    _hostChannel->disconnectFromHost();
+    delete _hostChannel;
+    _hostChannel = NULL;
+  }
+
+  if (_contextRef) {
+    JSGlobalContextRelease(_contextRef);
+    _contextRef = NULL;
+  }
+}
+@end
+
+@implementation OophmWebScriptObject (Private)
++ (void)logAndThrowString:(NSString*)message {
+  Debug::log(Debug::Info) << "Throwing exception from WSO: " << message << Debug::flush;
+  [WebScriptObject throwException:message];
+}
+
+- (void)addAllowedHost:(NSString*)host {
+  /*
+   * This is more complicated than usual because we're not using the
+   * application's default persestent domain.  Instead, we use a plugin-specific
+   * domain.
+   */
+  NSBundle* pluginBundle = [NSBundle bundleForClass:[OophmWebScriptObject class]];
+  NSString* bundleIdentifier = [pluginBundle bundleIdentifier];
+  
+  NSUserDefaults* shared = [NSUserDefaults standardUserDefaults];
+  NSDictionary* pluginDict = [shared persistentDomainForName:bundleIdentifier];
+  NSArray* allowedHosts = [pluginDict objectForKey:@"allowedHosts"];
+  
+  NSMutableArray* mutableHosts = [NSMutableArray arrayWithArray:allowedHosts];
+  NSMutableDictionary* mutableDict = [NSMutableDictionary dictionaryWithDictionary:pluginDict];
+  [mutableHosts addObject:host];
+  [mutableDict setObject:mutableHosts forKey:@"allowedHosts"];
+  [shared setPersistentDomain:mutableDict forName:bundleIdentifier];
+  [shared synchronize];
+}
+
+- (void)connectAlertDidEnd:(NSAlert *)alert
+                returnCode:(int)returnCode
+               contextInfo:(void *)contextInfo {
+  NSArray* contextArray = (NSArray*) contextInfo;
+  NSString* host = [[contextArray objectAtIndex:0] autorelease];
+  NSString* moduleName = [[contextArray objectAtIndex:1] autorelease];
+  [contextArray release];
+  
+  if (returnCode == NSAlertDefaultReturn) {
+    return;
+  } else if (returnCode == NSAlertAlternateReturn ||
+             [alert respondsToSelector:@selector(suppressionButton)] &&
+             [[alert suppressionButton] state] == NSOnState) {
+    NSArray* hostParts = [host componentsSeparatedByString:@":"];
+    [self addAllowedHost:[hostParts objectAtIndex:0]];
+  }
+
+  [self doConnectWithHost:host withModule:moduleName];
+}
+
+- (BOOL)doConnectWithHost:(NSString*) host
+               withModule:(NSString*) moduleName {
+  Debug::log(Debug::Debugging) << "connect : " << [host UTF8String] << " " <<
+      [moduleName UTF8String] << Debug::flush;
+  
+  if (_hostChannel != NULL) {
+    [OophmWebScriptObject logAndThrowString:@"Already connected"];
+    return NO;
+  }
+  
+  NSArray *parts = [host componentsSeparatedByString:@":"];
+  if ([parts count] != 2) {
+    [OophmWebScriptObject logAndThrowString:
+     [NSString stringWithFormat:@"Incorrect format for host string %i",
+      [parts count]]];
+    return NO;
+  }
+  
+  NSString *hostPart = [parts objectAtIndex:0];
+  NSString *portPart = [parts objectAtIndex:1];
+  
+  Debug::log(Debug::Debugging) << "Extracted host: " << [hostPart UTF8String] <<
+      " and port: " << [portPart UTF8String] << Debug::flush;
+  
+  char *hostAsChars = const_cast<char*>([hostPart UTF8String]);
+  unsigned portAsInt = [portPart intValue];
+  
+  _hostChannel = new HostChannel();
+  if (!_hostChannel->connectToHost(hostAsChars, portAsInt)) {
+    [OophmWebScriptObject logAndThrowString:@"HostChannel failed to connect"];
+    delete _hostChannel;
+    _hostChannel = NULL;
+    return NO;
+  }
+  
+  const char *moduleNameChars = [moduleName UTF8String];
+  
+  _crashHandler = new PluginCrashHandler(self);
+  _sessionHandler = new WebScriptSessionHandler(_hostChannel, _contextRef, _crashHandler);
+  
+  if (!LoadModuleMessage::send(*_hostChannel, BROWSERCHANNEL_PROTOCOL_VERSION,
+                               moduleNameChars, strlen(moduleNameChars),
+                               "Safari OOPHM", _sessionHandler)) {
+    _hostChannel->disconnectFromHost();
+    delete _hostChannel;
+    _hostChannel = NULL;
+    [OophmWebScriptObject logAndThrowString:@"Unable to load module"];
+    return NO;
+  }  
+  
+  return YES;
+}
+@end
diff --git a/plugins/webkit/Plugin/SlowScriptProxy.h b/plugins/webkit/Plugin/SlowScriptProxy.h
new file mode 100644
index 0000000..f46ab94
--- /dev/null
+++ b/plugins/webkit/Plugin/SlowScriptProxy.h
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+#import <Cocoa/Cocoa.h>
+#import <WebKit/WebKit.h>
+
+/*
+ * This NSProxy is used to prevent slow-script warnings from surfacing in the
+ * web browser.  This is something of a hack since the message that we want
+ * to override isn't public, but there's no way to directly reset the slow-scipt
+ * timer either.
+ */
+@interface SlowScriptProxy : NSProxy {
+@private
+  id _target;
+  WebView* _webView;
+}
+
+/*
+ * This will restore the original UIDelegate.
+ */
+- (void)dealloc;
+
+/*
+ * The proxy object will install itself as the UIDelegate on the given webView.
+ */
+- (id)initWithWebView: (WebView*)webView;
+
+/*
+ * Just delegates the invocation to the original UIDelegate.
+ */
+- (void)forwardInvocation:(NSInvocation *)anInvocation;
+
+/*
+ * Just delegates the invocation to the original UIDelegate.
+ */
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
+
+/*
+ * The WebView to which the proxy object has attached itself.
+ */
+- (WebView*)webView;
+
+/*
+ * This is the message that we want to intercept.
+ */
+- (BOOL)webViewShouldInterruptJavaScript:(WebView *)sender;
+@end
diff --git a/plugins/webkit/Plugin/SlowScriptProxy.m b/plugins/webkit/Plugin/SlowScriptProxy.m
new file mode 100644
index 0000000..8798ada
--- /dev/null
+++ b/plugins/webkit/Plugin/SlowScriptProxy.m
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+#import "SlowScriptProxy.h"
+
+@implementation SlowScriptProxy
+- (id)initWithWebView:(WebView*)webView {
+  _target = [[webView UIDelegate] retain];
+  _webView = [webView retain];
+  [_webView setUIDelegate:self];
+  return self;
+}
+
+- (void)dealloc {
+  // Restore the original delegate
+  [_webView setUIDelegate:_target];
+  [_webView release];
+  [_target release];
+  [super dealloc];
+}
+
+- (void)forwardInvocation:(NSInvocation *)anInvocation {
+  [anInvocation setTarget:_target];
+  [anInvocation invoke];
+}
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
+  return [_target methodSignatureForSelector:aSelector];
+}
+
+- (WebView*)webView {
+  return _webView;
+}
+
+- (BOOL)webViewShouldInterruptJavaScript:(WebView *)sender {
+  // TODO: (robertvawter) What do we want to do with repeated invocations?
+  return NO;
+}
+
+@end
diff --git a/plugins/webkit/Plugin/WebFrameNonTigerHeaders.h b/plugins/webkit/Plugin/WebFrameNonTigerHeaders.h
new file mode 100644
index 0000000..975ea6d
--- /dev/null
+++ b/plugins/webkit/Plugin/WebFrameNonTigerHeaders.h
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+#import <JavaScriptCore/JavaScriptCore.h>
+
+/*!
+ * The headers in Tiger don't include the globalContext method.
+ */
+@interface WebFrame (NonTigerHeaders)
+- (JSGlobalContextRef) globalContext;
+@end
\ No newline at end of file
diff --git a/plugins/webkit/build.xml b/plugins/webkit/build.xml
new file mode 100755
index 0000000..34fee9e
--- /dev/null
+++ b/plugins/webkit/build.xml
@@ -0,0 +1,18 @@
+<project name="webkit" default="build" basedir=".">
+	<property name="plugin.root" value="webkit" />
+	<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/webkit" />
+		<copy todir="${gwt.build.out}/plugins/webkit">
+			<fileset file="prebuilt/oophm.dmg" />
+		</copy>
+	</target>
+
+	<target name="test" description="Run any tests">
+	</target>
+
+	<target name="checkstyle" description="Static style analysis">
+	</target>
+</project>
diff --git a/plugins/webkit/gwtlogo.icns b/plugins/webkit/gwtlogo.icns
new file mode 100644
index 0000000..531d676
--- /dev/null
+++ b/plugins/webkit/gwtlogo.icns
Binary files differ
diff --git a/plugins/webkit/oophm.pmdoc/01oophm-contents.xml b/plugins/webkit/oophm.pmdoc/01oophm-contents.xml
new file mode 100644
index 0000000..5c9517c
--- /dev/null
+++ b/plugins/webkit/oophm.pmdoc/01oophm-contents.xml
@@ -0,0 +1 @@
+<pkg-contents spec="1.12"><f n="oophm.webplugin" o="root" g="admin" p="16893" pt="/Users/robertvawter/gwt/oophm/plugins/webkit/build/Release/oophm.webplugin" m="true" t="file"><f n="Contents" o="root" g="admin" p="16893"><f n="Info.plist" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MacOS" o="root" g="admin" p="16893"><f n="oophm" o="root" g="admin" p="33277"><mod>mode</mod></f><mod>mode</mod></f><f n="Resources" o="root" g="admin" p="16893"><f n="English.lproj" o="root" g="admin" p="16893"><f n="crash.html" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="InfoPlist.strings" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="gwtlogo.icns" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="README.google" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f></pkg-contents>
\ No newline at end of file
diff --git a/plugins/webkit/oophm.pmdoc/01oophm.xml b/plugins/webkit/oophm.pmdoc/01oophm.xml
new file mode 100644
index 0000000..ca52096
--- /dev/null
+++ b/plugins/webkit/oophm.pmdoc/01oophm.xml
@@ -0,0 +1 @@
+<pkgref spec="1.12" uuid="417BF300-1147-478E-9359-100836B507EE"><config><identifier>com.google.gwt.oophm.pkg</identifier><version>1</version><description></description><post-install type="none"/><requireAuthorization/><installFrom relative="true" mod="true" includeRoot="true">build/Release/oophm.webplugin</installFrom><installTo mod="true">/Library/Internet Plug-Ins</installTo><flags><followSymbolicLinks/><mod>overwriteDirectoryPermissions</mod></flags><packageStore type="internal"></packageStore><mod>parent</mod><mod>installTo</mod><mod>requireAuthorization</mod><mod>installFrom.isRelativeType</mod><mod>installTo.path</mod><mod>installFrom.path</mod><mod>identifier</mod><mod>includeRoot</mod></config><contents><file-list>01oophm-contents.xml</file-list><component id="com.google.gwt.oophm" path="/Users/robertvawter/gwt/oophm/plugins/webkit/build/Release/oophm.webplugin" version="0.1"/><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref>
\ No newline at end of file
diff --git a/plugins/webkit/oophm.pmdoc/index.xml b/plugins/webkit/oophm.pmdoc/index.xml
new file mode 100644
index 0000000..872d10b
--- /dev/null
+++ b/plugins/webkit/oophm.pmdoc/index.xml
@@ -0,0 +1,15 @@
+<pkmkdoc spec="1.12"><properties><title>GWT Out-of-Process Hosted Mode Plugins</title><build>/Users/robertvawter/Desktop/GWT Out-of-Process Hosted Mode Plugin.mpkg</build><organization>com.google.gwt</organization><userSees ui="custom"/><min-target os="2"/><domain system="true"/></properties><distribution><versions min-spec="1.000000"/><scripts></scripts></distribution><contents><choice title="WebKit Plugin" id="webkit" description="This plugin support WebKit-based browsers, such as Safari and Shiira.  Any other application that makes use of WebKit will also be able to load this plugin." starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="com.google.gwt.oophm.pkg"/></choice></contents><resources bg-scale="none" bg-align="bottomleft"><locale lang="en"><resource relative="true" mod="true" type="background">gwtlogo.icns</resource><resource relative="true" mod="true" type="license">../../distro-source/core/src/COPYING.html</resource><resource relative="true" mod="true" type="readme">../../distro-source/core/src/index.html</resource><resource mime-type="text/rtf" kind="embedded" type="welcome"><![CDATA[{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf270
+{\fonttbl\f0\fnil\fcharset0 LucidaGrande;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\f0\fs26 \cf0 This package contains browser plugins that allow the Google Web Toolkit hosted-mode system to interact with various browsers installed on your computer.\
+\
+These plugins 
+\b are not required
+\b0  to view web pages with GWT modules; they are only necessary if you are writing GWT applications and wish to debug them.}]]></resource><resource mime-type="text/rtf" kind="embedded" type="conclusion"><![CDATA[{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf270
+{\fonttbl\f0\fnil\fcharset0 LucidaGrande;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\f0\fs26 \cf0 Restart any WebKit-based browsers in order to use the plugin.}]]></resource></locale></resources><flags/><item type="file">01oophm.xml</item><mod>properties.customizeOption</mod><mod>properties.userDomain</mod><mod>properties.title</mod><mod>description</mod><mod>properties.systemDomain</mod><mod>properties.anywhereDomain</mod></pkmkdoc>
\ No newline at end of file
diff --git a/plugins/webkit/oophm.xcodeproj/project.pbxproj b/plugins/webkit/oophm.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..d788230
--- /dev/null
+++ b/plugins/webkit/oophm.xcodeproj/project.pbxproj
@@ -0,0 +1,833 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 42;
+	objects = {
+
+/* Begin PBXAggregateTarget section */
+		48420E420DD52761001F3839 /* oophm.dmg */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = 48420E5A0DD527AD001F3839 /* Build configuration list for PBXAggregateTarget "oophm.dmg" */;
+			buildPhases = (
+				48420E460DD52768001F3839 /* ShellScript */,
+			);
+			dependencies = (
+				48420E480DD5278D001F3839 /* PBXTargetDependency */,
+			);
+			name = oophm.dmg;
+			productName = oophm_package;
+		};
+		48547E030DD882170047AC8A /* symlinks */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = 48547E080DD8823B0047AC8A /* Build configuration list for PBXAggregateTarget "symlinks" */;
+			buildPhases = (
+				48547E020DD882170047AC8A /* Make symlink */,
+			);
+			comments = "This will create a symlink in ~/Library/Internet Plug-Ins to the plugin";
+			dependencies = (
+				48547E070DD8821D0047AC8A /* PBXTargetDependency */,
+			);
+			name = symlinks;
+			productName = oophm.symlink;
+		};
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+		480DDCAA0E381E22000711F4 /* AppController.m in Sources */ = {isa = PBXBuildFile; fileRef = 48A23BB50DD0E688004EF5CA /* AppController.m */; };
+		480DDCAB0E381E23000711F4 /* BrowserWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 48A23C770DD0F545004EF5CA /* BrowserWindow.m */; };
+		480DDCAC0E381E28000711F4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 48A23BB60DD0E688004EF5CA /* main.m */; };
+		48108DDF0E2C15BD007FA76C /* AllowedConnections.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 48108DDB0E2C15BD007FA76C /* AllowedConnections.cpp */; };
+		48108DE00E2C15BD007FA76C /* Socket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 48108DDD0E2C15BD007FA76C /* Socket.cpp */; };
+		48338DDF0E4A2CA7008ACF0F /* oophm_bypass.plist in Resources */ = {isa = PBXBuildFile; fileRef = 48338DDB0E4A2C49008ACF0F /* oophm_bypass.plist */; };
+		48420D410DD51A3D001F3839 /* GTMNSString+HTML.m in Sources */ = {isa = PBXBuildFile; fileRef = 48420D3E0DD51A3D001F3839 /* GTMNSString+HTML.m */; };
+		48420D420DD51A3D001F3839 /* GTMStackTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = 48420D3F0DD51A3D001F3839 /* GTMStackTrace.c */; };
+		4851A9D50DD1198300C577B2 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 48FD98A00DC62FD800E011A2 /* JavaScriptCore.framework */; };
+		48547F000DD889DA0047AC8A /* GTMSystemVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 48547EFF0DD889DA0047AC8A /* GTMSystemVersion.m */; };
+		48547F4B0DD88D110047AC8A /* NSMutableString+HtmlReplacement.m in Sources */ = {isa = PBXBuildFile; fileRef = 48547F4A0DD88D110047AC8A /* NSMutableString+HtmlReplacement.m */; };
+		485505ED0DCD475C0009536F /* SlowScriptProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 485505EC0DCD475C0009536F /* SlowScriptProxy.m */; };
+		4856DF890DCF95B8000BF47C /* HostChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4856DF750DCF95B8000BF47C /* HostChannel.cpp */; };
+		4856DF8A0DCF95B8000BF47C /* InvokeMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4856DF770DCF95B8000BF47C /* InvokeMessage.cpp */; };
+		4856DF8B0DCF95B8000BF47C /* LoadModuleMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4856DF790DCF95B8000BF47C /* LoadModuleMessage.cpp */; };
+		4856DF8E0DCF95B8000BF47C /* ReturnMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4856DF7F0DCF95B8000BF47C /* ReturnMessage.cpp */; };
+		4856DF8F0DCF95B8000BF47C /* README.google in Resources */ = {isa = PBXBuildFile; fileRef = 4856DF820DCF95B8000BF47C /* README.google */; };
+		4856DF900DCF95B8000BF47C /* ServerMethods.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4856DF840DCF95B8000BF47C /* ServerMethods.cpp */; };
+		485CCFF00DDDDEA400AEE666 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 485CCFEF0DDDDEA400AEE666 /* CoreFoundation.framework */; };
+		485CD0AA0DDDEAF300AEE666 /* Debug.mm in Sources */ = {isa = PBXBuildFile; fileRef = 485CD0A90DDDEAF300AEE666 /* Debug.mm */; };
+		486DA8F50DD22BD50065980B /* crash.html in Resources */ = {isa = PBXBuildFile; fileRef = 486DA8F40DD22BD50065980B /* crash.html */; };
+		48A237D10DCFB46D004EF5CA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; };
+		48A23BC60DD0E6EE004EF5CA /* browser.nib in Resources */ = {isa = PBXBuildFile; fileRef = 48A23BC50DD0E6EE004EF5CA /* browser.nib */; };
+		48A23BE00DD0E8B1004EF5CA /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 48FD98A10DC62FD800E011A2 /* WebKit.framework */; };
+		48A23BE10DD0E8B6004EF5CA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; };
+		48A23C510DD0F2D6004EF5CA /* Browser-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 48A23C500DD0F2D6004EF5CA /* Browser-Info.plist */; };
+		48A23C530DD0F302004EF5CA /* gwtlogo.icns in Resources */ = {isa = PBXBuildFile; fileRef = 48C4D72D0DCA2B6900C34919 /* gwtlogo.icns */; };
+		48ABDDC50DCBA04800B0159A /* WebScriptSessionHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 48ABDDC40DCBA04800B0159A /* WebScriptSessionHandler.cpp */; };
+		48C4D72E0DCA2B6900C34919 /* gwtlogo.icns in Resources */ = {isa = PBXBuildFile; fileRef = 48C4D72D0DCA2B6900C34919 /* gwtlogo.icns */; };
+		48C9EA4A0E37863700E691C6 /* FreeValueMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 48C9EA440E37863700E691C6 /* FreeValueMessage.cpp */; };
+		48C9EA4B0E37863700E691C6 /* InvokeSpecialMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 48C9EA460E37863700E691C6 /* InvokeSpecialMessage.cpp */; };
+		48C9EA4C0E37863700E691C6 /* LoadJsniMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 48C9EA480E37863700E691C6 /* LoadJsniMessage.cpp */; };
+		48EF692D0E318E200050F5D6 /* ObjectFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 48EF692C0E318E200050F5D6 /* ObjectFunctions.cpp */; };
+		48FD98900DC62E7400E011A2 /* OophmPlugin.mm in Sources */ = {isa = PBXBuildFile; fileRef = 48FD988F0DC62E7400E011A2 /* OophmPlugin.mm */; };
+		48FD98A20DC62FD800E011A2 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 48FD98A00DC62FD800E011A2 /* JavaScriptCore.framework */; };
+		48FD98A30DC62FD800E011A2 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 48FD98A10DC62FD800E011A2 /* WebKit.framework */; };
+		48FD99540DC6349F00E011A2 /* OophmWebScriptObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = 48FD99530DC6349F00E011A2 /* OophmWebScriptObject.mm */; };
+		8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		48420E470DD5278D001F3839 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 089C1669FE841209C02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 8D5B49AC048680CD000E48DA;
+			remoteInfo = oophm;
+		};
+		48547E060DD8821D0047AC8A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 089C1669FE841209C02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 8D5B49AC048680CD000E48DA;
+			remoteInfo = oophm;
+		};
+		485CD0C40DDDED1700AEE666 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 089C1669FE841209C02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 48547E030DD882170047AC8A;
+			remoteInfo = symlinks;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+		089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
+		089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
+		1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
+		32DBCF630370AF2F00C91783 /* oophm_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oophm_Prefix.pch; sourceTree = "<group>"; };
+		48108DDB0E2C15BD007FA76C /* AllowedConnections.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AllowedConnections.cpp; sourceTree = "<group>"; };
+		48108DDC0E2C15BD007FA76C /* AllowedConnections.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllowedConnections.h; sourceTree = "<group>"; };
+		48108DDD0E2C15BD007FA76C /* Socket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Socket.cpp; sourceTree = "<group>"; };
+		48108DDE0E2C15BD007FA76C /* Socket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Socket.h; sourceTree = "<group>"; };
+		48338DDB0E4A2C49008ACF0F /* oophm_bypass.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = oophm_bypass.plist; sourceTree = "<group>"; };
+		48420D3C0DD51A23001F3839 /* GTMDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMDefines.h; path = GTM/GTMDefines.h; sourceTree = "<group>"; };
+		48420D3D0DD51A3D001F3839 /* GTMNSString+HTML.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "GTMNSString+HTML.h"; path = "GTM/Foundation/GTMNSString+HTML.h"; sourceTree = "<group>"; };
+		48420D3E0DD51A3D001F3839 /* GTMNSString+HTML.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "GTMNSString+HTML.m"; path = "GTM/Foundation/GTMNSString+HTML.m"; sourceTree = "<group>"; };
+		48420D3F0DD51A3D001F3839 /* GTMStackTrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GTMStackTrace.c; path = GTM/Foundation/GTMStackTrace.c; sourceTree = "<group>"; };
+		48420D400DD51A3D001F3839 /* GTMStackTrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMStackTrace.h; path = GTM/Foundation/GTMStackTrace.h; sourceTree = "<group>"; };
+		48547EFE0DD889DA0047AC8A /* GTMSystemVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMSystemVersion.h; path = GTM/Foundation/GTMSystemVersion.h; sourceTree = "<group>"; };
+		48547EFF0DD889DA0047AC8A /* GTMSystemVersion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTMSystemVersion.m; path = GTM/Foundation/GTMSystemVersion.m; sourceTree = "<group>"; };
+		48547F490DD88D110047AC8A /* NSMutableString+HtmlReplacement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableString+HtmlReplacement.h"; sourceTree = "<group>"; };
+		48547F4A0DD88D110047AC8A /* NSMutableString+HtmlReplacement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableString+HtmlReplacement.m"; sourceTree = "<group>"; };
+		485505EB0DCD475C0009536F /* SlowScriptProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SlowScriptProxy.h; sourceTree = "<group>"; };
+		485505EC0DCD475C0009536F /* SlowScriptProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SlowScriptProxy.m; sourceTree = "<group>"; };
+		4856DF740DCF95B8000BF47C /* BrowserChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BrowserChannel.h; path = ../common/BrowserChannel.h; sourceTree = SOURCE_ROOT; };
+		4856DF750DCF95B8000BF47C /* HostChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HostChannel.cpp; path = ../common/HostChannel.cpp; sourceTree = SOURCE_ROOT; };
+		4856DF760DCF95B8000BF47C /* HostChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HostChannel.h; path = ../common/HostChannel.h; sourceTree = SOURCE_ROOT; };
+		4856DF770DCF95B8000BF47C /* InvokeMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InvokeMessage.cpp; path = ../common/InvokeMessage.cpp; sourceTree = SOURCE_ROOT; };
+		4856DF780DCF95B8000BF47C /* InvokeMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InvokeMessage.h; path = ../common/InvokeMessage.h; sourceTree = SOURCE_ROOT; };
+		4856DF790DCF95B8000BF47C /* LoadModuleMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LoadModuleMessage.cpp; path = ../common/LoadModuleMessage.cpp; sourceTree = SOURCE_ROOT; };
+		4856DF7A0DCF95B8000BF47C /* LoadModuleMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoadModuleMessage.h; path = ../common/LoadModuleMessage.h; sourceTree = SOURCE_ROOT; };
+		4856DF7D0DCF95B8000BF47C /* Message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Message.h; path = ../common/Message.h; sourceTree = SOURCE_ROOT; };
+		4856DF7E0DCF95B8000BF47C /* QuitMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = QuitMessage.h; path = ../common/QuitMessage.h; sourceTree = SOURCE_ROOT; };
+		4856DF7F0DCF95B8000BF47C /* ReturnMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ReturnMessage.cpp; path = ../common/ReturnMessage.cpp; sourceTree = SOURCE_ROOT; };
+		4856DF800DCF95B8000BF47C /* ReturnMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ReturnMessage.h; path = ../common/ReturnMessage.h; sourceTree = SOURCE_ROOT; };
+		4856DF820DCF95B8000BF47C /* README.google */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.google; path = ../common/scoped_ptr/README.google; sourceTree = SOURCE_ROOT; };
+		4856DF830DCF95B8000BF47C /* scoped_ptr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = scoped_ptr.h; path = ../common/scoped_ptr/scoped_ptr.h; sourceTree = SOURCE_ROOT; };
+		4856DF840DCF95B8000BF47C /* ServerMethods.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ServerMethods.cpp; path = ../common/ServerMethods.cpp; sourceTree = SOURCE_ROOT; };
+		4856DF850DCF95B8000BF47C /* ServerMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ServerMethods.h; path = ../common/ServerMethods.h; sourceTree = SOURCE_ROOT; };
+		4856DF860DCF95B8000BF47C /* SessionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SessionHandler.h; path = ../common/SessionHandler.h; sourceTree = SOURCE_ROOT; };
+		4856DF880DCF95B8000BF47C /* Value.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Value.h; path = ../common/Value.h; sourceTree = SOURCE_ROOT; };
+		485CCE650DDDC5E900AEE666 /* HashMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HashMap.h; sourceTree = "<group>"; };
+		485CCFEF0DDDDEA400AEE666 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
+		485CD0A90DDDEAF300AEE666 /* Debug.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Debug.mm; sourceTree = "<group>"; };
+		486DA8ED0DD22B850065980B /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = English; path = English.lproj/crash.html; sourceTree = "<group>"; wrapsLines = 0; };
+		48A23BA20DD0E5B4004EF5CA /* Browser.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Browser.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		48A23BB40DD0E688004EF5CA /* AppController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppController.h; sourceTree = "<group>"; };
+		48A23BB50DD0E688004EF5CA /* AppController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppController.m; sourceTree = "<group>"; };
+		48A23BB60DD0E688004EF5CA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		48A23BC50DD0E6EE004EF5CA /* browser.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; path = browser.nib; sourceTree = "<group>"; };
+		48A23C500DD0F2D6004EF5CA /* Browser-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Browser-Info.plist"; sourceTree = "<group>"; };
+		48A23C760DD0F545004EF5CA /* BrowserWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BrowserWindow.h; sourceTree = "<group>"; };
+		48A23C770DD0F545004EF5CA /* BrowserWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BrowserWindow.m; sourceTree = "<group>"; };
+		48ABDDC30DCBA04800B0159A /* WebScriptSessionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebScriptSessionHandler.h; sourceTree = "<group>"; };
+		48ABDDC40DCBA04800B0159A /* WebScriptSessionHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebScriptSessionHandler.cpp; sourceTree = "<group>"; };
+		48ABDDC80DCBA09D00B0159A /* TrackingData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackingData.h; sourceTree = "<group>"; };
+		48ABE1050DCBB67600B0159A /* SessionData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SessionData.h; sourceTree = "<group>"; };
+		48C4D72D0DCA2B6900C34919 /* gwtlogo.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = gwtlogo.icns; sourceTree = "<group>"; };
+		48C9EA440E37863700E691C6 /* FreeValueMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FreeValueMessage.cpp; sourceTree = "<group>"; };
+		48C9EA450E37863700E691C6 /* FreeValueMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FreeValueMessage.h; sourceTree = "<group>"; };
+		48C9EA460E37863700E691C6 /* InvokeSpecialMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InvokeSpecialMessage.cpp; sourceTree = "<group>"; };
+		48C9EA470E37863700E691C6 /* InvokeSpecialMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InvokeSpecialMessage.h; sourceTree = "<group>"; };
+		48C9EA480E37863700E691C6 /* LoadJsniMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LoadJsniMessage.cpp; sourceTree = "<group>"; };
+		48C9EA490E37863700E691C6 /* LoadJsniMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoadJsniMessage.h; sourceTree = "<group>"; };
+		48D5795D0DDB8C03005A3498 /* Debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Debug.h; sourceTree = "<group>"; };
+		48D5795E0DDB8C03005A3498 /* DebugLevel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugLevel.h; sourceTree = "<group>"; };
+		48EF692B0E318E200050F5D6 /* ObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectFunctions.h; sourceTree = "<group>"; };
+		48EF692C0E318E200050F5D6 /* ObjectFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectFunctions.cpp; sourceTree = "<group>"; };
+		48FD988E0DC62E7400E011A2 /* OophmPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OophmPlugin.h; sourceTree = "<group>"; };
+		48FD988F0DC62E7400E011A2 /* OophmPlugin.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OophmPlugin.mm; sourceTree = "<group>"; };
+		48FD989B0DC62F8800E011A2 /* WebFrameNonTigerHeaders.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebFrameNonTigerHeaders.h; sourceTree = "<group>"; };
+		48FD98A00DC62FD800E011A2 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = /System/Library/Frameworks/JavaScriptCore.framework; sourceTree = "<absolute>"; };
+		48FD98A10DC62FD800E011A2 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = /System/Library/Frameworks/WebKit.framework; sourceTree = "<absolute>"; };
+		48FD99520DC6349F00E011A2 /* OophmWebScriptObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OophmWebScriptObject.h; sourceTree = "<group>"; };
+		48FD99530DC6349F00E011A2 /* OophmWebScriptObject.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OophmWebScriptObject.mm; sourceTree = "<group>"; };
+		48FFCFC80DD35DA900805659 /* Platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Platform.h; sourceTree = "<group>"; };
+		8D5B49B6048680CD000E48DA /* oophm.webplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = oophm.webplugin; sourceTree = BUILT_PRODUCTS_DIR; };
+		8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Info.plist; sourceTree = "<group>"; };
+		D2F7E65807B2D6F200F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		48A23BA00DD0E5B4004EF5CA /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				48A23BE00DD0E8B1004EF5CA /* WebKit.framework in Frameworks */,
+				48A23BE10DD0E8B6004EF5CA /* Cocoa.framework in Frameworks */,
+				4851A9D50DD1198300C577B2 /* JavaScriptCore.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		8D5B49B3048680CD000E48DA /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				48FD98A20DC62FD800E011A2 /* JavaScriptCore.framework in Frameworks */,
+				48FD98A30DC62FD800E011A2 /* WebKit.framework in Frameworks */,
+				48A237D10DCFB46D004EF5CA /* Cocoa.framework in Frameworks */,
+				485CCFF00DDDDEA400AEE666 /* CoreFoundation.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		089C166AFE841209C02AAC07 /* oophm */ = {
+			isa = PBXGroup;
+			children = (
+				485506C90DCD54180009536F /* Classes */,
+				48420D3B0DD51A0F001F3839 /* GTM */,
+				32C88E010371C26100C91783 /* Other Sources */,
+				089C167CFE841241C02AAC07 /* Resources */,
+				089C1671FE841209C02AAC07 /* Frameworks and Libraries */,
+				19C28FB8FE9D52D311CA2CBB /* Products */,
+			);
+			comments = "/*\n * Copyright 2008 Google Inc.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * use this file except in compliance with the License. You may obtain a copy of\n * the License at\n * \n * http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations under\n * the License.\n */\n";
+			name = oophm;
+			sourceTree = "<group>";
+		};
+		089C1671FE841209C02AAC07 /* Frameworks and Libraries */ = {
+			isa = PBXGroup;
+			children = (
+				1058C7ACFEA557BF11CA2CBB /* Linked Frameworks */,
+				1058C7AEFEA557BF11CA2CBB /* Other Frameworks */,
+			);
+			name = "Frameworks and Libraries";
+			sourceTree = "<group>";
+		};
+		089C167CFE841241C02AAC07 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				48338DDB0E4A2C49008ACF0F /* oophm_bypass.plist */,
+				486DA8F40DD22BD50065980B /* crash.html */,
+				48C4D72D0DCA2B6900C34919 /* gwtlogo.icns */,
+				8D5B49B7048680CD000E48DA /* Info.plist */,
+				089C167DFE841241C02AAC07 /* InfoPlist.strings */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		1058C7ACFEA557BF11CA2CBB /* Linked Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				485CCFEF0DDDDEA400AEE666 /* CoreFoundation.framework */,
+				48FD98A00DC62FD800E011A2 /* JavaScriptCore.framework */,
+				48FD98A10DC62FD800E011A2 /* WebKit.framework */,
+				1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */,
+			);
+			name = "Linked Frameworks";
+			sourceTree = "<group>";
+		};
+		1058C7AEFEA557BF11CA2CBB /* Other Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				089C167FFE841241C02AAC07 /* AppKit.framework */,
+				D2F7E65807B2D6F200F64583 /* CoreData.framework */,
+				089C1672FE841209C02AAC07 /* Foundation.framework */,
+			);
+			name = "Other Frameworks";
+			sourceTree = "<group>";
+		};
+		19C28FB8FE9D52D311CA2CBB /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				8D5B49B6048680CD000E48DA /* oophm.webplugin */,
+				48A23BA20DD0E5B4004EF5CA /* Browser.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		32C88E010371C26100C91783 /* Other Sources */ = {
+			isa = PBXGroup;
+			children = (
+				4856DF730DCF95B8000BF47C /* common */,
+				32DBCF630370AF2F00C91783 /* oophm_Prefix.pch */,
+			);
+			name = "Other Sources";
+			sourceTree = "<group>";
+		};
+		48420D3B0DD51A0F001F3839 /* GTM */ = {
+			isa = PBXGroup;
+			children = (
+				48547EFE0DD889DA0047AC8A /* GTMSystemVersion.h */,
+				48547EFF0DD889DA0047AC8A /* GTMSystemVersion.m */,
+				48420D3D0DD51A3D001F3839 /* GTMNSString+HTML.h */,
+				48420D3E0DD51A3D001F3839 /* GTMNSString+HTML.m */,
+				48420D3F0DD51A3D001F3839 /* GTMStackTrace.c */,
+				48420D400DD51A3D001F3839 /* GTMStackTrace.h */,
+				48420D3C0DD51A23001F3839 /* GTMDefines.h */,
+			);
+			comments = "We just need a subset of the functionality available in GTM, so we'll pull in only the files we need as opposed to creating a cross-project dependency and having to package the framework in the plugin.";
+			name = GTM;
+			sourceTree = "<group>";
+		};
+		485506C90DCD54180009536F /* Classes */ = {
+			isa = PBXGroup;
+			children = (
+				48A23B9D0DD0E57E004EF5CA /* Browser */,
+				4856DFFB0DCFAEFD000BF47C /* Plugin */,
+				4856DFFA0DCFAEBC000BF47C /* Core */,
+			);
+			name = Classes;
+			sourceTree = "<group>";
+		};
+		4856DF730DCF95B8000BF47C /* common */ = {
+			isa = PBXGroup;
+			children = (
+				48C9EA440E37863700E691C6 /* FreeValueMessage.cpp */,
+				48C9EA450E37863700E691C6 /* FreeValueMessage.h */,
+				48C9EA460E37863700E691C6 /* InvokeSpecialMessage.cpp */,
+				48C9EA470E37863700E691C6 /* InvokeSpecialMessage.h */,
+				48C9EA480E37863700E691C6 /* LoadJsniMessage.cpp */,
+				48C9EA490E37863700E691C6 /* LoadJsniMessage.h */,
+				48108DDB0E2C15BD007FA76C /* AllowedConnections.cpp */,
+				48108DDC0E2C15BD007FA76C /* AllowedConnections.h */,
+				48108DDD0E2C15BD007FA76C /* Socket.cpp */,
+				48108DDE0E2C15BD007FA76C /* Socket.h */,
+				485CCE650DDDC5E900AEE666 /* HashMap.h */,
+				48D5795D0DDB8C03005A3498 /* Debug.h */,
+				48D5795E0DDB8C03005A3498 /* DebugLevel.h */,
+				48FFCFC80DD35DA900805659 /* Platform.h */,
+				4856DF740DCF95B8000BF47C /* BrowserChannel.h */,
+				4856DF750DCF95B8000BF47C /* HostChannel.cpp */,
+				4856DF760DCF95B8000BF47C /* HostChannel.h */,
+				4856DF770DCF95B8000BF47C /* InvokeMessage.cpp */,
+				4856DF780DCF95B8000BF47C /* InvokeMessage.h */,
+				4856DF790DCF95B8000BF47C /* LoadModuleMessage.cpp */,
+				4856DF7A0DCF95B8000BF47C /* LoadModuleMessage.h */,
+				4856DF7D0DCF95B8000BF47C /* Message.h */,
+				4856DF7E0DCF95B8000BF47C /* QuitMessage.h */,
+				4856DF7F0DCF95B8000BF47C /* ReturnMessage.cpp */,
+				4856DF800DCF95B8000BF47C /* ReturnMessage.h */,
+				4856DF810DCF95B8000BF47C /* scoped_ptr */,
+				4856DF840DCF95B8000BF47C /* ServerMethods.cpp */,
+				4856DF850DCF95B8000BF47C /* ServerMethods.h */,
+				4856DF860DCF95B8000BF47C /* SessionHandler.h */,
+				4856DF880DCF95B8000BF47C /* Value.h */,
+			);
+			name = common;
+			path = ../common;
+			sourceTree = SOURCE_ROOT;
+		};
+		4856DF810DCF95B8000BF47C /* scoped_ptr */ = {
+			isa = PBXGroup;
+			children = (
+				4856DF820DCF95B8000BF47C /* README.google */,
+				4856DF830DCF95B8000BF47C /* scoped_ptr.h */,
+			);
+			name = scoped_ptr;
+			path = ../common/scoped_ptr;
+			sourceTree = SOURCE_ROOT;
+		};
+		4856DFFA0DCFAEBC000BF47C /* Core */ = {
+			isa = PBXGroup;
+			children = (
+				48ABDDC30DCBA04800B0159A /* WebScriptSessionHandler.h */,
+				48ABDDC40DCBA04800B0159A /* WebScriptSessionHandler.cpp */,
+				48ABDDC80DCBA09D00B0159A /* TrackingData.h */,
+				48ABE1050DCBB67600B0159A /* SessionData.h */,
+				48EF692B0E318E200050F5D6 /* ObjectFunctions.h */,
+				48EF692C0E318E200050F5D6 /* ObjectFunctions.cpp */,
+			);
+			path = Core;
+			sourceTree = "<group>";
+		};
+		4856DFFB0DCFAEFD000BF47C /* Plugin */ = {
+			isa = PBXGroup;
+			children = (
+				485CD0A90DDDEAF300AEE666 /* Debug.mm */,
+				48FD988E0DC62E7400E011A2 /* OophmPlugin.h */,
+				48FD988F0DC62E7400E011A2 /* OophmPlugin.mm */,
+				48FD99520DC6349F00E011A2 /* OophmWebScriptObject.h */,
+				48FD99530DC6349F00E011A2 /* OophmWebScriptObject.mm */,
+				485505EB0DCD475C0009536F /* SlowScriptProxy.h */,
+				485505EC0DCD475C0009536F /* SlowScriptProxy.m */,
+				48FD989B0DC62F8800E011A2 /* WebFrameNonTigerHeaders.h */,
+				48547F490DD88D110047AC8A /* NSMutableString+HtmlReplacement.h */,
+				48547F4A0DD88D110047AC8A /* NSMutableString+HtmlReplacement.m */,
+			);
+			path = Plugin;
+			sourceTree = "<group>";
+		};
+		48A23B9D0DD0E57E004EF5CA /* Browser */ = {
+			isa = PBXGroup;
+			children = (
+				48A23C760DD0F545004EF5CA /* BrowserWindow.h */,
+				48A23C770DD0F545004EF5CA /* BrowserWindow.m */,
+				48A23C500DD0F2D6004EF5CA /* Browser-Info.plist */,
+				48A23BB40DD0E688004EF5CA /* AppController.h */,
+				48A23BB50DD0E688004EF5CA /* AppController.m */,
+				48A23BB60DD0E688004EF5CA /* main.m */,
+				48A23BC50DD0E6EE004EF5CA /* browser.nib */,
+			);
+			path = Browser;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		48A23BA10DD0E5B4004EF5CA /* Browser */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 48A23BA70DD0E5B5004EF5CA /* Build configuration list for PBXNativeTarget "Browser" */;
+			buildPhases = (
+				48A23B9E0DD0E5B4004EF5CA /* Resources */,
+				48A23B9F0DD0E5B4004EF5CA /* Sources */,
+				48A23BA00DD0E5B4004EF5CA /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				485CD0C50DDDED1700AEE666 /* PBXTargetDependency */,
+			);
+			name = Browser;
+			productName = Browser;
+			productReference = 48A23BA20DD0E5B4004EF5CA /* Browser.app */;
+			productType = "com.apple.product-type.application";
+		};
+		8D5B49AC048680CD000E48DA /* oophm */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 1DEB913A08733D840010E9CD /* Build configuration list for PBXNativeTarget "oophm" */;
+			buildPhases = (
+				8D5B49AF048680CD000E48DA /* Resources */,
+				8D5B49B1048680CD000E48DA /* Sources */,
+				8D5B49B3048680CD000E48DA /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = oophm;
+			productInstallPath = "$(HOME)/Library/Bundles";
+			productName = oophm;
+			productReference = 8D5B49B6048680CD000E48DA /* oophm.webplugin */;
+			productType = "com.apple.product-type.bundle";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		089C1669FE841209C02AAC07 /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "oophm" */;
+			compatibilityVersion = "Xcode 2.4";
+			hasScannedForEncodings = 1;
+			mainGroup = 089C166AFE841209C02AAC07 /* oophm */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				48A23BA10DD0E5B4004EF5CA /* Browser */,
+				8D5B49AC048680CD000E48DA /* oophm */,
+				48420E420DD52761001F3839 /* oophm.dmg */,
+				48547E030DD882170047AC8A /* symlinks */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		48A23B9E0DD0E5B4004EF5CA /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				48A23BC60DD0E6EE004EF5CA /* browser.nib in Resources */,
+				48A23C510DD0F2D6004EF5CA /* Browser-Info.plist in Resources */,
+				48A23C530DD0F302004EF5CA /* gwtlogo.icns in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		8D5B49AF048680CD000E48DA /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */,
+				48C4D72E0DCA2B6900C34919 /* gwtlogo.icns in Resources */,
+				4856DF8F0DCF95B8000BF47C /* README.google in Resources */,
+				486DA8F50DD22BD50065980B /* crash.html in Resources */,
+				48338DDF0E4A2CA7008ACF0F /* oophm_bypass.plist in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		48420E460DD52768001F3839 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+				"$(BUILT_PRODUCTS_DIR)/oophm.webplugin",
+			);
+			outputPaths = (
+				"$(BUILT_PRODUCTS_DIR)/oophm.dmg",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "set -x\n# This is because the PackageMaker definition has \"Release\" hard-coded into it\nif [ \"${CONFIGURATION}\" != \"Release\" ]; then\n  echo error: Must be in Release configuration to build disk image\n  exit 1\nfi\n\n/Developer/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker --doc \"${PROJECT_DIR}/oophm.pmdoc\" --out \"${TEMP_FILES_DIR}/oophm.mpkg\"\n\nhdiutil create -ov -srcfolder \"${TEMP_FILES_DIR}/oophm.mpkg\" -format UDBZ \"${BUILT_PRODUCTS_DIR}/oophm.dmg\"\nhdiutil internet-enable \"${BUILT_PRODUCTS_DIR}/oophm.dmg\"";
+			showEnvVarsInLog = 0;
+		};
+		48547E020DD882170047AC8A /* Make symlink */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+				"$(BUILT_PRODUCTS_DIR)/oophm.webplugin",
+			);
+			name = "Make symlink";
+			outputPaths = (
+				"$(USER_LIBRARY_DIR)/Internet Plug-Ins/oophm.webplugin/Contents",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "set -x\nln -sf \"${BUILT_PRODUCTS_DIR}/oophm.webplugin\" \"${USER_LIBRARY_DIR}/Internet Plug-Ins/.\"";
+			showEnvVarsInLog = 0;
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		48A23B9F0DD0E5B4004EF5CA /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				480DDCAA0E381E22000711F4 /* AppController.m in Sources */,
+				480DDCAB0E381E23000711F4 /* BrowserWindow.m in Sources */,
+				480DDCAC0E381E28000711F4 /* main.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		8D5B49B1048680CD000E48DA /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				48FD98900DC62E7400E011A2 /* OophmPlugin.mm in Sources */,
+				48FD99540DC6349F00E011A2 /* OophmWebScriptObject.mm in Sources */,
+				48ABDDC50DCBA04800B0159A /* WebScriptSessionHandler.cpp in Sources */,
+				485505ED0DCD475C0009536F /* SlowScriptProxy.m in Sources */,
+				4856DF890DCF95B8000BF47C /* HostChannel.cpp in Sources */,
+				4856DF8A0DCF95B8000BF47C /* InvokeMessage.cpp in Sources */,
+				4856DF8B0DCF95B8000BF47C /* LoadModuleMessage.cpp in Sources */,
+				4856DF8E0DCF95B8000BF47C /* ReturnMessage.cpp in Sources */,
+				4856DF900DCF95B8000BF47C /* ServerMethods.cpp in Sources */,
+				48420D410DD51A3D001F3839 /* GTMNSString+HTML.m in Sources */,
+				48420D420DD51A3D001F3839 /* GTMStackTrace.c in Sources */,
+				48547F000DD889DA0047AC8A /* GTMSystemVersion.m in Sources */,
+				48547F4B0DD88D110047AC8A /* NSMutableString+HtmlReplacement.m in Sources */,
+				485CD0AA0DDDEAF300AEE666 /* Debug.mm in Sources */,
+				48108DDF0E2C15BD007FA76C /* AllowedConnections.cpp in Sources */,
+				48108DE00E2C15BD007FA76C /* Socket.cpp in Sources */,
+				48EF692D0E318E200050F5D6 /* ObjectFunctions.cpp in Sources */,
+				48C9EA4A0E37863700E691C6 /* FreeValueMessage.cpp in Sources */,
+				48C9EA4B0E37863700E691C6 /* InvokeSpecialMessage.cpp in Sources */,
+				48C9EA4C0E37863700E691C6 /* LoadJsniMessage.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		48420E480DD5278D001F3839 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 8D5B49AC048680CD000E48DA /* oophm */;
+			targetProxy = 48420E470DD5278D001F3839 /* PBXContainerItemProxy */;
+		};
+		48547E070DD8821D0047AC8A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 8D5B49AC048680CD000E48DA /* oophm */;
+			targetProxy = 48547E060DD8821D0047AC8A /* PBXContainerItemProxy */;
+		};
+		485CD0C50DDDED1700AEE666 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 48547E030DD882170047AC8A /* symlinks */;
+			targetProxy = 485CD0C40DDDED1700AEE666 /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+		089C167DFE841241C02AAC07 /* InfoPlist.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				089C167EFE841241C02AAC07 /* English */,
+			);
+			name = InfoPlist.strings;
+			sourceTree = "<group>";
+		};
+		486DA8F40DD22BD50065980B /* crash.html */ = {
+			isa = PBXVariantGroup;
+			children = (
+				486DA8ED0DD22B850065980B /* English */,
+			);
+			name = crash.html;
+			path = Plugin;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		1DEB913B08733D840010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/GTM/build/TigerOrLater-Release\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = oophm_Prefix.pch;
+				GCC_WARN_EFFECTIVE_CPLUSPLUS_VIOLATIONS = NO;
+				GCC_WARN_NON_VIRTUAL_DESTRUCTOR = NO;
+				GCC_WARN_PEDANTIC = NO;
+				INFOPLIST_FILE = Info.plist;
+				INSTALL_PATH = "$(HOME)/Library/Bundles";
+				PRODUCT_NAME = oophm;
+				WRAPPER_EXTENSION = webplugin;
+				ZERO_LINK = YES;
+			};
+			name = Debug;
+		};
+		1DEB913C08733D840010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = (
+					ppc,
+					i386,
+				);
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/GTM/build/TigerOrLater-Release\"";
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = G5;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = oophm_Prefix.pch;
+				GCC_WARN_EFFECTIVE_CPLUSPLUS_VIOLATIONS = NO;
+				GCC_WARN_NON_VIRTUAL_DESTRUCTOR = NO;
+				GCC_WARN_PEDANTIC = NO;
+				INFOPLIST_FILE = Info.plist;
+				INSTALL_PATH = "$(HOME)/Library/Bundles";
+				PRODUCT_NAME = oophm;
+				STRIP_INSTALLED_PRODUCT = YES;
+				STRIP_STYLE = "non-global";
+				WRAPPER_EXTENSION = webplugin;
+			};
+			name = Release;
+		};
+		1DEB913F08733D840010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = "GWT_DEBUGLEVEL=Debugging";
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				OTHER_CFLAGS = "-mmacosx-version-min=10.4";
+				PREBINDING = NO;
+				SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
+				STRIP_INSTALLED_PRODUCT = NO;
+				STRIP_STYLE = "non-global";
+				SYMROOT = build;
+			};
+			name = Debug;
+		};
+		1DEB914008733D840010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_OPTIMIZATION_LEVEL = 3;
+				GCC_PREPROCESSOR_DEFINITIONS = GWT_DEBUGDISABLE;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				OTHER_CFLAGS = "-mmacosx-version-min=10.4";
+				PREBINDING = NO;
+				SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
+				STRIP_STYLE = "non-global";
+				SYMROOT = build;
+			};
+			name = Release;
+		};
+		48420E430DD52761001F3839 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				PRODUCT_NAME = oophm_package;
+			};
+			name = Debug;
+		};
+		48420E440DD52761001F3839 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				PRODUCT_NAME = oophm_package;
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		48547E040DD882170047AC8A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				PRODUCT_NAME = oophm.symlink;
+			};
+			name = Debug;
+		};
+		48547E050DD882170047AC8A /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				PRODUCT_NAME = oophm.symlink;
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		48A23BA50DD0E5B5004EF5CA /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = oophm_Prefix.pch;
+				INFOPLIST_FILE = "Browser/Browser-Info.plist";
+				INSTALL_PATH = "$(HOME)/Applications";
+				OTHER_LDFLAGS = (
+					"-framework",
+					Foundation,
+					"-framework",
+					AppKit,
+				);
+				PREBINDING = NO;
+				PRODUCT_NAME = Browser;
+				WRAPPER_EXTENSION = app;
+				ZERO_LINK = YES;
+			};
+			name = Debug;
+		};
+		48A23BA60DD0E5B5004EF5CA /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = (
+					i386,
+					ppc,
+				);
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_MODEL_TUNING = G5;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = oophm_Prefix.pch;
+				INFOPLIST_FILE = "Browser/Browser-Info.plist";
+				INSTALL_PATH = "$(HOME)/Applications";
+				OTHER_LDFLAGS = (
+					"-framework",
+					Foundation,
+					"-framework",
+					AppKit,
+				);
+				PREBINDING = NO;
+				PRODUCT_NAME = Browser;
+				STRIP_INSTALLED_PRODUCT = YES;
+				STRIP_STYLE = "non-global";
+				VALID_ARCHS = "ppc64 ppc7400 ppc970 i386 x86_64 ppc";
+				WRAPPER_EXTENSION = app;
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		1DEB913A08733D840010E9CD /* Build configuration list for PBXNativeTarget "oophm" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB913B08733D840010E9CD /* Debug */,
+				1DEB913C08733D840010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "oophm" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB913F08733D840010E9CD /* Debug */,
+				1DEB914008733D840010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		48420E5A0DD527AD001F3839 /* Build configuration list for PBXAggregateTarget "oophm.dmg" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				48420E430DD52761001F3839 /* Debug */,
+				48420E440DD52761001F3839 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		48547E080DD8823B0047AC8A /* Build configuration list for PBXAggregateTarget "symlinks" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				48547E040DD882170047AC8A /* Debug */,
+				48547E050DD882170047AC8A /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		48A23BA70DD0E5B5004EF5CA /* Build configuration list for PBXNativeTarget "Browser" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				48A23BA50DD0E5B5004EF5CA /* Debug */,
+				48A23BA60DD0E5B5004EF5CA /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 089C1669FE841209C02AAC07 /* Project object */;
+}
diff --git a/plugins/webkit/oophm_Prefix.pch b/plugins/webkit/oophm_Prefix.pch
new file mode 100644
index 0000000..e7b7f01
--- /dev/null
+++ b/plugins/webkit/oophm_Prefix.pch
@@ -0,0 +1,7 @@
+//
+// Prefix header for all source files of the 'oophm' target in the 'oophm' project.
+//
+
+#ifdef __OBJC__
+    #import <Cocoa/Cocoa.h>
+#endif
diff --git a/plugins/webkit/oophm_bypass.plist b/plugins/webkit/oophm_bypass.plist
new file mode 100644
index 0000000..b7af14f
--- /dev/null
+++ b/plugins/webkit/oophm_bypass.plist
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!-- Copy this to Library/Preferences/com.google.gwt.oophm.plist -->
+<plist version="1.0">
+<dict>
+	<key>allowAll</key>
+	<true/>
+</dict>
+</plist>
diff --git a/plugins/webkit/prebuilt/oophm.dmg b/plugins/webkit/prebuilt/oophm.dmg
new file mode 100644
index 0000000..54fd2d9
--- /dev/null
+++ b/plugins/webkit/prebuilt/oophm.dmg
Binary files differ
diff --git a/plugins/xpcom/ExternalWrapper.cpp b/plugins/xpcom/ExternalWrapper.cpp
new file mode 100644
index 0000000..9ce0103
--- /dev/null
+++ b/plugins/xpcom/ExternalWrapper.cpp
@@ -0,0 +1,147 @@
+/*
+ * 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 "ExternalWrapper.h"
+
+#include "nsIHttpProtocolHandler.h"
+#include "nsISupports.h"
+#include "nsNetCID.h"
+#include "nsCOMPtr.h"
+#include "nsMemory.h"
+#include "nsServiceManagerUtils.h"
+
+#ifndef NS_IMPL_ISUPPORTS2_CI
+#include "nsIClassInfoImpl.h" // 1.9 only
+#endif
+
+#include "LoadModuleMessage.h"
+#include "ServerMethods.h"
+
+NS_IMPL_ISUPPORTS2_CI(ExternalWrapper, IOOPHM, nsISecurityCheckedComponent)
+
+ExternalWrapper::ExternalWrapper() {
+  Debug::log(Debug::Spam) << "ExternalWrapper::ExternalWrapper()" << Debug::flush;
+}
+
+ExternalWrapper::~ExternalWrapper() {
+  Debug::log(Debug::Spam) << "ExternalWrapper::~ExternalWrapper" << Debug::flush;
+}
+
+// define the CID for nsIHttpProtocolHandler
+static NS_DEFINE_CID(kHttpHandlerCID, NS_HTTPPROTOCOLHANDLER_CID);
+
+static nsresult getUserAgent(std::string& userAgent) {
+  nsresult res;
+  nsCOMPtr<nsIHttpProtocolHandler> http = do_GetService(kHttpHandlerCID, &res);
+  if (NS_FAILED(res)) {
+    return res;
+  }
+  nsCString userAgentStr;
+  res = http->GetUserAgent(userAgentStr);
+  if (NS_FAILED(res)) {
+    return res;
+  }
+  userAgent.assign(userAgentStr.get());
+  return NS_OK;
+}
+
+// TODO: handle context object passed in (currently nsIDOMWindow below)
+NS_IMETHODIMP ExternalWrapper::Connect(const nsACString & aAddr, const nsACString & aModuleName, nsIDOMWindow* domWindow, PRBool *_retval) {
+  Debug::log(Debug::Spam) << "Address: " << aAddr << " Module: " << aModuleName << Debug::flush;
+
+  // TODO: string utilities?
+  nsCString addrAutoStr(aAddr), moduleAutoStr(aModuleName);
+  std::string url(addrAutoStr.get());
+  
+  size_t index = url.find(':');
+  if (index == std::string::npos) {
+    *_retval = false;
+    return NS_OK;
+  }
+  std::string hostPart = url.substr(0, index);
+  std::string portPart = url.substr(index + 1);
+
+  HostChannel* channel = new HostChannel();
+
+  Debug::log(Debug::Debugging) << "Connecting..." << Debug::flush;
+
+  if (!channel->connectToHost(
+      const_cast<char*>(hostPart.c_str()),
+      atoi(portPart.c_str()))) {
+    *_retval = false;
+    return NS_OK;
+  }
+
+  Debug::log(Debug::Debugging) << "...Connected" << Debug::flush;
+
+  sessionHandler.reset(new FFSessionHandler(channel/*, ctx*/));
+  std::string moduleName(moduleAutoStr.get());
+  std::string userAgent;
+
+  // get the user agent
+  nsresult res = getUserAgent(userAgent);
+  if (NS_FAILED(res)) {
+    return res;
+  }
+
+  LoadModuleMessage::send(*channel, 1,
+    moduleName.c_str(), moduleName.length(),
+    userAgent.c_str(),
+    sessionHandler.get());
+
+  // TODO: return session object?
+  *_retval = true;
+  return NS_OK;
+}
+
+// nsISecurityCheckedComponent
+static char* cloneAllAccess() {
+  static const char allAccess[] = "allAccess";
+  return static_cast<char*>(nsMemory::Clone(allAccess, sizeof(allAccess)));
+}
+
+static bool strEquals(const PRUnichar* utf16, const char* ascii) {
+  nsCString utf8;
+  NS_UTF16ToCString(nsDependentString(utf16), NS_CSTRING_ENCODING_UTF8, utf8);
+  return strcmp(ascii, utf8.get()) == 0;
+}
+
+NS_IMETHODIMP ExternalWrapper::CanCreateWrapper(const nsIID * iid, char **_retval) {
+  Debug::log(Debug::Spam) << "ExternalWrapper::CanCreateWrapper" << Debug::flush;
+  *_retval = cloneAllAccess();
+  return NS_OK;
+}
+
+NS_IMETHODIMP ExternalWrapper::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval) {
+  Debug::log(Debug::Spam) << "ExternalWrapper::CanCallMethod" << Debug::flush;
+  if (strEquals(methodName, "connect")) {
+    *_retval = cloneAllAccess();
+  } else {
+    *_retval = nsnull;
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP ExternalWrapper::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval) {
+  Debug::log(Debug::Spam) << "ExternalWrapper::CanGetProperty" << Debug::flush;
+  *_retval = nsnull;
+  return NS_OK;
+}
+NS_IMETHODIMP ExternalWrapper::CanSetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval) {
+  Debug::log(Debug::Spam) << "ExternalWrapper::CanSetProperty" << Debug::flush;
+  *_retval = nsnull;
+  return NS_OK;
+}
diff --git a/plugins/xpcom/ExternalWrapper.h b/plugins/xpcom/ExternalWrapper.h
new file mode 100755
index 0000000..a21204c
--- /dev/null
+++ b/plugins/xpcom/ExternalWrapper.h
@@ -0,0 +1,59 @@
+#ifndef _H_ExternalWrapper
+#define _H_ExternalWrapper
+/*
+ * 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 "mozincludes.h"
+
+#include "IOOPHM.h"
+
+#include "FFSessionHandler.h"
+#include "Debug.h"
+#include "scoped_ptr/scoped_ptr.h"
+#include "nsISecurityCheckedComponent.h"
+#include "nsStringAPI.h"
+
+class nsIDOMWindow;
+
+// {028DD88B-6D65-401D-AAFD-17E497D15D09}
+#define OOPHM_CID \
+  { 0x028DD88B, 0x6D65, 0x401D, \
+  { 0xAA, 0xFD, 0x17, 0xE4, 0x97, 0xD1, 0x5D, 0x09 } }
+
+#define OOPHM_CONTRACTID "@gwt.google.com/oophm/ExternalWrapper;1"
+#define OOPHM_CLASSNAME "GWT Hosted-mode component"
+
+class ExternalWrapper : public IOOPHM,
+                        public nsISecurityCheckedComponent {
+  NS_DECL_ISUPPORTS
+  NS_DECL_IOOPHM
+  NS_DECL_NSISECURITYCHECKEDCOMPONENT
+
+  ExternalWrapper();
+  virtual ~ExternalWrapper(); 
+private:
+  scoped_ptr<FFSessionHandler> sessionHandler;
+};
+
+inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, const nsACString& str) {
+  nsCString copy(str);
+  dbg << copy.get();
+  return dbg;
+}
+
+#endif
diff --git a/plugins/xpcom/FFSessionHandler.cpp b/plugins/xpcom/FFSessionHandler.cpp
new file mode 100755
index 0000000..908e755
--- /dev/null
+++ b/plugins/xpcom/FFSessionHandler.cpp
@@ -0,0 +1,554 @@
+/*
+ * 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 "FFSessionHandler.h"
+#include "HostChannel.h"
+#include "JavaObject.h"
+#include "JSRunner.h"
+#include "Debug.h"
+#include "XpcomDebug.h"
+#include "scoped_ptr/scoped_ptr.h"
+#include "RootedObject.h"
+#include "InvokeMessage.h"
+#include "ServerMethods.h"
+
+#include "jsapi.h"
+#include "nsCOMPtr.h"
+#include "nsIJSContextStack.h"
+#include "nsIPrincipal.h"
+#include "nsServiceManagerUtils.h"
+
+static JSContext* getJSContext() {
+  // Get JSContext from stack.
+  nsCOMPtr<nsIJSContextStack> stack =
+      do_GetService("@mozilla.org/js/xpc/ContextStack;1");
+  if (!stack) {
+    return NULL;
+  }
+
+  JSContext *cx;
+  if (NS_FAILED(stack->Peek(&cx))) {
+    return NULL;
+  }
+  return cx;
+}
+
+FFSessionHandler::FFSessionHandler(HostChannel* channel)
+    : SessionData(channel, this, getJSContext()), jsObjectId(0),
+    jsObjectsById(NULL), stringObjectClass(NULL) {
+  // TODO(jat): is there a way to avoid calling this twice, without keeping
+  // JSContext in an instance field?
+  JSContext* ctx = getJSContext();
+  if (!JS_AddNamedRoot(ctx, &jsObjectsById, "jsObjectsById")) {
+    Debug::log(Debug::Error) << "Error rooting jsObjectsById" << Debug::flush;
+  }
+  jsObjectsById = JS_NewArrayObject(ctx, 0, NULL);
+  if (!jsObjectsById) {
+    Debug::log(Debug::Error) << "Error rooting jsObjectsById" << Debug::flush;
+  }
+  if (!JS_AddNamedRoot(ctx, &toStringTearOff, "toStringTearOff")) {
+    Debug::log(Debug::Error) << "Error rooting toStringTearOff" << Debug::flush;
+  }
+  getStringObjectClass(ctx);
+  getToStringTearOff(ctx);
+}
+
+void FFSessionHandler::getStringObjectClass(JSContext* ctx) {
+  jsval str = JS_GetEmptyStringValue(ctx);
+  JSObject* obj = 0;
+  if (!JS_ValueToObject(ctx, str, &obj)) {
+    return;
+  }
+  if (!obj) {
+    return;
+  }
+  stringObjectClass = JS_GET_CLASS(ctx, obj);
+}
+
+void FFSessionHandler::getToStringTearOff(JSContext* ctx) {
+  jsval funcVal;
+  if (!JS_GetProperty(ctx, global, "__gwt_makeTearOff", &funcVal)) {
+    Debug::log(Debug::Error) << "Could not get function \"__gwt_makeTearOff\""
+        << Debug::flush;
+    return;
+  }
+  jsval jsargs[3] = {
+    JSVAL_NULL,                                     // no proxy
+    INT_TO_JSVAL(InvokeMessage::TOSTRING_DISP_ID),  // dispId
+    JSVAL_ZERO                                      // arg count is zero
+  };
+  if (!JS_CallFunctionValue(ctx, global, funcVal, 3, jsargs, &toStringTearOff)) {
+    jsval exc;
+    if (JS_GetPendingException(ctx, &exc)) {
+      Debug::log(Debug::Error)
+          << "__gwt_makeTearOff(null,0,0) threw exception "
+          << dumpJsVal(ctx, exc) << Debug::flush;
+    } else {
+      Debug::log(Debug::Error) << "Error creating toString tear-off"
+          << Debug::flush;
+    }
+    // TODO(jat): show some crash page and die
+  }
+}
+
+FFSessionHandler::~FFSessionHandler(void) {
+  Debug::log(Debug::Debugging) << "FFSessionHandler::~FFSessionHandler" << Debug::flush;
+  disconnect();
+  if (runtime) {
+    JS_RemoveRootRT(runtime, &jsObjectsById);
+    jsObjectsById = NULL;
+    JS_RemoveRootRT(runtime, &toStringTearOff);
+    runtime = NULL;
+  }
+}
+
+void FFSessionHandler::freeValue(HostChannel& channel, int idCount, const int* ids) {
+  Debug::DebugStream& dbg = Debug::log(Debug::Spam)
+      << "FFSessionHandler::freeValue [ ";
+  JSContext* ctx = getJSContext();
+
+  for (int i = 0; i < idCount; ++i) {
+    int objId = ids[i];
+    dbg << objId << " ";
+    jsval toRemove;
+    if (JS_GetElement(ctx, jsObjectsById, objId, &toRemove) && JSVAL_IS_OBJECT(toRemove)) {
+      jsIdsByObject.erase(JSVAL_TO_OBJECT(toRemove));
+      JS_DeleteElement(ctx, jsObjectsById, objId);
+    } else {
+      Debug::log(Debug::Error) << "Error deleting js objId=" << objId << Debug::flush;
+    }
+  }
+
+  dbg << "]" << Debug::flush;
+}
+
+void FFSessionHandler::loadJsni(HostChannel& channel, const std::string& js) {
+  Debug::log(Debug::Spam) << "FFSessionHandler::loadJsni " << js << "(EOM)" << Debug::flush;
+  JSContext* ctx = getJSContext();
+  if (!JSRunner::eval(ctx, global, js)) {
+    Debug::log(Debug::Error) << "Error executing script" << Debug::flush;
+  }
+}
+
+void FFSessionHandler::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();
+    }
+  }
+}
+
+bool FFSessionHandler::invoke(HostChannel& channel, const Value& thisObj, const std::string& methodName,
+    int numArgs, const Value* const args, Value* returnValue) {
+  Debug::log(Debug::Spam) << "FFSessionHandler::invoke " << thisObj.toString()
+      << "::" << methodName << Debug::flush;
+  JSContext* ctx = getJSContext();
+
+  // Used to root JSthis and args while making the JS call
+  // TODO(jat): keep one object and just keep a "stack pointer" into that
+  // object on the native stack so we don't keep allocating/rooting/freeing
+  // an object
+  RootedObject argsRoot(ctx, "FFSessionhandler::invoke");
+  argsRoot = JS_NewArrayObject(ctx, 0, NULL);
+  if (!JS_SetArrayLength(ctx, argsRoot.get(), numArgs + 1)) {
+    Debug::log(Debug::Error)
+        << "FFSessionhandler::invoke - could not set argsRoot length"
+        << Debug::flush;
+    return true;
+  }
+  
+  jsval jsThis;
+  if (thisObj.isNull()) {
+    jsThis = OBJECT_TO_JSVAL(global);
+    Debug::log(Debug::Spam) << "  using global object for this" << Debug::flush;
+  } else {
+    makeJsvalFromValue(jsThis, ctx, thisObj);
+    if (Debug::level(Debug::Spam)) {
+      Debug::log(Debug::Spam) << "  obj=" << dumpJsVal(ctx, jsThis)
+          << Debug::flush;
+    }
+  }
+  if (!JS_SetElement(ctx, argsRoot.get(), 0, &jsThis)) {
+    Debug::log(Debug::Error)
+        << "FFSessionhandler::invoke - could not set argsRoot[0] to this"
+        << Debug::flush;
+    return true;
+  }
+
+  jsval funcVal;
+  // TODO: handle non-ASCII method names
+  if (!JS_GetProperty(ctx, global, methodName.c_str(), &funcVal)) {
+    Debug::log(Debug::Error) << "Could not get function " << methodName << Debug::flush;
+    return true;
+  }
+
+  scoped_array<jsval> jsargs(new jsval[numArgs]);
+  for (int i = 0; i < numArgs; ++i) {
+    makeJsvalFromValue(jsargs[i], ctx, args[i]);
+    if (Debug::level(Debug::Spam)) {
+      Debug::log(Debug::Spam) << "  arg[" << i << "] = " << dumpJsVal(ctx,
+          jsargs[i]) << Debug::flush;
+    }
+    if (!JS_SetElement(ctx, argsRoot.get(), i + 1, &jsargs[i])) {
+      Debug::log(Debug::Error)
+          << "FFSessionhandler::invoke - could not set args[" << (i + 1) << "]"
+          << Debug::flush;
+      return true;
+    }
+  }
+
+  if (JS_IsExceptionPending(ctx)) {
+    JS_ClearPendingException(ctx);
+  }
+
+  jsval rval;
+  JSBool ok = JS_CallFunctionValue(ctx, JSVAL_TO_OBJECT(jsThis), funcVal,
+      numArgs, jsargs.get(), &rval);
+
+  if (!ok) {
+    if (JS_GetPendingException(ctx, &rval)) {
+      makeValueFromJsval(*returnValue, ctx, rval);
+      Debug::log(Debug::Debugging) << "FFSessionHandler::invoke "
+          << thisObj.toString() << "::" << methodName << " threw exception "
+          << dumpJsVal(ctx, rval) << Debug::flush;
+    } else {
+      Debug::log(Debug::Error) << "Non-exception failure invoking "
+          << methodName << Debug::flush;
+      returnValue->setUndefined();
+    }
+  } else {
+    makeValueFromJsval(*returnValue, ctx, rval);
+  }
+  Debug::log(Debug::Spam) << "  return= " << *returnValue << Debug::flush;
+  return !ok;
+}
+
+/**
+ * Invoke a plugin-provided method with the given args.  As above, this method does not own
+ * any of its args.
+ *
+ * Returns true if an exception occurred.
+ */
+bool FFSessionHandler::invokeSpecial(HostChannel& channel, SpecialMethodId method, int numArgs,
+    const Value* const args, Value* returnValue)  {
+  Debug::log(Debug::Spam) << "FFSessionHandler::invokeSpecial" << Debug::flush;
+  return false;
+}
+
+/**
+ * Convert UTF16 string to UTF8-encoded std::string.
+ * 
+ * @return UTF8-encoded string.
+ */
+static std::string utf8String(const jschar* str, unsigned len) {
+  std::string utf8str;
+  while (len-- > 0) {
+    unsigned ch = *str++;
+    // check for paired surrogates first, leave unpaired surrogates as-is
+    if (ch >= 0xD800 && ch < 0xDC00 && len > 0 && *str >= 0xDC00 && *str < 0xE000) {
+      ch = ((ch & 1023) << 10) + (*str++ & 1023) + 0x10000;
+      len--;
+    }
+    if (ch < 0x80) {          // U+0000 - U+007F as 0xxxxxxx
+      utf8str.append(1, ch);
+    } else if (ch < 0x800) {  // U+0080 - U+07FF as 110xxxxx 10xxxxxx
+      utf8str.append(1, 0xC0 + ((ch >> 6) & 31));
+      utf8str.append(1, 0x80 + (ch & 63));
+    } else if (ch < 0x10000) { // U+0800 - U+FFFF as 1110xxxx 10xxxxxx 10xxxxxx
+      utf8str.append(1, 0xE0 + ((ch >> 12) & 15));
+      utf8str.append(1, 0x80 + ((ch >> 6) & 63));
+      utf8str.append(1, 0x80 + (ch & 63));
+    } else {  // rest as 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+      utf8str.append(1, 0xF0 + ((ch >> 18) & 7));
+      utf8str.append(1, 0x80 + ((ch >> 12) & 63));
+      utf8str.append(1, 0x80 + ((ch >> 6) & 63));
+      utf8str.append(1, 0x80 + (ch & 63));
+    }
+  }
+  return utf8str;
+}
+
+/**
+ * Creates a JSString from a UTF8-encoded std::string.
+ * 
+ * @return the JSString object, which owns its memory buffer.
+ */
+static JSString* stringUtf8(JSContext* ctx, const std::string& utf8str) {
+  unsigned len = 0;
+  for (unsigned i = 0; i < utf8str.length(); ++i) {
+    char ch = utf8str[i];
+    switch (ch & 0xF8) {
+      // continuation & invalid chars
+      default:
+      // ASCII characters
+      case 0x00: case 0x08: case 0x10: case 0x18:
+      case 0x20: case 0x28: case 0x30: case 0x38:
+      case 0x40: case 0x48: case 0x50: case 0x58:
+      case 0x60: case 0x68: case 0x70: case 0x78:
+      // 2-byte UTF8 characters
+      case 0xC0: case 0xC8: case 0xD0: case 0xD8:
+      // 3-byte UTF8 characters
+      case 0xE0: case 0xE8:
+        ++len;
+        break;
+      case 0xF0:
+        len += 2;
+        break;
+    }
+  }
+  // Account for null terminator even if it isn't included in the string length
+  // Note that buf becomes owned by the JSString and must not be freed here.
+  jschar* buf = static_cast<jschar*>(JS_malloc(ctx, (len + 1) * sizeof(jschar)));
+  if (!buf) {
+    return NULL;
+  }
+  jschar* p = buf;
+  unsigned codePoint;
+  int charsLeft = -1;
+  for (unsigned i = 0; i < utf8str.length(); ++i) {
+    char ch = utf8str[i];
+    if (charsLeft >= 0) {
+      if ((ch & 0xC0) != 0x80) {
+        // invalid, missing continuation character
+        *p++ = static_cast<jschar>(0xFFFD);
+        charsLeft = -1;
+      } else {
+        codePoint = (codePoint << 6) | (ch & 63);
+        if (!--charsLeft) {
+          if (codePoint >= 0x10000) {
+            codePoint -= 0x10000;
+            *p++ = static_cast<jschar>(0xD800 + ((codePoint >> 10) & 1023));
+            *p++ = static_cast<jschar>(0xDC00 + (codePoint & 1023));
+          } else {
+            *p++ = static_cast<jschar>(codePoint);
+          }
+          charsLeft = -1;
+        }
+      }
+      continue;
+    }
+    // Look at the top 5 bits to determine how many bytes are in this character.
+    switch (ch & 0xF8) {
+      default: // skip invalid and continuation chars
+        break;
+      case 0x00: case 0x08: case 0x10: case 0x18:
+      case 0x20: case 0x28: case 0x30: case 0x38:
+      case 0x40: case 0x48: case 0x50: case 0x58:
+      case 0x60: case 0x68: case 0x70: case 0x78:
+        *p++ = static_cast<jschar>(ch);
+        break;
+      case 0xC0: case 0xC8: case 0xD0: case 0xD8:
+        charsLeft = 1;
+        codePoint = ch & 31;
+        break;
+      case 0xE0: case 0xE8:
+        charsLeft = 2;
+        codePoint = ch & 15;
+        break;
+      case 0xF0:
+        charsLeft = 3;
+        codePoint = ch & 7;
+        break;
+    }
+  }
+  // null terminator, apparently some code expects a terminator even though
+  // the strings are counted.  Note that this null word should not be included
+  // in the length, and that the buffer becomes owned by the JSString object.
+  *p = 0;
+  return JS_NewUCString(ctx, buf, p - buf);
+}
+
+void FFSessionHandler::makeValueFromJsval(Value& retVal, JSContext* ctx,
+    const jsval& value) {
+  if (JSVAL_IS_VOID(value)) {
+    retVal.setUndefined();
+  } else if (JSVAL_IS_NULL(value)) {
+    retVal.setNull();
+  } else if (JSVAL_IS_INT(value)) {
+    retVal.setInt(JSVAL_TO_INT(value));
+  } else if (JSVAL_IS_BOOLEAN(value)) {
+    retVal.setBoolean(JSVAL_TO_BOOLEAN(value));
+  } else if (JSVAL_IS_STRING(value)) {
+    JSString* str = JSVAL_TO_STRING(value);
+    retVal.setString(utf8String(JS_GetStringChars(str),
+        JS_GetStringLength(str)));
+  } else if (JSVAL_IS_DOUBLE(value)) {
+    retVal.setDouble(*JSVAL_TO_DOUBLE(value));
+  } else if (JSVAL_IS_OBJECT(value)) {
+    JSObject* obj = JSVAL_TO_OBJECT(value);
+    if (JavaObject::isJavaObject(ctx, obj)) {
+      retVal.setJavaObject(JavaObject::getObjectId(ctx, obj));
+    } else if (JS_GET_CLASS(ctx, obj) == stringObjectClass) {
+      // JS String wrapper object, treat as a string primitive
+      JSString* str = JS_ValueToString(ctx, value);
+      retVal.setString(utf8String(JS_GetStringChars(str),
+          JS_GetStringLength(str)));
+      // str will be garbage-collected, does not need to be freed
+    } else {
+      // It's a plain-old JavaScript Object
+      std::map<JSObject*, int>::iterator it = jsIdsByObject.find(obj);
+      if (it != jsIdsByObject.end()) {
+        retVal.setJsObjectId(it->second);
+      } else {
+        // Allocate a new id
+        int objId = ++jsObjectId;
+        JS_SetElement(ctx, jsObjectsById, objId, const_cast<jsval*>(&value));
+        jsIdsByObject[obj] = objId;
+        retVal.setJsObjectId(objId);
+      }
+    }
+  } else {
+    Debug::log(Debug::Error) << "Unhandled jsval type " << Debug::flush;
+    retVal.setString("Unhandled jsval type");
+  }
+}
+
+void FFSessionHandler::makeJsvalFromValue(jsval& retVal, JSContext* ctx,
+    const Value& value) {
+  switch (value.getType()) {
+    case Value::NULL_TYPE:
+      retVal = JSVAL_NULL;
+      break;
+    case Value::BOOLEAN:
+      retVal = BOOLEAN_TO_JSVAL(value.getBoolean());
+      break;
+    case Value::BYTE:
+      retVal = INT_TO_JSVAL((int) value.getByte());
+      break;
+    case Value::CHAR:
+      retVal = INT_TO_JSVAL((int) value.getChar());
+      break;
+    case Value::SHORT:
+      retVal = INT_TO_JSVAL((int) value.getShort());
+      break;
+    case Value::INT: {
+      int intValue = value.getInt();
+      if (INT_FITS_IN_JSVAL(intValue)) {
+        retVal = INT_TO_JSVAL(intValue);
+      } else {
+        JS_NewNumberValue(ctx, (jsdouble) intValue, &retVal);
+      }
+      break;
+    }
+    // TODO(jat): do we still need long support in the wire format and Value?
+//    case Value::LONG:
+//      retVal = value.getLong();
+//      break;
+    case Value::FLOAT:
+      JS_NewNumberValue(ctx, (jsdouble) value.getFloat(), &retVal);
+      break;
+    case Value::DOUBLE:
+      JS_NewNumberValue(ctx, (jsdouble) value.getDouble(), &retVal);
+      break;
+    case Value::STRING:
+      {
+        JSString* str = stringUtf8(ctx, value.getString());
+        retVal = STRING_TO_JSVAL(str);
+      }
+      break;
+    case Value::JAVA_OBJECT:
+      {
+        int javaId = value.getJavaObjectId();
+        std::map<int, JSObject*>::iterator i = javaObjectsById.find(javaId);
+        if (i == javaObjectsById.end()) {
+          JSObject* obj = JavaObject::construct(ctx, this, javaId);
+          javaObjectsById[javaId] = obj;
+          // 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);
+          retVal = OBJECT_TO_JSVAL(obj);
+        } else {
+          retVal = OBJECT_TO_JSVAL(i->second);
+        }
+      }
+      break;
+    case Value::JS_OBJECT:
+      {
+        int jsId = value.getJsObjectId();
+        if (!JS_GetElement(ctx, jsObjectsById, jsId, &retVal)) {
+          Debug::log(Debug::Error) << "Error getting jsObject with id " << jsId << Debug::flush;
+        }
+        if (!JSVAL_IS_OBJECT(retVal)) {
+          Debug::log(Debug::Error) << "Missing jsObject with id " << jsId << Debug::flush;
+        }
+      }
+      break;
+    case Value::UNDEFINED:
+      retVal = JSVAL_VOID;
+      break;
+    default:
+      Debug::log(Debug::Error) << "Unknown Value type " << value.toString() << Debug::flush;
+  }
+}
+
+void FFSessionHandler::freeJavaObject(int objectId) {
+  if (!javaObjectsById.erase(objectId)) {
+    Debug::log(Debug::Error) << "Trying to free unknown JavaObject: " << objectId << Debug::flush;
+    return;
+  }
+  javaObjectsToFree.insert(objectId);
+}
+
+void FFSessionHandler::disconnect() {
+  Debug::log(Debug::Debugging) << "FFSessionHandler::disconnect" << Debug::flush;
+  JSContext* ctx = getJSContext();
+  bool freeCtx = false;
+  if (!ctx) {
+    Debug::log(Debug::Debugging) << "  creating temporary context"
+        << Debug::flush;
+    freeCtx = true;
+    ctx = JS_NewContext(runtime, 8192);
+    if (ctx) {
+      JS_SetOptions(ctx, JSOPTION_VAROBJFIX);
+#ifdef JSVERSION_LATEST
+      JS_SetVersion(ctx, JSVERSION_LATEST);
+#endif
+    }
+  }
+  if (ctx) {
+    JS_BeginRequest(ctx);
+    for (std::map<int, JSObject*>::iterator it = javaObjectsById.begin();
+        it != javaObjectsById.end(); ++it) {
+      int javaId = it->first;
+      JSObject* obj = it->second;
+      if (JavaObject::isJavaObject(ctx, obj)) {
+        // clear the SessionData pointer -- JavaObject knows it is
+        // disconnected if this is null
+        JS_SetPrivate(ctx, obj, NULL);
+        javaObjectsToFree.erase(javaId);
+      }
+    }
+    JS_EndRequest(ctx);
+    if (freeCtx) {
+      JS_DestroyContext(ctx);
+    }
+  } else {
+    Debug::log(Debug::Warning)
+        << "FFSessionHandler::disconnect - no context available"
+        << Debug::flush;
+  }
+  HostChannel* channel = getHostChannel();
+  if (channel->isConnected()) {
+    channel->disconnectFromHost();
+  }
+}
diff --git a/plugins/xpcom/FFSessionHandler.h b/plugins/xpcom/FFSessionHandler.h
new file mode 100755
index 0000000..0583031
--- /dev/null
+++ b/plugins/xpcom/FFSessionHandler.h
@@ -0,0 +1,76 @@
+#ifndef _H_FFSessionHandler
+#define _H_FFSessionHandler
+/*
+ * 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 <set>
+#include <map>
+
+#include "mozincludes.h"
+#include "SessionData.h"
+
+#include "jsapi.h"
+
+class HostChannel;
+class Value;
+
+class FFSessionHandler : public SessionData, public SessionHandler {
+  friend class JavaObject;
+public:
+  FFSessionHandler(HostChannel* channel);
+  ~FFSessionHandler(void);
+  virtual void makeValueFromJsval(Value& retVal, JSContext* ctx,
+      const jsval& value);
+  virtual void makeJsvalFromValue(jsval& retVal, JSContext* ctx,
+      const Value& value);
+  virtual void freeJavaObject(int objectId);
+  void disconnect();
+
+protected:
+  virtual void freeValue(HostChannel& channel, int idCount, const int* ids);
+  virtual void loadJsni(HostChannel& channel, const std::string& js);
+  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 method, int numArgs,
+      const Value* const args, Value* returnValue);
+  virtual void sendFreeValues(HostChannel& channel);
+
+private:
+  void getStringObjectClass(JSContext* ctx);
+  void getToStringTearOff(JSContext* ctx);
+
+  int jsObjectId;
+
+  std::map<int, JSObject*> javaObjectsById;
+  std::set<int> javaObjectsToFree;
+
+  // Array of JSObjects exposed to the host
+  JSObject* jsObjectsById;
+  JSClass* stringObjectClass;
+
+  std::map<JSObject*, int> jsIdsByObject;
+};
+
+inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, JSString* str) {
+  if (str == NULL) {
+    dbg << "null";
+  } else {
+    dbg << std::string(JS_GetStringBytes(str), JS_GetStringLength(str));
+  }
+  return dbg;
+}
+
+#endif
diff --git a/plugins/xpcom/IOOPHM.idl b/plugins/xpcom/IOOPHM.idl
new file mode 100644
index 0000000..fdd206e
--- /dev/null
+++ b/plugins/xpcom/IOOPHM.idl
@@ -0,0 +1,9 @@
+#include "nsISupports.idl"
+
+interface nsIDOMWindow;
+
+[scriptable, uuid(90CEF17B-C3FE-4251-AF68-4381B3D938A0)]
+interface IOOPHM : nsISupports
+{
+  boolean connect( in ACString addr, in ACString moduleName, in nsIDOMWindow window );
+};
diff --git a/plugins/xpcom/IOOPHM.xpt b/plugins/xpcom/IOOPHM.xpt
new file mode 100644
index 0000000..4be87b7
--- /dev/null
+++ b/plugins/xpcom/IOOPHM.xpt
Binary files differ
diff --git a/plugins/xpcom/JSRunner.cpp b/plugins/xpcom/JSRunner.cpp
new file mode 100755
index 0000000..1a9c0ba
--- /dev/null
+++ b/plugins/xpcom/JSRunner.cpp
@@ -0,0 +1,107 @@
+/*
+ * 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 "JSRunner.h"
+
+#include "nsCOMPtr.h"
+#include "nsIPrincipal.h"
+#include "nsIScriptGlobalObject.h"
+#include "nsIScriptObjectPrincipal.h"
+#include "nsIURI.h"
+#include "nsIXPConnect.h"
+#include "nsStringAPI.h"
+
+// from js_runner_ff.cc in Gears (http://code.google.com/p/gears/)
+
+bool JSRunner::eval(JSContext* ctx, JSObject* object, const std::string& script) {
+  // To eval the script, we need the JSPrincipals to be acquired through
+  // nsIPrincipal.  nsIPrincipal can be queried through the
+  // nsIScriptObjectPrincipal interface on the Script Global Object.  In order
+  // to get the Script Global Object, we need to request the private data
+  // associated with the global JSObject on the current context.
+  nsCOMPtr<nsIScriptGlobalObject> sgo;
+  nsISupports *priv = reinterpret_cast<nsISupports *>(JS_GetPrivate(
+                                                          ctx,
+                                                          object));
+  nsCOMPtr<nsIXPConnectWrappedNative> wrapped_native = do_QueryInterface(priv);
+
+  if (wrapped_native) {
+    // The global object is a XPConnect wrapped native, the native in
+    // the wrapper might be the nsIScriptGlobalObject.
+    sgo = do_QueryWrappedNative(wrapped_native);
+  } else {
+    sgo = do_QueryInterface(priv);
+  }
+
+  JSPrincipals *jsprin;
+  nsresult nr;
+
+  nsCOMPtr<nsIScriptObjectPrincipal> obj_prin = do_QueryInterface(sgo, &nr);
+  if (NS_FAILED(nr)) {
+    return false;
+  }
+
+  nsIPrincipal *principal = obj_prin->GetPrincipal();
+  if (!principal) {
+    return false;
+  }
+
+  // Get the script scheme and host from the principal.  This is the URI that
+  // Firefox treats this script as running from.
+  nsCOMPtr<nsIURI> codebase;
+  principal->GetURI(getter_AddRefs(codebase));
+  if (!codebase) { return false; }
+  nsCString scheme;
+  nsCString host;
+  if (NS_FAILED(codebase->GetScheme(scheme)) ||
+      NS_FAILED(codebase->GetHostPort(host))) {
+    return false;
+  }
+
+  // Build a virtual filename that we'll run as.  This is to workaround
+  // http://lxr.mozilla.org/seamonkey/source/dom/src/base/nsJSEnvironment.cpp#500
+  // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=387477
+  // The filename is being used as the security origin instead of the principal.
+  // TODO(zork): Remove this section if this bug is resolved.
+  std::string virtual_filename(scheme.BeginReading());
+  virtual_filename += "://";
+  virtual_filename += host.BeginReading();
+
+  principal->GetJSPrincipals(ctx, &jsprin);
+
+  // Set up the JS stack so that our context is on top.  This is needed to
+  // play nicely with plugins that access the context stack, such as Firebug.
+//  nsCOMPtr<nsIJSContextStack> stack =
+//      do_GetService("@mozilla.org/js/xpc/ContextStack;1");
+//  if (!stack) { return false; }
+//
+//  stack->Push(js_engine_context_);
+
+  uintN line_number_start = 0;
+  jsval rval;
+  JSBool js_ok = 
+      JS_EvaluateScriptForPrincipals(ctx, object, jsprin, script.c_str(), script.length(),
+          virtual_filename.c_str(), line_number_start, &rval);
+
+  // Restore the context stack.
+//  JSContext *cx;
+//  stack->Pop(&cx);
+
+  // Decrements ref count on jsprin (Was added in GetJSPrincipals()).
+  (void)JSPRINCIPALS_DROP(ctx, jsprin);
+  if (!js_ok) { return false; }
+  return true;
+}
diff --git a/plugins/xpcom/JSRunner.h b/plugins/xpcom/JSRunner.h
new file mode 100755
index 0000000..733970e
--- /dev/null
+++ b/plugins/xpcom/JSRunner.h
@@ -0,0 +1,29 @@
+#ifndef _H_JSRunner
+#define _H_JSRunner
+/*
+ * 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 "mozincludes.h"
+#include "jsapi.h"
+
+class JSRunner {
+public:
+  static bool eval(JSContext* ctx, JSObject* global, const std::string& script);
+};
+
+#endif
diff --git a/plugins/xpcom/JavaObject.cpp b/plugins/xpcom/JavaObject.cpp
new file mode 100644
index 0000000..fd2af9f
--- /dev/null
+++ b/plugins/xpcom/JavaObject.cpp
@@ -0,0 +1,386 @@
+/*
+ * 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 "JavaObject.h"
+#include "FFSessionHandler.h"
+#include "SessionData.h"
+#include "ServerMethods.h"
+#include "Debug.h"
+#include "XpcomDebug.h"
+#include "HostChannel.h"
+#include "InvokeMessage.h"
+#include "ReturnMessage.h"
+#include "scoped_ptr/scoped_ptr.h"
+
+static JSClass JavaObjectClass = {
+  "GWTJavaObject", /* class name */
+  JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_NEW_ENUMERATE, /* flags */
+
+  JS_PropertyStub, /* add property */
+  JS_PropertyStub, /* delete property */
+  JavaObject::getProperty, /* get property */
+  JavaObject::setProperty, /* set property */
+
+  reinterpret_cast<JSEnumerateOp>(JavaObject::enumerate), /* enumerate */
+  JS_ResolveStub, /* resolve */
+  JS_ConvertStub, // JavaObject::convert, /* convert */
+  JavaObject::finalize, /* finalize */ //TODO
+
+  NULL, /* object hooks */
+  NULL, /* check access */
+  JavaObject::call, /* call */ //TODO
+  NULL, /* construct */
+  NULL, /* object serialization */
+  NULL, /* has instance */
+  NULL, /* mark */
+  NULL /* reserve slots */
+};
+
+int JavaObject::getObjectId(JSContext* ctx, JSObject* obj) {
+  jsval val;
+  JSClass* jsClass = JS_GET_CLASS(ctx, obj);
+#if 1
+  if (jsClass != &JavaObjectClass) {
+    Debug::log(Debug::Error)
+        << "JavaObject::getObjectId called on non-JavaObject: " << jsClass->name
+        << Debug::flush;
+    return -1;
+  }
+  if (JSCLASS_RESERVED_SLOTS(jsClass) < 1) {
+    Debug::log(Debug::Error)
+        << "JavaObject::getObjectId -- " << static_cast<void*>(obj)
+        << " has only " << (JSCLASS_RESERVED_SLOTS(jsClass))
+        << " reserved slots, no objectId present" << Debug::flush;
+    return -1;
+  }
+#endif
+  if (!JS_GetReservedSlot(ctx, obj, 0, &val)) {
+    Debug::log(Debug::Error) << "Error getting reserved slot" << Debug::flush;
+    return -1;
+  }
+  // TODO: assert JSVAL_IS_INT(val)
+  return JSVAL_TO_INT(val);
+}
+
+SessionData* JavaObject::getSessionData(JSContext* ctx, JSObject* obj) {
+  void* data = JS_GetInstancePrivate(ctx, obj, &JavaObjectClass, NULL);
+  return static_cast<SessionData*>(data);
+}
+
+
+bool JavaObject::isJavaObject(JSContext* ctx, JSObject* obj) {
+  return JS_GET_CLASS(ctx, obj) == &JavaObjectClass;
+}
+
+JSObject* JavaObject::construct(JSContext* ctx, SessionData* data, int objectRef) {
+  // TODO: prototype? parent?
+  Debug::log(Debug::Spam) << "JavaObject::construct objectId=" << objectRef << Debug::flush;
+  JSObject* obj = JS_NewObject(ctx, &JavaObjectClass, NULL, NULL);
+  Debug::log(Debug::Spam) << "  obj=" << obj << Debug::flush;
+  if (!obj) {
+    return NULL;
+  }
+  // set the session data
+  if (!JS_SetPrivate(ctx, obj, data)) {
+    Debug::log(Debug::Error) << "Could not set private data" << Debug::flush;
+    return NULL;
+  }
+  // set the objectId
+  if (!JS_SetReservedSlot(ctx, obj, 0, INT_TO_JSVAL(objectRef))) {
+    Debug::log(Debug::Error) << "Could not set reserved slot" << Debug::flush;
+    return NULL;
+  }
+  // define toString (TODO: some way to avoid doing this each time)
+#if 1
+  if (!JS_DefineFunction(ctx, obj, "toString", JavaObject::toString, 0, 0)) {
+    Debug::log(Debug::Error) << "Could not define toString method on object"
+        << Debug::flush;
+  }
+#endif
+  return obj;
+}
+
+JSBool JavaObject::getProperty(JSContext* ctx, JSObject* obj, jsval id,
+    jsval* rval) {
+  Debug::log(Debug::Spam) << "JavaObject::getProperty obj=" << obj << Debug::flush;
+  SessionData* data = JavaObject::getSessionData(ctx, obj);
+  if (!data) {
+    // TODO: replace the frame with an error page instead?
+    *rval = JSVAL_VOID;
+    return JS_TRUE;
+  }
+  int objectRef = JavaObject::getObjectId(ctx, obj);
+  if (JSVAL_IS_STRING(id)) {
+    JSString* str = JSVAL_TO_STRING(id);
+    if ((JS_GetStringLength(str) == 8) && !strncmp("toString",
+          JS_GetStringBytes(str), 8)) {
+      *rval = data->getToStringTearOff();
+      return JS_TRUE;
+    }
+    if ((JS_GetStringLength(str) == 2) && !strncmp("id",
+          JS_GetStringBytes(str), 2)) {
+      *rval = INT_TO_JSVAL(objectRef);
+      return JS_TRUE;
+    }
+    Debug::log(Debug::Error) << "Getting unexpected string property "
+        << dumpJsVal(ctx, id) << Debug::flush;
+    // TODO: throw a better exception here
+    return JS_FALSE;
+  }
+  if (!JSVAL_IS_INT(id)) {
+    Debug::log(Debug::Error) << "Getting non-int/non-string property "
+          << dumpJsVal(ctx, id) << Debug::flush;
+    // TODO: throw a better exception here
+    return JS_FALSE;
+  }
+  int dispId = JSVAL_TO_INT(id);
+
+  HostChannel* channel = data->getHostChannel();
+  SessionHandler* handler = data->getSessionHandler();
+
+  Value value = ServerMethods::getProperty(*channel, handler, objectRef, dispId);
+  data->makeJsvalFromValue(*rval, ctx, value);
+  return JS_TRUE;
+}
+
+JSBool JavaObject::setProperty(JSContext* ctx, JSObject* obj, jsval id,
+    jsval* vp) {
+  Debug::log(Debug::Spam) << "JavaObject::setProperty obj=" << obj << Debug::flush;
+  if (!JSVAL_IS_INT(id)) {
+    Debug::log(Debug::Error) << "  Error: setting string property id" << Debug::flush;
+    // TODO: throw a better exception here
+    return JS_FALSE;
+  }
+
+  SessionData* data = JavaObject::getSessionData(ctx, obj);
+  if (!data) {
+    return JS_TRUE;
+  }
+
+  int objectRef = JavaObject::getObjectId(ctx, obj);
+  int dispId = JSVAL_TO_INT(id);
+
+  Value value;
+  data->makeValueFromJsval(value, ctx, *vp);
+
+  HostChannel* channel = data->getHostChannel();
+  SessionHandler* handler = data->getSessionHandler();
+
+  if (!ServerMethods::setProperty(*channel, handler, objectRef, dispId, value)) {
+    // TODO: throw a better exception here
+    return JS_FALSE;
+  }
+  return JS_TRUE;
+}
+
+// TODO: can this be removed now?
+JSBool JavaObject::convert(JSContext* ctx, JSObject* obj, JSType type, jsval* vp) {
+  Debug::log(Debug::Spam) << "JavaObject::convert obj=" << obj
+      << " type=" << type << Debug::flush;
+  switch (type) {
+    case JSTYPE_STRING:
+      return toString(ctx, obj, 0, NULL, vp);
+    case JSTYPE_VOID:
+      *vp = JSVAL_VOID;
+      return JS_TRUE;
+    case JSTYPE_NULL:
+      *vp = JSVAL_NULL;
+      return JS_TRUE;
+    case JSTYPE_OBJECT:
+      *vp = OBJECT_TO_JSVAL(obj);
+      return JS_TRUE;
+    default:
+      break;
+  }
+  return JS_FALSE;
+}
+
+/**
+ * List of property names we want to fake on wrapped Java objects.
+ */
+static const char* propertyNames[] = {
+    "toString",
+    "id",
+};
+#define NUM_PROPERTY_NAMES (sizeof(propertyNames) / sizeof(propertyNames[0]))
+
+JSBool JavaObject::enumerate(JSContext* ctx, JSObject* obj, JSIterateOp op,
+    jsval* statep, jsid* idp) {
+  int objectId = JavaObject::getObjectId(ctx, obj);
+  switch (op) {
+    case JSENUMERATE_INIT:
+      Debug::log(Debug::Spam) << "JavaObject::enumerate(oid=" << objectId
+          << ", INIT)" << Debug::flush;
+      *statep = JSVAL_ZERO;
+      if (idp) {
+        *idp = INT_TO_JSVAL(NUM_PROPERTY_NAMES);
+      }
+      break;
+    case JSENUMERATE_NEXT:
+    {
+      int idNum = JSVAL_TO_INT(*statep);
+      Debug::log(Debug::Spam) << "JavaObject::enumerate(oid=" << objectId
+          << ", NEXT " << idNum << ")" << Debug::flush;
+      *statep = INT_TO_JSVAL(idNum + 1);
+      if (idNum >= NUM_PROPERTY_NAMES) {
+        *statep = JSVAL_NULL;
+        *idp = JSVAL_NULL;
+      } else {
+        const char* propName = propertyNames[idNum];
+        JSString* str = JS_NewStringCopyZ(ctx, propName);
+        return JS_ValueToId(ctx, STRING_TO_JSVAL(str), idp);
+      }
+      break;
+    }
+    case JSENUMERATE_DESTROY:
+      Debug::log(Debug::Spam) << "JavaObject::enumerate(oid=" << objectId
+          << ", DESTROY)" << Debug::flush;
+      *statep = JSVAL_NULL;
+      break;
+    default:
+      Debug::log(Debug::Error) << "Unknown Enumerate op " <<
+          static_cast<int>(op) << Debug::flush;
+      return JS_FALSE;
+  }
+  return JS_TRUE;
+}
+
+void JavaObject::finalize(JSContext* ctx, JSObject* obj) {
+  Debug::log(Debug::Debugging) << "JavaObject::finalize obj=" << obj
+      << " objId=" << JavaObject::getObjectId(ctx, obj) << Debug::flush;
+  SessionData* data = JavaObject::getSessionData(ctx, obj);
+  if (data) {
+    int objectId = JavaObject::getObjectId(ctx, obj);
+    data->freeJavaObject(objectId);
+    JS_SetPrivate(ctx, obj, NULL);
+  }
+}
+
+JSBool JavaObject::toString(JSContext* ctx, JSObject* obj, uintN argc,
+    jsval* argv, jsval* rval) {
+  SessionData* data = JavaObject::getSessionData(ctx, obj);
+  if (!data) {
+    *rval = JSVAL_VOID;
+    return JS_TRUE;
+  }
+  int oid = getObjectId(ctx, obj);
+  Debug::log(Debug::Spam) << "JavaObject::toString(id=" << oid << ")"
+      << Debug::flush;
+  Value javaThis;
+  javaThis.setJavaObject(oid);
+  // we ignore any supplied parameters
+  return invokeJava(ctx, data, javaThis, InvokeMessage::TOSTRING_DISP_ID, 0,
+      NULL, rval);
+}
+
+/**
+ * Called when the JavaObject is invoked as a function.
+ * We ignore the JSObject* argument, which is the 'this' context, which is
+ * usually the window object. The JavaObject instance is in argv[-2].
+ *
+ * Returns a JS array, with the first element being a boolean indicating that
+ * an exception occured, and the second element is either the return value or
+ * the exception which was thrown.  In this case, we always return false and
+ * raise the exception ourselves.
+ */
+JSBool JavaObject::call(JSContext* ctx, JSObject*, uintN argc, jsval* argv,
+    jsval* rval) {
+  // Get the JavaObject called as a function
+  JSObject* obj = JSVAL_TO_OBJECT(argv[-2]);
+  if (argc < 2 || !JSVAL_IS_INT(argv[0]) || !JSVAL_IS_OBJECT(argv[1])) {
+    Debug::log(Debug::Error) << "JavaObject::call incorrect arguments" << Debug::flush;
+    return JS_FALSE;
+  }
+  int dispId = JSVAL_TO_INT(argv[0]);
+  if (Debug::level(Debug::Spam)) {
+    Debug::DebugStream& dbg = Debug::log(Debug::Spam) << "JavaObject::call oid="
+        << JavaObject::getObjectId(ctx, obj) << ",dispId=" << dispId << " (";
+    for (unsigned i = 2; i < argc; ++i) {
+      if (i > 2) {
+        dbg << ", ";
+      }
+      dbg << dumpJsVal(ctx, argv[i]);
+    }
+    dbg << ")" << Debug::flush;
+  }
+
+  SessionData* data = JavaObject::getSessionData(ctx, obj);
+  if (!data) {
+    *rval = JSVAL_VOID;
+    return JS_TRUE;
+  }
+  Debug::log(Debug::Spam) << "Data = " << data << Debug::flush;
+
+  Value javaThis;
+  if (!JSVAL_IS_NULL(argv[1])) {
+    JSObject* thisObj = JSVAL_TO_OBJECT(argv[1]);
+    if (isJavaObject(ctx, thisObj)) {
+      javaThis.setJavaObject(getObjectId(ctx, thisObj));
+    } else {
+      data->makeValueFromJsval(javaThis, ctx, argv[1]);
+    }
+  } else {
+    int oid = getObjectId(ctx, obj);
+    javaThis.setJavaObject(oid);
+  }
+  return invokeJava(ctx, data, javaThis, dispId, argc - 2, &argv[2], rval);
+}
+
+/**
+ * Calls a method on a Java object and returns a two-element JS array, with
+ * the first element being a boolean flag indicating an exception was thrown,
+ * and the second element is the actual return value or exception.
+ */
+JSBool JavaObject::invokeJava(JSContext* ctx, SessionData* data,
+    const Value& javaThis, int dispId, int numArgs, const jsval* jsargs,
+    jsval* rval) {
+  HostChannel* channel = data->getHostChannel();
+  SessionHandler* handler = data->getSessionHandler();
+  scoped_array<Value> args(new Value[numArgs]);
+  for (int i = 0; i < numArgs; ++i) {
+    data->makeValueFromJsval(args[i], ctx, jsargs[i]);
+  }
+  if (!InvokeMessage::send(*channel, javaThis, dispId, numArgs, args.get())) {
+    Debug::log(Debug::Error) << "JavaObject::call failed to send invoke message" << Debug::flush;
+    return false;
+  }
+  Debug::log(Debug::Spam) << " return from invoke" << Debug::flush;
+  scoped_ptr<ReturnMessage> retMsg(channel->reactToMessagesWhileWaitingForReturn(handler));
+  if (!retMsg.get()) {
+    Debug::log(Debug::Error) << "JavaObject::call failed to get return value" << Debug::flush;
+    return false;
+  }
+  Value returnValue = retMsg->getReturnValue();
+  // Since we can set exceptions normally, we always return false to the
+  // wrapper function and set the exception ourselves if one occurs.
+  // TODO: cleanup exception case
+  jsval retvalArray[] = {JSVAL_FALSE, JSVAL_VOID};
+  JSObject* retval = JS_NewArrayObject(ctx, 2, retvalArray);
+  *rval = OBJECT_TO_JSVAL(retval);
+  jsval retJsVal;
+  Debug::log(Debug::Spam) << "  result is " << returnValue << Debug::flush;
+  data->makeJsvalFromValue(retJsVal, ctx, returnValue);
+  if (retMsg->isException()) {
+    JS_SetPendingException(ctx, retJsVal);
+    return false;
+  }
+  if (!JS_SetElement(ctx, retval, 1, &retJsVal)) {
+    Debug::log(Debug::Error) << "Error setting return value element in array"
+        << Debug::flush;
+    return false;
+  }
+  return true;
+}
diff --git a/plugins/xpcom/JavaObject.h b/plugins/xpcom/JavaObject.h
new file mode 100755
index 0000000..781a4f0
--- /dev/null
+++ b/plugins/xpcom/JavaObject.h
@@ -0,0 +1,45 @@
+#ifndef _H_JavaObject
+#define _H_JavaObject
+/*
+ * 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 "mozincludes.h"
+#include "jsapi.h"
+
+class SessionData;
+class Value;
+
+class JavaObject {
+public:
+  static bool isJavaObject(JSContext* ctx, JSObject* obj);
+  static JSObject* construct(JSContext* ctx, SessionData* data, int objectRef);
+  static int getObjectId(JSContext* ctx, JSObject* obj);
+  static JSBool getProperty(JSContext* ctx, JSObject* obj, jsval id, jsval* vp);
+  static JSBool setProperty(JSContext* ctx, JSObject* obj, jsval id, jsval* vp);
+  static JSBool resolve(JSContext* ctx, JSObject* obj, jsval id);
+  static JSBool convert(JSContext* cx, JSObject* obj, JSType type, jsval* vp);
+  static JSBool enumerate(JSContext* ctx, JSObject* obj, JSIterateOp op, jsval* statep, jsid* idp);
+  static void finalize(JSContext* ctx, JSObject* obj);
+  static JSBool toString(JSContext* ctx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
+  static JSBool call(JSContext* ctx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
+private:
+  static SessionData* getSessionData(JSContext* ctx, JSObject* obj);
+  static JSBool invokeJava(JSContext* ctx, SessionData* data,
+      const Value& javaThis, int dispId, int numArgs, const jsval* jsargs,
+      jsval* rval);
+};
+
+#endif
diff --git a/plugins/xpcom/Makefile b/plugins/xpcom/Makefile
new file mode 100644
index 0000000..5c1f343
--- /dev/null
+++ b/plugins/xpcom/Makefile
@@ -0,0 +1,257 @@
+# Copyright 2009 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 ../config.mk
+
+# Make variables intended to be settable fromthe command line:
+#   DEFAULT_FIREFOX_LIBS	points to /usr/lib/firefox or equivalent
+#   PLUGIN_SDKS			points to GWT /plugin-sdks directory
+#   GECKO_PLATFORM		XPCOM ABI (ie, Linux_x86_64-gcc3)
+#
+
+ifeq ($(OS),mac)
+DEFAULT_FIREFOX_LIBS ?= /Applications/Firefox.app/Contents/MacOS
+RUN_PATH_FLAG = -executable_path
+DLL_SUFFIX = .dylib
+DLLFLAGS = -bundle -arch i386 -arch ppc
+TARGET_PLATFORM = Darwin_x86-gcc3
+# Mac puts multiple architectures into the same files
+GECKO_PLATFORM = Darwin-gcc3
+else ifeq ($(OS),linux)
+DEFAULT_FIREFOX_LIBS ?= /usr/lib/firefox
+RUN_PATH_FLAG = -rpath-link
+DLL_SUFFIX = .so
+DLLFLAGS = -shared -m$(FLAG32BIT)
+TARGET_PLATFORM = Linux_$(ARCH)-gcc3
+else ifeq ($(OS),sun)
+TARGET_PLATFORM = SunOS_$(ARCH)-sunc
+RUN_PATH_FLAG = -rpath-link
+DLLFLAGS=
+endif
+
+export FLAG32BIT
+
+ifeq ($(BROWSER),)
+$(warning Defaulting to FF3 build)
+BROWSER=ff3
+endif
+
+GECKO_MINOR_VERSION=
+ifeq ($(BROWSER),ff2)
+BROWSER_VERSION   = 1.8
+CFLAGS += -DBROWSER_FF2
+else ifeq ($(BROWSER),ff3)
+BROWSER_VERSION   = 1.9.0
+CFLAGS += -DBROWSER_FF3
+else ifeq ($(BROWSER),ff3+)
+BROWSER_VERSION   = 1.9.0
+CFLAGS += -DBROWSER_FF3
+GECKO_MINOR_VERSION=.10
+else ifeq ($(BROWSER),ff35)
+BROWSER_VERSION   = 1.9.1
+CFLAGS += -DBROWSER_FF3
+else
+$(error Unrecognized BROWSER of $(BROWSER) - options are ff2, ff3, ff3+, ff35)
+endif
+
+CFLAGS += -fshort-wchar
+CXXFLAGS = $(CXXONLYFLAGS) $(CFLAGS)
+DIR = $(shell pwd)
+
+# Set $PLUGIN_SDKS if it isn't in the default location
+PLUGIN_SDKS ?= ../../../plugin-sdks
+GECKO_PLATFORM ?= $(TARGET_PLATFORM)
+
+COMMON            = ../common/libcommon$(FLAG32BIT).a
+
+OBJ_OUTDIR        = build/$(TARGET_PLATFORM)-$(BROWSER)
+EXTENSION_OUTDIR  = prebuilt/extension-$(BROWSER)
+FF_PLATFORM_DIR   = $(EXTENSION_OUTDIR)/platform/$(TARGET_PLATFORM)
+
+INSTALLER_XPI     = prebuilt/oophm-xpcom-$(BROWSER).xpi
+FF_DLL            = $(OBJ_OUTDIR)/liboophm_$(BROWSER)$(DLL_SUFFIX)
+#FF_TYPELIB        = build/IOOPHM.xpt
+#FF_HEADER         = $(OBJ_OUTDIR)/IOOPHM.h
+FF_TYPELIB        = prebuilt/extension/components/IOOPHM.xpt
+FF_HEADER         = prebuilt/$(BROWSER)/include/IOOPHM.h
+INSTALL_RDF       = $(EXTENSION_OUTDIR)/install.rdf
+
+SDK_PATH          = $(PLUGIN_SDKS)/gecko-sdks
+GECKO_SDK         = $(SDK_PATH)/gecko-$(BROWSER_VERSION)
+GECKO_PLAT_INC    = $(GECKO_SDK)/$(GECKO_PLATFORM)/include
+GECKO_LIBS        = $(GECKO_SDK)/$(GECKO_PLATFORM)/lib$(GECKO_MINOR_VERSION)
+XPIDL             = $(GECKO_SDK)/$(GECKO_PLATFORM)/bin/xpidl
+XPIDL_FLAGS       = -I$(GECKO_SDK)/idl
+
+#DLLFLAGS += \
+#		-L$(GECKO_LIBS) \
+#		-L$(FIREFOX_LIBS) \
+#		-Wl,$(RUN_PATH_FLAG),$(FIREFOX_LIBS) \
+#		-lxpcomglue_s -lxpcom -lnspr4 -lmozjs
+DLLFLAGS += \
+		-L$(DEFAULT_FIREFOX_LIBS) \
+		-L$(GECKO_LIBS) \
+		-Wl,$(RUN_PATH_FLAG),$(DEFAULT_FIREFOX_LIBS) \
+		-Wl,$(RUN_PATH_FLAG),$(GECKO_LIBS) \
+		-lxpcomglue_s -lxpcom -lnspr4 -lmozjs
+
+INC += -I$(GECKO_PLAT_INC) -I$(GECKO_SDK)/include -I$(dir $(FF_HEADER))
+
+VERSION=0.0.$(shell ./getversion).$(shell date +%Y%m%d%H%M%S)
+
+.PHONY: all xpi lib common browser clean depend install install-platform find-ff-libs
+
+all:: common xpi
+
+lib:: browser $(OBJ_OUTDIR) $(EXTENSION_OUTDIR) $(FF_DLL)
+xpi:: $(EXTENSION_OUTDIR) $(INSTALLER_XPI)
+
+find-ff-libs::
+ifeq ($(FIREFOX_LIBS),)
+	$(warning Using firefox libraries at $(GECKO_LIBS))
+	$(eval FIREFOX_LIBS = $(GECKO_LIBS))
+endif
+
+browser:: find-ff-libs
+#	if [ ! -r $(GECKO_LIBS)/libxpcom.so ]
+#	then
+#	    $(error Missing Firefox libraries at $(GECKO_LIBS))
+#	fi
+
+# Not needed currently, but keeping around for now in case we change back to
+# putting it in build
+$(EXTENSION_OUTDIR):
+	rm -rf $@
+	mkdir -p $@
+	#cp -r prebuilt/extension/. $(EXTENSION_OUTDIR)
+	cp -r prebuilt/extension-$(BROWSER)/. $(EXTENSION_OUTDIR)
+	@mkdir -p $@/components
+
+generate-install:: $(EXTENSION_OUTDIR) install-template-$(BROWSER).rdf
+	sed -e s/GWT_OOPHM_VERSION/$(VERSION)/ install-template-$(BROWSER).rdf >$(INSTALL_RDF)
+
+SRCS =	\
+		ExternalWrapper.cpp \
+		ModuleOOPHM.cpp \
+		FFSessionHandler.cpp \
+		JavaObject.cpp \
+		JSRunner.cpp \
+		XpcomDebug.cpp
+
+FF_OBJS = $(patsubst %.cpp,$(OBJ_OUTDIR)/%.o,$(SRCS))
+
+$(FF_OBJS): $(OBJ_OUTDIR)
+
+$(OBJ_OUTDIR)::
+	@mkdir -p $@
+
+$(INSTALLER_XPI): $(FF_TYPELIB) $(EXTENSION_OUTDIR) generate-install $(shell find prebuilt/extension $(EXTENSION_OUTDIR)) $(FF_DLL)
+	@mkdir -p $(EXTENSION_OUTDIR)/components
+	(cd prebuilt/extension; find . \( -name .svn -prune \) -o -print | cpio -pmdua ../../$(EXTENSION_OUTDIR))
+	-rm $(INSTALLER_XPI)
+	(cd $(EXTENSION_OUTDIR) && zip -r -D -9 $(DIR)/$(INSTALLER_XPI) * -x '*/.svn/*' -x 'META-INF/*')
+
+$(FF_TYPELIB): IOOPHM.idl
+	$(XPIDL) $(XPIDL_FLAGS) -m typelib -e $@ $<
+
+$(FF_HEADER): IOOPHM.idl
+	$(XPIDL) $(XPIDL_FLAGS) -m header -e $@ $<
+
+$(FF_DLL): $(FF_OBJS) $(COMMON)
+	$(CXX) -m$(FLAG32BIT) -o $@ $(FF_OBJS) $(COMMON) $(DLLFLAGS) 
+	@mkdir -p $(FF_PLATFORM_DIR)/components
+	cp $(FF_DLL) $(FF_PLATFORM_DIR)/components/
+ifeq ($(OS),mac)
+	@mkdir -p $(subst x86,ppc,$(FF_PLATFORM_DIR))/components
+	cp $(FF_DLL) $(subst x86,ppc,$(FF_PLATFORM_DIR))/components/
+endif
+
+$(OBJ_OUTDIR)/%.o: %.cpp $(FF_HEADER)
+	$(CXX) $(CXXFLAGS) -c -o $@ -I. -I../common $<
+
+common $(COMMON):
+	(cd ../common && $(MAKE))
+
+clean:
+	rm -rf build
+
+install-platform:
+ifdef BROWSER
+	@-mkdir -p $(subst $(EXTENSION_OUTDIR),prebuilt/extension-$(BROWSER),$(FF_PLATFORM_DIR))/components
+	-cp $(FF_DLL) $(subst $(EXTENSION_OUTDIR),prebuilt/extension-$(BROWSER),$(FF_PLATFORM_DIR))/components
+ifeq ($(OS),mac)
+	@-mkdir -p $(subst $(EXTENSION_OUTDIR),prebuilt/extension-$(BROWSER),$(subst x86,ppc,$(FF_PLATFORM_DIR)))/components
+	-cp $(FF_DLL) $(subst $(EXTENSION_OUTDIR),prebuilt/extension-$(BROWSER),$(subst x86,ppc,$(FF_PLATFORM_DIR)))/components
+endif
+else
+	@$(MAKE) $@ BROWSER=ff2
+	@$(MAKE) $@ BROWSER=ff3
+endif
+
+DEPEND = g++ -MM -MT'$$(OBJ_OUTDIR)/$(patsubst %.cpp,%.o,$(src))' \
+  -I. -I../common -isystem$(dir $(FF_HEADER)) -isystem$(GECKO_SDK)/include $(src) &&
+depend: browser $(OBJ_OUTDIR) $(FF_HEADER)
+	($(foreach src,$(SRCS),$(DEPEND)) true) >>Makefile
+#	makedepend -- $(CFLAGS) -- $(SRCS)
+
+# DO NOT DELETE
+$(OBJ_OUTDIR)/ExternalWrapper.o: ExternalWrapper.cpp ExternalWrapper.h \
+  mozincludes.h FFSessionHandler.h SessionData.h \
+  ../common/SessionHandler.h ../common/BrowserChannel.h ../common/Value.h \
+  ../common/Debug.h ../common/Platform.h ../common/DebugLevel.h \
+  ../common/BrowserChannel.h ../common/scoped_ptr/scoped_ptr.h \
+  ../common/LoadModuleMessage.h ../common/Message.h \
+  ../common/BrowserChannel.h ../common/HostChannel.h ../common/Debug.h \
+  ../common/ByteOrder.h ../common/Platform.h ../common/Socket.h \
+  ../common/Platform.h ../common/Debug.h ../common/AllowedConnections.h \
+  ../common/Platform.h ../common/Message.h ../common/ReturnMessage.h \
+  ../common/Message.h ../common/BrowserChannel.h ../common/Value.h \
+  ../common/Value.h ../common/SessionHandler.h ../common/SessionHandler.h \
+  ../common/ServerMethods.h ../common/Value.h
+$(OBJ_OUTDIR)/ModuleOOPHM.o: ModuleOOPHM.cpp ../common/Debug.h \
+  ../common/Platform.h ../common/DebugLevel.h ExternalWrapper.h \
+  mozincludes.h FFSessionHandler.h SessionData.h \
+  ../common/SessionHandler.h ../common/BrowserChannel.h ../common/Value.h \
+  ../common/Debug.h ../common/BrowserChannel.h \
+  ../common/scoped_ptr/scoped_ptr.h
+$(OBJ_OUTDIR)/FFSessionHandler.o: FFSessionHandler.cpp FFSessionHandler.h \
+  mozincludes.h SessionData.h ../common/SessionHandler.h \
+  ../common/BrowserChannel.h ../common/Value.h ../common/Debug.h \
+  ../common/Platform.h ../common/DebugLevel.h ../common/BrowserChannel.h \
+  ../common/HostChannel.h ../common/Debug.h ../common/ByteOrder.h \
+  ../common/Platform.h ../common/Socket.h ../common/Platform.h \
+  ../common/Debug.h ../common/AllowedConnections.h ../common/Platform.h \
+  ../common/Message.h ../common/ReturnMessage.h ../common/Message.h \
+  ../common/BrowserChannel.h ../common/Value.h ../common/Value.h \
+  ../common/SessionHandler.h JavaObject.h JSRunner.h XpcomDebug.h \
+  ../common/scoped_ptr/scoped_ptr.h RootedObject.h \
+  ../common/InvokeMessage.h ../common/Message.h \
+  ../common/BrowserChannel.h ../common/Value.h ../common/ServerMethods.h \
+  ../common/Value.h
+$(OBJ_OUTDIR)/JavaObject.o: JavaObject.cpp JavaObject.h mozincludes.h \
+  FFSessionHandler.h SessionData.h ../common/SessionHandler.h \
+  ../common/BrowserChannel.h ../common/Value.h ../common/Debug.h \
+  ../common/Platform.h ../common/DebugLevel.h ../common/BrowserChannel.h \
+  ../common/ServerMethods.h ../common/Value.h XpcomDebug.h \
+  ../common/HostChannel.h ../common/Debug.h ../common/ByteOrder.h \
+  ../common/Platform.h ../common/Socket.h ../common/Platform.h \
+  ../common/Debug.h ../common/AllowedConnections.h ../common/Platform.h \
+  ../common/Message.h ../common/ReturnMessage.h ../common/Message.h \
+  ../common/BrowserChannel.h ../common/Value.h ../common/Value.h \
+  ../common/SessionHandler.h ../common/InvokeMessage.h \
+  ../common/Message.h ../common/BrowserChannel.h ../common/Value.h \
+  ../common/scoped_ptr/scoped_ptr.h
+$(OBJ_OUTDIR)/JSRunner.o: JSRunner.cpp JSRunner.h mozincludes.h
+$(OBJ_OUTDIR)/XpcomDebug.o: XpcomDebug.cpp XpcomDebug.h mozincludes.h \
+  JavaObject.h
diff --git a/plugins/xpcom/ModuleOOPHM.cpp b/plugins/xpcom/ModuleOOPHM.cpp
new file mode 100644
index 0000000..33c5d73
--- /dev/null
+++ b/plugins/xpcom/ModuleOOPHM.cpp
@@ -0,0 +1,145 @@
+/*
+ * 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 "ExternalWrapper.h"
+
+#include "nsCOMPtr.h"
+#include "nsIGenericFactory.h"
+#include "nsICategoryManager.h"
+#include "nsISupports.h"
+#include "nsIXULAppInfo.h"
+#include "nsServiceManagerUtils.h"
+#include "nsXPCOMCID.h"
+
+#ifdef BROWSER_FF3
+#include "nsIClassInfoImpl.h" // 1.9 only
+#endif
+
+#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
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(ExternalWrapper)
+NS_DECL_CLASSINFO(ExternalWrapper)
+
+static NS_IMETHODIMP registerSelf(nsIComponentManager *aCompMgr, nsIFile *aPath,
+    const char *aLoaderStr, const char *aType,
+    const nsModuleComponentInfo *aInfo) {
+
+  Debug::log(Debug::Info) << "Registered GWT hosted mode plugin"
+      << Debug::flush;
+  nsresult rv;
+  nsCOMPtr<nsICategoryManager> categoryManager =
+      do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
+
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = categoryManager->AddCategoryEntry("JavaScript global property",
+      "__gwt_HostedModePlugin", OOPHM_CONTRACTID, true, true, nsnull);
+
+  if (rv != NS_OK) {
+    Debug::log(Debug::Error) << "ModuleOOPHM registerSelf returned " << rv
+        << Debug::flush;
+  }
+  return rv;
+}
+
+static NS_IMETHODIMP factoryDestructor(void) {
+  Debug::log(Debug::Debugging) << "ModuleOOPHM factoryDestructor()"
+      << Debug::flush;
+  return NS_OK;
+}
+
+static NS_IMETHODIMP unregisterSelf(nsIComponentManager *aCompMgr,
+    nsIFile *aPath, const char *aLoaderStr,
+    const nsModuleComponentInfo *aInfo) {
+  Debug::log(Debug::Debugging) << "ModuleOOPHM unRegisterSelf()"
+      << Debug::flush;
+  return NS_OK;
+}
+
+static nsModuleComponentInfo components[] = {
+    {
+       OOPHM_CLASSNAME,
+       OOPHM_CID,
+       OOPHM_CONTRACTID,
+       ExternalWrapperConstructor,
+       registerSelf,
+       unregisterSelf, /* unregister self */
+       factoryDestructor, /* factory destructor */
+       NS_CI_INTERFACE_GETTER_NAME(ExternalWrapper), /* get interfaces */
+       nsnull, /* language helper */
+       &NS_CLASSINFO_NAME(ExternalWrapper), /* global class-info pointer */
+       0 /* class flags */
+    }
+};
+
+// From Gears base/firefox/module.cc
+static nsModuleInfo const kModuleInfo = {
+  NS_MODULEINFO_VERSION,
+  ("ExternalWrapperModule"),
+  (components),
+  (sizeof(components) / sizeof(components[0])),
+  (nsnull),
+  (nsnull)
+};
+
+NSGETMODULE_ENTRY_POINT(ExternalWrapperModule) (nsIComponentManager *servMgr,
+    nsIFile* location, nsIModule** result) {
+  Debug::log(Debug::Debugging) << "OOPHM ExternalWrapperModule entry point"
+      << Debug::flush;
+
+  // CURRENTLY BUILT AS SEPARATE PLUGINS FOR FF1.5/2 and FF3, so the below
+  // comments are out of date.
+  //
+  // This module is compiled once against Gecko 1.8 (Firefox 1.5 and 2) and
+  // once against Gecko 1.9 (Firefox 3). We need to make sure that we are
+  // only loaded into the environment we were compiled against.
+  nsresult nr;
+  nsCOMPtr<nsIXULAppInfo> app_info =
+      do_GetService("@mozilla.org/xre/app-info;1", &nr);
+  if (NS_FAILED(nr) || !app_info) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCString gecko_version;
+  app_info->GetPlatformVersion(gecko_version);
+  Debug::log(Debug::Debugging) << "  gecko version = "
+      << gecko_version.BeginReading() << Debug::flush;
+#if defined(BROWSER_FF2)
+  if (strncmp(gecko_version.BeginReading(), "1.8", 3) != 0) {
+    return NS_ERROR_FAILURE;
+  }
+#elif defined(BROWSER_FF3)
+  if (strncmp(gecko_version.BeginReading(), "1.9", 3) != 0) {
+    return NS_ERROR_FAILURE;
+  }
+#endif
+
+  return NS_NewGenericModule2(&kModuleInfo, result);
+}
diff --git a/plugins/xpcom/README.txt b/plugins/xpcom/README.txt
new file mode 100644
index 0000000..a9aa410
--- /dev/null
+++ b/plugins/xpcom/README.txt
@@ -0,0 +1,25 @@
+You will need to checkout the SDKs required for building the plugin
+separately.  These are located at:
+	https://google-web-toolkit.googlecode.com/svn/plugin-sdks
+
+This assumes the SDKS are located in ../../../plugin-sdks -- if this is
+not correct, edit the definition in Makefile.
+
+Build by:
+
+make ARCH=x86 BROWSER=ff2
+make ARCH=x86_64 BROWSER=ff3
+
+etc -- default is current architecture and ff3.
+
+BROWSER values supported:
+  ff2	Firefox 1.5-2.0
+  ff3	Firefox 3.0
+  ff3+  Firefox 3.0.11+ on some platforms
+  ff35  Firefox 3.5
+
+You may need to try both ff3 and ff3+, as different platforms chose different
+library layouts.
+
+In the future, we will try and make a combined XPI which uses a JS shim plugin
+to select the proper shared library file to use based on the platform.
diff --git a/plugins/xpcom/RootedObject.h b/plugins/xpcom/RootedObject.h
new file mode 100755
index 0000000..7251034
--- /dev/null
+++ b/plugins/xpcom/RootedObject.h
@@ -0,0 +1,77 @@
+#ifndef _H_RootedObject
+#define _H_RootedObject
+/*
+ * 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 "jsapi.h"
+
+class RootedObject {
+public:
+  RootedObject(JSContext* ctx, const char* name = 0) : ctx(ctx), obj(0) {
+    if (!JS_AddNamedRoot(ctx, &obj, name)) {
+      Debug::log(Debug::Error) << "RootedObject(" << (name ? name : "")
+          << "): JS_AddNamedRoot failed" << Debug::flush;
+    }
+  }
+  
+  ~RootedObject() {
+    // Always returns success, so no need to check.
+    JS_RemoveRoot(ctx, &obj);
+  }
+  
+  JSObject& operator*() const {
+    assert(obj != 0);
+    return *obj;
+  }
+
+  JSObject* operator->() const  {
+    assert(obj != 0);
+    return obj;
+  }
+
+  bool operator==(JSObject* p) const {
+    return obj == p;
+  }
+
+  bool operator!=(JSObject* p) const {
+    return obj != p;
+  }
+
+  JSObject* get() const  {
+    return obj;
+  }
+  
+  RootedObject& operator=(JSObject* val) {
+    obj = val;
+    return *this;
+  }
+
+private:
+  JSContext* ctx;
+  JSObject* obj; 
+};
+
+inline bool operator==(JSObject* p, const RootedObject& ro) {
+  return p == ro.get();
+}
+
+inline bool operator!=(JSObject* p, const RootedObject& ro) {
+  return p != ro.get();
+}
+
+#endif
diff --git a/plugins/xpcom/SessionData.h b/plugins/xpcom/SessionData.h
new file mode 100755
index 0000000..a3dde0e
--- /dev/null
+++ b/plugins/xpcom/SessionData.h
@@ -0,0 +1,90 @@
+#ifndef _H_SessionData
+#define _H_SessionData
+/*
+ * 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 "mozincludes.h"
+
+#include "SessionHandler.h"
+
+#include "jsapi.h"
+
+class HostChannel;
+
+class SessionData {
+public:
+  SessionData(HostChannel* channel, SessionHandler* sessionHandler,
+      JSContext* ctx) : channel(channel), sessionHandler(sessionHandler),
+      global(JS_GetGlobalObject(ctx)), runtime(JS_GetRuntime(ctx)),
+      toStringTearOff(JSVAL_VOID)
+  {
+  }
+
+  HostChannel* getHostChannel() const {
+    return channel;
+  }
+
+  SessionHandler* getSessionHandler() const {
+    return sessionHandler;
+  }
+
+  JSObject* getGlobalObject() const {
+    return global;
+  }
+
+  jsval getToStringTearOff() const {
+    return toStringTearOff;
+  }
+
+  /*
+  * Convert a value from the JavaScript into something that can be sent back
+  * to the OOPHM host.
+  */
+  virtual void makeValueFromJsval(Value& retVal, JSContext* ctx, const jsval& value)=0;
+
+  /*
+  * Convert a value from the OOPHM host into something that can be passed into
+  * the JavaScript execution environment.
+  */
+  virtual void makeJsvalFromValue(jsval& retVal, JSContext* ctx, const Value& value)=0;
+  
+  /*
+  * Removes the JavaObject wrapper with the given id and notifies the host.
+  */
+  virtual void freeJavaObject(int objectId)=0;
+
+protected:
+  /*
+  * The communication channel used for the OOPHM session.
+  */
+  HostChannel* const channel;
+
+  /*
+  * A reference to the SessionHandler being used in the OOPHM session.
+  */
+  SessionHandler* const sessionHandler;
+
+  JSRuntime* runtime;
+  
+  JSObject* const global; 
+  
+  /**
+   * A function object representing the toString tear-off method.
+   */
+  jsval toStringTearOff;
+};
+
+#endif
diff --git a/plugins/xpcom/VisualStudio/ff2-xpcom.vcproj b/plugins/xpcom/VisualStudio/ff2-xpcom.vcproj
new file mode 100755
index 0000000..0575de1
--- /dev/null
+++ b/plugins/xpcom/VisualStudio/ff2-xpcom.vcproj
@@ -0,0 +1,767 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="8.00"

+	Name="ff2-xpcom"

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

+	RootNamespace="ff2-xpcom"

+	Keyword="Win32Proj"

+	>

+	<Platforms>

+		<Platform

+			Name="Win32"

+		/>

+	</Platforms>

+	<ToolFiles>

+	</ToolFiles>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="Debug"

+			IntermediateDirectory="Debug"

+			ConfigurationType="2"

+			UseOfMFC="1"

+			>

+			<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;;&quot;S:\xulrunner-sdk-win\sdk\include&quot;;&quot;S:\xulrunner-sdk-win\include\caps&quot;;&quot;s:\xulrunner-sdk-win\include\dom&quot;;&quot;s:\xulrunner-sdk-win\include\js&quot;;&quot;s:\xulrunner-sdk-win\include\necko&quot;;&quot;s:\xulrunner-sdk-win\include\string&quot;;&quot;s:\xulrunner-sdk-win\include\widget&quot;;&quot;s:\xulrunner-sdk-win\include\xpcom&quot;;&quot;s:\xulrunner-sdk-win\include\xpconnect&quot;;&quot;S:\xulrunner-sdk-win\include&quot;"

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

+				MinimalRebuild="true"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="1"

+				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 xpcomglue_s.lib xpcom.lib nspr4.lib js3250.lib"

+				ShowProgress="2"

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

+				LinkIncremental="1"

+				AdditionalLibraryDirectories="..\..\..\..\xulrunner-sdk-win\lib"

+				ModuleDefinitionFile="$(ProjectDir)\..\xpOOPHM.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;XPCOM_GLUE;XPCOM_GLUE_USE_NSPR;MOZILLA_STRICT_API"

+				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 xpcomglue_s.lib xpcom.lib nspr4.lib js3250.lib"

+				ShowProgress="2"

+				OutputFile="..\extension\platform\WINNT_x86-msvc\components\xpOOPHM.dll"

+				LinkIncremental="0"

+				AdditionalLibraryDirectories="..\..\..\..\xulrunner-sdk-win\lib"

+				ModuleDefinitionFile="..\xpOOPHM.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\ByteOrder.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\ExternalWrapper.h"

+				>

+			</File>

+			<File

+				RelativePath="..\FFSessionHandler.h"

+				>

+			</File>

+			<File

+				RelativePath="..\XpcomDebug.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="..\..\..\..\xulrunner-sdk-win\include\js\jsapi.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jsautocfg.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jscompat.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jsconfig.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jslong.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jsotypes.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jsproto.tbl"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jspubtd.h"

+				>

+			</File>

+			<File

+				RelativePath="..\JSRunner.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jstypes.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jsutil.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jsutil.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jsutil.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jsutil.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\ModuleOOPHM.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\mozilla-config.h"

+				>

+			</File>

+			<File

+				RelativePath="..\mozincludes.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpconnect\nsAXPCNativeCallContext.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsCOMPtr.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nscore.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nscore.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsCycleCollector.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsDebug.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsError.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\widget\nsEvent.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsICategoryManager.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIClassInfo.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIClassInfoImpl.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIComponentManager.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsID.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsIEnumerator.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsIException.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsIExceptionService.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIFactory.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIGenericFactory.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\necko\nsIHttpProtocolHandler.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsIInterfaceInfo.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsIInterfaceInfoManager.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpconnect\nsIJSContextStack.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIMemory.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIModule.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\caps\nsIPrincipal.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIProgrammingLanguage.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\necko\nsIProtocolHandler.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\necko\nsIProxiedProtocolHandler.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpconnect\nsIScriptableInterfaces.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\dom\nsIScriptGlobalObject.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\dom\nsIScriptObjectPrincipal.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\caps\nsISecurityCheckedComponent.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsISerializable.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIServiceManager.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsISimpleEnumerator.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsISimpleEnumerator.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsISupports.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsISupports.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsISupportsBase.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsISupportsBase.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsISupportsImpl.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsISupportsUtils.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsISupportsUtils.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIURI.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsIVariant.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpconnect\nsIXPConnect.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsMemory.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\necko\nsNetCID.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsrootidl.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsrootidl.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsServiceManagerUtils.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsStringAPI.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsTraceRefcnt.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsXPCOM.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsXPCOMCID.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsXPCOMStrings.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\pratom.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\prcpucfg.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\prinrval.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\prlock.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\prlog.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\prlong.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\obsolete\protypes.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\prthread.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\prtime.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\prtypes.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\RootedObject.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\SessionData.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpconnect\xpccomponents.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpconnect\xpcexception.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpconnect\xpcjsid.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\xpcom-config.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\xpt_arena.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\xpt_struct.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\xptinfo.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="..\xpOOPHM.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="..\ExternalWrapper.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\FFSessionHandler.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\XpcomDebug.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="..\JSRunner.cpp"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\ModuleOOPHM.cpp"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\xpOOPHM.def"

+				>

+			</File>

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/plugins/xpcom/VisualStudio/ff3-xpcom.sln b/plugins/xpcom/VisualStudio/ff3-xpcom.sln
new file mode 100755
index 0000000..a14bef1
--- /dev/null
+++ b/plugins/xpcom/VisualStudio/ff3-xpcom.sln
@@ -0,0 +1,20 @@
+

+Microsoft Visual Studio Solution File, Format Version 9.00

+# Visual Studio 2005

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

+EndProject

+Global

+	GlobalSection(SolutionConfigurationPlatforms) = preSolution

+		Debug|Win32 = Debug|Win32

+		Release|Win32 = Release|Win32

+	EndGlobalSection

+	GlobalSection(ProjectConfigurationPlatforms) = postSolution

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

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

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

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

+	EndGlobalSection

+	GlobalSection(SolutionProperties) = preSolution

+		HideSolutionNode = FALSE

+	EndGlobalSection

+EndGlobal

diff --git a/plugins/xpcom/VisualStudio/ff3-xpcom.vcproj b/plugins/xpcom/VisualStudio/ff3-xpcom.vcproj
new file mode 100755
index 0000000..d4a7485
--- /dev/null
+++ b/plugins/xpcom/VisualStudio/ff3-xpcom.vcproj
@@ -0,0 +1,787 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="8.00"

+	Name="ff3-xpcom"

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

+	RootNamespace="ff3-xpcom"

+	Keyword="Win32Proj"

+	>

+	<Platforms>

+		<Platform

+			Name="Win32"

+		/>

+	</Platforms>

+	<ToolFiles>

+	</ToolFiles>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="Debug"

+			IntermediateDirectory="Debug"

+			ConfigurationType="2"

+			UseOfMFC="1"

+			>

+			<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;;&quot;..\prebuilt\ff3\include&quot;;&quot;..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\WINNT_x86-msvc\include&quot;;&quot;..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include&quot;;&quot;..\..\..\..\gwt-tools\sdk\gecko-sdks\geck-1.9\include\caps&quot;;&quot;..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\dom&quot;;&quot;..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\js&quot;;&quot;..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\necko&quot;;&quot;..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\string&quot;;&quot;..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\widget&quot;;&quot;..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpcom&quot;;&quot;..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpconnect&quot;;&quot;..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include&quot;"

+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FIREFOXPLUGIN_EXPORTS;GWT_DEBUGLEVEL=Warning;XPCOM_GLUE;XPCOM_GLUE_USE_NSPR;MOZILLA_STRICT_API;BROWSER_FF3"

+				MinimalRebuild="true"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="1"

+				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 xpcomglue_s.lib xpcom.lib nspr4.lib js3250.lib"

+				ShowProgress="2"

+				OutputFile="$(ProjectDir)\..\prebuilt\extension-ff3\platform\WINNT_x86-msvc\components\xpOOPHM.dll"

+				LinkIncremental="1"

+				AdditionalLibraryDirectories="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\WINNT_x86-msvc\lib"

+				ModuleDefinitionFile="$(ProjectDir)\..\xpOOPHM.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;XPCOM_GLUE;XPCOM_GLUE_USE_NSPR;MOZILLA_STRICT_API;BROWSER_FF3"

+				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 xpcomglue_s.lib xpcom.lib nspr4.lib js3250.lib"

+				ShowProgress="2"

+				OutputFile="..\extension\platform\WINNT_x86-msvc\components\xpOOPHM.dll"

+				LinkIncremental="0"

+				AdditionalLibraryDirectories="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\WINNT_x86-msvc\lib"

+				ModuleDefinitionFile="..\xpOOPHM.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\ByteOrder.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\ExternalWrapper.h"

+				>

+			</File>

+			<File

+				RelativePath="..\FFSessionHandler.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="..\prebuilt\ff3\include\IOOPHM.h"

+				>

+			</File>

+			<File

+				RelativePath="..\JavaObject.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\js\jsapi.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\js\jsautocfg.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\js\jscompat.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\js\jsconfig.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\jscpucfg.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\js\jslong.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\jsosdep.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\js\jsotypes.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\js\jsproto.tbl"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\js\jspubtd.h"

+				>

+			</File>

+			<File

+				RelativePath="..\JSRunner.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\js\jstypes.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\js\jsutil.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\js\jsutil.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\js\jsutil.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\js\jsutil.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\ModuleOOPHM.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\WINNT_x86-msvc\include\mozilla-config.h"

+				>

+			</File>

+			<File

+				RelativePath="..\mozincludes.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpconnect\nsAXPCNativeCallContext.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsCOMPtr.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nscore.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpcom\nscore.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsCycleCollector.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsDebug.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsError.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\widget\nsEvent.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsICategoryManager.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsIClassInfo.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsIClassInfoImpl.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsIComponentManager.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsID.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpcom\nsIEnumerator.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpcom\nsIException.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpcom\nsIExceptionService.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsIFactory.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsIGenericFactory.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\necko\nsIHttpProtocolHandler.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpcom\nsIInterfaceInfo.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpcom\nsIInterfaceInfoManager.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpconnect\nsIJSContextStack.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsIMemory.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsIModule.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\caps\nsIPrincipal.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsIProgrammingLanguage.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\necko\nsIProtocolHandler.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\necko\nsIProxiedProtocolHandler.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpconnect\nsIScriptableInterfaces.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\dom\nsIScriptGlobalObject.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\dom\nsIScriptObjectPrincipal.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\caps\nsISecurityCheckedComponent.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpcom\nsISerializable.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsIServiceManager.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpcom\nsISimpleEnumerator.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsISimpleEnumerator.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsISupports.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpcom\nsISupports.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsISupportsBase.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpcom\nsISupportsBase.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsISupportsImpl.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpcom\nsISupportsUtils.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsISupportsUtils.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsIURI.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpcom\nsIVariant.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpconnect\nsIXPConnect.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsMemory.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\necko\nsNetCID.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsrootidl.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpcom\nsrootidl.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsServiceManagerUtils.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsStringAPI.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsTraceRefcnt.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsXPCOM.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsXPCOMCID.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\nsXPCOMStrings.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\pratom.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\prcpucfg.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\prinrval.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\prlock.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\prlog.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\prlong.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\obsolete\protypes.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\prthread.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\prtime.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\prtypes.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\RootedObject.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\SessionData.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpconnect\xpccomponents.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpconnect\xpcexception.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpconnect\xpcjsid.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\WINNT_x86-msvc\include\xpcom-config.h"

+				>

+			</File>

+			<File

+				RelativePath="..\XpcomDebug.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpcom\xpt_arena.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpcom\xpt_struct.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\gwt-tools\sdk\gecko-sdks\gecko-1.9\include\xpcom\xptinfo.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="..\xpOOPHM.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="..\ExternalWrapper.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\FFSessionHandler.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="..\JSRunner.cpp"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\ModuleOOPHM.cpp"

+				>

+				<FileConfiguration

+					Name="Debug|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						GeneratePreprocessedFile="0"

+					/>

+				</FileConfiguration>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\XpcomDebug.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\xpOOPHM.def"

+				>

+			</File>

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/plugins/xpcom/VisualStudio/firefox-xpcom.sln b/plugins/xpcom/VisualStudio/firefox-xpcom.sln
new file mode 100755
index 0000000..a50fc62
--- /dev/null
+++ b/plugins/xpcom/VisualStudio/firefox-xpcom.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-xpcom", "firefox-xpcom.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/xpcom/VisualStudio/firefox-xpcom.vcproj b/plugins/xpcom/VisualStudio/firefox-xpcom.vcproj
new file mode 100755
index 0000000..94b9004
--- /dev/null
+++ b/plugins/xpcom/VisualStudio/firefox-xpcom.vcproj
@@ -0,0 +1,767 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="8.00"

+	Name="firefox-xpcom"

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

+	RootNamespace="firefox-xpcom"

+	Keyword="Win32Proj"

+	>

+	<Platforms>

+		<Platform

+			Name="Win32"

+		/>

+	</Platforms>

+	<ToolFiles>

+	</ToolFiles>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="Debug"

+			IntermediateDirectory="Debug"

+			ConfigurationType="2"

+			UseOfMFC="1"

+			>

+			<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;;&quot;S:\xulrunner-sdk-win\sdk\include&quot;;&quot;S:\xulrunner-sdk-win\include\caps&quot;;&quot;s:\xulrunner-sdk-win\include\dom&quot;;&quot;s:\xulrunner-sdk-win\include\js&quot;;&quot;s:\xulrunner-sdk-win\include\necko&quot;;&quot;s:\xulrunner-sdk-win\include\string&quot;;&quot;s:\xulrunner-sdk-win\include\widget&quot;;&quot;s:\xulrunner-sdk-win\include\xpcom&quot;;&quot;s:\xulrunner-sdk-win\include\xpconnect&quot;;&quot;S:\xulrunner-sdk-win\include&quot;"

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

+				MinimalRebuild="true"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="1"

+				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 xpcomglue_s.lib xpcom.lib nspr4.lib js3250.lib"

+				ShowProgress="2"

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

+				LinkIncremental="1"

+				AdditionalLibraryDirectories="..\..\..\..\xulrunner-sdk-win\lib"

+				ModuleDefinitionFile="$(ProjectDir)\..\xpOOPHM.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;XPCOM_GLUE;XPCOM_GLUE_USE_NSPR;MOZILLA_STRICT_API"

+				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 xpcomglue_s.lib xpcom.lib nspr4.lib js3250.lib"

+				ShowProgress="2"

+				OutputFile="..\extension\platform\WINNT_x86-msvc\components\xpOOPHM.dll"

+				LinkIncremental="0"

+				AdditionalLibraryDirectories="..\..\..\..\xulrunner-sdk-win\lib"

+				ModuleDefinitionFile="..\xpOOPHM.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\ByteOrder.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\ExternalWrapper.h"

+				>

+			</File>

+			<File

+				RelativePath="..\FFSessionHandler.h"

+				>

+			</File>

+			<File

+				RelativePath="..\XpcomDebug.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="..\..\..\..\xulrunner-sdk-win\include\js\jsapi.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jsautocfg.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jscompat.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jsconfig.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jslong.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jsotypes.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jsproto.tbl"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jspubtd.h"

+				>

+			</File>

+			<File

+				RelativePath="..\JSRunner.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jstypes.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jsutil.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jsutil.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jsutil.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\js\jsutil.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\ModuleOOPHM.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\mozilla-config.h"

+				>

+			</File>

+			<File

+				RelativePath="..\mozincludes.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpconnect\nsAXPCNativeCallContext.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsCOMPtr.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nscore.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nscore.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsCycleCollector.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsDebug.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsError.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\widget\nsEvent.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsICategoryManager.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIClassInfo.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIClassInfoImpl.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIComponentManager.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsID.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsIEnumerator.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsIException.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsIExceptionService.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIFactory.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIGenericFactory.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\necko\nsIHttpProtocolHandler.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsIInterfaceInfo.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsIInterfaceInfoManager.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpconnect\nsIJSContextStack.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIMemory.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIModule.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\caps\nsIPrincipal.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIProgrammingLanguage.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\necko\nsIProtocolHandler.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\necko\nsIProxiedProtocolHandler.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpconnect\nsIScriptableInterfaces.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\dom\nsIScriptGlobalObject.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\dom\nsIScriptObjectPrincipal.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\caps\nsISecurityCheckedComponent.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsISerializable.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIServiceManager.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsISimpleEnumerator.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsISimpleEnumerator.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsISupports.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsISupports.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsISupportsBase.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsISupportsBase.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsISupportsImpl.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsISupportsUtils.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsISupportsUtils.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsIURI.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsIVariant.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpconnect\nsIXPConnect.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsMemory.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\necko\nsNetCID.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsrootidl.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\nsrootidl.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsServiceManagerUtils.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsStringAPI.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsTraceRefcnt.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsXPCOM.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsXPCOMCID.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\nsXPCOMStrings.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\pratom.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\prcpucfg.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\prinrval.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\prlock.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\prlog.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\prlong.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\obsolete\protypes.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\prthread.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\prtime.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\prtypes.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\RootedObject.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\SessionData.h"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpconnect\xpccomponents.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpconnect\xpcexception.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpconnect\xpcjsid.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\sdk\include\xpcom-config.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\xpt_arena.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\xpt_struct.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\..\..\xulrunner-sdk-win\include\xpcom\xptinfo.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="..\xpOOPHM.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="..\ExternalWrapper.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\FFSessionHandler.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\XpcomDebug.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="..\JSRunner.cpp"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\ModuleOOPHM.cpp"

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

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

+				>

+			</File>

+			<File

+				RelativePath="..\xpOOPHM.def"

+				>

+			</File>

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/plugins/xpcom/XpcomDebug.cpp b/plugins/xpcom/XpcomDebug.cpp
new file mode 100644
index 0000000..34ef738
--- /dev/null
+++ b/plugins/xpcom/XpcomDebug.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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 "XpcomDebug.h"
+#include "JavaObject.h"
+
+#ifdef _WINDOWS
+// avoid deprecation warnings for strncpy
+#define strncpy(d,s,c) strncpy_s((d),(c),(s),(c))
+
+#include <cstdarg>
+inline int snprintf(char* buf, size_t buflen, const char* fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+  int n = _vsnprintf_s(buf, buflen, buflen, fmt, args);
+  va_end(args);
+  return n;
+}
+
+#endif
+
+std::string dumpJsVal(JSContext* ctx, jsval v) {
+  char buf[70];
+  if (v == JSVAL_VOID) {
+    strncpy(buf, "undef", sizeof(buf));
+  } else if (v == JSVAL_NULL) {
+    strncpy(buf, "null", sizeof(buf));
+  } else {
+    switch (JSVAL_TAG(v)) {
+      case JSVAL_OBJECT:
+      {
+        JSObject* obj = JSVAL_TO_OBJECT(v);
+        if (JavaObject::isJavaObject(ctx, obj)) {
+          int oid = JavaObject::getObjectId(ctx, obj);
+          snprintf(buf, sizeof(buf), "JavaObj(%d)", oid);
+        } else {
+          JSClass* jsClass = JS_GET_CLASS(ctx, obj);
+          const char* name = jsClass->name ? jsClass->name : "<null>";
+          snprintf(buf, sizeof(buf), "Object(%.20s @ %p)", name, obj);
+        }
+        break;
+      }
+      case JSVAL_INT:
+        snprintf(buf, sizeof(buf), "int(%d)", JSVAL_TO_INT(v));
+        break;
+      case JSVAL_DOUBLE:
+        snprintf(buf, sizeof(buf), "double(%lf)", *JSVAL_TO_DOUBLE(v));
+        break;
+      case JSVAL_STRING:
+      {
+        JSString* str = JSVAL_TO_STRING(v);
+        size_t len = JS_GetStringLength(str);
+        const char* continued = "";
+        if (len > 20) {
+          len = 20;
+          continued = "...";
+        }
+        // TODO: trashes Unicode
+        snprintf(buf, sizeof(buf), "string(%.*s%s)", static_cast<int>(len),
+            JS_GetStringBytes(str), continued);
+        break;
+      }
+      case JSVAL_BOOLEAN:
+        snprintf(buf, sizeof(buf), "bool(%s)", JSVAL_TO_BOOLEAN(v) ? "true"
+            : " false");
+        break;
+    }
+  }
+  buf[sizeof(buf) - 1] = 0;
+  return std::string(buf);
+}
diff --git a/plugins/xpcom/XpcomDebug.h b/plugins/xpcom/XpcomDebug.h
new file mode 100644
index 0000000..4296ad2
--- /dev/null
+++ b/plugins/xpcom/XpcomDebug.h
@@ -0,0 +1,26 @@
+#ifndef _H_XpcomDebug
+#define _H_XpcomDebug
+/*
+ * 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 "mozincludes.h"
+#include "jsapi.h"
+
+std::string dumpJsVal(JSContext* ctx, jsval v);
+
+#endif
diff --git a/plugins/xpcom/getversion b/plugins/xpcom/getversion
new file mode 100755
index 0000000..7557e49
--- /dev/null
+++ b/plugins/xpcom/getversion
@@ -0,0 +1,10 @@
+#!/bin/sh
+# Wrapper to prevent failure if svnversion isn't available
+
+V=`svnversion ${PWD}/.. 2>/dev/null`
+if [ $? -gt 0 -o -z "$V" ]
+then
+  V='?'
+fi
+echo $V
+exit 0
diff --git a/plugins/xpcom/install-template-ff2.rdf b/plugins/xpcom/install-template-ff2.rdf
new file mode 100644
index 0000000..3516812
--- /dev/null
+++ b/plugins/xpcom/install-template-ff2.rdf
@@ -0,0 +1,46 @@
+<?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-xpcom-ff2@gwt.google.com</em:id>
+    <em:name>GWT Hosted Mode Plugin (XPCOM) for FF v1.5-2.x</em:name>
+    <em:version>GWT_OOPHM_VERSION</em:version>
+    <em:type>2</em:type>
+    <em:targetApplication>
+      <Description>
+        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+        <em:minVersion>1.5</em:minVersion>
+        <em:maxVersion>2.*</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+
+    <!-- Front End MetaData -->
+    <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>Darwin_x86-gcc3</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>
+    <em:updateURL>http://google-web-toolkit.googlecode.com/svn/trunk/plugins/xpcom/prebuilt/update.rdf</em:updateURL>
+
+    # platforms - any others?
+    <em:targetPlatform>WINNT_x86-msvc</em:targetPlatform>
+    <em:targetPlatform>Darwin_ppc-gcc3</em:targetPlatform>
+    <em:targetPlatform>SunOS_sparc-sunc</em:targetPlatform>
+    <em:targetPlatform>SunOS_x86-sunc</em:targetPlatform>
+    -->
+
+  </Description>
+</RDF>
diff --git a/plugins/xpcom/install-template-ff3+.rdf b/plugins/xpcom/install-template-ff3+.rdf
new file mode 100644
index 0000000..e4b39ac
--- /dev/null
+++ b/plugins/xpcom/install-template-ff3+.rdf
@@ -0,0 +1,46 @@
+<?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-xpcom-ff3@gwt.google.com</em:id>
+    <em:name>GWT Hosted Mode Plugin (XPCOM) for FF v3.x</em:name>
+    <em:version>GWT_OOPHM_VERSION</em:version>
+    <em:type>2</em:type>
+    <em:targetApplication>
+      <Description>
+        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+        <em:minVersion>3</em:minVersion>
+        <em:maxVersion>3.*</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+
+    <!-- Front End MetaData -->
+    <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>
+
+    <!-- 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>
+    <em:updateURL>http://google-web-toolkit.googlecode.com/svn/trunk/plugins/xpcom/prebuilt/update.rdf</em:updateURL>
+
+    # platforms - any others?
+    <em:targetPlatform>Darwin_ppc-gcc3</em:targetPlatform>
+    <em:targetPlatform>SunOS_sparc-sunc</em:targetPlatform>
+    <em:targetPlatform>SunOS_x86-sunc</em:targetPlatform>
+    -->
+
+  </Description>
+</RDF>
diff --git a/plugins/xpcom/install-template-ff3.rdf b/plugins/xpcom/install-template-ff3.rdf
new file mode 100644
index 0000000..e4b39ac
--- /dev/null
+++ b/plugins/xpcom/install-template-ff3.rdf
@@ -0,0 +1,46 @@
+<?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-xpcom-ff3@gwt.google.com</em:id>
+    <em:name>GWT Hosted Mode Plugin (XPCOM) for FF v3.x</em:name>
+    <em:version>GWT_OOPHM_VERSION</em:version>
+    <em:type>2</em:type>
+    <em:targetApplication>
+      <Description>
+        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+        <em:minVersion>3</em:minVersion>
+        <em:maxVersion>3.*</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+
+    <!-- Front End MetaData -->
+    <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>
+
+    <!-- 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>
+    <em:updateURL>http://google-web-toolkit.googlecode.com/svn/trunk/plugins/xpcom/prebuilt/update.rdf</em:updateURL>
+
+    # platforms - any others?
+    <em:targetPlatform>Darwin_ppc-gcc3</em:targetPlatform>
+    <em:targetPlatform>SunOS_sparc-sunc</em:targetPlatform>
+    <em:targetPlatform>SunOS_x86-sunc</em:targetPlatform>
+    -->
+
+  </Description>
+</RDF>
diff --git a/plugins/xpcom/install-template-ff35.rdf b/plugins/xpcom/install-template-ff35.rdf
new file mode 100644
index 0000000..95ab6e8
--- /dev/null
+++ b/plugins/xpcom/install-template-ff35.rdf
@@ -0,0 +1,46 @@
+<?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-xpcom-ff35@gwt.google.com</em:id>
+    <em:name>GWT Hosted Mode Plugin (XPCOM) for FF v3.5+</em:name>
+    <em:version>GWT_OOPHM_VERSION</em:version>
+    <em:type>2</em:type>
+    <em:targetApplication>
+      <Description>
+        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+        <em:minVersion>3.4</em:minVersion>
+        <em:maxVersion>3.*</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+
+    <!-- Front End MetaData -->
+    <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>
+
+    <!-- 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>
+    <em:updateURL>http://google-web-toolkit.googlecode.com/svn/trunk/plugins/xpcom/prebuilt/update.rdf</em:updateURL>
+
+    # platforms - any others?
+    <em:targetPlatform>Darwin_ppc-gcc3</em:targetPlatform>
+    <em:targetPlatform>SunOS_sparc-sunc</em:targetPlatform>
+    <em:targetPlatform>SunOS_x86-sunc</em:targetPlatform>
+    -->
+
+  </Description>
+</RDF>
diff --git a/plugins/xpcom/mozincludes.h b/plugins/xpcom/mozincludes.h
new file mode 100755
index 0000000..14f50e4
--- /dev/null
+++ b/plugins/xpcom/mozincludes.h
@@ -0,0 +1,14 @@
+#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 "xpcom-config.h"
+#include "mozilla-config.h"
+
+#endif
diff --git a/plugins/xpcom/prebuilt/LICENSE.txt b/plugins/xpcom/prebuilt/LICENSE.txt
new file mode 100644
index 0000000..326366d
--- /dev/null
+++ b/plugins/xpcom/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/xpcom/prebuilt/README.txt b/plugins/xpcom/prebuilt/README.txt
new file mode 100644
index 0000000..6f54ad5
--- /dev/null
+++ b/plugins/xpcom/prebuilt/README.txt
@@ -0,0 +1,6 @@
+Files common to all platforms should be placed under extension/...
+Files for FF1.5/2 should go under extension-ff2/...
+Files for FF3 should go under extension-ff3/...
+
+Files such as headers that need to be supplied pre-generated should be under
+ff2/ff3.
diff --git a/plugins/xpcom/prebuilt/extension-ff2/chrome.manifest b/plugins/xpcom/prebuilt/extension-ff2/chrome.manifest
new file mode 100644
index 0000000..38a0fdd
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff2/chrome.manifest
@@ -0,0 +1,2 @@
+content gwt-oophm content/
+skin gwt-oophm classic/1.0 skin/
diff --git a/plugins/xpcom/prebuilt/extension-ff2/components/IOOPHM.xpt b/plugins/xpcom/prebuilt/extension-ff2/components/IOOPHM.xpt
new file mode 100644
index 0000000..4be87b7
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff2/components/IOOPHM.xpt
Binary files differ
diff --git a/plugins/xpcom/prebuilt/extension-ff2/install.rdf b/plugins/xpcom/prebuilt/extension-ff2/install.rdf
new file mode 100644
index 0000000..7feda0c
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff2/install.rdf
@@ -0,0 +1,46 @@
+<?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-xpcom-ff2@gwt.google.com</em:id>
+    <em:name>GWT Hosted Mode Plugin (XPCOM) for FF v1.5-2.x</em:name>
+    <em:version>0.0.-1M.20090803104826</em:version>
+    <em:type>2</em:type>
+    <em:targetApplication>
+      <Description>
+        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+        <em:minVersion>1.5</em:minVersion>
+        <em:maxVersion>2.*</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+
+    <!-- Front End MetaData -->
+    <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>Darwin_x86-gcc3</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>
+    <em:updateURL>http://google-web-toolkit.googlecode.com/svn/trunk/plugins/xpcom/prebuilt/update.rdf</em:updateURL>
+
+    # platforms - any others?
+    <em:targetPlatform>WINNT_x86-msvc</em:targetPlatform>
+    <em:targetPlatform>Darwin_ppc-gcc3</em:targetPlatform>
+    <em:targetPlatform>SunOS_sparc-sunc</em:targetPlatform>
+    <em:targetPlatform>SunOS_x86-sunc</em:targetPlatform>
+    -->
+
+  </Description>
+</RDF>
diff --git a/plugins/xpcom/prebuilt/extension-ff2/platform/Linux_x86-gcc3/components/liboophm_ff2.so b/plugins/xpcom/prebuilt/extension-ff2/platform/Linux_x86-gcc3/components/liboophm_ff2.so
new file mode 100755
index 0000000..65b6dd9
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff2/platform/Linux_x86-gcc3/components/liboophm_ff2.so
Binary files differ
diff --git a/plugins/xpcom/prebuilt/extension-ff2/platform/Linux_x86_64-gcc3/components/liboophm_ff2.so b/plugins/xpcom/prebuilt/extension-ff2/platform/Linux_x86_64-gcc3/components/liboophm_ff2.so
new file mode 100755
index 0000000..f9dd5d3
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff2/platform/Linux_x86_64-gcc3/components/liboophm_ff2.so
Binary files differ
diff --git a/plugins/xpcom/prebuilt/extension-ff2/skin/icon.png b/plugins/xpcom/prebuilt/extension-ff2/skin/icon.png
new file mode 100644
index 0000000..7ba8270
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff2/skin/icon.png
Binary files differ
diff --git a/plugins/xpcom/prebuilt/extension-ff3+/chrome.manifest b/plugins/xpcom/prebuilt/extension-ff3+/chrome.manifest
new file mode 100644
index 0000000..38a0fdd
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff3+/chrome.manifest
@@ -0,0 +1,2 @@
+content gwt-oophm content/
+skin gwt-oophm classic/1.0 skin/
diff --git a/plugins/xpcom/prebuilt/extension-ff3+/components/IOOPHM.xpt b/plugins/xpcom/prebuilt/extension-ff3+/components/IOOPHM.xpt
new file mode 100644
index 0000000..4be87b7
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff3+/components/IOOPHM.xpt
Binary files differ
diff --git a/plugins/xpcom/prebuilt/extension-ff3+/install.rdf b/plugins/xpcom/prebuilt/extension-ff3+/install.rdf
new file mode 100644
index 0000000..31f4673
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff3+/install.rdf
@@ -0,0 +1,46 @@
+<?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-xpcom-ff3@gwt.google.com</em:id>
+    <em:name>GWT Hosted Mode Plugin (XPCOM) for FF v3.x</em:name>
+    <em:version>0.0.-1M.20090803104811</em:version>
+    <em:type>2</em:type>
+    <em:targetApplication>
+      <Description>
+        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+        <em:minVersion>3</em:minVersion>
+        <em:maxVersion>3.*</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+
+    <!-- Front End MetaData -->
+    <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>
+
+    <!-- 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>
+    <em:updateURL>http://google-web-toolkit.googlecode.com/svn/trunk/plugins/xpcom/prebuilt/update.rdf</em:updateURL>
+
+    # platforms - any others?
+    <em:targetPlatform>Darwin_ppc-gcc3</em:targetPlatform>
+    <em:targetPlatform>SunOS_sparc-sunc</em:targetPlatform>
+    <em:targetPlatform>SunOS_x86-sunc</em:targetPlatform>
+    -->
+
+  </Description>
+</RDF>
diff --git a/plugins/xpcom/prebuilt/extension-ff3+/platform/Linux_x86_64-gcc3/components/liboophm_ff3+.so b/plugins/xpcom/prebuilt/extension-ff3+/platform/Linux_x86_64-gcc3/components/liboophm_ff3+.so
new file mode 100755
index 0000000..2361279
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff3+/platform/Linux_x86_64-gcc3/components/liboophm_ff3+.so
Binary files differ
diff --git a/plugins/xpcom/prebuilt/extension-ff3+/skin/icon.png b/plugins/xpcom/prebuilt/extension-ff3+/skin/icon.png
new file mode 100644
index 0000000..7ba8270
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff3+/skin/icon.png
Binary files differ
diff --git a/plugins/xpcom/prebuilt/extension-ff3/chrome.manifest b/plugins/xpcom/prebuilt/extension-ff3/chrome.manifest
new file mode 100644
index 0000000..38a0fdd
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff3/chrome.manifest
@@ -0,0 +1,2 @@
+content gwt-oophm content/
+skin gwt-oophm classic/1.0 skin/
diff --git a/plugins/xpcom/prebuilt/extension-ff3/components/IOOPHM.xpt b/plugins/xpcom/prebuilt/extension-ff3/components/IOOPHM.xpt
new file mode 100644
index 0000000..4be87b7
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff3/components/IOOPHM.xpt
Binary files differ
diff --git a/plugins/xpcom/prebuilt/extension-ff3/install.rdf b/plugins/xpcom/prebuilt/extension-ff3/install.rdf
new file mode 100644
index 0000000..a782f87
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff3/install.rdf
@@ -0,0 +1,46 @@
+<?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-xpcom-ff3@gwt.google.com</em:id>
+    <em:name>GWT Hosted Mode Plugin (XPCOM) for FF v3.x</em:name>
+    <em:version>0.0.-1M.20090803104821</em:version>
+    <em:type>2</em:type>
+    <em:targetApplication>
+      <Description>
+        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+        <em:minVersion>3</em:minVersion>
+        <em:maxVersion>3.*</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+
+    <!-- Front End MetaData -->
+    <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>
+
+    <!-- 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>
+    <em:updateURL>http://google-web-toolkit.googlecode.com/svn/trunk/plugins/xpcom/prebuilt/update.rdf</em:updateURL>
+
+    # platforms - any others?
+    <em:targetPlatform>Darwin_ppc-gcc3</em:targetPlatform>
+    <em:targetPlatform>SunOS_sparc-sunc</em:targetPlatform>
+    <em:targetPlatform>SunOS_x86-sunc</em:targetPlatform>
+    -->
+
+  </Description>
+</RDF>
diff --git a/plugins/xpcom/prebuilt/extension-ff3/platform/Darwin_x86-gcc3/components/liboophm.dylib b/plugins/xpcom/prebuilt/extension-ff3/platform/Darwin_x86-gcc3/components/liboophm.dylib
new file mode 100755
index 0000000..eb3864d
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff3/platform/Darwin_x86-gcc3/components/liboophm.dylib
Binary files differ
diff --git a/plugins/xpcom/prebuilt/extension-ff3/platform/Linux_x86-gcc3/components/liboophm_ff3.so b/plugins/xpcom/prebuilt/extension-ff3/platform/Linux_x86-gcc3/components/liboophm_ff3.so
new file mode 100755
index 0000000..a8705e0
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff3/platform/Linux_x86-gcc3/components/liboophm_ff3.so
Binary files differ
diff --git a/plugins/xpcom/prebuilt/extension-ff3/platform/Linux_x86_64-gcc3/components/liboophm_ff3.so b/plugins/xpcom/prebuilt/extension-ff3/platform/Linux_x86_64-gcc3/components/liboophm_ff3.so
new file mode 100755
index 0000000..cb26cbe
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff3/platform/Linux_x86_64-gcc3/components/liboophm_ff3.so
Binary files differ
diff --git a/plugins/xpcom/prebuilt/extension-ff3/platform/WINNT_x86-msvc/components/xpOOPHM.dll b/plugins/xpcom/prebuilt/extension-ff3/platform/WINNT_x86-msvc/components/xpOOPHM.dll
new file mode 100755
index 0000000..6c8ec68
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff3/platform/WINNT_x86-msvc/components/xpOOPHM.dll
Binary files differ
diff --git a/plugins/xpcom/prebuilt/extension-ff3/skin/icon.png b/plugins/xpcom/prebuilt/extension-ff3/skin/icon.png
new file mode 100644
index 0000000..7ba8270
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff3/skin/icon.png
Binary files differ
diff --git a/plugins/xpcom/prebuilt/extension-ff35/chrome.manifest b/plugins/xpcom/prebuilt/extension-ff35/chrome.manifest
new file mode 100644
index 0000000..38a0fdd
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff35/chrome.manifest
@@ -0,0 +1,2 @@
+content gwt-oophm content/
+skin gwt-oophm classic/1.0 skin/
diff --git a/plugins/xpcom/prebuilt/extension-ff35/components/IOOPHM.xpt b/plugins/xpcom/prebuilt/extension-ff35/components/IOOPHM.xpt
new file mode 100644
index 0000000..4be87b7
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff35/components/IOOPHM.xpt
Binary files differ
diff --git a/plugins/xpcom/prebuilt/extension-ff35/install.rdf b/plugins/xpcom/prebuilt/extension-ff35/install.rdf
new file mode 100644
index 0000000..6148662
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff35/install.rdf
@@ -0,0 +1,46 @@
+<?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-xpcom-ff35@gwt.google.com</em:id>
+    <em:name>GWT Hosted Mode Plugin (XPCOM) for FF v3.5+</em:name>
+    <em:version>0.0.-1M.20090803104256</em:version>
+    <em:type>2</em:type>
+    <em:targetApplication>
+      <Description>
+        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+        <em:minVersion>3.4</em:minVersion>
+        <em:maxVersion>3.*</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+
+    <!-- Front End MetaData -->
+    <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>
+
+    <!-- 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>
+    <em:updateURL>http://google-web-toolkit.googlecode.com/svn/trunk/plugins/xpcom/prebuilt/update.rdf</em:updateURL>
+
+    # platforms - any others?
+    <em:targetPlatform>Darwin_ppc-gcc3</em:targetPlatform>
+    <em:targetPlatform>SunOS_sparc-sunc</em:targetPlatform>
+    <em:targetPlatform>SunOS_x86-sunc</em:targetPlatform>
+    -->
+
+  </Description>
+</RDF>
diff --git a/plugins/xpcom/prebuilt/extension-ff35/platform/Linux_x86_64-gcc3/components/liboophm_ff35.so b/plugins/xpcom/prebuilt/extension-ff35/platform/Linux_x86_64-gcc3/components/liboophm_ff35.so
new file mode 100755
index 0000000..1027a07
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff35/platform/Linux_x86_64-gcc3/components/liboophm_ff35.so
Binary files differ
diff --git a/plugins/xpcom/prebuilt/extension-ff35/skin/icon.png b/plugins/xpcom/prebuilt/extension-ff35/skin/icon.png
new file mode 100644
index 0000000..7ba8270
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension-ff35/skin/icon.png
Binary files differ
diff --git a/plugins/xpcom/prebuilt/extension/chrome.manifest b/plugins/xpcom/prebuilt/extension/chrome.manifest
new file mode 100644
index 0000000..38a0fdd
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension/chrome.manifest
@@ -0,0 +1,2 @@
+content gwt-oophm content/
+skin gwt-oophm classic/1.0 skin/
diff --git a/plugins/xpcom/prebuilt/extension/components/IOOPHM.xpt b/plugins/xpcom/prebuilt/extension/components/IOOPHM.xpt
new file mode 100644
index 0000000..4be87b7
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension/components/IOOPHM.xpt
Binary files differ
diff --git a/plugins/xpcom/prebuilt/extension/skin/icon.png b/plugins/xpcom/prebuilt/extension/skin/icon.png
new file mode 100644
index 0000000..7ba8270
--- /dev/null
+++ b/plugins/xpcom/prebuilt/extension/skin/icon.png
Binary files differ
diff --git a/plugins/xpcom/prebuilt/ff2/include/IOOPHM.h b/plugins/xpcom/prebuilt/ff2/include/IOOPHM.h
new file mode 100644
index 0000000..9ab769d
--- /dev/null
+++ b/plugins/xpcom/prebuilt/ff2/include/IOOPHM.h
@@ -0,0 +1,91 @@
+/*
+ * DO NOT EDIT.  THIS FILE IS GENERATED FROM IOOPHM.idl
+ */
+
+#ifndef __gen_IOOPHM_h__
+#define __gen_IOOPHM_h__
+
+
+#ifndef __gen_nsISupports_h__
+#include "nsISupports.h"
+#endif
+
+/* For IDL files that don't want to include root IDL files. */
+#ifndef NS_NO_VTABLE
+#define NS_NO_VTABLE
+#endif
+class nsIDOMWindow; /* forward declaration */
+
+
+/* starting interface:    IOOPHM */
+#define IOOPHM_IID_STR "90cef17b-c3fe-4251-af68-4381b3d938a0"
+
+#define IOOPHM_IID \
+  {0x90cef17b, 0xc3fe, 0x4251, \
+    { 0xaf, 0x68, 0x43, 0x81, 0xb3, 0xd9, 0x38, 0xa0 }}
+
+class NS_NO_VTABLE IOOPHM : public nsISupports {
+ public: 
+
+  NS_DEFINE_STATIC_IID_ACCESSOR(IOOPHM_IID)
+
+  /* boolean connect (in ACString addr, in ACString moduleName, in nsIDOMWindow window); */
+  NS_IMETHOD Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval) = 0;
+
+};
+
+/* Use this macro when declaring classes that implement this interface. */
+#define NS_DECL_IOOPHM \
+  NS_IMETHOD Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval); 
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object. */
+#define NS_FORWARD_IOOPHM(_to) \
+  NS_IMETHOD Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval) { return _to Connect(addr, moduleName, window, _retval); } 
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
+#define NS_FORWARD_SAFE_IOOPHM(_to) \
+  NS_IMETHOD Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Connect(addr, moduleName, window, _retval); } 
+
+#if 0
+/* Use the code below as a template for the implementation class for this interface. */
+
+/* Header file */
+class _MYCLASS_ : public IOOPHM
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_IOOPHM
+
+  _MYCLASS_();
+
+private:
+  ~_MYCLASS_();
+
+protected:
+  /* additional members */
+};
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS1(_MYCLASS_, IOOPHM)
+
+_MYCLASS_::_MYCLASS_()
+{
+  /* member initializers and constructor code */
+}
+
+_MYCLASS_::~_MYCLASS_()
+{
+  /* destructor code */
+}
+
+/* boolean connect (in ACString addr, in ACString moduleName, in nsIDOMWindow window); */
+NS_IMETHODIMP _MYCLASS_::Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* End of implementation class template. */
+#endif
+
+
+#endif /* __gen_IOOPHM_h__ */
diff --git a/plugins/xpcom/prebuilt/ff3+/include/IOOPHM.h b/plugins/xpcom/prebuilt/ff3+/include/IOOPHM.h
new file mode 100644
index 0000000..ba6f481
--- /dev/null
+++ b/plugins/xpcom/prebuilt/ff3+/include/IOOPHM.h
@@ -0,0 +1,93 @@
+/*
+ * DO NOT EDIT.  THIS FILE IS GENERATED FROM IOOPHM.idl
+ */
+
+#ifndef __gen_IOOPHM_h__
+#define __gen_IOOPHM_h__
+
+
+#ifndef __gen_nsISupports_h__
+#include "nsISupports.h"
+#endif
+
+/* For IDL files that don't want to include root IDL files. */
+#ifndef NS_NO_VTABLE
+#define NS_NO_VTABLE
+#endif
+class nsIDOMWindow; /* forward declaration */
+
+
+/* starting interface:    IOOPHM */
+#define IOOPHM_IID_STR "90cef17b-c3fe-4251-af68-4381b3d938a0"
+
+#define IOOPHM_IID \
+  {0x90cef17b, 0xc3fe, 0x4251, \
+    { 0xaf, 0x68, 0x43, 0x81, 0xb3, 0xd9, 0x38, 0xa0 }}
+
+class NS_NO_VTABLE NS_SCRIPTABLE IOOPHM : public nsISupports {
+ public: 
+
+  NS_DECLARE_STATIC_IID_ACCESSOR(IOOPHM_IID)
+
+  /* boolean connect (in ACString addr, in ACString moduleName, in nsIDOMWindow window); */
+  NS_SCRIPTABLE NS_IMETHOD Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval) = 0;
+
+};
+
+  NS_DEFINE_STATIC_IID_ACCESSOR(IOOPHM, IOOPHM_IID)
+
+/* Use this macro when declaring classes that implement this interface. */
+#define NS_DECL_IOOPHM \
+  NS_SCRIPTABLE NS_IMETHOD Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval); 
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object. */
+#define NS_FORWARD_IOOPHM(_to) \
+  NS_SCRIPTABLE NS_IMETHOD Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval) { return _to Connect(addr, moduleName, window, _retval); } 
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
+#define NS_FORWARD_SAFE_IOOPHM(_to) \
+  NS_SCRIPTABLE NS_IMETHOD Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Connect(addr, moduleName, window, _retval); } 
+
+#if 0
+/* Use the code below as a template for the implementation class for this interface. */
+
+/* Header file */
+class _MYCLASS_ : public IOOPHM
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_IOOPHM
+
+  _MYCLASS_();
+
+private:
+  ~_MYCLASS_();
+
+protected:
+  /* additional members */
+};
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS1(_MYCLASS_, IOOPHM)
+
+_MYCLASS_::_MYCLASS_()
+{
+  /* member initializers and constructor code */
+}
+
+_MYCLASS_::~_MYCLASS_()
+{
+  /* destructor code */
+}
+
+/* boolean connect (in ACString addr, in ACString moduleName, in nsIDOMWindow window); */
+NS_IMETHODIMP _MYCLASS_::Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* End of implementation class template. */
+#endif
+
+
+#endif /* __gen_IOOPHM_h__ */
diff --git a/plugins/xpcom/prebuilt/ff3/include/IOOPHM.h b/plugins/xpcom/prebuilt/ff3/include/IOOPHM.h
new file mode 100644
index 0000000..ba6f481
--- /dev/null
+++ b/plugins/xpcom/prebuilt/ff3/include/IOOPHM.h
@@ -0,0 +1,93 @@
+/*
+ * DO NOT EDIT.  THIS FILE IS GENERATED FROM IOOPHM.idl
+ */
+
+#ifndef __gen_IOOPHM_h__
+#define __gen_IOOPHM_h__
+
+
+#ifndef __gen_nsISupports_h__
+#include "nsISupports.h"
+#endif
+
+/* For IDL files that don't want to include root IDL files. */
+#ifndef NS_NO_VTABLE
+#define NS_NO_VTABLE
+#endif
+class nsIDOMWindow; /* forward declaration */
+
+
+/* starting interface:    IOOPHM */
+#define IOOPHM_IID_STR "90cef17b-c3fe-4251-af68-4381b3d938a0"
+
+#define IOOPHM_IID \
+  {0x90cef17b, 0xc3fe, 0x4251, \
+    { 0xaf, 0x68, 0x43, 0x81, 0xb3, 0xd9, 0x38, 0xa0 }}
+
+class NS_NO_VTABLE NS_SCRIPTABLE IOOPHM : public nsISupports {
+ public: 
+
+  NS_DECLARE_STATIC_IID_ACCESSOR(IOOPHM_IID)
+
+  /* boolean connect (in ACString addr, in ACString moduleName, in nsIDOMWindow window); */
+  NS_SCRIPTABLE NS_IMETHOD Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval) = 0;
+
+};
+
+  NS_DEFINE_STATIC_IID_ACCESSOR(IOOPHM, IOOPHM_IID)
+
+/* Use this macro when declaring classes that implement this interface. */
+#define NS_DECL_IOOPHM \
+  NS_SCRIPTABLE NS_IMETHOD Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval); 
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object. */
+#define NS_FORWARD_IOOPHM(_to) \
+  NS_SCRIPTABLE NS_IMETHOD Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval) { return _to Connect(addr, moduleName, window, _retval); } 
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
+#define NS_FORWARD_SAFE_IOOPHM(_to) \
+  NS_SCRIPTABLE NS_IMETHOD Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Connect(addr, moduleName, window, _retval); } 
+
+#if 0
+/* Use the code below as a template for the implementation class for this interface. */
+
+/* Header file */
+class _MYCLASS_ : public IOOPHM
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_IOOPHM
+
+  _MYCLASS_();
+
+private:
+  ~_MYCLASS_();
+
+protected:
+  /* additional members */
+};
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS1(_MYCLASS_, IOOPHM)
+
+_MYCLASS_::_MYCLASS_()
+{
+  /* member initializers and constructor code */
+}
+
+_MYCLASS_::~_MYCLASS_()
+{
+  /* destructor code */
+}
+
+/* boolean connect (in ACString addr, in ACString moduleName, in nsIDOMWindow window); */
+NS_IMETHODIMP _MYCLASS_::Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* End of implementation class template. */
+#endif
+
+
+#endif /* __gen_IOOPHM_h__ */
diff --git a/plugins/xpcom/prebuilt/ff35/include/IOOPHM.h b/plugins/xpcom/prebuilt/ff35/include/IOOPHM.h
new file mode 100644
index 0000000..47d62d2
--- /dev/null
+++ b/plugins/xpcom/prebuilt/ff35/include/IOOPHM.h
@@ -0,0 +1,93 @@
+/*
+ * DO NOT EDIT.  THIS FILE IS GENERATED FROM IOOPHM.idl
+ */
+
+#ifndef __gen_IOOPHM_h__
+#define __gen_IOOPHM_h__
+
+
+#ifndef __gen_nsISupports_h__
+#include "nsISupports.h"
+#endif
+
+/* For IDL files that don't want to include root IDL files. */
+#ifndef NS_NO_VTABLE
+#define NS_NO_VTABLE
+#endif
+class nsIDOMWindow; /* forward declaration */
+
+
+/* starting interface:    IOOPHM */
+#define IOOPHM_IID_STR "90cef17b-c3fe-4251-af68-4381b3d938a0"
+
+#define IOOPHM_IID \
+  {0x90cef17b, 0xc3fe, 0x4251, \
+    { 0xaf, 0x68, 0x43, 0x81, 0xb3, 0xd9, 0x38, 0xa0 }}
+
+class NS_NO_VTABLE NS_SCRIPTABLE IOOPHM : public nsISupports {
+ public: 
+
+  NS_DECLARE_STATIC_IID_ACCESSOR(IOOPHM_IID)
+
+  /* boolean connect (in ACString addr, in ACString moduleName, in nsIDOMWindow window); */
+  NS_SCRIPTABLE NS_IMETHOD Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval NS_OUTPARAM) = 0;
+
+};
+
+  NS_DEFINE_STATIC_IID_ACCESSOR(IOOPHM, IOOPHM_IID)
+
+/* Use this macro when declaring classes that implement this interface. */
+#define NS_DECL_IOOPHM \
+  NS_SCRIPTABLE NS_IMETHOD Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval NS_OUTPARAM); 
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object. */
+#define NS_FORWARD_IOOPHM(_to) \
+  NS_SCRIPTABLE NS_IMETHOD Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval NS_OUTPARAM) { return _to Connect(addr, moduleName, window, _retval); } 
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
+#define NS_FORWARD_SAFE_IOOPHM(_to) \
+  NS_SCRIPTABLE NS_IMETHOD Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval NS_OUTPARAM) { return !_to ? NS_ERROR_NULL_POINTER : _to->Connect(addr, moduleName, window, _retval); } 
+
+#if 0
+/* Use the code below as a template for the implementation class for this interface. */
+
+/* Header file */
+class _MYCLASS_ : public IOOPHM
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_IOOPHM
+
+  _MYCLASS_();
+
+private:
+  ~_MYCLASS_();
+
+protected:
+  /* additional members */
+};
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS1(_MYCLASS_, IOOPHM)
+
+_MYCLASS_::_MYCLASS_()
+{
+  /* member initializers and constructor code */
+}
+
+_MYCLASS_::~_MYCLASS_()
+{
+  /* destructor code */
+}
+
+/* boolean connect (in ACString addr, in ACString moduleName, in nsIDOMWindow window); */
+NS_IMETHODIMP _MYCLASS_::Connect(const nsACString & addr, const nsACString & moduleName, nsIDOMWindow *window, PRBool *_retval NS_OUTPARAM)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* End of implementation class template. */
+#endif
+
+
+#endif /* __gen_IOOPHM_h__ */
diff --git a/plugins/xpcom/prebuilt/oophm-xpcom-ff2.xpi b/plugins/xpcom/prebuilt/oophm-xpcom-ff2.xpi
new file mode 100644
index 0000000..96ae80f
--- /dev/null
+++ b/plugins/xpcom/prebuilt/oophm-xpcom-ff2.xpi
Binary files differ
diff --git a/plugins/xpcom/prebuilt/oophm-xpcom-ff3+.xpi b/plugins/xpcom/prebuilt/oophm-xpcom-ff3+.xpi
new file mode 100644
index 0000000..9e5cabc
--- /dev/null
+++ b/plugins/xpcom/prebuilt/oophm-xpcom-ff3+.xpi
Binary files differ
diff --git a/plugins/xpcom/prebuilt/oophm-xpcom-ff3.xpi b/plugins/xpcom/prebuilt/oophm-xpcom-ff3.xpi
new file mode 100644
index 0000000..d7fd35a
--- /dev/null
+++ b/plugins/xpcom/prebuilt/oophm-xpcom-ff3.xpi
Binary files differ
diff --git a/plugins/xpcom/prebuilt/oophm-xpcom-ff35.xpi b/plugins/xpcom/prebuilt/oophm-xpcom-ff35.xpi
new file mode 100644
index 0000000..3bf14d8
--- /dev/null
+++ b/plugins/xpcom/prebuilt/oophm-xpcom-ff35.xpi
Binary files differ
diff --git a/plugins/xpcom/prebuilt/update.rdf b/plugins/xpcom/prebuilt/update.rdf
new file mode 100644
index 0000000..157aec9
--- /dev/null
+++ b/plugins/xpcom/prebuilt/update.rdf
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+         xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+
+  <RDF:Description about="urn:mozilla:extension:oophm-xpcom-ff2@gwt.google.com">
+    <em:updates>
+      <RDF:Seq>
+
+        <RDF:li>
+          <RDF:Description>
+            <em:version>0.0.4229M.20081202172443</em:version>
+	    <em:targetApplication>
+	      <Description>
+		<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+		<em:minVersion>1.5</em:minVersion>
+		<em:maxVersion>2.*</em:maxVersion>
+                <em:updateLink>http://google-web-toolkit.googlecode.com/svn/changes/jat/oophm-plugins-trunk/plugins/xpcom/prebuilt/oophm-xpcom-ff2.xpi</em:updateLink>
+
+		<!--
+                <em:updateInfoURL>http://www.mysite.com/updateinfo2.2.xhtml</em:updateInfoURL>
+		-->
+	      </Description>
+	    </em:targetApplication>
+          </RDF:Description>
+        </RDF:li>
+
+      </RDF:Seq>
+    </em:updates>
+  </RDF:Description>
+
+  <RDF:Description about="urn:mozilla:extension:oophm-xpcom-ff3@gwt.google.com">
+    <em:updates>
+      <RDF:Seq>
+
+        <RDF:li>
+          <RDF:Description>
+            <em:version>0.0.4229M.20081202172443</em:version>
+	    <em:targetApplication>
+	      <Description>
+		<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+		<em:minVersion>3</em:minVersion>
+		<em:maxVersion>3.4.*</em:maxVersion>
+                <em:updateLink>http://google-web-toolkit.googlecode.com/svn/changes/jat/oophm-plugins-trunk/plugins/xpcom/prebuilt/oophm-xpcom-ff3.xpi</em:updateLink>
+
+		<!--
+                <em:updateInfoURL>http://www.mysite.com/updateinfo2.2.xhtml</em:updateInfoURL>
+		-->
+	      </Description>
+	    </em:targetApplication>
+          </RDF:Description>
+        </RDF:li>
+
+      </RDF:Seq>
+    </em:updates>
+  </RDF:Description>
+
+  <RDF:Description about="urn:mozilla:extension:oophm-xpcom-ff3+@gwt.google.com">
+    <em:updates>
+      <RDF:Seq>
+
+        <RDF:li>
+          <RDF:Description>
+            <em:version>0.0.4229M.20081202172443</em:version>
+	    <em:targetApplication>
+	      <Description>
+		<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+		<em:minVersion>3</em:minVersion>
+		<em:maxVersion>3.4.*</em:maxVersion>
+                <em:updateLink>http://google-web-toolkit.googlecode.com/svn/changes/jat/oophm-plugins-trunk/plugins/xpcom/prebuilt/oophm-xpcom-ff3+.xpi</em:updateLink>
+
+		<!--
+                <em:updateInfoURL>http://www.mysite.com/updateinfo2.2.xhtml</em:updateInfoURL>
+		-->
+	      </Description>
+	    </em:targetApplication>
+          </RDF:Description>
+        </RDF:li>
+
+      </RDF:Seq>
+    </em:updates>
+  </RDF:Description>
+
+  <RDF:Description about="urn:mozilla:extension:oophm-xpcom-ff35@gwt.google.com">
+    <em:updates>
+      <RDF:Seq>
+
+        <RDF:li>
+          <RDF:Description>
+            <em:version>0.0.4229M.20081202172443</em:version>
+	    <em:targetApplication>
+	      <Description>
+		<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+		<em:minVersion>3.5</em:minVersion>
+		<em:maxVersion>3.*</em:maxVersion>
+                <em:updateLink>http://google-web-toolkit.googlecode.com/svn/changes/jat/oophm-plugins-trunk/plugins/xpcom/prebuilt/oophm-xpcom-ff35.xpi</em:updateLink>
+
+		<!--
+                <em:updateInfoURL>http://www.mysite.com/updateinfo2.2.xhtml</em:updateInfoURL>
+		-->
+	      </Description>
+	    </em:targetApplication>
+          </RDF:Description>
+        </RDF:li>
+
+      </RDF:Seq>
+    </em:updates>
+  </RDF:Description>
+</RDF:RDF>
diff --git a/plugins/xpcom/version b/plugins/xpcom/version
new file mode 100644
index 0000000..5a86de9
--- /dev/null
+++ b/plugins/xpcom/version
@@ -0,0 +1 @@
+0.0.3745.20081013203929
diff --git a/plugins/xpcom/xpOOPHM.def b/plugins/xpcom/xpOOPHM.def
new file mode 100644
index 0000000..9b66173
--- /dev/null
+++ b/plugins/xpcom/xpOOPHM.def
@@ -0,0 +1,3 @@
+LIBRARY XPOOPHM
+
+EXPORTS
diff --git a/plugins/xpcom/xpOOPHM.rc b/plugins/xpcom/xpOOPHM.rc
new file mode 100644
index 0000000..e5c007c
--- /dev/null
+++ b/plugins/xpcom/xpOOPHM.rc
@@ -0,0 +1,71 @@
+#define APSTUDIO_READONLY_SYMBOLS
+#include "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 XPCOM 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 XPCOM OOPHM Plugin"
+  	  VALUE "LegalCopyright",	"Copyright © 2008 Google Inc.  Licensed under Apache 2.0 license."
+  	  VALUE "MIMEType",			"application/x-gwt-hosted-mode"
+  	  VALUE "OriginalFilename",	"xpOOPHM.dll"
+  	  VALUE "ProductName",		"GWT XPCOM 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 ""afxres.h""\r\n"
+  "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+  "\r\n"
+  "\0"
+END
+
+#endif
+
+#else
+
+#endif