ipc/glue imported verbatim from http://hg.mozilla.org/users/bturner_mozilla.com/libchromiumipc/
authorBenjamin Smedberg <benjamin@smedbergs.us>
Mon, 29 Jun 2009 14:38:29 -0400
changeset 35734 f1e7c7881534882a6fc63cb1cf093937e58c8c9e
parent 35733 919f10919769dffe2176f42bc50bcb89df49b03d
child 35735 4b0b6f1327c54aed8b6175b4ef637f201fb26df4
push id10694
push userbsmedberg@mozilla.com
push dateMon, 14 Dec 2009 15:23:10 +0000
treeherdermozilla-central@683dfdc4adf0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.2a1pre
ipc/glue imported verbatim from http://hg.mozilla.org/users/bturner_mozilla.com/libchromiumipc/
ipc/Makefile.in
ipc/chromium/Makefile.in
ipc/chromium/chromium-config.mk
ipc/glue/GeckoChildProcessHost.cpp
ipc/glue/GeckoChildProcessHost.h
ipc/glue/GeckoThread.cpp
ipc/glue/GeckoThread.h
ipc/glue/IPCMessageUtils.h
ipc/glue/Makefile.in
ipc/glue/MessagePump.cpp
ipc/glue/MessagePump.h
ipc/glue/MessageTypes.h
ipc/glue/RPCChannel.cpp
ipc/glue/RPCChannel.h
ipc/glue/ScopedXREEmbed.cpp
ipc/glue/ScopedXREEmbed.h
ipc/glue/StringUtil.cpp
--- a/ipc/Makefile.in
+++ b/ipc/Makefile.in
@@ -36,11 +36,11 @@
 
 DEPTH = ..
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-DIRS += chromium
+DIRS += chromium glue
 
 include $(topsrcdir)/config/rules.mk
--- a/ipc/chromium/Makefile.in
+++ b/ipc/chromium/Makefile.in
@@ -286,10 +286,8 @@ CSRCS += \
   $(NULL)
 endif # }
 
 endif # }
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
-
-CXXFLAGS += $(MOZ_RTTI_FLAGS_ON)
--- a/ipc/chromium/chromium-config.mk
+++ b/ipc/chromium/chromium-config.mk
@@ -39,25 +39,26 @@ ifndef INCLUDED_CONFIG_MK
 endif
 
 ifdef CHROMIUM_CONFIG_INCLUDED
 $(error Must not include chromium-config.mk twice.)
 endif
 
 CHROMIUM_CONFIG_INCLUDED = 1
 
-EXTRA_DEPS += $(topsrcdir)/ipc/chromium/chromium-defs.mk
+EXTRA_DEPS += $(topsrcdir)/ipc/chromium/chromium-config.mk
 
 DEFINES += \
   -DEXCLUDE_SKIA_DEPENDENCIES \
   -DCHROMIUM_MOZILLA_BUILD \
   $(NULL)
 
 LOCAL_INCLUDES += \
   -I$(topsrcdir)/ipc/chromium/src \
+  -I$(topsrcdir)/ipc/glue \
   $(NULL)
 
 ifeq ($(OS_ARCH),Darwin) # {
 
 OS_MACOSX = 1
 OS_POSIX = 1
 
 DEFINES += \
@@ -103,8 +104,12 @@ DEFINES += \
 OS_CXXFLAGS := $(filter-out -pedantic,$(OS_CXXFLAGS))
 
 # TODO support !GTK
 OS_CXXFLAGS += $(MOZ_GTK2_CFLAGS)
 OS_CFLAGS += $(MOZ_GTK2_CFLAGS)
 
 endif # }
 endif # }
+
+ifdef OS_POSIX
+CXXFLAGS += $(MOZ_RTTI_FLAGS_ON)
+endif
new file mode 100644
--- /dev/null
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -0,0 +1,103 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ *   Ben Turner <bent.mozilla@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "GeckoChildProcessHost.h"
+
+#include "base/command_line.h"
+#include "base/path_service.h"
+#include "chrome/common/chrome_switches.h"
+
+using mozilla::ipc::GeckoChildProcessHost;
+
+GeckoChildProcessHost::GeckoChildProcessHost(ProcessType type)
+: ChildProcessHost(type)
+{
+}
+
+bool
+GeckoChildProcessHost::Init()
+{
+  if (!CreateChannel()) {
+    return false;
+  }
+
+  FilePath exePath =
+    FilePath::FromWStringHack(CommandLine::ForCurrentProcess()->program());
+  exePath = exePath.DirName();
+
+#if defined(OS_WIN)
+  exePath = exePath.AppendASCII("mozilla-runtime.exe");
+  // no fd mapping necessary
+#elif defined(OS_POSIX)
+  exePath = exePath.AppendASCII("mozilla-runtime");
+
+  int srcChannelFd, dstChannelFd;
+  channel().GetClientFileDescriptorMapping(&srcChannelFd, &dstChannelFd);
+  mFileMap.push_back(std::pair<int,int>(srcChannelFd, dstChannelFd));
+#else
+#error Bad!
+#endif
+
+  CommandLine cmdLine(exePath.ToWStringHack());
+  cmdLine.AppendSwitchWithValue(switches::kProcessChannelID, channel_id());
+
+  base::ProcessHandle process;
+#if defined(OS_WIN)
+  base::LaunchApp(cmdLine, false, false, &process);
+#elif defined(OS_POSIX)
+  base::LaunchApp(cmdLine.argv(), mFileMap, false, &process);
+#else
+#error Bad!
+#endif
+
+  if (!process) {
+    return false;
+  }
+  SetHandle(process);
+
+  return true;
+}
+
+void
+GeckoChildProcessHost::OnMessageReceived(const IPC::Message& aMsg)
+{
+}
+
+void
+GeckoChildProcessHost::OnChannelError()
+{
+  // XXXbent Notify that the child process is gone?
+}
new file mode 100644
--- /dev/null
+++ b/ipc/glue/GeckoChildProcessHost.h
@@ -0,0 +1,76 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ *   Ben Turner <bent.mozilla@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __IPC_GLUE_GECKOCHILDPROCESSHOST_H__
+#define __IPC_GLUE_GECKOCHILDPROCESSHOST_H__
+
+#include "base/file_path.h"
+#include "base/process_util.h"
+#include "base/scoped_ptr.h"
+#include "base/waitable_event.h"
+#include "chrome/common/child_process_host.h"
+
+namespace mozilla {
+namespace ipc {
+
+class GeckoChildProcessHost : public ChildProcessHost
+{
+public:
+  GeckoChildProcessHost(ProcessType type=RENDER_PROCESS);
+
+  bool Init();
+
+  virtual void OnMessageReceived(const IPC::Message& aMsg);
+  virtual void OnChannelError();
+
+  virtual bool CanShutdown() { return true; }
+
+protected:
+
+  FilePath mProcessPath;
+
+#if defined(OS_POSIX)
+  base::file_handle_mapping_vector mFileMap;
+#endif
+
+private:
+  DISALLOW_EVIL_CONSTRUCTORS(GeckoChildProcessHost);
+};
+
+} /* namespace ipc */
+} /* namespace mozilla */
+
+#endif /* __IPC_GLUE_GECKOCHILDPROCESSHOST_H__ */
new file mode 100644
--- /dev/null
+++ b/ipc/glue/GeckoThread.cpp
@@ -0,0 +1,162 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Plugin App.
+ *
+ * The Initial Developer of the Original Code is
+ *   Ben Turner <bent.mozilla@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "mozilla/ipc/GeckoThread.h"
+
+#include "chrome/common/notification_service.h"
+
+#include "nsXPCOM.h"
+
+#if defined(OS_WIN)
+#include <objbase.h>
+#endif
+
+using mozilla::ipc::GeckoThread;
+using mozilla::ipc::BrowserProcessSubThread;
+
+void
+GeckoThread::OnControlMessageReceived(const IPC::Message& aMessage) {
+  /*
+  IPC_BEGIN_MESSAGE_MAP(GeckoThread, aMessage)
+  IPC_END_MESSAGE_MAP()
+  */
+}
+
+void
+GeckoThread::Init()
+{
+  ChildThread::Init();
+
+  // Certain plugins, such as flash, steal the unhandled exception filter
+  // thus we never get crash reports when they fault. This call fixes it.
+  message_loop()->set_exception_restoration(true);
+
+  NS_LogInit();
+  mXREEmbed.Start();
+}
+
+void
+GeckoThread::CleanUp()
+{
+  mXREEmbed.Stop();
+  NS_LogTerm();
+
+  // Maybe kill process?
+
+  // Call this last according to chrome source comments.
+  ChildThread::CleanUp();
+}
+
+//
+// BrowserProcessSubThread
+//
+
+// Friendly names for the well-known threads.
+static const char* kBrowserThreadNames[BrowserProcessSubThread::ID_COUNT] = {
+  "Gecko_IOThread",  // IO
+//  "Chrome_FileThread",  // FILE
+//  "Chrome_DBThread",  // DB
+//  "Chrome_HistoryThread",  // HISTORY
+#if defined(OS_LINUX)
+  "Gecko_Background_X11Thread",  // BACKGROUND_X11
+#endif
+};
+
+Lock BrowserProcessSubThread::sLock;
+BrowserProcessSubThread* BrowserProcessSubThread::sBrowserThreads[ID_COUNT] = {
+  NULL,  // IO
+//  NULL,  // FILE
+//  NULL,  // DB
+//  NULL,  // HISTORY
+#if defined(OS_LINUX)
+  NULL,  // BACKGROUND_X11
+#endif
+};
+
+BrowserProcessSubThread::BrowserProcessSubThread(ID aId) :
+    base::Thread(kBrowserThreadNames[aId]),
+    mIdentifier(aId),
+    mNotificationService(NULL)
+{
+    AutoLock lock(sLock);
+    DCHECK(aId >= 0 && aId < ID_COUNT);
+    DCHECK(sBrowserThreads[aId] == NULL);
+    sBrowserThreads[aId] = this;
+}
+
+BrowserProcessSubThread::~BrowserProcessSubThread()
+{
+    Stop();
+    {AutoLock lock(sLock);
+        sBrowserThreads[mIdentifier] = NULL;
+    }
+
+}
+
+void
+BrowserProcessSubThread::Init()
+{
+#if defined(OS_WIN)
+  // Initializes the COM library on the current thread.
+  CoInitialize(NULL);
+#endif
+  mNotificationService = new NotificationService();
+}
+
+void
+BrowserProcessSubThread::CleanUp()
+{
+  delete mNotificationService;
+  mNotificationService = NULL;
+
+#if defined(OS_WIN)
+  // Closes the COM library on the current thread. CoInitialize must
+  // be balanced by a corresponding call to CoUninitialize.
+  CoUninitialize();
+#endif
+}
+
+// static
+MessageLoop*
+BrowserProcessSubThread::GetMessageLoop(ID aId) {
+  AutoLock lock(sLock);
+  DCHECK(aId >= 0 && aId < ID_COUNT);
+
+  if (sBrowserThreads[aId])
+    return sBrowserThreads[aId]->message_loop();
+
+  return NULL;
+}
new file mode 100644
--- /dev/null
+++ b/ipc/glue/GeckoThread.h
@@ -0,0 +1,127 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Plugin App.
+ *
+ * The Initial Developer of the Original Code is
+ *   Ben Turner <bent.mozilla@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __IPC_GLUE_GECKOTHREAD_H__
+#define __IPC_GLUE_GECKOTHREAD_H__
+
+#include "base/thread.h"
+#include "base/lock.h"
+
+#include "chrome/common/child_thread.h"
+
+#include "mozilla/ipc/ScopedXREEmbed.h"
+
+class NotificationService;
+
+namespace mozilla {
+namespace ipc {
+
+class GeckoThread : public ChildThread
+{
+public:
+  GeckoThread()
+  : ChildThread(base::Thread::Options(MessageLoop::TYPE_MOZILLA_CHILD, 0))
+  { }
+
+protected:
+  virtual void OnControlMessageReceived(const IPC::Message& aMessage);
+
+  // Thread implementation:
+  virtual void Init();
+  virtual void CleanUp();
+
+  ScopedXREEmbed mXREEmbed;
+
+  DISALLOW_EVIL_CONSTRUCTORS(GeckoThread);
+};
+
+// Copied from browser_process_impl.cc, modified slightly.
+class BrowserProcessSubThread : public base::Thread
+{
+public:
+  // An enumeration of the well-known threads.
+  enum ID {
+      IO,
+      //FILE,
+      //DB,
+      //HISTORY,
+#if defined(OS_LINUX)
+      // This thread has a second connection to the X server and is used
+      // to process UI requests when routing the request to the UI
+      // thread would risk deadlock.
+      BACKGROUND_X11,
+#endif
+
+      // This identifier does not represent a thread.  Instead it counts
+      // the number of well-known threads.  Insert new well-known
+      // threads before this identifier.
+      ID_COUNT
+  };
+
+  explicit BrowserProcessSubThread(ID aId);
+  ~BrowserProcessSubThread();
+
+  static MessageLoop* GetMessageLoop(ID identifier);
+
+protected:
+  virtual void Init();
+  virtual void CleanUp();
+
+private:
+  // The identifier of this thread.  Only one thread can exist with a given
+  // identifier at a given time.
+  ID mIdentifier;
+
+  NotificationService* mNotificationService;
+
+  // This lock protects |browser_threads_|.  Do not read or modify that array
+  // without holding this lock.  Do not block while holding this lock.
+
+  // FIXME/cjones: XPCOM doesn't like static vars, so can't use 
+  // mozilla::Mutex
+  static Lock sLock;
+
+  // An array of the ChromeThread objects.  This array is protected by |lock_|.
+  // The threads are not owned by this array.  Typically, the threads are owned
+  // on the UI thread by the g_browser_process object.  ChromeThreads remove
+  // themselves from this array upon destruction.
+  static BrowserProcessSubThread* sBrowserThreads[ID_COUNT];
+};
+
+} /* namespace ipc */
+} /* namespace mozilla */
+
+#endif /* __IPC_GLUE_GECKOTHREAD_H__ */
new file mode 100644
--- /dev/null
+++ b/ipc/glue/IPCMessageUtils.h
@@ -0,0 +1,246 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ *   Ben Turner <bent.mozilla@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __IPC_GLUE_IPCMESSAGEUTILS_H__
+#define __IPC_GLUE_IPCMESSAGEUTILS_H__
+
+#include "chrome/common/ipc_message_utils.h"
+
+#include "prtypes.h"
+#include "nsStringGlue.h"
+#include "nsTArray.h"
+
+// Used by chrome code, we override this here and #ifdef theirs out. See the
+// comments in chrome/common/ipc_message_utils.h for info about this enum.
+enum IPCMessageStart {
+  NPAPI_ParentToChildMsgStart = 0,
+  NPAPI_ChildToParentMsgStart,
+  NPP_ParentToChildMsgStart,
+  NPP_ChildToParentMsgStart,
+  NPObject_ParentToChildMsgStart,
+  NPObject_ChildToParentMsgStart,
+
+  IFrameEmbedding_ParentToChildMsgStart,
+  IFrameEmbedding_ChildToParentMsgStart,
+
+  LastMsgIndex
+};
+
+COMPILE_ASSERT(LastMsgIndex <= 16, need_to_update_IPC_MESSAGE_MACRO);
+
+namespace IPC {
+
+
+// FIXME/cjones: PRInt16 traits had a stack corruption bug that took
+// a long time to find.  putting these on ice until we need them
+#if 0
+
+template <>
+struct ParamTraits<PRUint8>
+{
+  typedef PRUint8 paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    aMsg->WriteBytes(&aParam, sizeof(aParam));
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    return aMsg->ReadBytes(aIter, reinterpret_cast<const char**>(aResult),
+                           sizeof(*aResult));
+  }
+
+  static void Log(const paramType& aParam, std::wstring* aLog)
+  {
+    aLog->append(StringPrintf(L"%u", aParam));
+  }
+};
+
+template <>
+struct ParamTraits<PRInt8>
+{
+  typedef PRInt8 paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    aMsg->WriteBytes(&aParam, sizeof(aParam));
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    return aMsg->ReadBytes(aIter, reinterpret_cast<const char**>(aResult),
+                           sizeof(*aResult));
+  }
+
+  static void Log(const paramType& aParam, std::wstring* aLog)
+  {
+    aLog->append(StringPrintf(L"%d", aParam));
+  }
+};
+
+template <>
+struct ParamTraits<nsACString>
+{
+  typedef nsACString paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    PRUint32 length = aParam.Length();
+    WriteParam(aMsg, length);
+    aMsg->WriteBytes(aParam.BeginReading(), length);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType& aResult)
+  {
+    PRUint32 length;
+    if (ReadParam(aMsg, aIter, &length)) {
+      const char* buf;
+      if (aMsg->ReadBytes(aIter, &buf, length)) {
+        aResult.Assign(buf, length);
+        return true;
+      }
+    }
+    return false;
+  }
+
+  static void Log(const paramType& aParam, std::wstring* aLog)
+  {
+    aLog->append(UTF8ToWide(aParam.BeginReading()));
+  }
+};
+
+template <>
+struct ParamTraits<nsAString>
+{
+  typedef nsAString paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    PRUint32 length = aParam.Length();
+    WriteParam(aMsg, length);
+    aMsg->WriteBytes(aParam.BeginReading(), length * sizeof(PRUnichar));
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType& aResult)
+  {
+    PRUint32 length;
+    if (ReadParam(aMsg, aIter, &length)) {
+      const PRUnichar* buf;
+      if (aMsg->ReadBytes(aIter, reinterpret_cast<const char**>(&buf),
+                       length * sizeof(PRUnichar))) {
+        aResult.Assign(buf, length);
+        return true;
+      }
+    }
+    return false;
+  }
+
+  static void Log(const paramType& aParam, std::wstring* aLog)
+  {
+#ifdef WCHAR_T_IS_UTF16
+    aLog->append(reinterpret_cast<const wchar_t*>(aParam.BeginReading()));
+#else
+    PRUint32 length = aParam.Length();
+    for (PRUint32 index = 0; index < length; index++) {
+      aLog->push_back(std::wstring::value_type(aParam[index]));
+    }
+#endif
+  }
+};
+
+template <typename E>
+struct ParamTraits<nsTArray<E> >
+{
+  typedef nsTArray<E> paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    PRUint32 length = aParam.Length();
+    WriteParam(aMsg, length);
+    for (PRUint32 index = 0; index < length; index++) {
+      WriteParam(aMsg, aParam[index]);
+    }
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType& aResult)
+  {
+    PRUint32 length;
+    if (!ReadParam(aMsg, aIter, &length)) {
+      return false;
+    }
+
+    // Check to make sure the message is valid before requesting a huge chunk
+    // of memory.
+    if (aMsg->IteratorHasRoomFor(*aIter, length * sizeof(E)) &&
+        aResult.SetCapacity(length)) {
+      for (PRUint32 index = 0; index < length; index++) {
+        if (!ReadParam(aMsg, aIter, &aResult[index])) {
+          return false;
+        }
+      }
+    }
+    else {
+      // Push elements individually.
+      aResult.Clear();
+      E element;
+      for (PRUint32 index = 0; index < length; index++) {
+        if (!ReadParam(aMsg, aIter, &element) ||
+            !aResult.AppendElement(element)) {
+          return false;
+        }
+      }
+    }
+
+    return true;
+  }
+
+  static void Log(const paramType& aParam, std::wstring* aLog)
+  {
+    for (PRUint32 index = 0; index < aParam.Length(); index++) {
+      if (index) {
+        aLog->append(L" ");
+      }
+      LogParam(aParam[index], aLog);
+    }
+  }
+};
+
+#endif
+
+} /* namespace IPC */
+
+#endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */
new file mode 100644
--- /dev/null
+++ b/ipc/glue/Makefile.in
@@ -0,0 +1,87 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+#   Ben Turner <bent.mozilla@gmail.com>.
+# Portions created by the Initial Developer are Copyright (C) 2009
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipc
+LIBRARY_NAME = mozipc_s
+FORCE_STATIC_LIB = 1
+LIBXUL_LIBRARY = 1
+
+EXPORTS_NAMESPACES = IPC mozilla/ipc
+
+EXPORTS_IPC =					\
+  IPCMessageUtils.h 				\
+  $(NULL)
+
+# FIXME/cjones: "ChromeThread" is a misnomer
+EXPORTS_mozilla/ipc =				\
+  GeckoChildProcessHost.h			\
+  GeckoThread.h 				\
+  MessageTypes.h 				\
+  RPCChannel.h					\
+  ScopedXREEmbed.h				\
+  $(NULL)
+
+ENABLE_CXX_EXCEPTIONS = 1
+DEFINES += -DNO_NSPR_10_SUPPORT=1
+
+REQUIRES += \
+  string \
+  widget \
+  xpcom \
+  xulapp \
+  $(NULL)
+
+CPPSRCS += \
+  GeckoChildProcessHost.cpp \
+  GeckoThread.cpp \
+  MessagePump.cpp \
+  RPCChannel.cpp \
+  ScopedXREEmbed.cpp \
+  StringUtil.cpp \
+  $(NULL)
+
+#  ChromeThread.cpp \
+
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/ipc/glue/MessagePump.cpp
@@ -0,0 +1,235 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ *   Ben Turner <bent.mozilla@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "MessagePump.h"
+
+#include "nsIAppShell.h"
+#include "nsIThread.h"
+#include "nsIThreadInternal.h"
+
+#include "nsCOMPtr.h"
+#include "nsServiceManagerUtils.h"
+#include "nsStringGlue.h"
+#include "nsThreadUtils.h"
+#include "nsWidgetsCID.h"
+#include "prthread.h"
+
+#include "base/logging.h"
+#include "base/scoped_nsautorelease_pool.h"
+
+using mozilla::ipc::MessagePump;
+using mozilla::ipc::MessagePumpForChildProcess;
+
+static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
+
+namespace mozilla {
+namespace ipc {
+
+class UIThreadObserver : public nsIThreadObserver
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSITHREADOBSERVER
+
+  UIThreadObserver(MessagePump& aPump,
+                   nsIThreadObserver* aRealObserver)
+  : mPump(aPump),
+    mRealObserver(aRealObserver),
+    mPRThread(PR_GetCurrentThread())
+  {
+    NS_ASSERTION(aRealObserver, "This should never be null!");
+  }
+
+private:
+  MessagePump& mPump;
+  nsIThreadObserver* mRealObserver;
+  PRThread* mPRThread;
+};
+
+} /* namespace ipc */
+} /* namespace mozilla */
+
+using mozilla::ipc::UIThreadObserver;
+
+NS_IMETHODIMP_(nsrefcnt)
+UIThreadObserver::AddRef()
+{
+  return 2;
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+UIThreadObserver::Release()
+{
+  return 1;
+}
+
+NS_IMPL_QUERY_INTERFACE1(UIThreadObserver, nsIThreadObserver)
+
+NS_IMETHODIMP
+UIThreadObserver::OnDispatchedEvent(nsIThreadInternal* aThread)
+{
+  // XXXbent See if we can figure out some faster way of doing this. On posix
+  // the Signal() call grabs a lock and on windows it calls SetEvent. Seems
+  // like a good idea to avoid calling Signal if we're on the main thead.
+  if (PR_GetCurrentThread() != mPRThread) {
+    mPump.event_.Signal();
+  }
+  return mRealObserver->OnDispatchedEvent(aThread);
+}
+
+NS_IMETHODIMP
+UIThreadObserver::OnProcessNextEvent(nsIThreadInternal* aThread,
+                                     PRBool aMayWait,
+                                     PRUint32 aRecursionDepth)
+{
+  return mRealObserver->OnProcessNextEvent(aThread, aMayWait, aRecursionDepth);
+}
+
+NS_IMETHODIMP
+UIThreadObserver::AfterProcessNextEvent(nsIThreadInternal* aThread,
+                                        PRUint32 aRecursionDepth)
+{
+  return mRealObserver->AfterProcessNextEvent(aThread, aRecursionDepth);
+}
+
+void
+MessagePump::Run(MessagePump::Delegate* aDelegate)
+{
+  NS_ASSERTION(keep_running_, "Quit must have been called outside of Run!");
+
+  nsCOMPtr<nsIThread> thread(do_GetCurrentThread());
+  NS_ASSERTION(thread, "This should never be null!");
+
+  nsCOMPtr<nsIThreadInternal> threadInternal(do_QueryInterface(thread));
+  NS_ASSERTION(threadInternal, "QI failed?!");
+
+  nsCOMPtr<nsIThreadObserver> realObserver;
+  threadInternal->GetObserver(getter_AddRefs(realObserver));
+  NS_ASSERTION(realObserver, "This should never be null!");
+
+  UIThreadObserver observer(*this, realObserver);
+  threadInternal->SetObserver(&observer);
+
+#ifdef DEBUG
+  {
+    nsCOMPtr<nsIAppShell> appShell(do_QueryInterface(realObserver));
+    NS_ASSERTION(appShell, "Should be the app shell!");
+  }
+#endif
+
+
+  for (;;) {
+    // XXXbent This looks fishy... Maybe have one that calls Recycle each time
+    // through the loop? Copied straight from message_pump_default.
+    base::ScopedNSAutoreleasePool autorelease_pool;
+
+    bool did_work = NS_ProcessNextEvent(thread, PR_FALSE) ? true : false;
+    if (!keep_running_)
+      break;
+
+    did_work |= aDelegate->DoWork();
+    if (!keep_running_)
+      break;
+
+    did_work |= aDelegate->DoDelayedWork(&delayed_work_time_);
+    if (!keep_running_)
+      break;
+
+    if (did_work)
+      continue;
+
+    did_work = aDelegate->DoIdleWork();
+    if (!keep_running_)
+      break;
+
+    if (did_work)
+      continue;
+
+    if (delayed_work_time_.is_null()) {
+      event_.Wait();
+    } else {
+      base::TimeDelta delay = delayed_work_time_ - base::Time::Now();
+      if (delay > base::TimeDelta()) {
+        event_.TimedWait(delay);
+      } else {
+        // It looks like delayed_work_time_ indicates a time in the past, so we
+        // need to call DoDelayedWork now.
+        delayed_work_time_ = base::Time();
+      }
+    }
+    // Since event_ is auto-reset, we don't need to do anything special here
+    // other than service each delegate method.
+  }
+
+  threadInternal->SetObserver(realObserver);
+
+  keep_running_ = true;
+}
+
+#ifdef DEBUG
+namespace {
+MessagePump::Delegate* gFirstDelegate = nsnull;
+}
+#endif
+
+void
+MessagePumpForChildProcess::Run(MessagePump::Delegate* aDelegate)
+{
+  if (mFirstRun) {
+#ifdef DEBUG
+    NS_ASSERTION(aDelegate && gFirstDelegate == nsnull, "Huh?!");
+    gFirstDelegate = aDelegate;
+#endif
+    mFirstRun = false;
+    nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
+    NS_WARN_IF_FALSE(appShell, "Failed to get app shell?!");
+    if (appShell) {
+      nsresult rv = appShell->Run();
+      if (NS_FAILED(rv)) {
+        NS_WARNING("Failed to run app shell?!");
+      }
+    }
+#ifdef DEBUG
+    NS_ASSERTION(aDelegate && aDelegate == gFirstDelegate, "Huh?!");
+    gFirstDelegate = nsnull;
+#endif
+    return;
+  }
+#ifdef DEBUG
+  NS_ASSERTION(aDelegate && aDelegate == gFirstDelegate, "Huh?!");
+#endif
+  mozilla::ipc::MessagePump::Run(aDelegate);
+}
new file mode 100644
--- /dev/null
+++ b/ipc/glue/MessagePump.h
@@ -0,0 +1,69 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ *   Ben Turner <bent.mozilla@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __IPC_GLUE_MESSAGEPUMP_H__
+#define __IPC_GLUE_MESSAGEPUMP_H__
+
+#include "base/message_pump_default.h"
+
+namespace mozilla {
+namespace ipc {
+
+class MessagePump : public base::MessagePumpDefault
+{
+public:
+  friend class UIThreadObserver;
+
+  virtual void Run(base::MessagePump::Delegate* aDelegate);
+};
+
+class MessagePumpForChildProcess : public MessagePump
+{
+public:
+  MessagePumpForChildProcess()
+  : mFirstRun(true)
+  { }
+
+  virtual void Run(base::MessagePump::Delegate* aDelegate);
+
+private:
+  bool mFirstRun;
+};
+
+} /* namespace ipc */
+} /* namespace mozilla */
+
+#endif /* __IPC_GLUE_MESSAGEPUMP_H__ */
new file mode 100644
--- /dev/null
+++ b/ipc/glue/MessageTypes.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: sw=4 ts=4 et :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Plugin App.
+ *
+ * The Initial Developer of the Original Code is
+ *   Chris Jones <jones.chris.g@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_ipc_MessageTypes_h
+#define mozilla_ipc_MessageTypes_h 1
+
+// FIXME/cjones: maybe not the best basic types in the long run.  what else?
+#include <string>
+#include <vector>
+
+namespace mozilla {
+namespace ipc {
+
+typedef std::string String;
+typedef std::vector<String> StringArray;
+
+} // namespace ipc
+} // namespace mozilla
+
+#endif // ifndef mozilla_ipc_MessageTypes_h
new file mode 100644
--- /dev/null
+++ b/ipc/glue/RPCChannel.cpp
@@ -0,0 +1,231 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: sw=4 ts=4 et :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Plugin App.
+ *
+ * The Initial Developer of the Original Code is
+ *   Chris Jones <jones.chris.g@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "mozilla/ipc/GeckoThread.h"
+#include "mozilla/ipc/RPCChannel.h"
+
+#include "nsDebug.h"
+
+using mozilla::MutexAutoLock;
+
+template<>
+struct RunnableMethodTraits<mozilla::ipc::RPCChannel>
+{
+    static void RetainCallee(mozilla::ipc::RPCChannel* obj) { }
+    static void ReleaseCallee(mozilla::ipc::RPCChannel* obj) { }
+};
+
+namespace mozilla {
+namespace ipc {
+
+
+bool
+RPCChannel::Open(Transport* aTransport, MessageLoop* aIOLoop)
+{
+    NS_PRECONDITION(!mTransport, "Open() called > once");
+    NS_PRECONDITION(aTransport, "need transport layer");
+
+    // FIXME need to check for valid channel
+
+    mTransport = aTransport;
+    mTransport->set_listener(this);
+
+    // FIXME do away with this
+    bool needOpen = true;
+    if(!aIOLoop) {
+        needOpen = false;
+        aIOLoop = BrowserProcessSubThread
+                  ::GetMessageLoop(BrowserProcessSubThread::IO);
+    }
+
+    mIOLoop = aIOLoop;
+    mWorkerLoop = MessageLoop::current();
+
+    NS_ASSERTION(mIOLoop, "need an IO loop");
+    NS_ASSERTION(mWorkerLoop, "need a worker loop");
+
+    if (needOpen) {
+        mIOLoop->PostTask(FROM_HERE, 
+                          NewRunnableMethod(this,
+                                            &RPCChannel::OnChannelOpened));
+    }
+
+    return true;
+}
+
+void
+RPCChannel::Close()
+{
+    // FIXME impl
+
+    mChannelState = ChannelClosed;
+}
+
+bool
+RPCChannel::Call(Message* msg, Message* reply)
+{
+    mMutex.Lock();
+
+    mPending.push(*msg);
+    mIOLoop->PostTask(FROM_HERE, NewRunnableMethod(this,
+                                                   &RPCChannel::SendCall,
+                                                   msg));
+    while (1) {
+        // here we're waiting for something to happen.  it may either
+        // be a reply to an outstanding message, or a recursive call
+        // from the other side
+        mCvar.Wait();
+
+        Message recvd = mPending.top();
+        mPending.pop();
+
+        if (recvd.is_reply()) {
+            // we received a reply to our most recent message.  pop this
+            // frame and return the reply
+            NS_ASSERTION(0 < mPending.size(), "invalid RPC stack");
+            mPending.pop();
+            *reply = recvd;
+
+            mMutex.Unlock();
+            return true;
+        }
+        else {
+            mMutex.Unlock();
+
+            // someone called in to us from the other side.  handle the call
+            if (!ProcessIncomingCall(recvd))
+                return false;
+
+            mMutex.Lock();
+        }
+    }
+
+    delete msg;
+
+    return true;
+}
+
+bool
+RPCChannel::ProcessIncomingCall(Message call)
+{
+   Message* reply;
+
+    switch (mListener->OnCallReceived(call, &reply)) {
+    case Listener::MsgProcessed:
+        mIOLoop->PostTask(FROM_HERE,
+                          NewRunnableMethod(this,
+                                            &RPCChannel::SendReply,
+                                            reply));
+        return true;
+
+    case Listener::MsgNotKnown:
+    case Listener::MsgNotAllowed:
+        //OnError()?
+        return false;
+
+    default:
+        NOTREACHED();
+        return false;
+    }
+}
+
+void
+RPCChannel::OnIncomingCall(Message msg)
+{
+    NS_ASSERTION(0 == mPending.size(),
+                 "woke up the worker thread when it had outstanding work!");
+    ProcessIncomingCall(msg);
+}
+
+//
+// The methods below run in the context of the IO thread, and can proxy
+// back to the methods above
+//
+
+void
+RPCChannel::OnMessageReceived(const Message& msg)
+{MutexAutoLock lock(mMutex);
+    if (0 == mPending.size()) {
+        // wake up the worker, there's work to do
+        mWorkerLoop->PostTask(FROM_HERE,
+                              NewRunnableMethod(this,
+                                                &RPCChannel::OnIncomingCall,
+                                                msg));
+    }
+    else {
+        // let the worker know something new has happened
+        mPending.push(msg);
+        mCvar.Notify();
+    }
+}
+
+void
+RPCChannel::OnChannelConnected(int peer_pid)
+{
+    mChannelState = ChannelConnected;
+}
+
+void
+RPCChannel::OnChannelError()
+{
+    // FIXME/cjones impl
+    mChannelState = ChannelError;
+}
+
+void
+RPCChannel::OnChannelOpened()
+{
+    mChannelState = ChannelOpening;
+    /*assert*/mTransport->Connect();
+}
+
+void
+RPCChannel::SendCall(Message* aCall)
+{
+    mTransport->Send(aCall);
+}
+
+void
+RPCChannel::SendReply(Message* aReply)
+{
+    mTransport->Send(aReply);
+}
+
+
+} // namespace ipc
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/ipc/glue/RPCChannel.h
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: sw=4 ts=4 et :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Plugin App.
+ *
+ * The Initial Developer of the Original Code is
+ *   Chris Jones <jones.chris.g@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef ipc_glue_RPCChannel_h
+#define ipc_glue_RPCChannel_h 1
+
+// FIXME/cjones probably shouldn't depend on this
+#include <stack>
+
+#include "base/message_loop.h"
+#include "chrome/common/ipc_channel.h"
+
+#include "mozilla/CondVar.h"
+#include "mozilla/Mutex.h"
+
+namespace mozilla {
+namespace ipc {
+//-----------------------------------------------------------------------------
+
+class RPCChannel : public IPC::Channel::Listener
+{
+private:
+    typedef mozilla::CondVar CondVar;
+    typedef mozilla::Mutex Mutex;
+
+    enum ChannelState {
+        ChannelClosed,
+        ChannelOpening,
+        ChannelConnected,
+        ChannelError
+    };
+
+public:
+    typedef IPC::Channel Transport;
+    typedef IPC::Message Message;
+
+    class Listener
+    {
+    public:
+        enum Result {
+            // We processed the message, and it can be forgotten
+            MsgProcessed,
+            // We haven't heard of this message type
+            MsgNotKnown,
+            // We weren't in a state to receive this message
+            MsgNotAllowed
+        };
+
+        virtual ~Listener() { }
+        virtual Result OnCallReceived(const Message& aMessage,
+                                      Message** aReply) = 0;
+    };
+
+    /**
+     * Convert the asynchronous channel |aChannel| into a channel with
+     * RPC semantics.  Received messages are passed down to
+     * |aListener|.
+     *
+     * FIXME do away with |aMode|
+     */
+    RPCChannel(Listener* aListener) :
+        mTransport(0),
+        mListener(aListener),
+        mChannelState(ChannelClosed),
+        mMutex("mozilla.ipc.RPCChannel.mMutex"),
+        mCvar(mMutex, "mozilla.ipc.RPCChannel.mCvar")
+    {
+    }
+
+    virtual ~RPCChannel()
+    {
+        if (mTransport)
+            Close();
+        mTransport = 0;
+    }
+
+    // Open  from the perspective of the RPC layer; the transport
+    // should already be connected, or ready to connect.
+    bool Open(Transport* aTransport, MessageLoop* aIOLoop=0);
+    
+    // Close from the perspective of the RPC layer; leaves the
+    // underlying transport channel open, however.
+    void Close();
+
+    // Implement the IPC::Channel::Listener interface
+    virtual void OnMessageReceived(const Message& msg);
+    virtual void OnChannelConnected(int32 peer_pid);
+    virtual void OnChannelError();
+
+    // Make an RPC to the other side of the channel
+    virtual bool Call(Message* msg, Message* reply);
+
+private:
+    // Task created when we're idle (wrt this channel), and the other 
+    // side has made an RPC to us
+    void OnIncomingCall(Message msg);
+    // Process an RPC made from the other side to here
+    bool ProcessIncomingCall(Message msg);
+
+    void OnChannelOpened();
+    void SendCall(Message* aCall);
+    void SendReply(Message* aReply);
+
+    Transport* mTransport;
+    Listener* mListener;
+    ChannelState mChannelState;
+    MessageLoop* mIOLoop;       // thread where IO happens
+    MessageLoop* mWorkerLoop;   // thread where work is done
+    Mutex mMutex;
+    CondVar mCvar;
+    std::stack<Message> mPending;
+};
+
+
+} // namespace ipc
+} // namespace mozilla
+#endif  // ifndef ipc_glue_RPCChannel_h
new file mode 100644
--- /dev/null
+++ b/ipc/glue/ScopedXREEmbed.cpp
@@ -0,0 +1,91 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Plugin App.
+ *
+ * The Initial Developer of the Original Code is
+ *   Ben Turner <bent.mozilla@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "ScopedXREEmbed.h"
+
+#include "base/command_line.h"
+#include "base/string_util.h"
+
+#include "nsIFile.h"
+#include "nsILocalFile.h"
+
+#include "nsCOMPtr.h"
+#include "nsServiceManagerUtils.h"
+#include "nsStringGlue.h"
+#include "nsXULAppAPI.h"
+
+using mozilla::ipc::ScopedXREEmbed;
+
+ScopedXREEmbed::ScopedXREEmbed()
+: mShouldKillEmbedding(false)
+{
+}
+
+ScopedXREEmbed::~ScopedXREEmbed()
+{
+  Stop();
+}
+
+void
+ScopedXREEmbed::Start()
+{
+  std::string path = WideToUTF8(CommandLine::ForCurrentProcess()->program());
+
+  nsCOMPtr<nsILocalFile> localFile;
+  nsresult rv = XRE_GetBinaryPath(path.c_str(), getter_AddRefs(localFile));
+  NS_ENSURE_SUCCESS(rv,);
+
+  nsCOMPtr<nsIFile> parent;
+  rv = localFile->GetParent(getter_AddRefs(parent));
+  NS_ENSURE_SUCCESS(rv,);
+
+  localFile = do_QueryInterface(parent);
+  NS_ENSURE_TRUE(localFile,);
+
+  rv = XRE_InitEmbedding(localFile, localFile, nsnull, nsnull, 0);
+  NS_ENSURE_SUCCESS(rv,);
+
+  mShouldKillEmbedding = true;
+}
+
+void
+ScopedXREEmbed::Stop()
+{
+  if (mShouldKillEmbedding) {
+    XRE_TermEmbedding();
+    mShouldKillEmbedding = false;
+  }
+}
new file mode 100644
--- /dev/null
+++ b/ipc/glue/ScopedXREEmbed.h
@@ -0,0 +1,59 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Plugin App.
+ *
+ * The Initial Developer of the Original Code is
+ *   Ben Turner <bent.mozilla@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __IPC_GLUE_SCOPEDXREEMBED_H__
+#define __IPC_GLUE_SCOPEDXREEMBED_H__
+
+namespace mozilla {
+namespace ipc {
+
+class ScopedXREEmbed
+{
+public:
+  ScopedXREEmbed();
+  ~ScopedXREEmbed();
+
+  void Start();
+  void Stop();
+
+private:
+  bool mShouldKillEmbedding;
+};
+
+} /* namespace ipc */
+} /* namespace mozilla */
+
+#endif /* __IPC_GLUE_SCOPEDXREEMBED_H__ */
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/ipc/glue/StringUtil.cpp
@@ -0,0 +1,153 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ *   Chris Jones <jones.chris.g@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "base/string_util.h"
+
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/sys_string_conversions.h"
+
+#include "base/string_piece.h"
+#include "base/string_util.h"
+
+#include "build/build_config.h"
+
+// FIXME/cjones: these really only pertain to the linux sys string
+// converters.
+#ifdef WCHAR_T_IS_UTF16
+#  define ICONV_WCHAR_T_ENCODING "UTF-16"
+#else
+#  define ICONV_WCHAR_T_ENCODING "WCHAR_T"
+#endif
+
+// FIXME/cjones: BIG assumption here that std::string is a good
+// container of UTF8-encoded strings.  this is probably wrong, as its
+// API doesn't really make sense for UTF8.
+
+namespace base {
+string16 SysWideToUTF16(const std::wstring& wide);
+
+// FIXME/cjones: as its name implies, this function is a hack.
+template<typename FromType, typename ToType>
+ToType
+GhettoStringConvert(const FromType& in)
+{
+  // FIXME/cjones: assumes no non-ASCII characters in |in|
+  ToType out;
+  out.resize(in.length());
+  for (int i = 0; i < static_cast<int>(in.length()); ++i)
+      out[i] = static_cast<typename ToType::value_type>(in[i]);
+  return out;
+}
+}
+
+// Implement functions that were in the chromium ICU library, which
+// we're not taking.
+
+std::string
+WideToUTF8(const std::wstring& wide)
+{
+    return base::SysWideToUTF8(wide);
+}
+
+string16
+UTF8ToUTF16(const std::string& utf8)
+{
+    // FIXME/cjones: do proper conversion
+    return base::GhettoStringConvert<std::string, string16>(utf8);
+}
+
+std::wstring
+UTF8ToWide(const StringPiece& utf8)
+{
+    return base::SysUTF8ToWide(utf8);
+}
+
+string16
+WideToUTF16(const std::wstring& wide)
+{
+    return base::SysWideToUTF16(wide);
+}
+
+std::string
+UTF16ToUTF8(const string16& utf16)
+{
+    // FIXME/cjones: do proper conversion
+    return base::GhettoStringConvert<string16, std::string>(utf16);
+}
+
+namespace base {
+
+// FIXME/cjones: here we're entirely replacing the linux string
+// converters, and implementing the one that doesn't exist for OS X.
+
+#ifndef OS_MACOSX
+std::string SysWideToUTF8(const std::wstring& wide) {
+  // FIXME/cjones: do this with iconv
+  return GhettoStringConvert<std::wstring, std::string>(wide);
+}
+#endif
+
+string16 SysWideToUTF16(const std::wstring& wide)
+{
+#if defined(WCHAR_T_IS_UTF16)
+  return wide;
+#else
+  // FIXME/cjones: do this with iconv for linux, other for OS X
+  return GhettoStringConvert<std::wstring, string16>(wide);
+#endif
+}
+
+#ifndef OS_MACOSX
+std::wstring SysUTF8ToWide(const StringPiece& utf8) {
+  // FIXME/cjones: do this with iconv
+  return GhettoStringConvert<StringPiece, std::wstring>(utf8);
+}
+
+std::string SysWideToNativeMB(const std::wstring& wide) {
+  // TODO(evanm): we can't assume Linux is UTF-8.
+  return SysWideToUTF8(wide);
+}
+
+std::wstring SysNativeMBToWide(const StringPiece& native_mb) {
+  // TODO(evanm): we can't assume Linux is UTF-8.
+  return SysUTF8ToWide(native_mb);
+}
+#endif
+
+}  // namespace base