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/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