Transplant the initial merge electrolysis to mozilla-central, revision 8ef83d174df3, back onto the Lorentz/1.9.2 branch.
authorBenjamin Smedberg <benjamin@smedbergs.us>
Wed, 17 Mar 2010 17:36:17 -0400
changeset 33818 bc64b441ee183f96ed46af48210db78df4fca530
parent 33817 db261d9f0611a4fb00abcbf578a430367604d7d5
child 33819 42ddb7b587822760dcbe9014a81657349113b04f
push id1209
push userbsmedberg@mozilla.com
push dateWed, 07 Apr 2010 13:09:43 +0000
milestone1.9.2.3pre
Transplant the initial merge electrolysis to mozilla-central, revision 8ef83d174df3, back onto the Lorentz/1.9.2 branch.
.hgtags
browser/app/profile/firefox.js
browser/installer/package-manifest.in
config/autoconf.mk.in
configure.in
dom/Makefile.in
gfx/Makefile.in
layout/generic/nsObjectFrame.cpp
layout/generic/nsObjectFrame.h
modules/plugin/base/src/Makefile.in
modules/plugin/base/src/nsJSNPRuntime.cpp
modules/plugin/base/src/nsNPAPIPlugin.cpp
modules/plugin/base/src/nsNPAPIPlugin.h
modules/plugin/base/src/nsNPAPIPluginInstance.cpp
modules/plugin/base/src/nsNPAPIPluginInstance.h
modules/plugin/base/src/nsNPAPIPluginStreamListener.h
modules/plugin/base/src/nsPluginHost.cpp
modules/plugin/base/src/nsPluginNativeWindowWin.cpp
modules/plugin/base/src/nsPluginSafety.h
modules/plugin/base/src/nsPluginsDirWin.cpp
modules/plugin/test/mochitest/Makefile.in
modules/plugin/test/mochitest/crashing_subpage.html
modules/plugin/test/mochitest/test_crashing.html
modules/plugin/test/mochitest/test_streamNotify.html
testing/testsuite-targets.mk
toolkit/library/dlldeps-xul.cpp
toolkit/library/libxul-config.mk
toolkit/toolkit-makefiles.sh
toolkit/toolkit-tiers.mk
toolkit/xre/Makefile.in
toolkit/xre/nsAppRunner.cpp
toolkit/xre/nsConsoleWriter.cpp
toolkit/xre/nsEmbedFunctions.cpp
widget/src/windows/Makefile.in
widget/src/windows/nsAccelerometerWin.cpp
widget/src/windows/nsDeviceContextSpecWin.cpp
widget/src/windows/nsWindow.cpp
widget/src/xpwidgets/Makefile.in
widget/src/xpwidgets/nsBaseAppShell.cpp
widget/src/xpwidgets/nsBaseAppShell.h
xpcom/base/Makefile.in
xpcom/base/nsDebugImpl.cpp
xpcom/base/nsTraceRefcntImpl.cpp
xpcom/build.mk
xpcom/build/Makefile.in
xpcom/build/nsXPComInit.cpp
xpcom/build/nsXULAppAPI.h
--- a/.hgtags
+++ b/.hgtags
@@ -27,17 +27,27 @@ 0000000000000000000000000000000000000000
 0cd41f5990807fb6ab52cb59ba3c8e8247281045 GECKO_1_9_1_BASE
 8df5a90281cd4d75835e4b7696da200555eed15f GECKO_1_9_1_BASE
 8a601ed6bc4c7b3d1e35aa9e81f257512d984bd5 FENNEC_A2
 d7d64f68423b68a671f623f123e90057ebc49dac UPDATE_PACKAGING_R7
 fb32f6e1859c07846a01b4478a7b1678019e0b45 UPDATE_PACKAGING_R7
 f817a4378f32b1ad0a7c4b5a9949586dba816da5 FENNEC_M11
 5c1e7c779b6edc8ff912001990edc579f80597f4 FENNEC_B1
 fe9cc55b8db7f56f7e68a246acba363743854979 UPDATE_PACKAGING_R8
+6fd4bb500d425c406c1b52f66e5b195b20ae5e0a chromium-import-r15462
+6fd4bb500d425c406c1b52f66e5b195b20ae5e0a chromium-import-latest
 376b78fc72230aaf2ca4e279a8f4ef1efd4a1d9f GECKO_1_9_2_BASE
+941ad9d7d079246481f365c3cfbfc75a5bbefc94 last-mozilla-central
+2bae3bbf866e7de2a4b2377e7c2f52cc9ac14a22 last-mozilla-central
+2bae3bbf866e7de2a4b2377e7c2f52cc9ac14a22 last-mozilla-central
+65c1582465efe99899189519fccaf7b2826fcb2e last-mozilla-central
+65c1582465efe99899189519fccaf7b2826fcb2e last-mozilla-central
+27937722da69ad0e8fd140a00671413068226a5b last-mozilla-central
+27937722da69ad0e8fd140a00671413068226a5b last-mozilla-central
+a732c6d3c078f80635255c78bfaadffa5828a8a5 last-mozilla-central
 f029575f82e4303241c14630c80a8fc05a997ac7 UPDATE_PACKAGING_R9
 f029575f82e4303241c14630c80a8fc05a997ac7 UPDATE_PACKAGING_R10
 cc96a47d605c79215e25adb7aed5b8010e4ec512 FIREFOX_3_6b1_RELEASE
 c60105da01a09ff3b902744879a58247f5717029 FIREFOX_3_6b1_RELEASE
 cc96a47d605c79215e25adb7aed5b8010e4ec512 FIREFOX_3_6b1_BUILD1
 c60105da01a09ff3b902744879a58247f5717029 FIREFOX_3_6b1_BUILD1
 3596945fe21ef9974367519ec72d872e4435041f FENNEC_1_0_BUILD1
 3596945fe21ef9974367519ec72d872e4435041f FENNEC_1_0_RELEASE
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -904,15 +904,17 @@ pref("browser.sessionstore.interval", 60
 
 // Whether to use a panel that looks like an OS X sheet for customization
 #ifdef XP_MACOSX
 pref("toolbar.customization.usesheet", true);
 #else
 pref("toolbar.customization.usesheet", false);
 #endif
 
+pref("dom.ipc.plugins.enabled", false);
+
 #ifdef XP_WIN
 #ifndef WINCE
 pref("browser.taskbar.previews.enable", false);
 pref("browser.taskbar.previews.max", 20);
 pref("browser.taskbar.previews.cachetime", 20);
 #endif
 #endif
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -49,16 +49,19 @@
 @BINPATH@/@DLL_PREFIX@plds4@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@xpcom@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@
 #ifdef XP_MACOSX
 @BINPATH@/XUL
 #else
 @BINPATH@/@DLL_PREFIX@xul@DLL_SUFFIX@
 #endif
+#ifdef MOZ_IPC
+@BINPATH@/mozilla-runtime@BIN_SUFFIX@
+#endif
 #ifdef WINCE
 @BINPATH@/mozce_shunt.dll
 #elifdef XP_WIN32
 #ifndef MOZ_MEMORY
 @BINPATH@/Microsoft.VC80.CRT.manifest
 @BINPATH@/msvcm80.dll
 @BINPATH@/msvcp80.dll
 @BINPATH@/msvcr80.dll
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -101,16 +101,18 @@ MOZ_DEBUG_ENABLE_DEFS		= @MOZ_DEBUG_ENAB
 MOZ_DEBUG_DISABLE_DEFS	= @MOZ_DEBUG_DISABLE_DEFS@
 MOZ_DEBUG_FLAGS	= @MOZ_DEBUG_FLAGS@
 MOZ_DEBUG_LDFLAGS=@MOZ_DEBUG_LDFLAGS@
 MOZ_DBGRINFO_MODULES	= @MOZ_DBGRINFO_MODULES@
 MOZ_EXTENSIONS  = @MOZ_EXTENSIONS@
 MOZ_IMG_DECODERS= @MOZ_IMG_DECODERS@
 MOZ_IMG_ENCODERS= @MOZ_IMG_ENCODERS@
 MOZ_JSDEBUGGER  = @MOZ_JSDEBUGGER@
+MOZ_IPC         = @MOZ_IPC@
+MOZ_IPDL_TESTS  = @MOZ_IPDL_TESTS@
 MOZ_PERF_METRICS = @MOZ_PERF_METRICS@
 MOZ_LEAKY	= @MOZ_LEAKY@
 MOZ_MEMORY      = @MOZ_MEMORY@
 MOZ_JPROF       = @MOZ_JPROF@
 MOZ_SHARK       = @MOZ_SHARK@
 MOZ_CALLGRIND   = @MOZ_CALLGRIND@
 MOZ_VTUNE       = @MOZ_VTUNE@
 MOZ_TRACEVIS    = @MOZ_TRACEVIS@
--- a/configure.in
+++ b/configure.in
@@ -456,21 +456,17 @@ fi
 
 dnl Special win32 checks
 dnl ========================================================
 case "$target" in
 *-wince)
     WINVER=500
     ;;
 *)
-    if test -n "$GNU_CC"; then  
-        WINVER=501
-    else    
-        WINVER=500
-    fi
+    WINVER=502
     ;;
 esac
 
 dnl Target the Windows 7 SDK by default
 WINSDK_TARGETVER=601
 
 MOZ_ARG_WITH_STRING(windows-version,
 [  --with-windows-version=WINSDK_TARGETVER
@@ -4174,17 +4170,17 @@ dnl are defined in build/autoconf/altopt
 
 dnl ========================================================
 dnl =
 dnl = Check for external package dependencies
 dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(External Packages)
 
-MOZ_ENABLE_LIBXUL=
+MOZ_ENABLE_LIBXUL=1
 
 MOZ_ARG_WITH_STRING(libxul-sdk,
 [  --with-libxul-sdk=PFX   Use the libXUL SDK at <PFX>],
   LIBXUL_SDK_DIR=$withval)
 
 if test "$LIBXUL_SDK_DIR" = "yes"; then
     AC_MSG_ERROR([--with-libxul-sdk must specify a path])
 elif test -n "$LIBXUL_SDK_DIR" -a "$LIBXUL_SDK_DIR" != "no"; then
@@ -5339,16 +5335,61 @@ dnl = JS Debugger XPCOM component (js/js
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(jsd,
 [  --disable-jsd           Disable JavaScript debug library],
     MOZ_JSDEBUGGER=,
     MOZ_JSDEBUGGER=1)
 
 
 dnl ========================================================
+dnl = Disable IPC support for tabs and plugins
+dnl ========================================================
+MOZ_IPC=1
+
+case "${target}" in
+*-apple-darwin*)
+    MOZ_IPC=
+    ;;
+*wince)
+    MOZ_IPC=
+    ;;
+esac
+
+MOZ_ARG_DISABLE_BOOL(ipc,
+[  --disable-ipc           Disable IPC supports for tabs and plugins],
+    MOZ_IPC=,
+    MOZ_IPC=1)
+
+if test -n "$MOZ_IPC"; then
+    AC_DEFINE(MOZ_IPC)
+fi
+
+AC_SUBST(MOZ_IPC)
+
+dnl ========================================================
+dnl = Enable IPDL's "expensive" unit tests
+dnl ========================================================
+MOZ_IPDL_TESTS=
+
+MOZ_ARG_ENABLE_BOOL(ipdl-tests,
+[  --enable-ipdl-tests     Enable expensive IPDL tests],
+    MOZ_IPDL_TESTS=1,
+    MOZ_IPDL_TESTS=)
+
+if test -z "$MOZ_IPC" -a -n "$MOZ_IPDL_TESTS"; then
+    AC_MSG_ERROR([--enable-ipdl-tests requires --enable-ipc])
+fi
+
+if test -n "$MOZ_IPDL_TESTS"; then
+    AC_DEFINE(MOZ_IPDL_TESTS)
+fi
+
+AC_SUBST(MOZ_IPDL_TESTS)
+
+dnl ========================================================
 dnl = Disable plugin support
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(plugins,
 [  --disable-plugins       Disable plugins support],
     MOZ_PLUGINS=,
     MOZ_PLUGINS=1)
 
 dnl ========================================================
@@ -7373,16 +7414,17 @@ if test "$ac_nscap_nonconst_opeq_bug" = 
     AC_DEFINE(NSCAP_DONT_PROVIDE_NONCONST_OPEQ)
 fi
 fi # SKIP_COMPILER_CHECKS
 
 dnl ========================================================
 dnl C++ rtti
 dnl Should be smarter and check that the compiler does indeed have rtti
 dnl ========================================================
+
 MOZ_ARG_ENABLE_BOOL(cpp-rtti,
 [  --enable-cpp-rtti       Enable C++ RTTI ],
 [ _MOZ_USE_RTTI=1 ],
 [ _MOZ_USE_RTTI= ])
 
 if test "$_MOZ_USE_RTTI"; then
    _MOZ_RTTI_FLAGS=$_MOZ_RTTI_FLAGS_ON
 else
@@ -7481,34 +7523,33 @@ dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(Static build options)
 
 MOZ_ARG_ENABLE_BOOL(static,
 [  --enable-static         Enable building of internal static libs],
     BUILD_STATIC_LIBS=1,
     BUILD_STATIC_LIBS=)
 
-dnl Disable libxul in debug builds, but not for xulrunner.
-if test -n "$MOZ_DEBUG" -a "$MOZ_BUILD_APP" != "xulrunner"; then
-   MOZ_ENABLE_LIBXUL=
-fi
-
 MOZ_ARG_ENABLE_BOOL(libxul,
 [  --enable-libxul         Enable building of libxul],
     MOZ_ENABLE_LIBXUL=1,
     MOZ_ENABLE_LIBXUL=)
 
 if test -n "$MOZ_STATIC_BUILD_UNSUPPORTED" -a -n "$BUILD_STATIC_LIBS"; then
 	AC_MSG_ERROR([--enable-static is not supported for building $MOZ_APP_NAME. You probably want --enable-libxul.])
 fi
 
 if test -n "$MOZ_ENABLE_LIBXUL" -a -n "$BUILD_STATIC_LIBS"; then
 	AC_MSG_ERROR([--enable-libxul is not compatible with --enable-static])
 fi
 
+if test -n "$MOZ_IPC" -a -z "$MOZ_ENABLE_LIBXUL"; then
+    AC_MSG_ERROR([--enable-ipc requires --enable-libxul])
+fi
+
 AC_SUBST(LIBXUL_LIBS)
 
 if test -n "$MOZ_ENABLE_LIBXUL"; then
     XPCOM_LIBS="$LIBXUL_LIBS"
     AC_DEFINE(MOZ_ENABLE_LIBXUL)
 else
     if test -n "$BUILD_STATIC_LIBS"; then
         AC_DEFINE(MOZ_STATIC_BUILD)
--- a/dom/Makefile.in
+++ b/dom/Makefile.in
@@ -74,16 +74,17 @@ ifdef MOZ_SMIL
 DIRS += interfaces/smil
 endif
 
 DIRS += \
   public/coreEvents \
   base \
   src \
   locales \
+  plugins \
   $(NULL)
 
 ifdef ENABLE_TESTS
 DIRS += tests
 endif
 
 include $(topsrcdir)/config/rules.mk
 
--- a/gfx/Makefile.in
+++ b/gfx/Makefile.in
@@ -45,15 +45,19 @@ include $(DEPTH)/config/autoconf.mk
 MODULE		= gfx
 
 ifdef MOZ_TREE_CAIRO
 DIRS		= cairo
 endif
 
 DIRS		+= thebes public idl src qcms
 
+ifdef MOZ_IPC
+DIRS		+= ipc
+endif
+
 ifdef ENABLE_TESTS
 ifndef MOZ_ENABLE_LIBXUL
 TOOL_DIRS	+= tests
 endif
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -208,16 +208,19 @@ enum { XKeyPress = KeyPress };
 
 #ifdef MOZ_WIDGET_QT
 #include "gfxQtNativeRenderer.h"
 #endif
 
 #ifdef XP_WIN
 #include <wtypes.h>
 #include <winuser.h>
+#ifdef MOZ_IPC
+#define NS_OOPP_DOUBLEPASS_MSGID TEXT("MozDoublePassMsg")
+#endif
 #endif
 
 #ifdef CreateEvent // Thank you MS.
 #undef CreateEvent
 #endif
 
 #ifdef PR_LOGGING 
 static PRLogModuleInfo *nsObjectFrameLM = PR_NewLogModule("nsObjectFrame");
@@ -672,16 +675,20 @@ NS_IMETHODIMP
 nsObjectFrame::Init(nsIContent*      aContent,
                     nsIFrame*        aParent,
                     nsIFrame*        aPrevInFlow)
 {
   NS_PRECONDITION(aContent, "How did that happen?");
   mPreventInstantiation =
     (aContent->GetCurrentDoc()->GetDisplayDocument() != nsnull);
 
+#ifdef XP_WIN
+  mDoublePassEvent = 0;
+#endif
+
   PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
          ("Initializing nsObjectFrame %p for content %p\n", this, aContent));
 
   return nsObjectFrameSuper::Init(aContent, aParent, aPrevInFlow);
 }
 
 void
 nsObjectFrame::Destroy()
@@ -1728,16 +1735,17 @@ nsObjectFrame::PaintPlugin(nsIRenderingC
 
     if (window->type == nsPluginWindowType_Drawable) {
       // check if we need to call SetWindow with updated parameters
       PRBool doupdatewindow = PR_FALSE;
       // the offset of the DC
       nsPoint origin;
       
       gfxWindowsNativeDrawing nativeDraw(ctx, frameGfxRect);
+      PRBool doublePass = PR_FALSE;
       do {
         HDC hdc = nativeDraw.BeginNativeDrawing();
         if (!hdc)
           return;
 
         RECT dest;
         nativeDraw.TransformToNativeRect(frameGfxRect, dest);
         RECT dirty;
@@ -1790,17 +1798,36 @@ nsObjectFrame::PaintPlugin(nsIRenderingC
             inst->HandleEvent(&pluginEvent, &eventHandled);
           }
 
           inst->SetWindow(window);        
         }
 
         mInstanceOwner->Paint(dirty, hdc);
         nativeDraw.EndNativeDrawing();
-      } while (nativeDraw.ShouldRenderAgain());
+        doublePass = nativeDraw.ShouldRenderAgain();
+#ifdef MOZ_IPC
+        if (doublePass) {
+          // OOP plugin specific: let the shim know we are in the middle of a double pass
+          // render. The second pass will reuse the previous rendering without going over
+          // the wire.
+          if (!mDoublePassEvent)
+            mDoublePassEvent = ::RegisterWindowMessage(NS_OOPP_DOUBLEPASS_MSGID);
+          if (mDoublePassEvent) {
+            NPEvent pluginEvent;
+            pluginEvent.event = mDoublePassEvent;
+            pluginEvent.wParam = 0;
+            pluginEvent.lParam = 0;
+            PRBool eventHandled = PR_FALSE;
+
+            inst->HandleEvent(&pluginEvent, &eventHandled);
+          }          
+        }
+#endif
+      } while (doublePass);
 
       nativeDraw.PaintToContext();
     } else if (!(ctx->GetFlags() & gfxContext::FLAG_DESTINED_FOR_SCREEN)) {
       // Get PrintWindow dynamically since it's not present on Win2K,
       // which we still support
       typedef BOOL (WINAPI * PrintWindowPtr)
           (HWND hwnd, HDC hdcBlt, UINT nFlags);
       PrintWindowPtr printProc = nsnull;
--- a/layout/generic/nsObjectFrame.h
+++ b/layout/generic/nsObjectFrame.h
@@ -241,16 +241,19 @@ private:
   private:
     nsString mEventType;
   };
   
   nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
   nsIView*                        mInnerView;
   nsCOMPtr<nsIWidget>             mWidget;
   nsIntRect                       mWindowlessRect;
+#ifdef XP_WIN
+  PRUint32                        mDoublePassEvent;
+#endif
 
   // For assertions that make it easier to determine if a crash is due
   // to the underlying problem described in bug 136927, and to prevent
   // reentry into instantiation.
   PRBool mPreventInstantiation;
 };
 
 class nsDisplayPlugin : public nsDisplayItem {
--- a/modules/plugin/base/src/Makefile.in
+++ b/modules/plugin/base/src/Makefile.in
@@ -141,16 +141,20 @@ EXTRA_DSO_LDOPTS = \
 ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
 EXTRA_DSO_LDOPTS += $(TK_LIBS)
 endif
 
 ifndef WINCE
 ENABLE_CXX_EXCEPTIONS = 1
 endif
 
+include $(topsrcdir)/config/config.mk
+ifdef MOZ_IPC
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
+endif
 include $(topsrcdir)/config/rules.mk
 
 ifeq ($(OS_ARCH),WINNT)
 OS_LIBS		+= $(call EXPAND_LIBNAME,version)
 endif
 
 ifeq ($(OS_ARCH), OpenVMS)
 DEFINES		+= -DGENERIC_MOTIF_REDEFINES
--- a/modules/plugin/base/src/nsJSNPRuntime.cpp
+++ b/modules/plugin/base/src/nsJSNPRuntime.cpp
@@ -48,16 +48,18 @@
 #include "nsIXPConnect.h"
 #include "nsIDOMElement.h"
 #include "prmem.h"
 #include "nsIContent.h"
 
 // FIXME(bug 332648): Give me a real API please!
 #include "jscntxt.h"
 
+using namespace mozilla::plugins::parent;
+
 // Hash of JSObject wrappers that wraps JSObjects as NPObjects. There
 // will be one wrapper per JSObject per plugin instance, i.e. if two
 // plugins access the JSObject x, two wrappers for x will be
 // created. This is needed to be able to properly drop the wrappers
 // when a plugin is torn down in case there's a leak in the plugin (we
 // don't want to leak the world just because a plugin leaks an
 // NPObject).
 static PLDHashTable sJSObjWrappers;
@@ -73,16 +75,17 @@ static PRInt32 sWrapperCount;
 // The JSRuntime. Used to unroot JSObjects when no JSContext is
 // reachable.
 static JSRuntime *sJSRuntime;
 
 // The JS context stack, we use this to push a plugin's JSContext onto
 // while executing JS on the context.
 static nsIJSContextStack *sContextStack;
 
+static nsTArray<NPObject*>* sDelayedReleases;
 
 // Helper class that reports any JS exceptions that were thrown while
 // the plugin executed JS.
 
 class AutoJSExceptionReporter
 {
 public:
   AutoJSExceptionReporter(JSContext *cx)
@@ -193,27 +196,52 @@ static JSClass sNPObjectMemberClass =
     JS_PropertyStub, JS_PropertyStub,
     JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
     JS_ResolveStub, NPObjectMember_Convert,
     NPObjectMember_Finalize, nsnull, nsnull, NPObjectMember_Call,
     nsnull, nsnull, nsnull, NPObjectMember_Mark, nsnull
   };
 
 static void
+OnWrapperDestroyed();
+
+static JSBool
+DelayedReleaseGCCallback(JSContext* cx, JSGCStatus status)
+{
+  if (JSGC_END == status) {
+    if (sDelayedReleases) {
+      for (PRInt32 i = 0; i < sDelayedReleases->Length(); ++i) {
+        NPObject* obj = (*sDelayedReleases)[i];
+        if (obj)
+          _releaseobject(obj);
+        OnWrapperDestroyed();
+      }
+      delete sDelayedReleases;
+      sDelayedReleases = NULL;
+    }
+  }
+  return JS_TRUE;
+}
+
+static void
 OnWrapperCreated()
 {
   if (sWrapperCount++ == 0) {
     static const char rtsvc_id[] = "@mozilla.org/js/xpc/RuntimeService;1";
     nsCOMPtr<nsIJSRuntimeService> rtsvc(do_GetService(rtsvc_id));
     if (!rtsvc)
       return;
 
     rtsvc->GetRuntime(&sJSRuntime);
     NS_ASSERTION(sJSRuntime != nsnull, "no JSRuntime?!");
 
+    // Register our GC callback to perform delayed destruction of finalized
+    // NPObjects. Leave this callback around and don't ever unregister it.
+    rtsvc->RegisterGCCallback(DelayedReleaseGCCallback);
+
     CallGetService("@mozilla.org/js/xpc/ContextStack;1", &sContextStack);
   }
 }
 
 static void
 OnWrapperDestroyed()
 {
   NS_ASSERTION(sWrapperCount, "Whaaa, unbalanced created/destroyed calls!");
@@ -483,21 +511,24 @@ ReportExceptionIfPending(JSContext *cx)
 
   return JS_FALSE;
 }
 
 
 nsJSObjWrapper::nsJSObjWrapper(NPP npp)
   : nsJSObjWrapperKey(nsnull, npp)
 {
+  MOZ_COUNT_CTOR(nsJSObjWrapper);
   OnWrapperCreated();
 }
 
 nsJSObjWrapper::~nsJSObjWrapper()
 {
+  MOZ_COUNT_DTOR(nsJSObjWrapper);
+
   // Invalidate first, since it relies on sJSRuntime and sJSObjWrappers.
   NP_Invalidate(this);
 
   OnWrapperDestroyed();
 }
 
 // static
 NPObject *
@@ -1620,27 +1651,25 @@ NPObjWrapper_Convert(JSContext *cx, JSOb
 
   return JS_TRUE;
 }
 
 static void
 NPObjWrapper_Finalize(JSContext *cx, JSObject *obj)
 {
   NPObject *npobj = (NPObject *)::JS_GetPrivate(cx, obj);
-
   if (npobj) {
     if (sNPObjWrappers.ops) {
       PL_DHashTableOperate(&sNPObjWrappers, npobj, PL_DHASH_REMOVE);
     }
-
-    // Let go of our NPObject
-    _releaseobject(npobj);
   }
 
-  OnWrapperDestroyed();
+  if (!sDelayedReleases)
+    sDelayedReleases = new nsTArray<NPObject*>;
+  sDelayedReleases->AppendElement(npobj);
 }
 
 static JSBool
 NPObjWrapper_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
                   jsval *rval)
 {
   return CallNPMethodInternal(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv, rval,
                               PR_FALSE);
@@ -1851,16 +1880,26 @@ NPObjWrapperPluginDestroyedCallback(PLDH
     table->ops = nsnull;
 
     NPObject *npobj = entry->mNPObj;
 
     if (npobj->_class && npobj->_class->invalidate) {
       npobj->_class->invalidate(npobj);
     }
 
+#ifdef NS_BUILD_REFCNT_LOGGING
+    {
+      int32_t refCnt = npobj->referenceCount;
+      while (refCnt) {
+        --refCnt;
+        NS_LOG_RELEASE(npobj, refCnt, "BrowserNPObject");
+      }
+    }
+#endif
+
     // Force deallocation of plugin objects since the plugin they came
     // from is being torn down.
     if (npobj->_class && npobj->_class->deallocate) {
       npobj->_class->deallocate(npobj);
     } else {
       PR_Free(npobj);
     }
 
--- a/modules/plugin/base/src/nsNPAPIPlugin.cpp
+++ b/modules/plugin/base/src/nsNPAPIPlugin.cpp
@@ -31,18 +31,23 @@
  * 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 ***** */
 
+#ifdef MOZ_IPC
+#include "base/basictypes.h"
+#endif 
+
 #include "prtypes.h"
 #include "prmem.h"
+#include "prenv.h"
 #include "prclist.h"
 #include "nsAutoLock.h"
 #include "nsNPAPIPlugin.h"
 #include "nsNPAPIPluginInstance.h"
 #include "nsNPAPIPluginStreamListener.h"
 #include "nsIServiceManager.h"
 #include "nsThreadUtils.h"
 #include "nsIPrivateBrowsingService.h"
@@ -82,98 +87,39 @@
 #include <gdk/gdkx.h>
 #include "gtk2xtbin.h"
 #endif
 
 #include "nsJSNPRuntime.h"
 #include "nsIHttpAuthManager.h"
 #include "nsICookieService.h"
 
+#include "mozilla/PluginLibrary.h"
+using mozilla::PluginLibrary;
+
+#include "mozilla/PluginPRLibrary.h"
+using mozilla::PluginPRLibrary;
+
+#ifdef MOZ_IPC
+#include "mozilla/plugins/PluginModuleParent.h"
+using mozilla::plugins::PluginModuleParent;
+#endif
+
 static PRLock *sPluginThreadAsyncCallLock = nsnull;
 static PRCList sPendingAsyncCalls = PR_INIT_STATIC_CLIST(&sPendingAsyncCalls);
 
 // POST/GET stream type
 enum eNPPStreamTypeInternal {
   eNPPStreamTypeInternal_Get,
   eNPPStreamTypeInternal_Post
 };
 
 static NS_DEFINE_IID(kMemoryCID, NS_MEMORY_CID);
 
-// Static stub functions that are exported to the plugin as entry
-// points via the CALLBACKS variable.
-PR_BEGIN_EXTERN_C
-
-  static NPError NP_CALLBACK
-  _requestread(NPStream *pstream, NPByteRange *rangeList);
-
-  static NPError NP_CALLBACK
-  _geturlnotify(NPP npp, const char* relativeURL, const char* target,
-                void* notifyData);
-
-  static NPError NP_CALLBACK
-  _getvalue(NPP npp, NPNVariable variable, void *r_value);
-
-  static NPError NP_CALLBACK
-  _setvalue(NPP npp, NPPVariable variable, void *r_value);
-
-  static NPError NP_CALLBACK
-  _geturl(NPP npp, const char* relativeURL, const char* target);
-
-  static NPError NP_CALLBACK
-  _posturlnotify(NPP npp, const char* relativeURL, const char *target,
-                 uint32_t len, const char *buf, NPBool file, void* notifyData);
-
-  static NPError NP_CALLBACK
-  _posturl(NPP npp, const char* relativeURL, const char *target, uint32_t len,
-              const char *buf, NPBool file);
-
-  static NPError NP_CALLBACK
-  _newstream(NPP npp, NPMIMEType type, const char* window, NPStream** pstream);
-
-  static int32_t NP_CALLBACK
-  _write(NPP npp, NPStream *pstream, int32_t len, void *buffer);
-
-  static NPError NP_CALLBACK
-  _destroystream(NPP npp, NPStream *pstream, NPError reason);
-
-  static void NP_CALLBACK
-  _status(NPP npp, const char *message);
-
-  static void NP_CALLBACK
-  _memfree (void *ptr);
-
-  static uint32_t NP_CALLBACK
-  _memflush(uint32_t size);
-
-  static void NP_CALLBACK
-  _reloadplugins(NPBool reloadPages);
-
-  static void NP_CALLBACK
-  _invalidaterect(NPP npp, NPRect *invalidRect);
-
-  static void NP_CALLBACK
-  _invalidateregion(NPP npp, NPRegion invalidRegion);
-
-  static void NP_CALLBACK
-  _forceredraw(NPP npp);
-
-  static const char* NP_CALLBACK
-  _useragent(NPP npp);
-
-  static void* NP_CALLBACK
-  _memalloc (uint32_t size);
-
-  // Deprecated entry points for the old Java plugin.
-  static void* NP_CALLBACK /* OJI type: JRIEnv* */
-  _getJavaEnv(void);
-  static void* NP_CALLBACK /* OJI type: jref */
-  _getJavaPeer(NPP npp);
-
-PR_END_EXTERN_C
+using namespace mozilla::plugins::parent;
 
 // This function sends a notification using the observer service to any object
 // registered to listen to the "experimental-notify-plugin-call" subject.
 // Each "experimental-notify-plugin-call" notification carries with it the run
 // time value in milliseconds that the call took to execute.
 void NS_NotifyPluginCall(PRIntervalTime startTime) 
 {
   PRIntervalTime endTime = PR_IntervalNow() - startTime;
@@ -280,62 +226,58 @@ nsNPAPIPlugin::nsNPAPIPlugin(nsIPluginOl
   mShadow = aShadow;
   fLibrary = nsnull;
   fShutdownEntry = nsnull;
   memset((void*) &fCallbacks, 0, sizeof(fCallbacks));
   CheckClassInitialized();
 }
 #endif
 
-nsNPAPIPlugin::nsNPAPIPlugin(NPPluginFuncs* callbacks, PRLibrary* aLibrary,
-                             NP_PLUGINSHUTDOWN aShutdown)
+nsNPAPIPlugin::nsNPAPIPlugin(NPPluginFuncs* callbacks,
+                             PluginLibrary* aLibrary)
 {
   memset((void*) &fCallbacks, 0, sizeof(fCallbacks));
   fLibrary = nsnull;
 #ifdef OJI
   mShadow = nsnull;
 #endif
 
 #if defined(XP_WIN) || defined(XP_OS2)
   // On Windows (and Mac) we need to keep a direct reference to the
   // fCallbacks and NOT just copy the struct. See Bugzilla 85334
 
-  NP_GETENTRYPOINTS pfnGetEntryPoints =
-    (NP_GETENTRYPOINTS)PR_FindSymbol(aLibrary, "NP_GetEntryPoints");
-
-  if (!pfnGetEntryPoints)
+  NPError gepError;
+  nsresult gepResult = aLibrary->NP_GetEntryPoints(&fCallbacks, &gepError);
+  if (gepResult != NS_OK || gepError != NPERR_NO_ERROR)
     return;
 
   fCallbacks.size = sizeof(fCallbacks);
 
-  nsresult result = pfnGetEntryPoints(&fCallbacks);
-  NS_ASSERTION(result == NS_OK, "Failed to get callbacks");
-
   NS_ASSERTION(HIBYTE(fCallbacks.version) >= NP_VERSION_MAJOR,
                "callback version is less than NP version");
 
-  fShutdownEntry = (NP_PLUGINSHUTDOWN)PR_FindSymbol(aLibrary, "NP_Shutdown");
 #elif defined(XP_MACOSX)
   NPPluginFuncs np_callbacks;
   memset((void*) &np_callbacks, 0, sizeof(np_callbacks));
   np_callbacks.size = sizeof(np_callbacks);
 
-  fShutdownEntry = (NP_PLUGINSHUTDOWN)PR_FindSymbol(aLibrary, "NP_Shutdown");
-  NP_GETENTRYPOINTS pfnGetEntryPoints = (NP_GETENTRYPOINTS)PR_FindSymbol(aLibrary, "NP_GetEntryPoints");
-  NP_PLUGININIT pfnInitialize = (NP_PLUGININIT)PR_FindSymbol(aLibrary, "NP_Initialize");
-  if (!pfnGetEntryPoints || !pfnInitialize || !fShutdownEntry) {
+  if (!aLibrary->HasRequiredFunctions()) {
     NS_WARNING("Not all necessary functions exposed by plugin, it will not load.");
     return;
   }
 
   // we call NP_Initialize before getting function pointers to match
   // WebKit's behavior. They implemented this first on Mac OS X.
-  if (pfnInitialize(&(nsNPAPIPlugin::CALLBACKS)) != NPERR_NO_ERROR)
+  NPError initError;
+  nsresult initResult = aLibrary->NP_Initialize(&(nsNPAPIPlugin::CALLBACKS), &initError);
+  if (initResult != NS_OK || initError != NPERR_NO_ERROR)
     return;
-  if (pfnGetEntryPoints(&np_callbacks) != NPERR_NO_ERROR)
+  NPError gepError;
+  nsresult gepResult = aLibrary->NP_GetEntryPoints(&np_callbacks, &gepError);
+  if (gepResult != NS_OK || gepError != NPERR_NO_ERROR)
     return;
 
   fCallbacks.size = sizeof(fCallbacks);
   fCallbacks.version = np_callbacks.version;
   fCallbacks.newp = (NPP_NewProcPtr)np_callbacks.newp;
   fCallbacks.destroy = (NPP_DestroyProcPtr)np_callbacks.destroy;
   fCallbacks.setwindow = (NPP_SetWindowProcPtr)np_callbacks.setwindow;
   fCallbacks.newstream = (NPP_NewStreamProcPtr)np_callbacks.newstream;
@@ -345,115 +287,154 @@ nsNPAPIPlugin::nsNPAPIPlugin(NPPluginFun
   fCallbacks.write = (NPP_WriteProcPtr)np_callbacks.write;
   fCallbacks.print = (NPP_PrintProcPtr)np_callbacks.print;
   fCallbacks.event = (NPP_HandleEventProcPtr)np_callbacks.event;
   fCallbacks.urlnotify = (NPP_URLNotifyProcPtr)np_callbacks.urlnotify;
   fCallbacks.getvalue = (NPP_GetValueProcPtr)np_callbacks.getvalue;
   fCallbacks.setvalue = (NPP_SetValueProcPtr)np_callbacks.setvalue;
 #else // for everyone else
   memcpy((void*) &fCallbacks, (void*) callbacks, sizeof(fCallbacks));
-  fShutdownEntry = aShutdown;
 #endif
 
   fLibrary = aLibrary;
 }
 
 nsNPAPIPlugin::~nsNPAPIPlugin()
 {
   // reset the callbacks list
   memset((void*) &fCallbacks, 0, sizeof(fCallbacks));
 
 #ifdef OJI
   NS_IF_RELEASE(mShadow);
 #endif
+
+  delete fLibrary;
+  fLibrary = NULL;
 }
 
 
 #if defined(XP_MACOSX)
 void
 nsNPAPIPlugin::SetPluginRefNum(short aRefNum)
 {
   fPluginRefNum = aRefNum;
 }
 #endif
 
+namespace {
+
+#ifdef MOZ_IPC
+
+inline PRBool
+OOPPluginsEnabled()
+{
+  if (PR_GetEnv("MOZ_DISABLE_OOP_PLUGINS")) {
+    return PR_FALSE;
+  }
+
+  nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
+  if (!prefs) {
+    return PR_FALSE;
+  }
+
+  PRBool oopPluginsEnabled = PR_FALSE;
+  prefs->GetBoolPref("dom.ipc.plugins.enabled", &oopPluginsEnabled);
+
+  if (!oopPluginsEnabled) {
+    return PR_FALSE;
+  }
+
+  return PR_TRUE;
+}
+
+#endif // MOZ_IPC
+
+inline PluginLibrary*
+GetNewPluginLibrary(const char* aFilePath,
+                    PRLibrary* aLibrary)
+{
+#ifdef MOZ_IPC
+  if (aFilePath && OOPPluginsEnabled()) {
+    return PluginModuleParent::LoadModule(aFilePath);
+  }
+#endif
+  return new PluginPRLibrary(aFilePath, aLibrary);
+}
+
+} /* anonymous namespace */
+
+
 // Creates the nsNPAPIPlugin object. One nsNPAPIPlugin object exists per plugin (not instance).
 nsresult
 nsNPAPIPlugin::CreatePlugin(const char* aFilePath, PRLibrary* aLibrary,
                             nsIPlugin** aResult)
 {
   CheckClassInitialized();
 
   nsRefPtr<nsNPAPIPlugin> plugin;
 
 #if defined(XP_UNIX) && !defined(XP_MACOSX)
   NPPluginFuncs callbacks;
   memset((void*) &callbacks, 0, sizeof(callbacks));
   callbacks.size = sizeof(callbacks);
 
-  NP_PLUGINSHUTDOWN pfnShutdown =
-    (NP_PLUGINSHUTDOWN)PR_FindFunctionSymbol(aLibrary, "NP_Shutdown");
+  PluginLibrary* pluginLib = GetNewPluginLibrary(aFilePath, aLibrary);
 
   // create the new plugin handler
-  plugin =
-    new nsNPAPIPlugin(&callbacks, aLibrary, pfnShutdown);
+  plugin = new nsNPAPIPlugin(&callbacks, pluginLib);
   if (!plugin)
     return NS_ERROR_OUT_OF_MEMORY;
 
   // Do not initialize if the file path is NULL.
   if (!aFilePath) {
     *aResult = plugin.forget().get();
     return NS_OK;
   }
 
   // we must init here because the plugin may call NPN functions
   // when we call into the NP_Initialize entry point - NPN functions
   // require that mBrowserManager be set up
   plugin->Initialize();
 
-  NP_PLUGINUNIXINIT pfnInitialize =
-    (NP_PLUGINUNIXINIT)PR_FindFunctionSymbol(aLibrary, "NP_Initialize");
-
-  if (!pfnInitialize)
-    return NS_ERROR_UNEXPECTED;
-
-  if (pfnInitialize(&(nsNPAPIPlugin::CALLBACKS),&callbacks) != NS_OK)
+  NPError initError;
+  nsresult initResult = pluginLib->NP_Initialize(&(nsNPAPIPlugin::CALLBACKS), &callbacks, &initError);
+  if (initResult != NS_OK || initError != NPERR_NO_ERROR)
     return NS_ERROR_UNEXPECTED;
 
   // now copy function table back to nsNPAPIPlugin instance
   memcpy((void*) &(plugin->fCallbacks), (void*)&callbacks, sizeof(callbacks));
 #endif
 
 #ifdef XP_WIN
+  PluginLibrary* pluginLib = GetNewPluginLibrary(aFilePath, aLibrary);
+
   // Note: on Windows, we must use the fCallback because plugins may
   // change the function table. The Shockwave installer makes changes
   // in the table while running
-  plugin = new nsNPAPIPlugin(nsnull, aLibrary, nsnull);
+  plugin = new nsNPAPIPlugin(nsnull, pluginLib);
   if (!plugin)
     return NS_ERROR_OUT_OF_MEMORY;
 
   // we must init here because the plugin may call NPN functions
   // when we call into the NP_Initialize entry point - NPN functions
   // require that mBrowserManager be set up
   if (NS_FAILED(plugin->Initialize()))
     return NS_ERROR_FAILURE;
 
-  NP_PLUGININIT pfnInitialize =
-    (NP_PLUGININIT)PR_FindSymbol(aLibrary, "NP_Initialize");
-
-  if (!pfnInitialize)
-    return NS_ERROR_UNEXPECTED;
-
-  if (pfnInitialize(&(nsNPAPIPlugin::CALLBACKS)) != NS_OK)
-    return NS_ERROR_UNEXPECTED;
+  NPError initError;
+  nsresult initResult = pluginLib->NP_Initialize(&(nsNPAPIPlugin::CALLBACKS), &initError);
+  if (initResult != NS_OK || initError != NPERR_NO_ERROR)
+    return NS_ERROR_FAILURE;
 #endif
 
 #ifdef XP_OS2
+  PluginLibrary* pluginLib = GetNewPluginLibrary(aFilePath, aLibrary);
+
   // create the new plugin handler
-  plugin = new nsNPAPIPlugin(nsnull, aLibrary, nsnull);
+  plugin = new nsNPAPIPlugin(nsnull, pluginLib);
   if (!plugin)
     return NS_ERROR_OUT_OF_MEMORY;
 
   // we must init here because the plugin may call NPN functions
   // when we call into the NP_Initialize entry point - NPN functions
   // require that mBrowserManager be set up
   if (NS_FAILED(plugin->Initialize()))
     return NS_ERROR_FAILURE;
@@ -532,17 +513,18 @@ nsNPAPIPlugin::CreatePlugin(const char* 
   NS_NewNativeLocalFile(nsDependentCString(aFilePath), PR_TRUE,
                         getter_AddRefs(pluginPath));
   nsPluginFile pluginFile(pluginPath);
 
 #ifndef __LP64__
   pluginRefNum = pluginFile.OpenPluginResource();
 #endif
 
-  plugin = new nsNPAPIPlugin(nsnull, aLibrary, nsnull);
+  PluginLibrary* pluginLib = GetNewPluginLibrary(aFilePath, aLibrary);
+  plugin = new nsNPAPIPlugin(nsnull, pluginLib);
 #ifndef __LP64__
   ::UseResFile(appRefNum);
 #endif
   if (!plugin)
     return NS_ERROR_OUT_OF_MEMORY;
 
   if (NS_FAILED(plugin->Initialize()))
     return NS_ERROR_FAILURE;
@@ -551,16 +533,18 @@ nsNPAPIPlugin::CreatePlugin(const char* 
   plugin->SetPluginRefNum(pluginRefNum);
 #endif
 #endif
 
 #ifdef XP_BEOS
   // I just copied UNIX version.
   // Makoto Hamanaka <VYA04230@nifty.com>
 
+  // XXX this code won't compile with the new e10s changes
+
   NPPluginFuncs callbacks;
   memset((void*) &callbacks, 0, sizeof(callbacks));
   callbacks.size = sizeof(callbacks);
 
   NP_PLUGINSHUTDOWN pfnShutdown =
     (NP_PLUGINSHUTDOWN)PR_FindSymbol(aLibrary, "NP_Shutdown");
 
   // create the new plugin handler
@@ -815,72 +799,56 @@ nsNPAPIPlugin::Shutdown(void)
 #ifdef OJI
   if (mShadow)
     return mShadow->Shutdown();
 #endif
 
   NPP_PLUGIN_LOG(PLUGIN_LOG_BASIC,
                  ("NPP Shutdown to be called: this=%p\n", this));
 
-  if (fShutdownEntry) {
-#if defined(XP_MACOSX)
-    (*fShutdownEntry)();
-    if (fPluginRefNum > 0)
-      ::CloseResFile(fPluginRefNum);
-#else
-    NS_TRY_SAFE_CALL_VOID(fShutdownEntry(), fLibrary, nsnull);
+  NPError shutdownError;
+  fLibrary->NP_Shutdown(&shutdownError);
+#ifdef XP_MACOSX
+  if (shutdownError == NS_OK && fPluginRefNum > 0)
+    ::CloseResFile(fPluginRefNum);
 #endif
-    fShutdownEntry = nsnull;
-  }
-
-  PLUGIN_LOG(PLUGIN_LOG_NORMAL,
-             ("NPAPIPlugin Shutdown done, this=%p", this));
   return NS_OK;
 }
 
 nsresult
 nsNPAPIPlugin::GetMIMEDescription(const char* *resultingDesc)
 {
 #ifdef OJI
   if (mShadow)
     return mShadow->GetMIMEDescription(resultingDesc);
 #endif
 
-  const char* (*npGetMIMEDescription)() =
-    (const char* (*)()) PR_FindFunctionSymbol(fLibrary, "NP_GetMIMEDescription");
-
-  *resultingDesc = npGetMIMEDescription ? npGetMIMEDescription() : "";
-
-  PLUGIN_LOG(PLUGIN_LOG_NORMAL,
-             ("nsNPAPIPlugin::GetMIMEDescription called: this=%p, result=%s\n",
-              this, *resultingDesc));
+  nsresult gmdResult = fLibrary->NP_GetMIMEDescription((char**)resultingDesc);
+  if (gmdResult != NS_OK) {
+    return gmdResult;
+  }
 
   return NS_OK;
 }
 
 nsresult
 nsNPAPIPlugin::GetValue(nsPluginVariable variable, void *value)
 {
 #ifdef OJI
   if (mShadow)
     return mShadow->GetValue(variable, value);
 #endif
 
   PLUGIN_LOG(PLUGIN_LOG_NORMAL,
   ("nsNPAPIPlugin::GetValue called: this=%p, variable=%d\n", this, variable));
 
-  NPError (*npGetValue)(void*, nsPluginVariable, void*) =
-    (NPError (*)(void*, nsPluginVariable, void*)) PR_FindFunctionSymbol(fLibrary,
-                                                                "NP_GetValue");
-
-  if (npGetValue && NPERR_NO_ERROR == npGetValue(nsnull, variable, value)) {
-    return NS_OK;
-  }
-
-  return NS_ERROR_FAILURE;
+  NPError gvError;
+  fLibrary->NP_GetValue(nsnull, variable, value, &gvError);
+
+  return gvError;
 }
 
 // Create a new NPP GET or POST (given in the type argument) url
 // stream that may have a notify callback
 NPError
 MakeNewNPAPIStreamInternal(NPP npp, const char *relativeURL, const char *target,
                           eNPPStreamTypeInternal type,
                           PRBool bDoNotify = PR_FALSE,
@@ -922,20 +890,327 @@ MakeNewNPAPIStreamInternal(NPP npp, cons
     }
   default:
     NS_ASSERTION(0, "how'd I get here");
   }
 
   return NPERR_NO_ERROR;
 }
 
+#if defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_WINCE)
+extern "C" size_t malloc_usable_size(const void *ptr);
+#endif
+
+namespace {
+
+static char *gNPPException;
+
+// A little helper class used to wrap up plugin manager streams (that is,
+// streams from the plugin to the browser).
+class nsNPAPIStreamWrapper : nsISupports
+{
+public:
+  NS_DECL_ISUPPORTS
+
+protected:
+  nsIOutputStream *fStream;
+  NPStream        fNPStream;
+
+public:
+  nsNPAPIStreamWrapper(nsIOutputStream* stream);
+  ~nsNPAPIStreamWrapper();
+
+  void GetStream(nsIOutputStream* &result);
+  NPStream* GetNPStream(void) { return &fNPStream; }
+};
+
+class nsPluginThreadRunnable : public nsRunnable,
+                               public PRCList
+{
+public:
+  nsPluginThreadRunnable(NPP instance, PluginThreadCallback func,
+                         void *userData);
+  virtual ~nsPluginThreadRunnable();
+
+  NS_IMETHOD Run();
+
+  PRBool IsForInstance(NPP instance)
+  {
+    return (mInstance == instance);
+  }
+
+  void Invalidate()
+  {
+    mFunc = nsnull;
+  }
+
+  PRBool IsValid()
+  {
+    return (mFunc != nsnull);
+  }
+
+private:  
+  NPP mInstance;
+  PluginThreadCallback mFunc;
+  void *mUserData;
+};
+
+static nsIDocument *
+GetDocumentFromNPP(NPP npp)
+{
+  NS_ENSURE_TRUE(npp, nsnull);
+
+  nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)npp->ndata;
+  NS_ENSURE_TRUE(inst, nsnull);
+
+  PluginDestructionGuard guard(inst);
+
+  nsCOMPtr<nsIPluginInstanceOwner> owner;
+  inst->GetOwner(getter_AddRefs(owner));
+  NS_ENSURE_TRUE(owner, nsnull);
+
+  nsCOMPtr<nsIDocument> doc;
+  owner->GetDocument(getter_AddRefs(doc));
+
+  return doc;
+}
+
+static JSContext *
+GetJSContextFromDoc(nsIDocument *doc)
+{
+  nsIScriptGlobalObject *sgo = doc->GetScriptGlobalObject();
+  NS_ENSURE_TRUE(sgo, nsnull);
+
+  nsIScriptContext *scx = sgo->GetContext();
+  NS_ENSURE_TRUE(scx, nsnull);
+
+  return (JSContext *)scx->GetNativeContext();
+}
+
+static JSContext *
+GetJSContextFromNPP(NPP npp)
+{
+  nsIDocument *doc = GetDocumentFromNPP(npp);
+  NS_ENSURE_TRUE(doc, nsnull);
+
+  return GetJSContextFromDoc(doc);
+}
+
+static NPIdentifier
+doGetIdentifier(JSContext *cx, const NPUTF8* name)
+{
+  NS_ConvertUTF8toUTF16 utf16name(name);
+
+  JSString *str = ::JS_InternUCStringN(cx, (jschar *)utf16name.get(),
+                                       utf16name.Length());
+
+  if (!str)
+    return NULL;
+
+  return (NPIdentifier)STRING_TO_JSVAL(str);
+}
+
+#if defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_WINCE)
+BOOL
+InHeap(HANDLE hHeap, LPVOID lpMem)
+{
+  BOOL success = FALSE;
+  PROCESS_HEAP_ENTRY he;
+  he.lpData = NULL;
+  while (HeapWalk(hHeap, &he) != 0) {
+    if (he.lpData == lpMem) {
+      success = TRUE;
+      break;
+    }
+  }
+  HeapUnlock(hHeap);
+  return success;
+}
+#endif
+
+} /* anonymous namespace */
+
+NS_IMPL_ISUPPORTS1(nsNPAPIStreamWrapper, nsISupports)
+
+nsNPAPIStreamWrapper::nsNPAPIStreamWrapper(nsIOutputStream* stream)
+: fStream(stream)
+{
+  NS_ASSERTION(stream, "bad stream");
+
+  fStream = stream;
+  NS_ADDREF(fStream);
+
+  memset(&fNPStream, 0, sizeof(fNPStream));
+  fNPStream.ndata = (void*) this;
+}
+
+nsNPAPIStreamWrapper::~nsNPAPIStreamWrapper(void)
+{
+  fStream->Close();
+  NS_IF_RELEASE(fStream);
+}
+
+void
+nsNPAPIStreamWrapper::GetStream(nsIOutputStream* &result)
+{
+  result = fStream;
+  NS_IF_ADDREF(fStream);
+}
+
+NPPExceptionAutoHolder::NPPExceptionAutoHolder()
+  : mOldException(gNPPException)
+{
+  gNPPException = nsnull;
+}
+
+NPPExceptionAutoHolder::~NPPExceptionAutoHolder()
+{
+  NS_ASSERTION(!gNPPException, "NPP exception not properly cleared!");
+
+  gNPPException = mOldException;
+}
+
+nsPluginThreadRunnable::nsPluginThreadRunnable(NPP instance,
+                                               PluginThreadCallback func,
+                                               void *userData)
+  : mInstance(instance), mFunc(func), mUserData(userData)
+{
+  if (!sPluginThreadAsyncCallLock) {
+    // Failed to create lock, not much we can do here then...
+    mFunc = nsnull;
+
+    return;
+  }
+
+  PR_INIT_CLIST(this);
+
+  {
+    nsAutoLock lock(sPluginThreadAsyncCallLock);
+
+    nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
+    if (!inst || !inst->IsStarted()) {
+      // The plugin was stopped, ignore this async call.
+      mFunc = nsnull;
+
+      return;
+    }
+
+    PR_APPEND_LINK(this, &sPendingAsyncCalls);
+  }
+}
+
+nsPluginThreadRunnable::~nsPluginThreadRunnable()
+{
+  if (!sPluginThreadAsyncCallLock) {
+    return;
+  }
+
+  {
+    nsAutoLock lock(sPluginThreadAsyncCallLock);
+
+    PR_REMOVE_LINK(this);
+  }
+}
+
+NS_IMETHODIMP
+nsPluginThreadRunnable::Run()
+{
+  if (mFunc) {
+    PluginDestructionGuard guard(mInstance);
+
+    NS_TRY_SAFE_CALL_VOID(mFunc(mUserData), nsnull, nsnull);
+  }
+
+  return NS_OK;
+}
+
+void
+OnPluginDestroy(NPP instance)
+{
+  if (!sPluginThreadAsyncCallLock) {
+    return;
+  }
+
+  {
+    nsAutoLock lock(sPluginThreadAsyncCallLock);
+
+    if (PR_CLIST_IS_EMPTY(&sPendingAsyncCalls)) {
+      return;
+    }
+
+    nsPluginThreadRunnable *r =
+      (nsPluginThreadRunnable *)PR_LIST_HEAD(&sPendingAsyncCalls);
+
+    do {
+      if (r->IsForInstance(instance)) {
+        r->Invalidate();
+      }
+
+      r = (nsPluginThreadRunnable *)PR_NEXT_LINK(r);
+    } while (r != &sPendingAsyncCalls);
+  }
+}
+
+void
+OnShutdown()
+{
+  NS_ASSERTION(PR_CLIST_IS_EMPTY(&sPendingAsyncCalls),
+               "Pending async plugin call list not cleaned up!");
+
+  if (sPluginThreadAsyncCallLock) {
+    nsAutoLock::DestroyLock(sPluginThreadAsyncCallLock);
+
+    sPluginThreadAsyncCallLock = nsnull;
+  }
+}
+
+void
+EnterAsyncPluginThreadCallLock()
+{
+  if (sPluginThreadAsyncCallLock) {
+    PR_Lock(sPluginThreadAsyncCallLock);
+  }
+}
+
+void
+ExitAsyncPluginThreadCallLock()
+{
+  if (sPluginThreadAsyncCallLock) {
+    PR_Unlock(sPluginThreadAsyncCallLock);
+  }
+}
+
+NPP NPPStack::sCurrentNPP = nsnull;
+
+const char *
+PeekException()
+{
+  return gNPPException;
+}
+
+void
+PopException()
+{
+  NS_ASSERTION(gNPPException, "Uh, no NPP exception to pop!");
+
+  if (gNPPException) {
+    free(gNPPException);
+
+    gNPPException = nsnull;
+  }
+}
+
 //
 // Static callbacks that get routed back through the new C++ API
 //
 
+namespace mozilla {
+namespace plugins {
+namespace parent {
+
 NPError NP_CALLBACK
 _geturl(NPP npp, const char* relativeURL, const char* target)
 {
   if (!NS_IsMainThread()) {
     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_geturl called from the wrong thread\n"));
     return NPERR_INVALID_PARAM;
   }
 
@@ -987,16 +1262,19 @@ NPError NP_CALLBACK
 NPError NP_CALLBACK
 _posturlnotify(NPP npp, const char *relativeURL, const char *target,
                uint32_t len, const char *buf, NPBool file, void *notifyData)
 {
   if (!NS_IsMainThread()) {
     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_posturlnotify called from the wrong thread\n"));
     return NPERR_INVALID_PARAM;
   }
+  if (!buf)
+    return NPERR_INVALID_PARAM;
+
   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
                  ("NPN_PostURLNotify: npp=%p, target=%s, len=%d, file=%d, "
                   "notify=%p, url=%s, buf=%s\n",
                   (void*)npp, target, len, file, notifyData, relativeURL,
                   buf));
 
   PluginDestructionGuard guard(npp);
 
@@ -1020,62 +1298,16 @@ NPError NP_CALLBACK
 
   PluginDestructionGuard guard(npp);
 
   return MakeNewNPAPIStreamInternal(npp, relativeURL, target,
                                     eNPPStreamTypeInternal_Post, PR_FALSE, nsnull,
                                     len, buf, file);
 }
 
-// A little helper class used to wrap up plugin manager streams (that is,
-// streams from the plugin to the browser).
-class nsNPAPIStreamWrapper : nsISupports
-{
-public:
-  NS_DECL_ISUPPORTS
-
-protected:
-  nsIOutputStream *fStream;
-  NPStream        fNPStream;
-
-public:
-  nsNPAPIStreamWrapper(nsIOutputStream* stream);
-  ~nsNPAPIStreamWrapper();
-
-  void GetStream(nsIOutputStream* &result);
-  NPStream* GetNPStream(void) { return &fNPStream; }
-};
-
-NS_IMPL_ISUPPORTS1(nsNPAPIStreamWrapper, nsISupports)
-
-nsNPAPIStreamWrapper::nsNPAPIStreamWrapper(nsIOutputStream* stream)
-: fStream(stream)
-{
-  NS_ASSERTION(stream, "bad stream");
-
-  fStream = stream;
-  NS_ADDREF(fStream);
-
-  memset(&fNPStream, 0, sizeof(fNPStream));
-  fNPStream.ndata = (void*) this;
-}
-
-nsNPAPIStreamWrapper::~nsNPAPIStreamWrapper(void)
-{
-  fStream->Close();
-  NS_IF_RELEASE(fStream);
-}
-
-void
-nsNPAPIStreamWrapper::GetStream(nsIOutputStream* &result)
-{
-  result = fStream;
-  NS_IF_ADDREF(fStream);
-}
-
 NPError NP_CALLBACK
 _newstream(NPP npp, NPMIMEType type, const char* target, NPStream* *result)
 {
   if (!NS_IsMainThread()) {
     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_newstream called from the wrong thread\n"));
     return NPERR_INVALID_PARAM;
   }
   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
@@ -1311,57 +1543,16 @@ void NP_CALLBACK
 
   nsIPluginInstance *inst = (nsIPluginInstance *) npp->ndata;
 
   PluginDestructionGuard guard(inst);
 
   inst->ForceRedraw();
 }
 
-static nsIDocument *
-GetDocumentFromNPP(NPP npp)
-{
-  NS_ENSURE_TRUE(npp, nsnull);
-
-  nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)npp->ndata;
-  NS_ENSURE_TRUE(inst, nsnull);
-
-  PluginDestructionGuard guard(inst);
-
-  nsCOMPtr<nsIPluginInstanceOwner> owner;
-  inst->GetOwner(getter_AddRefs(owner));
-  NS_ENSURE_TRUE(owner, nsnull);
-
-  nsCOMPtr<nsIDocument> doc;
-  owner->GetDocument(getter_AddRefs(doc));
-
-  return doc;
-}
-
-static JSContext *
-GetJSContextFromDoc(nsIDocument *doc)
-{
-  nsIScriptGlobalObject *sgo = doc->GetScriptGlobalObject();
-  NS_ENSURE_TRUE(sgo, nsnull);
-
-  nsIScriptContext *scx = sgo->GetContext();
-  NS_ENSURE_TRUE(scx, nsnull);
-
-  return (JSContext *)scx->GetNativeContext();
-}
-
-static JSContext *
-GetJSContextFromNPP(NPP npp)
-{
-  nsIDocument *doc = GetDocumentFromNPP(npp);
-  NS_ENSURE_TRUE(doc, nsnull);
-
-  return GetJSContextFromDoc(doc);
-}
-
 NPObject* NP_CALLBACK
 _getwindowobject(NPP npp)
 {
   if (!NS_IsMainThread()) {
     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getwindowobject called from the wrong thread\n"));
     return nsnull;
   }
   JSContext *cx = GetJSContextFromNPP(npp);
@@ -1405,30 +1596,16 @@ NPObject* NP_CALLBACK
 
   JSObject* obj = nsnull;
   holder->GetJSObject(&obj);
   NS_ENSURE_TRUE(obj, nsnull);
 
   return nsJSObjWrapper::GetNewOrUsed(npp, cx, obj);
 }
 
-static NPIdentifier
-doGetIdentifier(JSContext *cx, const NPUTF8* name)
-{
-  NS_ConvertUTF8toUTF16 utf16name(name);
-
-  JSString *str = ::JS_InternUCStringN(cx, (jschar *)utf16name.get(),
-                                       utf16name.Length());
-
-  if (!str)
-    return NULL;
-
-  return (NPIdentifier)STRING_TO_JSVAL(str);
-}
-
 NPIdentifier NP_CALLBACK
 _getstringidentifier(const NPUTF8* name)
 {
   if (!name) {
     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS, ("NPN_getstringidentifier: passed null name"));
     return NULL;
   }
   if (!NS_IsMainThread()) {
@@ -1564,47 +1741,50 @@ NPObject* NP_CALLBACK
     npobj = aClass->allocate(npp, aClass);
   } else {
     npobj = (NPObject *)PR_Malloc(sizeof(NPObject));
   }
 
   if (npobj) {
     npobj->_class = aClass;
     npobj->referenceCount = 1;
+    NS_LOG_ADDREF(npobj, 1, "BrowserNPObject", sizeof(NPObject));
   }
 
   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
                  ("Created NPObject %p, NPClass %p\n", npobj, aClass));
 
   return npobj;
 }
 
 NPObject* NP_CALLBACK
 _retainobject(NPObject* npobj)
 {
   if (!NS_IsMainThread()) {
     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_retainobject called from the wrong thread\n"));
   }
   if (npobj) {
-    PR_AtomicIncrement((PRInt32*)&npobj->referenceCount);
+    int32_t refCnt = PR_AtomicIncrement((PRInt32*)&npobj->referenceCount);
+    NS_LOG_ADDREF(npobj, refCnt, "BrowserNPObject", sizeof(NPObject));
   }
 
   return npobj;
 }
 
 void NP_CALLBACK
 _releaseobject(NPObject* npobj)
 {
   if (!NS_IsMainThread()) {
     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_releaseobject called from the wrong thread\n"));
   }
   if (!npobj)
     return;
 
   int32_t refCnt = PR_AtomicDecrement((PRInt32*)&npobj->referenceCount);
+  NS_LOG_RELEASE(npobj, refCnt, "BrowserNPObject");
 
   if (refCnt == 0) {
     nsNPObjWrapper::OnDestroy(npobj);
 
     NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
                    ("Deleting NPObject %p, refcount hit 0\n", npobj));
 
     if (npobj->_class && npobj->_class->deallocate) {
@@ -1892,36 +2072,16 @@ bool NP_CALLBACK
   }
 
   NPPExceptionAutoHolder nppExceptionHolder;
   NPPAutoPusher nppPusher(npp);
 
   return npobj->_class->construct(npobj, args, argCount, result);
 }
 
-#if defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_WINCE)
-extern "C" size_t malloc_usable_size(const void *ptr);
-
-BOOL
-InHeap(HANDLE hHeap, LPVOID lpMem)
-{
-  BOOL success = FALSE;
-  PROCESS_HEAP_ENTRY he;
-  he.lpData = NULL;
-  while (HeapWalk(hHeap, &he) != 0) {
-    if (he.lpData == lpMem) {
-      success = TRUE;
-      break;
-    }
-  }
-  HeapUnlock(hHeap);
-  return success;
-}
-#endif
-
 void NP_CALLBACK
 _releasevariantvalue(NPVariant* variant)
 {
   if (!NS_IsMainThread()) {
     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_releasevariantvalue called from the wrong thread\n"));
   }
   switch (variant->type) {
   case NPVariantType_Void :
@@ -1982,18 +2142,16 @@ bool NP_CALLBACK
   if (!NS_IsMainThread()) {
     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_tostring called from the wrong thread\n"));
     return false;
   }
 
   return false;
 }
 
-static char *gNPPException;
-
 void NP_CALLBACK
 _setexception(NPObject* npobj, const NPUTF8 *message)
 {
   if (!NS_IsMainThread()) {
     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_setexception called from the wrong thread\n"));
     return;
   }
 
@@ -2001,47 +2159,16 @@ void NP_CALLBACK
     // If a plugin throws multiple exceptions, we'll only report the
     // last one for now.
     free(gNPPException);
   }
 
   gNPPException = strdup(message);
 }
 
-const char *
-PeekException()
-{
-  return gNPPException;
-}
-
-void
-PopException()
-{
-  NS_ASSERTION(gNPPException, "Uh, no NPP exception to pop!");
-
-  if (gNPPException) {
-    free(gNPPException);
-
-    gNPPException = nsnull;
-  }
-}
-
-NPPExceptionAutoHolder::NPPExceptionAutoHolder()
-  : mOldException(gNPPException)
-{
-  gNPPException = nsnull;
-}
-
-NPPExceptionAutoHolder::~NPPExceptionAutoHolder()
-{
-  NS_ASSERTION(!gNPPException, "NPP exception not properly cleared!");
-
-  gNPPException = mOldException;
-}
-
 NPError NP_CALLBACK
 _getvalue(NPP npp, NPNVariable variable, void *result)
 {
   if (!NS_IsMainThread()) {
     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getvalue called from the wrong thread\n"));
     return NPERR_INVALID_PARAM;
   }
   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetValue: npp=%p, var=%d\n",
@@ -2152,17 +2279,17 @@ NPError NP_CALLBACK
     *(NPBool*)result = PR_FALSE;
 #endif
     return NPERR_NO_ERROR;
   }
 
   case NPNVWindowNPObject: {
     *(NPObject **)result = _getwindowobject(npp);
 
-    return NPERR_NO_ERROR;
+    return *(NPObject **)result ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
   }
 
   case NPNVPluginElementNPObject: {
     *(NPObject **)result = _getpluginelement(npp);
 
     return NPERR_NO_ERROR;
   }
 
@@ -2474,101 +2601,16 @@ void NP_CALLBACK
   }
   nsNPAPIPluginInstance *inst = npp ? (nsNPAPIPluginInstance *)npp->ndata : NULL;
   if (!inst)
     return;
 
   inst->PopPopupsEnabledState();
 }
 
-class nsPluginThreadRunnable : public nsRunnable,
-                               public PRCList
-{
-public:
-  nsPluginThreadRunnable(NPP instance, PluginThreadCallback func,
-                         void *userData);
-  virtual ~nsPluginThreadRunnable();
-
-  NS_IMETHOD Run();
-
-  PRBool IsForInstance(NPP instance)
-  {
-    return (mInstance == instance);
-  }
-
-  void Invalidate()
-  {
-    mFunc = nsnull;
-  }
-
-  PRBool IsValid()
-  {
-    return (mFunc != nsnull);
-  }
-
-private:  
-  NPP mInstance;
-  PluginThreadCallback mFunc;
-  void *mUserData;
-};
-
-nsPluginThreadRunnable::nsPluginThreadRunnable(NPP instance,
-                                               PluginThreadCallback func,
-                                               void *userData)
-  : mInstance(instance), mFunc(func), mUserData(userData)
-{
-  if (!sPluginThreadAsyncCallLock) {
-    // Failed to create lock, not much we can do here then...
-    mFunc = nsnull;
-
-    return;
-  }
-
-  PR_INIT_CLIST(this);
-
-  {
-    nsAutoLock lock(sPluginThreadAsyncCallLock);
-
-    nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
-    if (!inst || !inst->IsStarted()) {
-      // The plugin was stopped, ignore this async call.
-      mFunc = nsnull;
-
-      return;
-    }
-
-    PR_APPEND_LINK(this, &sPendingAsyncCalls);
-  }
-}
-
-nsPluginThreadRunnable::~nsPluginThreadRunnable()
-{
-  if (!sPluginThreadAsyncCallLock) {
-    return;
-  }
-
-  {
-    nsAutoLock lock(sPluginThreadAsyncCallLock);
-
-    PR_REMOVE_LINK(this);
-  }
-}
-
-NS_IMETHODIMP
-nsPluginThreadRunnable::Run()
-{
-  if (mFunc) {
-    PluginDestructionGuard guard(mInstance);
-
-    NS_TRY_SAFE_CALL_VOID(mFunc(mUserData), nsnull, nsnull);
-  }
-
-  return NS_OK;
-}
-
 void NP_CALLBACK
 _pluginthreadasynccall(NPP instance, PluginThreadCallback func, void *userData)
 {
   if (NS_IsMainThread()) {
     NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,("NPN_pluginthreadasynccall called from the main thread\n"));
   } else {
     NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,("NPN_pluginthreadasynccall called from a non main thread\n"));
   }
@@ -2741,90 +2783,31 @@ NPError NP_CALLBACK
   *ulen = *username ? uname8.Length() : 0;
 
   *password = ToNewCString(pwd8);
   *plen = *password ? pwd8.Length() : 0;
 
   return NPERR_NO_ERROR;
 }
 
-// We need extern "C" here because it has a function pointer as an argument.
-// See Bug 501889.
-PR_BEGIN_EXTERN_C
 uint32_t NP_CALLBACK
-_scheduletimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID))
+_scheduletimer(NPP instance, uint32_t interval, NPBool repeat, PluginTimerFunc timerFunc)
 {
   nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
   if (!inst)
     return 0;
 
   return inst->ScheduleTimer(interval, repeat, timerFunc);
 }
-PR_END_EXTERN_C
 
 void NP_CALLBACK
 _unscheduletimer(NPP instance, uint32_t timerID)
 {
   nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
   if (!inst)
     return;
 
   inst->UnscheduleTimer(timerID);
 }
 
-void
-OnPluginDestroy(NPP instance)
-{
-  if (!sPluginThreadAsyncCallLock) {
-    return;
-  }
-
-  {
-    nsAutoLock lock(sPluginThreadAsyncCallLock);
-
-    if (PR_CLIST_IS_EMPTY(&sPendingAsyncCalls)) {
-      return;
-    }
-
-    nsPluginThreadRunnable *r =
-      (nsPluginThreadRunnable *)PR_LIST_HEAD(&sPendingAsyncCalls);
-
-    do {
-      if (r->IsForInstance(instance)) {
-        r->Invalidate();
-      }
-
-      r = (nsPluginThreadRunnable *)PR_NEXT_LINK(r);
-    } while (r != &sPendingAsyncCalls);
-  }
-}
-
-void
-OnShutdown()
-{
-  NS_ASSERTION(PR_CLIST_IS_EMPTY(&sPendingAsyncCalls),
-               "Pending async plugin call list not cleaned up!");
-
-  if (sPluginThreadAsyncCallLock) {
-    nsAutoLock::DestroyLock(sPluginThreadAsyncCallLock);
-
-    sPluginThreadAsyncCallLock = nsnull;
-  }
-}
-
-void
-EnterAsyncPluginThreadCallLock()
-{
-  if (sPluginThreadAsyncCallLock) {
-    PR_Lock(sPluginThreadAsyncCallLock);
-  }
-}
-
-void
-ExitAsyncPluginThreadCallLock()
-{
-  if (sPluginThreadAsyncCallLock) {
-    PR_Unlock(sPluginThreadAsyncCallLock);
-  }
-}
-
-NPP NPPStack::sCurrentNPP = nsnull;
-
+} /* namespace parent */
+} /* namespace plugins */
+} /* namespace mozilla */
--- a/modules/plugin/base/src/nsNPAPIPlugin.h
+++ b/modules/plugin/base/src/nsNPAPIPlugin.h
@@ -43,16 +43,18 @@
 #include "nsIPluginOld.h"
 #include "nsIJVMPlugin.h"
 #include "nsIJVMConsole.h"
 #endif
 #include "prlink.h"
 #include "npfunctions.h"
 #include "nsPluginHost.h"
 
+#include "mozilla/PluginLibrary.h"
+
 /*
  * Use this macro before each exported function
  * (between the return address and the function
  * itself), to ensure that the function has the
  * right calling conventions on OS/2.
  */
 #ifdef XP_OS2
 #define NP_CALLBACK _System
@@ -78,22 +80,25 @@ typedef NS_NPAPIPLUGIN_CALLBACK(NPError,
 
 class nsNPAPIPlugin : public nsIPlugin
 #ifdef OJI
                      ,public nsIPluginOld,
                       public nsIJVMPlugin,
                       public nsIJVMConsole
 #endif
 {
+private:
+  typedef mozilla::PluginLibrary PluginLibrary;
+
 public:
 #ifdef OJI
   nsNPAPIPlugin(nsIPluginOld *aShadow);
 #endif
-  nsNPAPIPlugin(NPPluginFuncs* callbacks, PRLibrary* aLibrary,
-                NP_PLUGINSHUTDOWN aShutdown);
+  nsNPAPIPlugin(NPPluginFuncs* callbacks,
+                PluginLibrary* aLibrary /*assume ownership*/);
   virtual ~nsNPAPIPlugin();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPLUGIN
 
 #ifdef OJI
   NS_DECL_NSIFACTORY
 
@@ -135,30 +140,31 @@ protected:
 
 #ifdef XP_MACOSX
   short fPluginRefNum;
 #endif
 
   // The plugin-side callbacks that the browser calls. One set of
   // plugin callbacks for each plugin.
   NPPluginFuncs fCallbacks;
-  PRLibrary*    fLibrary;
-
-  NP_PLUGINSHUTDOWN fShutdownEntry;
+  PluginLibrary* fLibrary;
+  PRLibrary* fPRLibrary;
 
   // Browser-side callbacks that the plugin calls.
   static NPNetscapeFuncs CALLBACKS;
 
 #ifdef OJI
   nsIPluginOld *mShadow; // Strong
 #endif
 };
 
+namespace mozilla {
+namespace plugins {
+namespace parent {
 
-PR_BEGIN_EXTERN_C
 NPObject* NP_CALLBACK
 _getwindowobject(NPP npp);
 
 NPObject* NP_CALLBACK
 _getpluginelement(NPP npp);
 
 NPIdentifier NP_CALLBACK
 _getstringidentifier(const NPUTF8* name);
@@ -239,33 +245,105 @@ void NP_CALLBACK
 typedef void(*PluginThreadCallback)(void *);
 void NP_CALLBACK
 _pluginthreadasynccall(NPP instance, PluginThreadCallback func,
                        void *userData);
 
 NPError NP_CALLBACK
 _getvalueforurl(NPP instance, NPNURLVariable variable, const char *url,
                 char **value, uint32_t *len);
+
 NPError NP_CALLBACK
 _setvalueforurl(NPP instance, NPNURLVariable variable, const char *url,
                 const char *value, uint32_t len);
 
 NPError NP_CALLBACK
 _getauthenticationinfo(NPP instance, const char *protocol, const char *host,
                        int32_t port, const char *scheme, const char *realm,
                        char **username, uint32_t *ulen, char **password,
                        uint32_t *plen);
 
+typedef void(*PluginTimerFunc)(NPP npp, uint32_t timerID);
+
 uint32_t NP_CALLBACK
-_scheduletimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID));
+_scheduletimer(NPP instance, uint32_t interval, NPBool repeat, PluginTimerFunc timerFunc);
 
 void NP_CALLBACK
 _unscheduletimer(NPP instance, uint32_t timerID);
 
-PR_END_EXTERN_C
+NPError NP_CALLBACK
+_requestread(NPStream *pstream, NPByteRange *rangeList);
+
+NPError NP_CALLBACK
+_geturlnotify(NPP npp, const char* relativeURL, const char* target,
+              void* notifyData);
+
+NPError NP_CALLBACK
+_getvalue(NPP npp, NPNVariable variable, void *r_value);
+
+NPError NP_CALLBACK
+_setvalue(NPP npp, NPPVariable variable, void *r_value);
+
+NPError NP_CALLBACK
+_geturl(NPP npp, const char* relativeURL, const char* target);
+
+NPError NP_CALLBACK
+_posturlnotify(NPP npp, const char* relativeURL, const char *target,
+               uint32_t len, const char *buf, NPBool file, void* notifyData);
+
+NPError NP_CALLBACK
+_posturl(NPP npp, const char* relativeURL, const char *target, uint32_t len,
+            const char *buf, NPBool file);
+
+NPError NP_CALLBACK
+_newstream(NPP npp, NPMIMEType type, const char* window, NPStream** pstream);
+
+int32_t NP_CALLBACK
+_write(NPP npp, NPStream *pstream, int32_t len, void *buffer);
+
+NPError NP_CALLBACK
+_destroystream(NPP npp, NPStream *pstream, NPError reason);
+
+void NP_CALLBACK
+_status(NPP npp, const char *message);
+
+void NP_CALLBACK
+_memfree (void *ptr);
+
+uint32_t NP_CALLBACK
+_memflush(uint32_t size);
+
+void NP_CALLBACK
+_reloadplugins(NPBool reloadPages);
+
+void NP_CALLBACK
+_invalidaterect(NPP npp, NPRect *invalidRect);
+
+void NP_CALLBACK
+_invalidateregion(NPP npp, NPRegion invalidRegion);
+
+void NP_CALLBACK
+_forceredraw(NPP npp);
+
+const char* NP_CALLBACK
+_useragent(NPP npp);
+
+void* NP_CALLBACK
+_memalloc (uint32_t size);
+
+// Deprecated entry points for the old Java plugin.
+void* NP_CALLBACK /* OJI type: JRIEnv* */
+_getJavaEnv(void);
+
+void* NP_CALLBACK /* OJI type: jref */
+_getJavaPeer(NPP npp);
+
+} /* namespace parent */
+} /* namespace plugins */
+} /* namespace mozilla */
 
 const char *
 PeekException();
 
 void
 PopException();
 
 void
--- a/modules/plugin/base/src/nsNPAPIPluginInstance.cpp
+++ b/modules/plugin/base/src/nsNPAPIPluginInstance.cpp
@@ -52,16 +52,18 @@
 
 #include "nsIDocument.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptContext.h"
 #include "nsDirectoryServiceDefs.h"
 
 #include "nsJSNPRuntime.h"
 
+using namespace mozilla::plugins::parent;
+
 static NS_DEFINE_IID(kIPluginStreamListenerIID, NS_IPLUGINSTREAMLISTENER_IID);
 
 // nsPluginStreamToFile
 // --------------------
 // Used to handle NPN_NewStream() - writes the stream as received by the plugin
 // to a file and at completion (NPN_DestroyStream), tells the browser to load it into
 // a plugin-specified target
 
@@ -264,17 +266,19 @@ nsresult nsNPAPIPluginStreamListener::Cl
   mInst->GetCallbacks(&callbacks);
   if (!callbacks)
     return rv;
 
   NPP npp;
   mInst->GetNPP(&npp);
 
   if (mStreamStarted && callbacks->destroystream) {
-    PRLibrary* lib = nsnull;
+    NPPAutoPusher nppPusher(npp);
+
+    PluginLibrary* lib = nsnull;
     lib = mInst->mLibrary;
     NPError error;
     NS_TRY_SAFE_CALL_RETURN(error, (*callbacks->destroystream)(npp, &mNPStream, reason), lib, mInst);
 
     NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
     ("NPP DestroyStream called: this=%p, npp=%p, reason=%d, return=%d, url=%s\n",
     this, npp, reason, error, mNPStream.url));
 
@@ -353,16 +357,18 @@ nsNPAPIPluginStreamListener::OnStartBind
   
   if (!mResponseHeaders.IsEmpty()) {
     mResponseHeaderBuf = PL_strdup(mResponseHeaders.get());
     mNPStream.headers = mResponseHeaderBuf;
   }
 
   mStreamInfo = pluginInfo;
 
+  NPPAutoPusher nppPusher(npp);
+
   NS_TRY_SAFE_CALL_RETURN(error, (*callbacks->newstream)(npp, (char*)contentType, &mNPStream, seekable, &streamType), mInst->mLibrary, mInst);
 
   NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
   ("NPP NewStream called: this=%p, npp=%p, mime=%s, seek=%d, type=%d, return=%d, url=%s\n",
   this, npp, (char *)contentType, seekable, streamType, error, mNPStream.url));
 
   if (error != NPERR_NO_ERROR)
     return NS_ERROR_FAILURE;
@@ -592,16 +598,18 @@ nsNPAPIPluginStreamListener::OnDataAvail
     PRInt32 zeroBytesWriteCount = 0;
 
     // mStreamBufferByteCount tells us how many bytes there are in the
     // buffer. WriteReady returns to us how many bytes the plugin is
     // ready to handle.
     while (mStreamBufferByteCount > 0) {
       PRInt32 numtowrite;
       if (callbacks->writeready) {
+        NPPAutoPusher nppPusher(npp);
+
         NS_TRY_SAFE_CALL_RETURN(numtowrite, (*callbacks->writeready)(npp, &mNPStream), mInst->mLibrary, mInst);
         NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY,
                        ("NPP WriteReady called: this=%p, npp=%p, "
                         "return(towrite)=%d, url=%s\n",
                         this, npp, numtowrite, mNPStream.url));
 
         if (!mStreamStarted) {
           // The plugin called NPN_DestroyStream() from within
@@ -638,16 +646,18 @@ nsNPAPIPluginStreamListener::OnDataAvail
 
         numtowrite = PR_MIN(numtowrite, mStreamBufferByteCount);
       } else {
         // if WriteReady is not supported by the plugin, just write
         // the whole buffer
         numtowrite = mStreamBufferByteCount;
       }
 
+      NPPAutoPusher nppPusher(npp);
+
       PRInt32 writeCount = 0; // bytes consumed by plugin instance
       NS_TRY_SAFE_CALL_RETURN(writeCount, (*callbacks->write)(npp, &mNPStream, streamPosition, numtowrite, ptrStreamBuffer), mInst->mLibrary, mInst);
 
       NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY,
                      ("NPP Write called: this=%p, npp=%p, pos=%d, len=%d, "
                       "buf=%s, return(written)=%d,  url=%s\n",
                       this, npp, streamPosition, numtowrite,
                       ptrStreamBuffer, writeCount, mNPStream.url));
@@ -743,17 +753,17 @@ nsNPAPIPluginStreamListener::OnFileAvail
   const NPPluginFuncs *callbacks = nsnull;
   mInst->GetCallbacks(&callbacks);
   if (!callbacks || !callbacks->asfile)
     return NS_ERROR_FAILURE;
   
   NPP npp;
   mInst->GetNPP(&npp);
 
-  PRLibrary* lib = nsnull;
+  PluginLibrary* lib = nsnull;
   lib = mInst->mLibrary;
 
   NS_TRY_SAFE_CALL_VOID((*callbacks->asfile)(npp, &mNPStream, fileName), lib, mInst);
 
   NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
   ("NPP StreamAsFile called: this=%p, npp=%p, url=%s, file=%s\n",
   this, npp, mNPStream.url, fileName));
 
@@ -897,17 +907,17 @@ nsNPAPIPluginInstance::nsNPAPIPluginInst
     mStreams(nsnull),
     mMIMEType(nsnull),
     mShadow(aShadow)
 {
 }
 #endif
 
 nsNPAPIPluginInstance::nsNPAPIPluginInstance(NPPluginFuncs* callbacks,
-                                       PRLibrary* aLibrary)
+                                             PluginLibrary* aLibrary)
   : mCallbacks(callbacks),
 #ifdef XP_MACOSX
 #ifdef NP_NO_QUICKDRAW
     mDrawingModel(NPDrawingModelCoreGraphics),
 #else
     mDrawingModel(NPDrawingModelQuickDraw),
 #endif
 #endif
@@ -1287,18 +1297,16 @@ nsNPAPIPluginInstance::InitializePlugin(
         NS_ASSERTION(!values[count], "attribute/parameter array not setup correctly for NPAPI plugins");
         if (pcount)
           count += ++pcount; // if it's all setup correctly, then all we need is to
                              // change the count (attrs + PARAM/blank + params)
       }
     }
   }
 
-  NS_ENSURE_TRUE(mCallbacks->newp, NS_ERROR_FAILURE);
-  
   // XXX Note that the NPPluginType_* enums were crafted to be
   // backward compatible...
   
   nsPluginMode  mode;
   const char*   mimetype;
   NPError       error;
 
   GetMode(&mode);
@@ -1357,17 +1365,22 @@ nsNPAPIPluginInstance::InitializePlugin(
   // Mark this instance as started before calling NPP_New because the plugin may
   // call other NPAPI functions, like NPN_GetURLNotify, that assume this is set
   // before returning. If the plugin returns failure, we'll clear it out below.
   mStarted = PR_TRUE;
 
   PRBool oldVal = mInPluginInitCall;
   mInPluginInitCall = PR_TRUE;
 
-  NS_TRY_SAFE_CALL_RETURN(error, (*mCallbacks->newp)((char*)mimetype, &mNPP, (PRUint16)mode, count, (char**)names, (char**)values, NULL), mLibrary,this);
+  // Need this on the stack before calling NPP_New otherwise some callbacks that
+  // the plugin may make could fail (NPN_HasProperty, for example).
+  NPPAutoPusher autopush(&mNPP);
+  nsresult newResult = mLibrary->NPP_New((char*)mimetype, &mNPP, (PRUint16)mode, count, (char**)names, (char**)values, NULL, &error);
+  if (NS_FAILED(newResult))
+    return newResult;
 
   mInPluginInitCall = oldVal;
 
   NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
   ("NPP New called: this=%p, npp=%p, mime=%s, mode=%d, argc=%d, return=%d\n",
   this, &mNPP, mimetype, mode, count, error));
 
   if (error != NPERR_NO_ERROR) {
@@ -1406,16 +1419,18 @@ NS_IMETHODIMP nsNPAPIPluginInstance::Set
     // XXX Turns out that NPPluginWindow and NPWindow are structurally
     // identical (on purpose!), so there's no need to make a copy.
 
     PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::SetWindow (about to call it) this=%p\n",this));
 
     PRBool oldVal = mInPluginInitCall;
     mInPluginInitCall = PR_TRUE;
 
+    NPPAutoPusher nppPusher(&mNPP);
+
     NS_TRY_SAFE_CALL_RETURN(error, (*mCallbacks->setwindow)(&mNPP, (NPWindow*)window), mLibrary, this);
 
     mInPluginInitCall = oldVal;
 
     NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
     ("NPP SetWindow called: this=%p, [x=%d,y=%d,w=%d,h=%d], clip[t=%d,b=%d,l=%d,r=%d], return=%d\n",
     this, window->x, window->y, window->width, window->height,
     window->clipRect.top, window->clipRect.bottom, window->clipRect.left, window->clipRect.right, error));
--- a/modules/plugin/base/src/nsNPAPIPluginInstance.h
+++ b/modules/plugin/base/src/nsNPAPIPluginInstance.h
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -53,17 +53,17 @@
 #include "nsIPluginInstancePeer2.h"
 #include "nsPIPluginInstancePeer.h"
 #include "nsIScriptablePlugin.h"
 #include "nsIPluginInstanceInternal.h"
 #include "nsIJVMPluginInstance.h"
 #endif
 
 #include "npfunctions.h"
-#include "prlink.h"
+#include "mozilla/PluginLibrary.h"
 
 class nsNPAPIPluginStreamListener;
 class nsPIDOMWindow;
 
 struct nsInstanceStream
 {
   nsInstanceStream *mNext;
   nsNPAPIPluginStreamListener *mPluginStreamListener;
@@ -84,16 +84,19 @@ public:
 class nsNPAPIPluginInstance : public nsIPluginInstance
 #ifdef OJI
                              ,public nsIPluginInstanceOld,
                               public nsIScriptablePlugin,
                               public nsIPluginInstanceInternal,
                               public nsIJVMPluginInstance
 #endif
 {
+private:
+  typedef mozilla::PluginLibrary PluginLibrary;
+
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPLUGININSTANCE
 
 #ifdef OJI
   NS_DECL_NSISCRIPTABLEPLUGIN
   NS_DECL_NSIJVMPLUGININSTANCE
 
@@ -138,17 +141,17 @@ public:
                            void* notifyData, 
                            PRBool aCallNotify,
                            const char * aURL);
 
 #ifdef OJI
   nsNPAPIPluginInstance(nsIPluginInstanceOld *aShadow);
 #endif
 
-  nsNPAPIPluginInstance(NPPluginFuncs* callbacks, PRLibrary* aLibrary);
+  nsNPAPIPluginInstance(NPPluginFuncs* callbacks, PluginLibrary* aLibrary);
 
   // Use Release() to destroy this
   virtual ~nsNPAPIPluginInstance();
 
   // returns the state of mStarted
   PRBool IsStarted();
 
   // cache this NPAPI plugin
@@ -196,17 +199,17 @@ protected:
   PRPackedBool mTransparent;
   PRPackedBool mStarted;
   PRPackedBool mCached;
   PRPackedBool mWantsAllNetworkStreams;
 
 public:
   // True while creating the plugin, or calling NPP_SetWindow() on it.
   PRPackedBool mInPluginInitCall;
-  PRLibrary* mLibrary;
+  PluginLibrary* mLibrary;
   nsInstanceStream *mStreams;
 
 private:
   nsTArray<PopupControlState> mPopupStates;
 
   char* mMIMEType;
 
   // Weak pointer to the owner. The owner nulls this out (by calling
--- a/modules/plugin/base/src/nsNPAPIPluginStreamListener.h
+++ b/modules/plugin/base/src/nsNPAPIPluginStreamListener.h
@@ -49,16 +49,19 @@
 
 class nsNPAPIPluginInstance;
 class nsINPAPIPluginStreamInfo;
 
 class nsNPAPIPluginStreamListener : public nsIPluginStreamListener,
                                  public nsITimerCallback,
                                  public nsIHTTPHeaderListener
 {
+private:
+  typedef mozilla::PluginLibrary PluginLibrary;
+
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPLUGINSTREAMLISTENER
   NS_DECL_NSITIMERCALLBACK
   NS_DECL_NSIHTTPHEADERLISTENER
 
   // nsNPAPIPluginStreamListener specific methods:
   nsNPAPIPluginStreamListener(nsNPAPIPluginInstance* inst, void* notifyData,
--- a/modules/plugin/base/src/nsPluginHost.cpp
+++ b/modules/plugin/base/src/nsPluginHost.cpp
@@ -3613,26 +3613,26 @@ nsPluginHost::TrySetUpPluginInstance(con
   GetPlugin(mimetype, getter_AddRefs(plugin));
 
   if (plugin) {
 #if defined(XP_WIN) && !defined(WINCE)
     static BOOL firstJavaPlugin = FALSE;
     BOOL restoreOrigDir = FALSE;
     char origDir[_MAX_PATH];
     if (pluginTag->mIsJavaPlugin && !firstJavaPlugin) {
-      DWORD dw = ::GetCurrentDirectory(_MAX_PATH, origDir);
+      DWORD dw = GetCurrentDirectoryA(_MAX_PATH, origDir);
       NS_ASSERTION(dw <= _MAX_PATH, "Falied to obtain the current directory, which may leads to incorrect class laoding");
       nsCOMPtr<nsIFile> binDirectory;
       result = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR,
                                       getter_AddRefs(binDirectory));
 
       if (NS_SUCCEEDED(result)) {
         nsCAutoString path;
         binDirectory->GetNativePath(path);
-        restoreOrigDir = ::SetCurrentDirectory(path.get());
+        restoreOrigDir = SetCurrentDirectoryA(path.get());
       }
     }
 #endif
 #ifdef OJI
     nsNPAPIPlugin *pluginPriv = static_cast<nsNPAPIPlugin*>(plugin.get());
     nsIPluginOld *shadowPlugin = pluginPriv->GetShadow();
     if (shadowPlugin) {
       nsIPluginInstanceOld *shadowInstance = nsnull;
@@ -3650,17 +3650,17 @@ nsPluginHost::TrySetUpPluginInstance(con
       result = plugin->CreatePluginInstance(getter_AddRefs(instance));
     }
 #else
     result = plugin->CreatePluginInstance(getter_AddRefs(instance));
 #endif
 
 #if defined(XP_WIN) && !defined(WINCE)
     if (!firstJavaPlugin && restoreOrigDir) {
-      BOOL bCheck = ::SetCurrentDirectory(origDir);
+      BOOL bCheck = SetCurrentDirectoryA(origDir);
       NS_ASSERTION(bCheck, " Error restoring driectoy");
       firstJavaPlugin = TRUE;
     }
 #endif
   }
 
   if (NS_FAILED(result))
     return result;
@@ -4186,16 +4186,17 @@ NS_IMETHODIMP nsPluginHost::GetPlugin(co
     }
 #else
     if (!plugin) {
       // Now lets try to get the entry point from an NPAPI plugin
       rv = CreateNPAPIPlugin(pluginTag, getter_AddRefs(plugin));
       if (NS_FAILED(rv))
         return rv;
 
+      NS_ASSERTION(plugin, "CreateNPAPIPlugin succeeded without setting 'plugin'");
       pluginTag->mEntryPoint = plugin;
     }
 #endif
 
     if (!plugin)
       return NS_ERROR_FAILURE;
 
 
--- a/modules/plugin/base/src/nsPluginNativeWindowWin.cpp
+++ b/modules/plugin/base/src/nsPluginNativeWindowWin.cpp
@@ -528,16 +528,20 @@ nsresult nsPluginNativeWindowWin::Subcla
   if (!hWnd)
     return NS_ERROR_FAILURE;
 
   // check if we need to re-subclass
   WNDPROC currentWndProc = (WNDPROC)::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
   if (PluginWndProc == currentWndProc)
     return NS_OK;
 
+  LONG style = GetWindowLongPtr(hWnd, GWL_STYLE);
+  style |= WS_CLIPCHILDREN;
+  SetWindowLongPtr(hWnd, GWL_STYLE, style);
+
   mPluginWinProc = SubclassWindow(hWnd, (LONG_PTR)PluginWndProc);
   if (!mPluginWinProc)
     return NS_ERROR_FAILURE;
 
   nsPluginNativeWindowWin * win = (nsPluginNativeWindowWin *)::GetProp(hWnd, NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION);
   NS_ASSERTION(!win || (win == this), "plugin window already has property and this is not us");
   
   if (!::SetProp(hWnd, NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION, (HANDLE)this))
@@ -557,16 +561,20 @@ nsresult nsPluginNativeWindowWin::UndoSu
     ::RemoveProp(hWnd, NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION);
 
   // restore the original win proc
   // but only do this if this were us last time
   if (mPluginWinProc) {
     WNDPROC currentWndProc = (WNDPROC)::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
     if (currentWndProc == PluginWndProc)
       SubclassWindow(hWnd, (LONG_PTR)mPluginWinProc);
+
+    LONG style = GetWindowLongPtr(hWnd, GWL_STYLE);
+    style &= ~WS_CLIPCHILDREN;
+    SetWindowLongPtr(hWnd, GWL_STYLE, style);
   }
 
   return NS_OK;
 }
 #endif // WINCE
 
 nsresult PLUG_NewPluginNativeWindow(nsPluginNativeWindow ** aPluginNativeWindow)
 {
--- a/modules/plugin/base/src/nsPluginSafety.h
+++ b/modules/plugin/base/src/nsPluginSafety.h
@@ -73,17 +73,17 @@ PR_BEGIN_MACRO                          
     {                                              \
       ret = fun;                                   \
     }                                              \
     catch(...)                                     \
     {                                              \
       nsresult res;                                \
       nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &res));\
       if(NS_SUCCEEDED(res) && (host != nsnull))    \
-        host->HandleBadPlugin(library, pluginInst);\
+        host->HandleBadPlugin(nsnull, pluginInst); \
       ret = (NPError)NS_ERROR_FAILURE;             \
     }                                              \
   }                                                \
   NS_NotifyPluginCall(startTime);		   \
 PR_END_MACRO
 
 #define NS_TRY_SAFE_CALL_VOID(fun, library, pluginInst) \
 PR_BEGIN_MACRO                              \
@@ -96,17 +96,17 @@ PR_BEGIN_MACRO                          
     {                                       \
       fun;                                  \
     }                                       \
     catch(...)                              \
     {                                       \
       nsresult res;                         \
       nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &res));\
       if(NS_SUCCEEDED(res) && (host != nsnull))\
-        host->HandleBadPlugin(library, pluginInst);\
+        host->HandleBadPlugin(nsnull, pluginInst);\
     }                                       \
   }                                         \
   NS_NotifyPluginCall(startTime);		   \
 PR_END_MACRO
 
 #else // vanilla calls
 
 #define NS_TRY_SAFE_CALL_RETURN(ret, fun, library, pluginInst) \
--- a/modules/plugin/base/src/nsPluginsDirWin.cpp
+++ b/modules/plugin/base/src/nsPluginsDirWin.cpp
@@ -234,30 +234,30 @@ nsresult nsPluginFile::LoadPlugin(PRLibr
   if (!index) {
     PL_strfree(pluginFolderPath);
     return NS_ERROR_FILE_INVALID_PATH;
   }
   *index = 0;
 
   BOOL restoreOrigDir = FALSE;
   char aOrigDir[MAX_PATH + 1];
-  DWORD dwCheck = ::GetCurrentDirectory(sizeof(aOrigDir), aOrigDir);
+  DWORD dwCheck = GetCurrentDirectoryA(sizeof(aOrigDir), aOrigDir);
   NS_ASSERTION(dwCheck <= MAX_PATH + 1, "Error in Loading plugin");
 
   if (dwCheck <= MAX_PATH + 1) {
-    restoreOrigDir = ::SetCurrentDirectory(pluginFolderPath);
+    restoreOrigDir = SetCurrentDirectoryA(pluginFolderPath);
     NS_ASSERTION(restoreOrigDir, "Error in Loading plugin");
   }
 #endif
 
   outLibrary = PR_LoadLibrary(temp.get());
 
 #ifndef WINCE    
   if (restoreOrigDir) {
-    BOOL bCheck = ::SetCurrentDirectory(aOrigDir);
+    BOOL bCheck = SetCurrentDirectoryA(aOrigDir);
     NS_ASSERTION(bCheck, "Error in Loading plugin");
   }
 
   PL_strfree(pluginFolderPath);
 #endif
 
   return NS_OK;
 }
--- a/modules/plugin/test/mochitest/Makefile.in
+++ b/modules/plugin/test/mochitest/Makefile.in
@@ -54,18 +54,28 @@ include $(topsrcdir)/config/rules.mk
 		test_pluginstream_src.html \
 		test_pluginstream_geturl.html \
 		test_pluginstream_geturlnotify.html \
 		test_pluginstream_asfile.html \
 		test_pluginstream_asfileonly.html \
 		test_pluginstream_post.html \
 		test_pluginstream_poststream.html \
 		test_pluginstream_seek.html \
+		test_streamNotify.html \
 		$(NULL)
 
+#		test_npruntime_npnsetexception.html \ Disabled for e10s
+
+#ifdef MOZ_IPC
+#_MOCHITEST_FILES += \
+#		test_crashing.html \
+#		crashing_subpage.html \
+#		$(NULL)
+#endif
+
 _MOCHICHROME_FILES = \
 		test_bug479979.xul \
 		test_npruntime.xul   \
 		test_privatemode.xul \
 		test_wmode.xul \
 		$(NULL)
 
 libs:: $(_MOCHICHROME_FILES)
new file mode 100644
--- /dev/null
+++ b/modules/plugin/test/mochitest/crashing_subpage.html
@@ -0,0 +1,4 @@
+<html>
+<body onload="window.parent.frameLoaded()">
+  <h1>Crashing subpage</h1>
+  <embed id="plugin1" type="application/x-test" width="400" height="400" drawmode="solid" color="FF00FFFF"></embed>
new file mode 100644
--- /dev/null
+++ b/modules/plugin/test/mochitest/test_crashing.html
@@ -0,0 +1,59 @@
+<head>
+  <title>Plugin crashing</title>
+  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body>
+  <iframe id="iframe1" src="crashing_subpage.html" width="600" height="600"></iframe>
+
+  <script class="testbody" type="application/javascript">
+  SimpleTest.waitForExplicitFinish();
+
+  var iframe = document.getElementById('iframe1');
+
+  window.frameLoaded = function frameLoaded_toCrash() {
+    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+    var prefs = Components.classes['@mozilla.org/preferences-service;1']
+      .getService(Components.interfaces.nsIPrefBranch);
+    if (!prefs.getBoolPref('dom.ipc.plugins.enabled')) {
+      ok(true, "Skipping this test when IPC plugins are not enabled.");
+      SimpleTest.finish();
+      return;
+    }
+
+    var p = iframe.contentDocument.getElementById('plugin1');
+
+    p.setColor("FFFF00FF");
+
+    try {
+      p.crash();
+      ok(false, "p.crash() should throw an exception");
+    }
+    catch (e) {
+      ok(true, "p.crash() should throw an exception");
+    }
+
+    try {
+      p.setColor("FFFF0000");
+      ok(false, "p.setColor should throw after the plugin crashes");
+    }
+    catch (e) {
+      ok(true, "p.setColor should throw after the plugin crashes");
+    }
+
+    window.frameLoaded = function reloaded() {
+      var p = iframe.contentDocument.getElementById('plugin1');
+      try {
+        p.setColor('FF00FF00');
+        ok(true, "Reloading worked");
+      }
+      catch (e) {
+        ok(false, "Reloading didn't give us a usable plugin");
+      }
+      SimpleTest.finish();
+    }
+
+    iframe.contentWindow.location.reload();
+  }
+
+  </script>
new file mode 100644
--- /dev/null
+++ b/modules/plugin/test/mochitest/test_streamNotify.html
@@ -0,0 +1,55 @@
+<head>
+  <title>NPN_Get/PostURLNotify tests</title>
+  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body onload="runTests()">
+  <embed id="plugin1" type="application/x-test" width="400" height="400"></embed>
+
+  <script class="testbody" type="application/javascript">
+  SimpleTest.waitForExplicitFinish();
+
+  var pending = 4;
+  function testDone() {
+    dump("testDone: " + pending + "\n")
+    --pending;
+    if (0 == pending)
+      SimpleTest.finish();
+  }
+
+  function runTests() {
+    var p = document.getElementById('plugin1');
+
+    ok(p.streamTest("loremipsum.txt", false, null,
+                    function(r, t) {
+                      is(r, 0, "GET loremipsum.txt");
+                      is(t.substr(0, 11), "Lorem ipsum",
+                         "GET loremipsum.txt correct");
+                      testDone();
+                    }), "streamTest GET");
+
+    ok(!p.streamTest("post.sjs", true, null,
+                     function(r, t) {
+                       ok(false, "Shouldn't get callback from null post");
+                     }), "streamTest POST null postdata");
+
+    ok(p.streamTest("post.sjs", true, "Something good",
+                    function(r, t) {
+                      is(r, 0, "POST something good");
+                      is(t, "Something good", "POST non-null correct");
+                      testDone();
+                    }), "streamTest POST valid postdata");
+
+    ok(p.streamTest("http://example.invalid/", false, null,
+                    function(r, t) {
+                      is(r, 1, "Shouldn't load example.invalid DNS name");
+                      testDone();
+                    }), "streamTest GET bad DNS");
+
+    ok(p.streamTest("http://localhost:-8/", false, null,
+                    function(r, t) {
+                      is(r, 1, "Shouldn't load invalid URI");
+                      testDone();
+                    }), "streamTest GET invalid URL");
+  }
+  </script>
--- a/testing/testsuite-targets.mk
+++ b/testing/testsuite-targets.mk
@@ -42,17 +42,17 @@
 ifdef TEST_PATH
 TEST_PATH_ARG := --test-path=$(TEST_PATH)
 else
 TEST_PATH_ARG :=
 endif
 
 
 # Usage: |make [TEST_PATH=...] [EXTRA_TEST_ARGS=...] mochitest*|.
-mochitest:: mochitest-plain mochitest-chrome mochitest-a11y
+mochitest:: mochitest-plain mochitest-chrome mochitest-a11y mochitest-ipcplugins
 
 RUN_MOCHITEST = \
 	rm -f ./$@.log && \
 	$(PYTHON) _tests/testing/mochitest/runtests.py --autorun --close-when-done \
 	  --console-level=INFO --log-file=./$@.log --file-level=INFO \
 	  $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS)
 
 ifndef NO_FAIL_ON_TEST_ERRORS
@@ -76,16 +76,20 @@ mochitest-chrome:
 	$(RUN_MOCHITEST) --chrome
 	$(CHECK_TEST_ERROR)
 
 mochitest-a11y:
 	$(RUN_MOCHITEST) --a11y
 	$(CHECK_TEST_ERROR)
 
 
+mochitest-ipcplugins:
+	$(RUN_MOCHITEST) --setpref=dom.ipc.plugins.enabled=true --test-path=modules/plugin/test
+	$(CHECK_TEST_ERROR)
+
 # Usage: |make [EXTRA_TEST_ARGS=...] *test|.
 RUN_REFTEST = rm -f ./$@.log && $(PYTHON) _tests/reftest/runreftest.py $(EXTRA_TEST_ARGS) $(1) | tee ./$@.log
 
 reftest:
 	$(call RUN_REFTEST,$(topsrcdir)/layout/reftests/reftest.list)
 	$(CHECK_TEST_ERROR)
 
 crashtest:
@@ -137,13 +141,13 @@ stage-reftest: make-stage-dir
 
 stage-xpcshell: make-stage-dir
 	$(MAKE) -C $(DEPTH)/testing/xpcshell stage-package
 
 stage-jstests: make-stage-dir
 	$(MAKE) -C $(DEPTH)/js/src/tests stage-package
 
 .PHONY: \
-  mochitest mochitest-plain mochitest-chrome mochitest-a11y \
+  mochitest mochitest-plain mochitest-chrome mochitest-a11y mochitest-ipcplugins \
   reftest crashtest \
   xpcshell-tests \
   jstestbrowser \
   package-tests make-stage-dir stage-mochitest stage-reftest stage-xpcshell stage-jstests
--- a/toolkit/library/dlldeps-xul.cpp
+++ b/toolkit/library/dlldeps-xul.cpp
@@ -44,9 +44,18 @@ void xxxNeverCalledXUL()
   XRE_GetStaticComponents(nsnull, nsnull);
   XRE_LockProfileDirectory(nsnull, nsnull);
   XRE_InitEmbedding(nsnull, nsnull, nsnull, nsnull, 0);
   XRE_NotifyProfile();
   XRE_TermEmbedding();
   XRE_CreateAppData(nsnull, nsnull);
   XRE_ParseAppData(nsnull, nsnull);
   XRE_FreeAppData(nsnull);
+  XRE_ChildProcessTypeToString(GeckoProcessType_Default);
+  XRE_StringToChildProcessType("");
+  XRE_GetProcessType();
+#ifdef MOZ_IPC
+  XRE_InitChildProcess(0, nsnull, GeckoProcessType_Default);
+  XRE_InitParentProcess(0, nsnull, nsnull, nsnull);
+  XRE_RunAppShell();
+  XRE_ShutdownChildProcess();
+#endif
 }
--- a/toolkit/library/libxul-config.mk
+++ b/toolkit/library/libxul-config.mk
@@ -86,16 +86,37 @@ ifdef MOZ_ENABLE_LIBXUL
 RESFILE = xulrunos2.res
 RCFLAGS += -i $(topsrcdir)/widget/src/os2
 endif
 
 LOCAL_INCLUDES += -I$(topsrcdir)/widget/src/os2
 endif
 
 # dependent libraries
+ifdef MOZ_IPC
+STATIC_LIBS += \
+  domplugins_s \
+  mozipc_s \
+  mozipdlgen_s \
+  chromium_s \
+  gfxipc_s \
+  $(NULL)
+
+ifdef MOZ_IPDL_TESTS
+STATIC_LIBS += ipdlunittest_s
+endif
+
+ifeq (Linux,$(OS_ARCH))
+OS_LIBS += -lrt
+endif
+ifeq (WINNT,$(OS_ARCH))
+OS_LIBS += psapi.lib dbghelp.lib
+endif
+endif
+
 STATIC_LIBS += \
 	xpcom_core \
 	ucvutil_s \
 	gkgfx \
 	$(NULL)
 
 #ifndef MOZ_EMBEDDING_LEVEL_DEFAULT
 ifndef WINCE
--- a/toolkit/toolkit-makefiles.sh
+++ b/toolkit/toolkit-makefiles.sh
@@ -43,16 +43,21 @@ MAKEFILES_db="
   db/mdb/Makefile
   db/mdb/public/Makefile
   db/mork/Makefile
   db/mork/build/Makefile
   db/mork/src/Makefile
 "
 
 MAKEFILES_dom="
+  ipc/Makefile
+  ipc/chromium/Makefile
+  ipc/glue/Makefile
+  ipc/ipdl/Makefile
+  ipc/testshell/Makefile
   dom/Makefile
   dom/public/coreEvents/Makefile
   dom/interfaces/base/Makefile
   dom/interfaces/canvas/Makefile
   dom/interfaces/core/Makefile
   dom/interfaces/css/Makefile
   dom/interfaces/events/Makefile
   dom/interfaces/geolocation/Makefile
@@ -75,16 +80,18 @@ MAKEFILES_dom="
   dom/src/events/Makefile
   dom/src/jsurl/Makefile
   dom/src/geolocation/Makefile
   dom/src/json/Makefile
   dom/src/offline/Makefile
   dom/src/storage/Makefile
   dom/src/threads/Makefile
   dom/locales/Makefile
+  dom/plugins/Makefile
+  dom/ipc/Makefile
 "
 
 MAKEFILES_editor="
   editor/Makefile
   editor/public/Makefile
   editor/idl/Makefile
   editor/txmgr/Makefile
   editor/txmgr/idl/Makefile
--- a/toolkit/toolkit-tiers.mk
+++ b/toolkit/toolkit-tiers.mk
@@ -76,16 +76,20 @@ tier_external_dirs	+= gfx/qcms
 ifeq ($(OS_ARCH),WINCE)
 tier_external_dirs += modules/lib7z
 endif
 
 #
 # tier "gecko" - core components
 #
 
+ifdef MOZ_IPC
+tier_gecko_dirs += ipc
+endif
+
 tier_gecko_dirs += \
 		js/src/xpconnect \
 		js/ctypes \
 		intl/chardet \
 		$(NULL)
 
 ifdef BUILD_CTYPES
 ifndef _MSC_VER
--- a/toolkit/xre/Makefile.in
+++ b/toolkit/xre/Makefile.in
@@ -197,18 +197,22 @@ SHARED_LIBRARY_LIBS += \
   $(NULL)
 endif
 endif
 
 ifdef ENABLE_TESTS
 DIRS += test
 endif
 
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
+LOCAL_INCLUDES += -I$(topsrcdir)/dom/ipc
+
 ifdef BUILD_STATIC_LIBS
 export::
 	@$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_COMP_NAMES) Apprunner
 #	embedding/browser/gtk/src/Makefile.in sucks! we need to add an empty line to 
 # FINAL_LINK_COMPS to keep the two lists in sync :-(
 	@$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_COMPS) ""
 endif
 
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -203,16 +203,20 @@
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #include "nsICrashReporter.h"
 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
 #include "nsIPrefService.h"
 #endif
 
+#ifdef MOZ_IPC
+#include "base/command_line.h"
+#endif
+
 #ifdef WINCE
 class WindowsMutex {
 public:
   WindowsMutex(const wchar_t *name) {
     mHandle = CreateMutexW(0, FALSE, name);
   }
 
   ~WindowsMutex() {
@@ -3028,16 +3032,19 @@ XRE_main(int argc, char* argv[], const n
   }
     
 #ifdef NS_TRACE_MALLOC
   gArgc = argc = NS_TraceMallocStartupArgs(gArgc, gArgv);
 #endif
 
   MOZ_SPLASHSCREEN_UPDATE(20);
 
+  rv = XRE_InitCommandLine(gArgc, gArgv);
+  NS_ENSURE_SUCCESS(rv, 1);
+
   {
     nsXREDirProvider dirProvider;
     rv = dirProvider.Initialize(gAppData->directory, gAppData->xreDirectory);
     if (NS_FAILED(rv))
       return 1;
 
     // Check for -register, which registers chrome and then exits immediately.
     ar = CheckArg("register", PR_TRUE);
@@ -3496,23 +3503,24 @@ XRE_main(int argc, char* argv[], const n
                                      PromiseFlatCString(profileName).get());
 #endif /* MOZ_ENABLE_XREMOTE */
 
             // enable win32 DDE responses and Mac appleevents responses
             nativeApp->Enable();
           }
 
           MOZ_SPLASHSCREEN_UPDATE(90);
-
-          NS_TIMELINE_ENTER("appStartup->Run");
-          rv = appStartup->Run();
-          NS_TIMELINE_LEAVE("appStartup->Run");
-          if (NS_FAILED(rv)) {
-            NS_ERROR("failed to run appstartup");
-            gLogConsoleErrors = PR_TRUE;
+          {
+            NS_TIMELINE_ENTER("appStartup->Run");
+            rv = appStartup->Run();
+            NS_TIMELINE_LEAVE("appStartup->Run");
+            if (NS_FAILED(rv)) {
+              NS_ERROR("failed to run appstartup");
+              gLogConsoleErrors = PR_TRUE;
+            }
           }
 
           // Check for an application initiated restart.  This is one that
           // corresponds to nsIAppStartup.quit(eRestart)
           if (rv == NS_SUCCESS_RESTART_APP) {
             needsRestart = PR_TRUE;
             appInitiatedRestart = PR_TRUE;
           }
@@ -3621,10 +3629,12 @@ XRE_main(int argc, char* argv[], const n
 #endif
   }
 
 #ifdef MOZ_CRASHREPORTER
   if (appData.flags & NS_XRE_ENABLE_CRASH_REPORTER)
       CrashReporter::UnsetExceptionHandler();
 #endif
 
+  XRE_DeinitCommandLine();
+
   return NS_FAILED(rv) ? 1 : 0;
 }
--- a/toolkit/xre/nsConsoleWriter.cpp
+++ b/toolkit/xre/nsConsoleWriter.cpp
@@ -29,16 +29,20 @@
  * 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 ***** */
 
+#ifdef NO_NSPR_10_SUPPORT
+#undef NO_NSPR_10_SUPPORT
+#endif
+
 #include "nsAppRunner.h"
 
 #include "prio.h"
 #include "prprf.h"
 #include "prtime.h"
 #include "prenv.h"
 
 #include "nsCRT.h"
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -30,32 +30,81 @@
  * 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 ***** */
 
+#ifdef MOZ_IPC
+#include "base/basictypes.h"
+#endif
+
 #include "nsXULAppAPI.h"
 
 #include <stdlib.h>
+#if defined(MOZ_WIDGET_GTK2)
+#include <glib.h>
+#endif
 
+#include "prenv.h"
+
+#include "nsIAppShell.h"
 #include "nsIAppStartupNotifier.h"
 #include "nsIDirectoryService.h"
 #include "nsILocalFile.h"
 #include "nsIToolkitChromeRegistry.h"
+#include "nsIToolkitProfile.h"
 
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsAppRunner.h"
+#include "nsAutoRef.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsStaticComponents.h"
 #include "nsString.h"
+#include "nsThreadUtils.h"
+#include "nsWidgetsCID.h"
+#include "nsXPFEComponentsCID.h"
 #include "nsXREDirProvider.h"
-#include "nsIToolkitProfile.h"
+
+#ifdef MOZ_IPC
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/message_loop.h"
+#include "base/process_util.h"
+#include "chrome/common/child_process.h"
+
+#include "mozilla/ipc/GeckoChildProcessHost.h"
+#include "mozilla/ipc/GeckoThread.h"
+#include "ScopedXREEmbed.h"
+
+#include "mozilla/plugins/PluginThreadChild.h"
+
+#include "mozilla/Monitor.h"
+
+#ifdef MOZ_IPDL_TESTS
+#include "mozilla/_ipdltest/IPDLUnitTests.h"
+#include "mozilla/_ipdltest/IPDLUnitTestThreadChild.h"
+
+using mozilla::_ipdltest::IPDLUnitTestThreadChild;
+#endif  // ifdef MOZ_IPDL_TESTS
+
+using mozilla::ipc::GeckoChildProcessHost;
+using mozilla::ipc::GeckoThread;
+using mozilla::ipc::BrowserProcessSubThread;
+using mozilla::ipc::ScopedXREEmbed;
+
+using mozilla::plugins::PluginThreadChild;
+
+using mozilla::Monitor;
+using mozilla::MonitorAutoEnter;
+#endif
+
+static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 void
 XRE_GetStaticComponents(nsStaticModuleInfo const **aStaticComponents,
                         PRUint32 *aComponentCount)
 {
   *aStaticComponents = kPStaticModules;
   *aComponentCount = kStaticModuleCount;
 }
@@ -156,8 +205,313 @@ XRE_TermEmbedding()
   NS_ASSERTION(gDirServiceProvider,
                "XRE_TermEmbedding without XRE_InitEmbedding");
 
   gDirServiceProvider->DoShutdown();
   NS_ShutdownXPCOM(nsnull);
   delete [] sCombined;
   delete gDirServiceProvider;
 }
+
+const char*
+XRE_ChildProcessTypeToString(GeckoProcessType aProcessType)
+{
+  return (aProcessType < GeckoProcessType_End) ?
+    kGeckoProcessTypeString[aProcessType] : nsnull;
+}
+
+GeckoProcessType
+XRE_StringToChildProcessType(const char* aProcessTypeString)
+{
+  for (int i = 0;
+       i < (int) NS_ARRAY_LENGTH(kGeckoProcessTypeString);
+       ++i) {
+    if (!strcmp(kGeckoProcessTypeString[i], aProcessTypeString)) {
+      return static_cast<GeckoProcessType>(i);
+    }
+  }
+  return GeckoProcessType_Invalid;
+}
+
+#ifdef MOZ_IPC
+static GeckoProcessType sChildProcessType = GeckoProcessType_Default;
+
+static MessageLoop* sIOMessageLoop;
+
+nsresult
+XRE_InitChildProcess(int aArgc,
+                     char* aArgv[],
+                     GeckoProcessType aProcess)
+{
+  NS_ENSURE_ARG_MIN(aArgc, 2);
+  NS_ENSURE_ARG_POINTER(aArgv);
+  NS_ENSURE_ARG_POINTER(aArgv[0]);
+
+  sChildProcessType = aProcess;
+  
+#if defined(MOZ_WIDGET_GTK2)
+  g_thread_init(NULL);
+#endif
+
+  if (PR_GetEnv("MOZ_DEBUG_CHILD_PROCESS")) {
+#ifdef OS_POSIX
+      printf("\n\nCHILDCHILDCHILDCHILD\n  debug me @%d\n\n", getpid());
+      sleep(30);
+#elif defined(OS_WIN)
+      Sleep(30000);
+#endif
+  }
+
+  // child processes launched by GeckoChildProcessHost get this magic
+  // argument appended to their command lines
+  const char* const parentPIDString = aArgv[aArgc-1];
+  NS_ABORT_IF_FALSE(parentPIDString, "NULL parent PID");
+  --aArgc;
+
+  char* end = 0;
+  base::ProcessId parentPID = strtol(parentPIDString, &end, 10);
+  NS_ABORT_IF_FALSE(!*end, "invalid parent PID");
+
+  base::ProcessHandle parentHandle;
+  bool ok = base::OpenProcessHandle(parentPID, &parentHandle);
+  NS_ABORT_IF_FALSE(ok, "can't open handle to parent");
+
+  base::AtExitManager exitManager;
+
+  NS_LogInit();
+
+  int rv = XRE_InitCommandLine(aArgc, aArgv);
+  if (NS_FAILED(rv)) {
+    NS_LogTerm();
+    return NS_ERROR_FAILURE;
+  }
+
+  MessageLoopForIO mainMessageLoop;
+
+  {
+    ChildThread* mainThread;
+
+    switch (aProcess) {
+    case GeckoProcessType_Default:
+      mainThread = new GeckoThread(parentHandle);
+      break;
+
+    case GeckoProcessType_Plugin:
+      mainThread = new PluginThreadChild(parentHandle);
+      break;
+
+    case GeckoProcessType_IPDLUnitTest:
+#ifdef MOZ_IPDL_TESTS
+      mainThread = new IPDLUnitTestThreadChild(parentHandle);
+#else
+      NS_RUNTIMEABORT("rebuild with --enable-ipdl-tests");
+#endif
+      break;
+
+    default:
+      NS_RUNTIMEABORT("Unknown main thread class");
+    }
+
+    ChildProcess process(mainThread);
+
+    // Do IPC event loop
+    sIOMessageLoop = MessageLoop::current();
+
+    sIOMessageLoop->Run();
+
+    sIOMessageLoop = nsnull;
+  }
+
+  NS_LogTerm();
+  return XRE_DeinitCommandLine();
+}
+
+MessageLoop*
+XRE_GetIOMessageLoop()
+{
+  if (sChildProcessType == GeckoProcessType_Default) {
+    NS_ASSERTION(!sIOMessageLoop, "Shouldn't be set on parent process!");
+    return BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO);
+  }
+  return sIOMessageLoop;
+}
+
+namespace {
+
+class MainFunctionRunnable : public nsRunnable
+{
+public:
+  NS_DECL_NSIRUNNABLE
+
+  MainFunctionRunnable(MainFunction aFunction,
+                       void* aData)
+  : mFunction(aFunction),
+    mData(aData)
+  { 
+    NS_ASSERTION(aFunction, "Don't give me a null pointer!");
+  }
+
+private:
+  MainFunction mFunction;
+  void* mData;
+};
+
+} /* anonymous namespace */
+
+NS_IMETHODIMP
+MainFunctionRunnable::Run()
+{
+  mFunction(mData);
+  return NS_OK;
+}
+
+nsresult
+XRE_InitParentProcess(int aArgc,
+                      char* aArgv[],
+                      MainFunction aMainFunction,
+                      void* aMainFunctionData)
+{
+  NS_ENSURE_ARG_MIN(aArgc, 1);
+  NS_ENSURE_ARG_POINTER(aArgv);
+  NS_ENSURE_ARG_POINTER(aArgv[0]);
+
+  int rv = XRE_InitCommandLine(aArgc, aArgv);
+  if (NS_FAILED(rv))
+      return NS_ERROR_FAILURE;
+
+  ScopedXREEmbed embed;
+
+  {
+    embed.Start();
+
+    nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
+    NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
+
+    if (aMainFunction) {
+      nsCOMPtr<nsIRunnable> runnable =
+        new MainFunctionRunnable(aMainFunction, aMainFunctionData);
+      NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
+
+      nsresult rv = NS_DispatchToCurrentThread(runnable);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+
+    // Do event loop
+    if (NS_FAILED(appShell->Run())) {
+      NS_WARNING("Failed to run appshell");
+      return NS_ERROR_FAILURE;
+    }
+  }
+
+  return XRE_DeinitCommandLine();
+}
+
+#ifdef MOZ_IPDL_TESTS
+//-----------------------------------------------------------------------------
+// IPDL unit test
+
+int
+XRE_RunIPDLTest(int aArgc, char** aArgv)
+{
+    if (aArgc < 2) {
+        fprintf(stderr, "TEST-UNEXPECTED-FAIL | <---> | insufficient #args, need at least 2\n");
+        return 1;
+    }
+
+    void* data = reinterpret_cast<void*>(aArgv[aArgc-1]);
+
+    nsresult rv =
+        XRE_InitParentProcess(
+            --aArgc, aArgv, mozilla::_ipdltest::IPDLUnitTestMain, data);
+    NS_ENSURE_SUCCESS(rv, 1);
+
+    return 0;
+}
+#endif  // ifdef MOZ_IPDL_TESTS
+
+nsresult
+XRE_RunAppShell()
+{
+    nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
+    NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
+
+    return appShell->Run();
+}
+
+void
+XRE_ShutdownChildProcess()
+{
+    NS_ABORT_IF_FALSE(NS_IsMainThread(), "Wrong thread!");
+
+    MessageLoop* ioLoop = XRE_GetIOMessageLoop();
+    NS_ABORT_IF_FALSE(!!ioLoop, "Bad shutdown order");
+
+    ioLoop->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+}
+
+#endif // MOZ_IPC
+
+
+nsresult
+XRE_InitCommandLine(int aArgc, char* aArgv[])
+{
+  nsresult rv = NS_OK;
+
+#if defined(MOZ_IPC)
+
+#if defined(OS_WIN)
+  CommandLine::Init(aArgc, aArgv);
+#else
+  // these leak on error, but that's OK: we'll just exit()
+  char** canonArgs = new char*[aArgc];
+
+  // get the canonical version of the binary's path
+  nsCOMPtr<nsILocalFile> binFile;
+  rv = XRE_GetBinaryPath(aArgv[0], getter_AddRefs(binFile));
+  if (NS_FAILED(rv))
+    return NS_ERROR_FAILURE;
+
+  nsCAutoString canonBinPath;
+  rv = binFile->GetNativePath(canonBinPath);
+  if (NS_FAILED(rv))
+    return NS_ERROR_FAILURE;
+
+  canonArgs[0] = strdup(canonBinPath.get());
+
+  for (int i = 1; i < aArgc; ++i) {
+    if (aArgv[i]) {
+      canonArgs[i] = strdup(aArgv[i]);
+    }
+  }
+ 
+  NS_ASSERTION(!CommandLine::IsInitialized(), "Bad news!");
+  CommandLine::Init(aArgc, canonArgs);
+
+  for (int i = 0; i < aArgc; ++i)
+      free(canonArgs[i]);
+  delete[] canonArgs;
+#endif
+#endif
+  return rv;
+}
+
+nsresult
+XRE_DeinitCommandLine()
+{
+  nsresult rv = NS_OK;
+
+#if defined(MOZ_IPC)
+  CommandLine::Terminate();
+#endif
+
+  return rv;
+}
+
+GeckoProcessType
+XRE_GetProcessType()
+{
+#ifdef MOZ_IPC
+  return sChildProcessType;
+#else
+  return GeckoProcessType_Default;
+#endif
+}
+
--- a/widget/src/windows/Makefile.in
+++ b/widget/src/windows/Makefile.in
@@ -150,11 +150,16 @@ FORCE_STATIC_LIB = 1
 ifdef WINCE
 EXTRA_DSO_LDOPTS += ddraw.lib
 endif
 
 ifndef WINCE
 ENABLE_CXX_EXCEPTIONS = 1
 endif
 
+ifdef MOZ_IPC
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
+endif
+
 include $(topsrcdir)/config/rules.mk
 
 CXXFLAGS += $(MOZ_CAIRO_CFLAGS)
--- a/widget/src/windows/nsAccelerometerWin.cpp
+++ b/widget/src/windows/nsAccelerometerWin.cpp
@@ -405,17 +405,17 @@ ThinkPadSensor::ThinkPadSensor()
 
 ThinkPadSensor::~ThinkPadSensor()
 {
 }
 
 PRBool
 ThinkPadSensor::Startup()
 {
-  mLibrary = LoadLibrary("sensor.dll");
+  mLibrary = LoadLibraryW(L"sensor.dll");
   if (!mLibrary)
     return PR_FALSE;
 
   gShockproofGetAccelerometerData = (ShockproofGetAccelerometerData)
     GetProcAddress(mLibrary, "ShockproofGetAccelerometerData");
   if (!gShockproofGetAccelerometerData) {
     FreeLibrary(mLibrary);
     mLibrary = nsnull;
--- a/widget/src/windows/nsDeviceContextSpecWin.cpp
+++ b/widget/src/windows/nsDeviceContextSpecWin.cpp
@@ -90,33 +90,33 @@ PRLogModuleInfo * kWidgetPrintingLogMod 
 class GlobalPrinters {
 public:
   static GlobalPrinters* GetInstance() { return &mGlobalPrinters; }
   ~GlobalPrinters() { FreeGlobalPrinters(); }
 
   void FreeGlobalPrinters();
 
   PRBool       PrintersAreAllocated() { return mPrinters != nsnull; }
-  LPTSTR       GetItemFromList(PRInt32 aInx) { return mPrinters?mPrinters->ElementAt(aInx):nsnull; }
+  LPWSTR       GetItemFromList(PRInt32 aInx) { return mPrinters?mPrinters->ElementAt(aInx):nsnull; }
   nsresult     EnumeratePrinterList();
-  void         GetDefaultPrinterName(LPTSTR& aDefaultPrinterName);
+  void         GetDefaultPrinterName(nsString& aDefaultPrinterName);
   PRInt32      GetNumPrinters() { return mPrinters?mPrinters->Length():0; }
 
 protected:
   GlobalPrinters() {}
   nsresult EnumerateNativePrinters();
   void     ReallocatePrinters();
 
   static GlobalPrinters    mGlobalPrinters;
-  static nsTArray<LPTSTR>* mPrinters;
+  static nsTArray<LPWSTR>* mPrinters;
 };
 //---------------
 // static members
 GlobalPrinters    GlobalPrinters::mGlobalPrinters;
-nsTArray<LPTSTR>* GlobalPrinters::mPrinters = nsnull;
+nsTArray<LPWSTR>* GlobalPrinters::mPrinters = nsnull;
 
 
 //******************************************************
 // Define native paper sizes
 //******************************************************
 typedef struct {
   short  mPaperSize; // native enum
   double mWidth;
@@ -203,63 +203,59 @@ nsDeviceContextSpecWin::~nsDeviceContext
   GlobalPrinters::GetInstance()->FreeGlobalPrinters();
 }
 
 
 //------------------------------------------------------------------
 // helper
 static PRUnichar * GetDefaultPrinterNameFromGlobalPrinters()
 {
-  PRUnichar * printerName;
-  LPTSTR lpPrtName;
-  GlobalPrinters::GetInstance()->GetDefaultPrinterName(lpPrtName);
-  nsAutoString str;
-  NS_CopyNativeToUnicode(nsDependentCString((char *)lpPrtName), str);
-  printerName = ToNewUnicode(str);
-  free(lpPrtName);
-  return printerName;
+  nsAutoString printerName;
+  GlobalPrinters::GetInstance()->GetDefaultPrinterName(printerName);
+  return ToNewUnicode(printerName);
 }
 
 //----------------------------------------------------------------
 static nsresult 
 EnumerateNativePrinters(DWORD aWhichPrinters, LPWSTR aPrinterName, PRBool& aIsFound, PRBool& aIsFile)
 {
 #ifdef WINCE
   aIsFound = PR_FALSE;
 #else
   DWORD             dwSizeNeeded = 0;
   DWORD             dwNumItems   = 0;
   LPPRINTER_INFO_2W  lpInfo        = NULL;
 
   // Get buffer size
-  if (::EnumPrinters ( aWhichPrinters, NULL, 2, NULL, 0, &dwSizeNeeded, &dwNumItems )) {
+  if (::EnumPrintersW(aWhichPrinters, NULL, 2, NULL, 0, &dwSizeNeeded,
+                      &dwNumItems)) {
     return NS_ERROR_FAILURE;
   }
 
   // allocate memory
-  lpInfo = (LPPRINTER_INFO_2W)HeapAlloc ( GetProcessHeap (), HEAP_ZERO_MEMORY, dwSizeNeeded );
-  if ( lpInfo == NULL ) {
+  lpInfo = (LPPRINTER_INFO_2W) malloc(dwSizeNeeded);
+  if (!lpInfo) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  if (::EnumPrinters ( PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)lpInfo, dwSizeNeeded, &dwSizeNeeded, &dwNumItems) == 0 ) {
-    ::HeapFree(GetProcessHeap (), 0, lpInfo);
+  if (::EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)lpInfo,
+                      dwSizeNeeded, &dwSizeNeeded, &dwNumItems) == 0) {
+    free(lpInfo);
     return NS_OK;
   }
 
-
   for (DWORD i = 0; i < dwNumItems; i++ ) {
     if (wcscmp(lpInfo[i].pPrinterName, aPrinterName) == 0) {
       aIsFound = PR_TRUE;
       aIsFile  = wcscmp(lpInfo[i].pPortName, L"FILE:") == 0;
       break;
     }
   }
 
-  ::HeapFree(GetProcessHeap (), 0, lpInfo);
+  free(lpInfo);
 #endif
   return NS_OK;
 }
 
 //----------------------------------------------------------------
 static void 
 CheckForPrintToFileWithName(LPWSTR aPrinterName, PRBool& aIsFile)
 {
@@ -670,39 +666,17 @@ SetupDevModeFromSettings(LPDEVMODEW aDev
     PRInt32 copies;
     aPrintSettings->GetNumCopies(&copies);
     aDevMode->dmCopies = copies;
     aDevMode->dmFields |= DM_COPIES;
   }
 
 }
 
-#if defined(DEBUG_rods) || defined(DEBUG_dcone)
-static void DisplayLastError()
-{
-  LPVOID lpMsgBuf;
-  DWORD errCode = GetLastError();
-
-  FormatMessage( 
-      FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
-      NULL,
-      GetLastError(),
-      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
-      (LPTSTR) &lpMsgBuf,
-      0,
-      NULL 
-  );
-
-  // Display the string.
-  MessageBox( NULL, (const char *)lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );
-}
-#define DISPLAY_LAST_ERROR DisplayLastError();
-#else
 #define DISPLAY_LAST_ERROR 
-#endif
 
 //----------------------------------------------------------------------------------
 // Setup the object's data member with the selected printer's data
 nsresult
 nsDeviceContextSpecWin::GetDataFromPrinter(const PRUnichar * aName, nsIPrintSettings* aPS)
 {
 #ifdef WINCE 
   return NS_ERROR_NOT_IMPLEMENTED;
@@ -940,17 +914,17 @@ nsPrinterEnumeratorWin::GetPrinterNameLi
 
   PRInt32 numPrinters = GlobalPrinters::GetInstance()->GetNumPrinters();
   nsTArray<nsString> *printers = new nsTArray<nsString>(numPrinters);
   if (!printers)
     return NS_ERROR_OUT_OF_MEMORY;
 
   PRInt32 printerInx = 0;
   while( printerInx < numPrinters ) {
-    LPTSTR name = GlobalPrinters::GetInstance()->GetItemFromList(printerInx++);
+    LPWSTR name = GlobalPrinters::GetInstance()->GetItemFromList(printerInx++);
 #ifdef UNICODE
     nsDependentString newName(name);
 #else
     nsAutoString newName; 
     NS_CopyNativeToUnicode(nsDependentCString(name), newName);
 #endif
     printers->AppendElement(newName);
   }
@@ -973,17 +947,17 @@ NS_IMETHODIMP nsPrinterEnumeratorWin::Di
 //----------------------------------------------------------------------------------
 // THe array hold the name and port for each printer
 void 
 GlobalPrinters::ReallocatePrinters()
 {
   if (PrintersAreAllocated()) {
     FreeGlobalPrinters();
   }
-  mPrinters = new nsTArray<LPTSTR>();
+  mPrinters = new nsTArray<LPWSTR>();
   NS_ASSERTION(mPrinters, "Printers Array is NULL!");
 }
 
 //----------------------------------------------------------------------------------
 void 
 GlobalPrinters::FreeGlobalPrinters()
 {
   if (mPrinters != nsnull) {
@@ -999,26 +973,28 @@ GlobalPrinters::FreeGlobalPrinters()
 nsresult 
 GlobalPrinters::EnumerateNativePrinters()
 {
   nsresult rv = NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE;
 #ifndef WINCE
   PR_PL(("-----------------------\n"));
   PR_PL(("EnumerateNativePrinters\n"));
 
-  TCHAR szDefaultPrinterName[1024];    
-  DWORD status = GetProfileString("devices", 0, ",", szDefaultPrinterName, sizeof(szDefaultPrinterName)/sizeof(TCHAR));
+  WCHAR szDefaultPrinterName[1024];    
+  DWORD status = GetProfileStringW(L"devices", 0, L",",
+                                   szDefaultPrinterName,
+                                   NS_ARRAY_LENGTH(szDefaultPrinterName));
   if (status > 0) {
     DWORD count = 0;
-    LPTSTR sPtr   = (LPTSTR)szDefaultPrinterName;
-    LPTSTR ePtr   = (LPTSTR)(szDefaultPrinterName+(status*sizeof(TCHAR)));
-    LPTSTR prvPtr = sPtr;
+    LPWSTR sPtr   = szDefaultPrinterName;
+    LPWSTR ePtr   = szDefaultPrinterName + status;
+    LPWSTR prvPtr = sPtr;
     while (sPtr < ePtr) {
       if (*sPtr == NULL) {
-        LPTSTR name = _tcsdup(prvPtr);
+        LPWSTR name = wcsdup(prvPtr);
         mPrinters->AppendElement(name);
         PR_PL(("Printer Name:    %s\n", prvPtr));
         prvPtr = sPtr+1;
         count++;
       }
       sPtr++;
     }
     rv = NS_OK;
@@ -1026,38 +1002,40 @@ GlobalPrinters::EnumerateNativePrinters(
   PR_PL(("-----------------------\n"));
 #endif
   return rv;
 }
 
 //------------------------------------------------------------------
 // Uses the GetProfileString to get the default printer from the registry
 void 
-GlobalPrinters::GetDefaultPrinterName(LPTSTR& aDefaultPrinterName)
+GlobalPrinters::GetDefaultPrinterName(nsString& aDefaultPrinterName)
 {
 #ifndef WINCE
-  aDefaultPrinterName = nsnull;
-  TCHAR szDefaultPrinterName[1024];    
-  DWORD status = GetProfileString("windows", "device", 0, szDefaultPrinterName, sizeof(szDefaultPrinterName)/sizeof(TCHAR));
+  aDefaultPrinterName.Truncate();
+  WCHAR szDefaultPrinterName[1024];    
+  DWORD status = GetProfileStringW(L"windows", L"device", 0,
+                                   szDefaultPrinterName,
+                                   NS_ARRAY_LENGTH(szDefaultPrinterName));
   if (status > 0) {
-    TCHAR comma = (TCHAR)',';
-    LPTSTR sPtr = (LPTSTR)szDefaultPrinterName;
+    WCHAR comma = ',';
+    LPWSTR sPtr = szDefaultPrinterName;
     while (*sPtr != comma && *sPtr != NULL) 
       sPtr++;
     if (*sPtr == comma) {
       *sPtr = NULL;
     }
-    aDefaultPrinterName = _tcsdup(szDefaultPrinterName);
+    aDefaultPrinterName = szDefaultPrinterName;
   } else {
-    aDefaultPrinterName = _tcsdup("");
+    aDefaultPrinterName = NS_LITERAL_STRING("");
   }
 
   PR_PL(("DEFAULT PRINTER [%s]\n", aDefaultPrinterName));
 #else
-  aDefaultPrinterName = TEXT("UNKNOWN");
+  aDefaultPrinterName = NS_LITERAL_STRING("UNKNOWN");
 #endif
 }
 
 //----------------------------------------------------------------------------------
 // This goes and gets the list of available printers and puts
 // the default printer at the beginning of the list
 nsresult 
 GlobalPrinters::EnumeratePrinterList()
@@ -1067,33 +1045,32 @@ GlobalPrinters::EnumeratePrinterList()
   ReallocatePrinters();
 
   // any of these could only fail with an OUT_MEMORY_ERROR
   // PRINTER_ENUM_LOCAL should get the network printers on Win95
   nsresult rv = EnumerateNativePrinters();
   if (NS_FAILED(rv)) return rv;
 
   // get the name of the default printer
-  LPTSTR defPrinterName;
+  nsAutoString defPrinterName;
   GetDefaultPrinterName(defPrinterName);
 
   // put the default printer at the beginning of list
-  if (defPrinterName != nsnull) {
+  if (!defPrinterName.IsEmpty()) {
     for (PRInt32 i=0;i<mPrinters->Length();i++) {
-      LPTSTR name = mPrinters->ElementAt(i);
-      if (!_tcscmp(name, defPrinterName)) {
+      LPWSTR name = mPrinters->ElementAt(i);
+      if (defPrinterName.Equals(name)) {
         if (i > 0) {
-          LPTSTR ptr = mPrinters->ElementAt(0);
+          LPWSTR ptr = mPrinters->ElementAt(0);
           mPrinters->ElementAt(0) = name;
           mPrinters->ElementAt(i) = ptr;
         }
         break;
       }
     }
-    free(defPrinterName);
   }
 
   // make sure we at least tried to get the printers
   if (!PrintersAreAllocated()) {
     PR_PL(("***** nsDeviceContextSpecWin::EnumeratePrinterList - Printers aren`t allocated\n"));
     return NS_ERROR_FAILURE;
   }
 
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -99,16 +99,20 @@
  **
  ** BLOCK: Includes
  **
  ** Include headers.
  **
  **************************************************************
  **************************************************************/
 
+#ifdef MOZ_IPC
+#include "mozilla/ipc/SyncChannel.h"
+#endif
+
 #include "nsWindow.h"
 
 #include <windows.h>
 #include <process.h>
 #include <commctrl.h>
 #include <unknwn.h>
 
 #include "prlog.h"
@@ -3563,16 +3567,21 @@ PRBool nsWindow::ConvertStatus(nsEventSt
  * The main Windows event procedures and associated
  * message processing methods.
  *
  **************************************************************/
 
 // The WndProc procedure for all nsWindows in this toolkit
 LRESULT CALLBACK nsWindow::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
+#ifdef MOZ_IPC
+  NS_ASSERTION(!mozilla::ipc::SyncChannel::IsPumpingMessages(),
+               "Failed to prevent a nonqueued message from running!");
+#endif
+
   // create this here so that we store the last rolled up popup until after
   // the event has been processed.
   nsAutoRollup autoRollup;
 
   LRESULT popupHandlingResult;
   if ( DealWithPopups(hWnd, msg, wParam, lParam, &popupHandlingResult) )
     return popupHandlingResult;
 
--- a/widget/src/xpwidgets/Makefile.in
+++ b/widget/src/xpwidgets/Makefile.in
@@ -60,17 +60,21 @@ REQUIRES	= xpcom \
 		  uconv \
 		  unicharutil \
 		  view \
 		  windowwatcher \
 		  qcms \
 		  thebes \
 		  $(NULL)
 
-DEFINES		+= -D_IMPL_NS_WIDGET -DUSE_TLS_FOR_TOOLKIT
+DEFINES += \
+  -D_IMPL_NS_WIDGET \
+  -DUSE_TLS_FOR_TOOLKIT \
+  -DNO_NSPR_10_SUPPORT=1 \
+  $(NULL)
 
 CPPSRCS		= \
 		nsBaseAppShell.cpp \
 		nsBaseWidget.cpp \
 		nsTransferable.cpp \
 		nsHTMLFormatConverter.cpp \
 		nsBaseDragService.cpp \
 		nsPrimitiveHelpers.cpp \
@@ -93,20 +97,21 @@ ifneq (,$(filter beos qt gtk2 os2 cocoa 
 CPPSRCS += nsBaseFilePicker.cpp
 REQUIRES += docshell view intl
 endif
 
 ifneq (,$(filter qt gtk2 windows cocoa,$(MOZ_WIDGET_TOOLKIT)))
 CPPSRCS += nsNativeTheme.cpp
 endif
 
-LOCAL_INCLUDES	= \
+LOCAL_INCLUDES	+= \
 		-I$(srcdir)/../$(MOZ_WIDGET_TOOLKIT) \
 		-I$(srcdir) \
 		$(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
 CXXFLAGS	+= $(TK_CFLAGS)
-
--- a/widget/src/xpwidgets/nsBaseAppShell.cpp
+++ b/widget/src/xpwidgets/nsBaseAppShell.cpp
@@ -36,16 +36,20 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsBaseAppShell.h"
 #include "nsThreadUtils.h"
 #include "nsIObserverService.h"
 #include "nsServiceManagerUtils.h"
 
+#ifdef MOZ_IPC
+#include "base/message_loop.h"
+#endif
+
 // When processing the next thread event, the appshell may process native
 // events (if not in performance mode), which can result in suppressing the
 // next thread event for at most this many ticks:
 #define THREAD_EVENT_STARVATION_LIMIT PR_MillisecondsToInterval(20)
 
 NS_IMPL_THREADSAFE_ISUPPORTS3(nsBaseAppShell, nsIAppShell, nsIThreadObserver,
                               nsIObserver)
 
@@ -54,17 +58,17 @@ nsBaseAppShell::nsBaseAppShell()
   , mBlockedWait(nsnull)
   , mFavorPerf(0)
   , mNativeEventPending(0)
   , mEventloopNestingLevel(0)
   , mStarvationDelay(0)
   , mSwitchTime(0)
   , mLastNativeEventTime(0)
   , mEventloopNestingState(eEventloopNone)
-  , mRunWasCalled(PR_FALSE)
+  , mRunning(PR_FALSE)
   , mExiting(PR_FALSE)
   , mBlockNativeEvent(PR_FALSE)
 {
 }
 
 nsresult
 nsBaseAppShell::Init()
 {
@@ -156,31 +160,42 @@ nsBaseAppShell::DoProcessNextNativeEvent
 }
 
 //-------------------------------------------------------------------------
 // nsIAppShell methods:
 
 NS_IMETHODIMP
 nsBaseAppShell::Run(void)
 {
+  NS_ENSURE_STATE(!mRunning);  // should not call Run twice
+  mRunning = PR_TRUE;
+
   nsIThread *thread = NS_GetCurrentThread();
 
-  NS_ENSURE_STATE(!mRunWasCalled);  // should not call Run twice
-  mRunWasCalled = PR_TRUE;
-
+#ifdef MOZ_IPC
+  MessageLoop::current()->Run();
+#else
   while (!mExiting)
     NS_ProcessNextEvent(thread);
+#endif
 
   NS_ProcessPendingEvents(thread);
+
+  mRunning = PR_FALSE;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBaseAppShell::Exit(void)
 {
+#ifdef MOZ_IPC
+  if (mRunning && !mExiting) {
+    MessageLoop::current()->Quit();
+  }
+#endif
   mExiting = PR_TRUE;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBaseAppShell::FavorPerformanceHint(PRBool favorPerfOverStarvation,
                                      PRUint32 starvationDelay)
 {
--- a/widget/src/xpwidgets/nsBaseAppShell.h
+++ b/widget/src/xpwidgets/nsBaseAppShell.h
@@ -114,17 +114,17 @@ private:
   PRIntervalTime mSwitchTime;
   PRIntervalTime mLastNativeEventTime;
   enum EventloopNestingState {
     eEventloopNone,  // top level thread execution
     eEventloopXPCOM, // innermost native event loop is ProcessNextNativeEvent
     eEventloopOther  // innermost native event loop is a native library/plugin etc
   };
   EventloopNestingState mEventloopNestingState;
-  PRPackedBool mRunWasCalled;
+  PRPackedBool mRunning;
   PRPackedBool mExiting;
   /**
    * mBlockNativeEvent blocks the appshell from processing native events.
    * It is set to PR_TRUE while a nested native event loop (eEventloopOther)
    * is processing gecko events in NativeEventCallback(), thus queuing up
    * native events until we return to that loop (bug 420148).
    * We force mBlockNativeEvent to PR_FALSE in case handling one of the gecko
    * events spins up a nested XPCOM event loop (eg. modal window) which would
--- a/xpcom/base/Makefile.in
+++ b/xpcom/base/Makefile.in
@@ -42,16 +42,17 @@ VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= xpcom
 XPIDL_MODULE	= xpcom_base
 LIBRARY_NAME	= xpcombase_s
 GRE_MODULE	= 1
 MOZILLA_INTERNAL_API =1
+LIBXUL_LIBRARY = 1
 
 REQUIRES	= string \
 		  $(NULL)
 
 CPPSRCS		= \
 		nsAllocator.cpp \
 		nsVersionComparatorImpl.cpp \
 		nsConsoleMessage.cpp \
--- a/xpcom/base/nsDebugImpl.cpp
+++ b/xpcom/base/nsDebugImpl.cpp
@@ -71,16 +71,19 @@
 #include <tchar.h>
 #include "nsString.h"
 #endif
 
 static void
 Abort(const char *aMsg);
 
 static void
+RealBreak();
+
+static void
 Break(const char *aMsg);
 
 #if defined(XP_OS2)
 #  define INCL_WINDIALOGS  // need for WinMessageBox
 #  include <os2.h>
 #  include <string.h>
 #endif /* XP_OS2 */
 
@@ -312,16 +315,19 @@ NS_DebugBreak(PRUint32 aSeverity, const 
    case NS_DEBUG_WARNING:
      return;
 
    case NS_DEBUG_BREAK:
      Break(buf.buffer);
      return;
 
    case NS_DEBUG_ABORT:
+#ifdef DEBUG
+     RealBreak();
+#endif
      nsTraceRefcntImpl::WalkTheStack(stderr);
      Abort(buf.buffer);
      return;
    }
 
    // Now we deal with assertions
    PR_AtomicIncrement(&gAssertionCount);
 
@@ -383,16 +389,35 @@ Abort(const char *aMsg)
   // (Written this way to lessen the likelihood of it being optimized away.)
   gAssertionCount += *((PRInt32 *) 0); // TODO annotation saying we know 
                                        // this is crazy
 
   // Still haven't aborted?  Try _exit().
   PR_ProcessExit(127);
 }
 
+static void
+RealBreak()
+{
+#if defined(_WIN32)
+#ifndef WINCE
+  ::DebugBreak();
+#endif
+#elif defined(XP_OS2)
+   asm("int $3");
+#elif defined(XP_BEOS)
+#elif defined(XP_MACOSX)
+   raise(SIGTRAP);
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__i386) || defined(__x86_64__))
+   asm("int $3");
+#else
+   // don't know how to break on this platform
+#endif
+}
+
 // Abort() calls this function, don't call it!
 static void
 Break(const char *aMsg)
 {
 #if defined(_WIN32)
 #ifndef WINCE // we really just want to crash for now
   static int ignoreDebugger;
   if (!ignoreDebugger) {
@@ -443,18 +468,17 @@ Break(const char *aMsg)
       //If we are ignored exit this way..
       _exit(3);
          
     case IDIGNORE:
       return;
     }
   }
 
-  ::DebugBreak();
-
+  RealBreak();
 #endif // WINCE
 #elif defined(XP_OS2)
    char msg[1200];
    PR_snprintf(msg, sizeof(msg),
                "%s\n\nClick Cancel to Debug Application.\n"
                "Click Enter to continue running the Application.", aMsg);
    ULONG code = MBID_ERROR;
    code = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, msg, 
@@ -467,27 +491,28 @@ Break(const char *aMsg)
     * Break()
     * Actually, that's a really bad idea since this happens a lot with threadsafe
     * assertions and since it means that you can't actually run the debug build
     * outside a debugger without it crashing constantly.
     */
    if (( code == MBID_ENTER ) || (code == MBID_ERROR))
      return;
 
-   asm("int $3");
+   RealBreak();
 #elif defined(XP_BEOS)
    DEBUGGER(aMsg);
+   RealBreak();
 #elif defined(XP_MACOSX)
    /* Note that we put this Mac OS X test above the GNUC/x86 test because the
     * GNUC/x86 test is also true on Intel Mac OS X and we want the PPC/x86
     * impls to be the same.
     */
-   raise(SIGTRAP);
+   RealBreak();
 #elif defined(__GNUC__) && (defined(__i386__) || defined(__i386) || defined(__x86_64__))
-   asm("int $3");
+   RealBreak();
 #else
    // don't know how to break on this platform
 #endif
 }
 
 static const nsDebugImpl kImpl;
 
 NS_METHOD
--- a/xpcom/base/nsTraceRefcntImpl.cpp
+++ b/xpcom/base/nsTraceRefcntImpl.cpp
@@ -44,16 +44,27 @@
 #include "prlog.h"
 #include "plstr.h"
 #include "prlink.h"
 #include <stdlib.h>
 #include "nsCOMPtr.h"
 #include "nsCRT.h"
 #include <math.h>
 #include "nsStackWalk.h"
+#include "nsString.h"
+
+#ifdef MOZ_IPC
+#include "nsXULAppAPI.h"
+#ifdef XP_WIN
+#include <process.h>
+#define getpid _getpid
+#else
+#include <unistd.h>
+#endif
+#endif
 
 #ifdef HAVE_LIBDL
 #include <dlfcn.h>
 #endif
 
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_COM void
@@ -313,18 +324,22 @@ public:
   }
 
   static PRBool HaveLeaks(nsTraceRefcntStats* stats) {
     return ((stats->mAddRefs != stats->mReleases) ||
             (stats->mCreates != stats->mDestroys));
   }
 
   PRBool PrintDumpHeader(FILE* out, const char* msg, nsTraceRefcntImpl::StatisticsType type) {
+#ifdef MOZ_IPC
+    fprintf(out, "\n== BloatView: %s, %s process %d\n", msg,
+            XRE_ChildProcessTypeToString(XRE_GetProcessType()), getpid());
+#else
     fprintf(out, "\n== BloatView: %s\n", msg);
-
+#endif
     nsTraceRefcntStats& stats =
       (type == nsTraceRefcntImpl::NEW_STATS) ? mNewStats : mAllStats;
     if (gLogLeaksOnly && !HaveLeaks(&stats))
       return PR_FALSE;
 
     fprintf(out,
         "\n" \
         "     |<----------------Class--------------->|<-----Bytes------>|<----------------Objects---------------->|<--------------References-------------->|\n" \
@@ -629,28 +644,43 @@ static PRBool InitLog(const char* envVar
     }
     else if (nsCRT::strcmp(value, "2") == 0) {
       *result = stderr;
       fprintf(stdout, "### %s defined -- logging %s to stderr\n",
               envVar, msg);
       return PR_TRUE;
     }
     else {
-      FILE *stream = ::fopen(value, "w");
+      FILE *stream;
+      nsCAutoString fname(value);
+#ifdef MOZ_IPC
+      if (XRE_GetProcessType() != GeckoProcessType_Default) {
+        bool hasLogExtension = 
+            fname.RFind(".log", PR_TRUE, -1, 4) == kNotFound ? false : true;
+        if (hasLogExtension)
+          fname.Cut(fname.Length() - 4, 4);
+        fname.AppendLiteral("_");
+        fname.Append((char*)XRE_ChildProcessTypeToString(XRE_GetProcessType()));
+        fname.AppendLiteral("_pid");
+        fname.AppendInt(getpid());
+        if (hasLogExtension)
+          fname.AppendLiteral(".log");
+      }
+#endif
+      stream = ::fopen(fname.get(), "w");
       if (stream != NULL) {
         *result = stream;
         fprintf(stdout, "### %s defined -- logging %s to %s\n",
-                envVar, msg, value);
-        return PR_TRUE;
+                envVar, msg, fname.get());
       }
       else {
         fprintf(stdout, "### %s defined -- unable to log %s to %s\n",
-                envVar, msg, value);
-        return PR_FALSE;
+                envVar, msg, fname.get());
       }
+      return stream != NULL;
     }
   }
   return PR_FALSE;
 }
 
 
 static PLHashNumber HashNumber(const void* aKey)
 {
--- a/xpcom/build.mk
+++ b/xpcom/build.mk
@@ -37,8 +37,12 @@
 
 TIERS += xpcom
 
 ifdef NS_TRACE_MALLOC
 tier_xpcom_dirs = tools/trace-malloc/lib
 endif
 
 tier_xpcom_dirs += xpcom
+
+ifdef MOZ_IPC
+tier_xpcom_dirs += ipc/chromium ipc/glue
+endif
--- a/xpcom/build/Makefile.in
+++ b/xpcom/build/Makefile.in
@@ -155,16 +155,18 @@ ifndef MOZ_ENABLE_LIBXUL
 FORCE_SHARED_LIB = 1
 endif
 
 # UNIX98 iconv support
 OS_LIBS += $(LIBICONV)
 
 GARBAGE         += $(XPCOM_GLUE_SRC_LCSRCS) $(XPCOM_GLUE_SRC_LCPPSRCS) $(XPCOM_GLUENS_SRC_LCPPSRCS) $(wildcard *.$(OBJ_SUFFIX))
 
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
 DEFINES		+= \
 		-D_IMPL_NS_COM \
 		-D_IMPL_NS_STRINGAPI \
 		-DEXPORT_XPT_API \
 		-DEXPORT_XPTC_API
 
--- a/xpcom/build/nsXPComInit.cpp
+++ b/xpcom/build/nsXPComInit.cpp
@@ -32,17 +32,22 @@
  * 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 ***** */
 
+#ifdef MOZ_IPC
+#include "base/basictypes.h"
+#endif
+
 #include "mozilla/XPCOM.h"
+#include "nsXULAppAPI.h"
 
 #include "nsXPCOMPrivate.h"
 #include "nsXPCOMCIDInternal.h"
 
 #include "nsStaticComponents.h"
 #include "prlink.h"
 
 #include "nsObserverList.h"
@@ -140,16 +145,36 @@ NS_DECL_CLASSINFO(nsStringInputStream)
 #include "nsMacUtilsImpl.h"
 #endif
 
 #include "nsSystemInfo.h"
 #include "nsMemoryReporterManager.h"
 
 #include <locale.h>
 
+#ifdef MOZ_IPC
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/message_loop.h"
+
+#include "mozilla/ipc/GeckoThread.h"
+
+using base::AtExitManager;
+using mozilla::ipc::BrowserProcessSubThread;
+
+namespace {
+
+static AtExitManager* sExitManager;
+static MessageLoop* sMessageLoop;
+static bool sCommandLineWasInitialized;
+static BrowserProcessSubThread* sIOThread;
+
+} /* anonymous namespace */
+#endif
+
 using mozilla::TimeStamp;
 
 // Registry Factory creation function defined in nsRegistry.cpp
 // We hook into this function locally to create and register the registry
 // Since noone outside xpcom needs to know about this and nsRegistry.cpp
 // does not have a local include file, we are putting this definition
 // here rather than in nsIRegistry.h
 extern nsresult NS_RegistryGetFactory(nsIFactory** aFactory);
@@ -544,16 +569,44 @@ NS_InitXPCOM3(nsIServiceManager* *result
         staticComponents = kPStaticModules;
         componentCount = kStaticModuleCount;
     }
 #endif
 
      // We are not shutting down
     gXPCOMShuttingDown = PR_FALSE;
 
+#ifdef MOZ_IPC
+    // Set up chromium libs
+    NS_ASSERTION(!sExitManager && !sMessageLoop, "Bad logic!");
+
+    if (!AtExitManager::AlreadyRegistered()) {
+        sExitManager = new AtExitManager();
+        NS_ENSURE_STATE(sExitManager);
+    }
+
+    if (!MessageLoop::current()) {
+        sMessageLoop = new MessageLoopForUI();
+        NS_ENSURE_STATE(sMessageLoop);
+    }
+
+    if (XRE_GetProcessType() == GeckoProcessType_Default &&
+        !BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO)) {
+        scoped_ptr<BrowserProcessSubThread> ioThread(
+            new BrowserProcessSubThread(BrowserProcessSubThread::IO));
+        NS_ENSURE_TRUE(ioThread.get(), NS_ERROR_OUT_OF_MEMORY);
+
+        base::Thread::Options options;
+        options.message_loop_type = MessageLoop::TYPE_IO;
+        NS_ENSURE_TRUE(ioThread->StartWithOptions(options), NS_ERROR_FAILURE);
+
+        sIOThread = ioThread.release();
+    }
+#endif
+
     NS_LogInit();
 
     // Set up TimeStamp
     rv = TimeStamp::Startup();
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Establish the main thread here.
     rv = nsThreadManager::get()->Init();
@@ -604,16 +657,40 @@ NS_InitXPCOM3(nsIServiceManager* *result
         nsDirectoryService::gService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib);
     }
     
     if (appFileLocationProvider) {
         rv = nsDirectoryService::gService->RegisterProvider(appFileLocationProvider);
         if (NS_FAILED(rv)) return rv;
     }
 
+#ifdef MOZ_IPC
+    if ((sCommandLineWasInitialized = !CommandLine::IsInitialized())) {
+#ifdef OS_WIN
+        CommandLine::Init(0, nsnull);
+#else
+        nsCOMPtr<nsIFile> binaryFile;
+        nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, 
+                                          NS_GET_IID(nsIFile), 
+                                          getter_AddRefs(binaryFile));
+        NS_ENSURE_STATE(binaryFile);
+        
+        rv = binaryFile->AppendNative(NS_LITERAL_CSTRING("nonexistent-executable"));
+        NS_ENSURE_SUCCESS(rv, rv);
+        
+        nsCString binaryPath;
+        rv = binaryFile->GetNativePath(binaryPath);
+        NS_ENSURE_SUCCESS(rv, rv);
+        
+        static char const *const argv = { strdup(binaryPath.get()) };
+        CommandLine::Init(1, &argv);
+#endif
+    }
+#endif
+
     NS_ASSERTION(nsComponentManagerImpl::gComponentManager == NULL, "CompMgr not null at init");
 
     // Create the Component/Service Manager
     nsComponentManagerImpl *compMgr = new nsComponentManagerImpl();
     if (compMgr == NULL)
         return NS_ERROR_OUT_OF_MEMORY;
     NS_ADDREF(compMgr);
     
@@ -912,16 +989,35 @@ ShutdownXPCOM(nsIServiceManager* servMgr
      * BlockingResourceBase::Shutdown() runs after all other shutdown
      * functions.
      */
     BlockingResourceBase::Shutdown();
 #endif
     
     NS_LogTerm();
 
+#ifdef MOZ_IPC
+    if (sIOThread) {
+        delete sIOThread;
+        sIOThread = nsnull;
+    }
+    if (sMessageLoop) {
+        delete sMessageLoop;
+        sMessageLoop = nsnull;
+    }
+    if (sCommandLineWasInitialized) {
+        CommandLine::Terminate();
+        sCommandLineWasInitialized = false;
+    }
+    if (sExitManager) {
+        delete sExitManager;
+        sExitManager = nsnull;
+    }
+#endif
+
 #ifdef GC_LEAK_DETECTOR
     // Shutdown the Leak detector.
     NS_ShutdownLeakDetector();
 #endif
 
     return NS_OK;
 }
 
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -40,16 +40,17 @@
 #ifndef _nsXULAppAPI_h__
 #define _nsXULAppAPI_h__
 
 #include "prtypes.h"
 #include "nsID.h"
 #include "xrecore.h"
 #include "nsXPCOM.h"
 #include "nsISupports.h"
+#include "prlog.h"
 
 /**
  * Application-specific data needed to start the apprunner.
  *
  * @status FROZEN - This API is stable. Additional fields may be added to the
  *                  end of the structure in the future. Runtime detection
  *                  of the version of nsXREAppData can be determined by
  *                  examining the "size" field.
@@ -413,9 +414,86 @@ XRE_API(nsresult,
                            nsXREAppData *aAppData))
 
 /**
  * Free a nsXREAppData structure that was allocated with XRE_CreateAppData.
  */
 XRE_API(void,
         XRE_FreeAppData, (nsXREAppData *aAppData))
 
+enum GeckoProcessType {
+  GeckoProcessType_Default = 0,
+
+  GeckoProcessType_Plugin,
+  GeckoProcessType_Content,
+
+  GeckoProcessType_IPDLUnitTest,
+
+  GeckoProcessType_End,
+  GeckoProcessType_Invalid = GeckoProcessType_End
+};
+
+static const char* const kGeckoProcessTypeString[] = {
+  "default",
+  "plugin",
+  "tab",
+  "ipdlunittest"
+};
+
+PR_STATIC_ASSERT(sizeof(kGeckoProcessTypeString) /
+                 sizeof(kGeckoProcessTypeString[0]) ==
+                 GeckoProcessType_End);
+
+
+XRE_API(const char*,
+        XRE_ChildProcessTypeToString, (GeckoProcessType aProcessType))
+
+XRE_API(GeckoProcessType,
+        XRE_StringToChildProcessType, (const char* aProcessTypeString))
+
+XRE_API(nsresult,
+        XRE_InitChildProcess, (int aArgc,
+                               char* aArgv[],
+                               GeckoProcessType aProcess))
+
+XRE_API(GeckoProcessType,
+        XRE_GetProcessType, ())
+
+typedef void (*MainFunction)(void* aData);
+
+XRE_API(nsresult,
+        XRE_InitParentProcess, (int aArgc,
+                                char* aArgv[],
+                                MainFunction aMainFunction,
+                                void* aMainFunctionExtraData))
+
+XRE_API(int,
+        XRE_RunIPDLTest, (int aArgc,
+                          char* aArgv[]))
+
+XRE_API(nsresult,
+        XRE_RunAppShell, ())
+
+XRE_API(nsresult,
+        XRE_InitCommandLine, (int aArgc, char* aArgv[]))
+
+XRE_API(nsresult,
+        XRE_DeinitCommandLine, ())
+
+class MessageLoop;
+
+XRE_API(void,
+        XRE_ShutdownChildProcess, ())
+
+XRE_API(MessageLoop*,
+        XRE_GetIOMessageLoop, ())
+
+struct JSContext;
+struct JSString;
+
+XRE_API(bool,
+        XRE_SendTestShellCommand, (JSContext* aCx,
+                                   JSString* aCommand,
+                                   void* aCallback))
+XRE_API(bool,
+        XRE_ShutdownTestShell, ())
+
 #endif // _nsXULAppAPI_h__