Rework chromium initialization, r=beast
authorBen Turner <bent.mozilla@gmail.com>
Fri, 28 Aug 2009 12:46:21 -0700
changeset 35878 cc6a5092ce5b54eae508fdc21ca142fc35f1b1ff
parent 35877 8efc56c31e8902dfaed68aa616b005fca064dffc
child 35879 c25f8028ecdfb8ae73daa4a896be2fe1081fb45c
push idunknown
push userunknown
push dateunknown
reviewersbeast
milestone1.9.3a1pre
Rework chromium initialization, r=beast
ipc/Makefile.in
ipc/glue/AsyncChannel.cpp
ipc/glue/GeckoThread.cpp
ipc/glue/MessagePump.cpp
toolkit/library/dlldeps-xul.cpp
toolkit/xre/nsAppRunner.cpp
toolkit/xre/nsEmbedFunctions.cpp
xpcom/build.mk
xpcom/build/nsXPComInit.cpp
xpcom/build/nsXULAppAPI.h
--- a/ipc/Makefile.in
+++ b/ipc/Makefile.in
@@ -36,12 +36,12 @@
 
 DEPTH = ..
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-DIRS += ipdl chromium glue test-harness testshell
+DIRS += test-harness testshell
 TOOL_DIRS = app
 
 include $(topsrcdir)/config/rules.mk
--- a/ipc/glue/AsyncChannel.cpp
+++ b/ipc/glue/AsyncChannel.cpp
@@ -35,36 +35,26 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/ipc/AsyncChannel.h"
 #include "mozilla/ipc/GeckoThread.h"
 
-#include "mozilla/dom/ContentProcessChild.h"
-using mozilla::dom::ContentProcessChild;
-
 #include "nsDebug.h"
 #include "nsXULAppAPI.h"
 
 template<>
 struct RunnableMethodTraits<mozilla::ipc::AsyncChannel>
 {
     static void RetainCallee(mozilla::ipc::AsyncChannel* obj) { }
     static void ReleaseCallee(mozilla::ipc::AsyncChannel* obj) { }
 };
 
-template<>
-struct RunnableMethodTraits<ContentProcessChild>
-{
-    static void RetainCallee(ContentProcessChild* obj) { }
-    static void ReleaseCallee(ContentProcessChild* obj) { }
-};
-
 namespace mozilla {
 namespace ipc {
 
 bool
 AsyncChannel::Open(Transport* aTransport, MessageLoop* aIOLoop)
 {
     NS_PRECONDITION(!mTransport, "Open() called > once");
     NS_PRECONDITION(aTransport, "need transport layer");
@@ -176,19 +166,17 @@ AsyncChannel::OnChannelError()
 
     if (XRE_GetProcessType() == GeckoProcessType_Default) {
         // Parent process, one of our children died. Notify?
     }
     else {
         // Child process, initiate quit sequence.
 #ifdef DEBUG
         // XXXbent this is totally out of place, but works for now.
-        mWorkerLoop->PostTask(FROM_HERE,
-            NewRunnableMethod(ContentProcessChild::GetSingleton(),
-                              &ContentProcessChild::Quit));
+        XRE_ShutdownChildProcess(mWorkerLoop);
 
         // Must exit the IO loop, which will then join with the UI loop.
         MessageLoop::current()->Quit();
 #else
         // Go ahead and abort here.
         NS_DebugBreak(NS_DEBUG_ABORT, nsnull, nsnull, nsnull, 0);
 #endif
     }
--- a/ipc/glue/GeckoThread.cpp
+++ b/ipc/glue/GeckoThread.cpp
@@ -35,18 +35,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/ipc/GeckoThread.h"
 
 #include "chrome/common/notification_service.h"
 
 #include "nsXPCOM.h"
 
-#include "nsRegion.h"
-
 #if defined(OS_WIN)
 #include <objbase.h>
 #endif
 
 using mozilla::ipc::GeckoThread;
 using mozilla::ipc::BrowserProcessSubThread;
 
 void
--- a/ipc/glue/MessagePump.cpp
+++ b/ipc/glue/MessagePump.cpp
@@ -31,37 +31,34 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "MessagePump.h"
 
-#include "nsIAppShell.h"
 #include "nsIThread.h"
 #include "nsITimer.h"
 
 #include "nsComponentManagerUtils.h"
 #include "nsCOMPtr.h"
 #include "nsServiceManagerUtils.h"
 #include "nsStringGlue.h"
 #include "nsThreadUtils.h"
-#include "nsWidgetsCID.h"
+#include "nsXULAppAPI.h"
 #include "pratom.h"
 #include "prthread.h"
 
 #include "base/logging.h"
 #include "base/scoped_nsautorelease_pool.h"
 
 using mozilla::ipc::MessagePump;
 using mozilla::ipc::MessagePumpForChildProcess;
 
-static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
-
 namespace {
 
 void
 TimerCallback(nsITimer* aTimer,
               void* aClosure)
 {
   MessagePump* messagePump = reinterpret_cast<MessagePump*>(aClosure);
   messagePump->ScheduleWork();
@@ -184,23 +181,18 @@ void
 MessagePumpForChildProcess::Run(MessagePump::Delegate* aDelegate)
 {
   if (mFirstRun) {
 #ifdef DEBUG
     NS_ASSERTION(aDelegate && gFirstDelegate == nsnull, "Huh?!");
     gFirstDelegate = aDelegate;
 #endif
     mFirstRun = false;
-    nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
-    NS_WARN_IF_FALSE(appShell, "Failed to get app shell?!");
-    if (appShell) {
-      nsresult rv = appShell->Run();
-      if (NS_FAILED(rv)) {
+    if (NS_FAILED(XRE_RunAppShell())) {
         NS_WARNING("Failed to run app shell?!");
-      }
     }
 #ifdef DEBUG
     NS_ASSERTION(aDelegate && aDelegate == gFirstDelegate, "Huh?!");
     gFirstDelegate = nsnull;
 #endif
     return;
   }
 
--- a/toolkit/library/dlldeps-xul.cpp
+++ b/toolkit/library/dlldeps-xul.cpp
@@ -51,9 +51,13 @@ void xxxNeverCalledXUL()
   XRE_FreeAppData(nsnull);
   XRE_ChildProcessTypeToString(GeckoProcessType_Default);
   XRE_StringToChildProcessType("");
   XRE_InitChildProcess(0, nsnull, GeckoProcessType_Default);
   XRE_InitParentProcess(0, nsnull, nsnull, nsnull);
   XRE_RunTestShell(0, nsnull);
   XRE_GetProcessType();
   XRE_ShutdownChildProcess();
+  XRE_RunAppShell();
+  XRE_ShutdownChildProcess();
+  XRE_GetContentProcessParent();
+  XRE_GetContentProcessChild();
 }
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -204,21 +204,16 @@
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #include "nsICrashReporter.h"
 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
 #endif
 
 #ifdef MOZ_IPC
 #include "base/command_line.h"
-#include "base/thread.h"
-#include "mozilla/ipc/GeckoThread.h"
-
-using mozilla::ipc::BrowserProcessSubThread;
-using mozilla::ipc::GeckoThread;
 #endif
 
 #ifdef WINCE
 class WindowsMutex {
 public:
   WindowsMutex(const wchar_t *name) {
     mHandle = CreateMutexW(0, FALSE, name);
   }
@@ -3048,17 +3043,17 @@ XRE_main(int argc, char* argv[], const n
   }
     
 #ifdef NS_TRACE_MALLOC
   gArgc = argc = NS_TraceMallocStartupArgs(gArgc, gArgv);
 #endif
 
   MOZ_SPLASHSCREEN_UPDATE(20);
 
-#ifdef MOZ_IPC
+#if defined(MOZ_IPC) && !defined(OS_WIN)
   // FIXME: this and its constituents leak
   char** canonArgs = new char*[gArgc];
 
   // get the canonical version of the binary's path
   nsCOMPtr<nsILocalFile> binFile;
   rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(binFile));
   NS_ENSURE_SUCCESS(rv, 2);
 
@@ -3525,37 +3520,16 @@ XRE_main(int argc, char* argv[], const n
 #endif /* MOZ_ENABLE_XREMOTE */
 
             // enable win32 DDE responses and Mac appleevents responses
             nativeApp->Enable();
           }
 
           MOZ_SPLASHSCREEN_UPDATE(90);
           {
-#if 0 && defined(OS_LINUX)
-            // The lifetime of the BACKGROUND_X11 thread is a subset
-            // of the IO thread so we start it now.
-             scoped_ptr<base::Thread> x11Thread(
-               new BrowserProcessSubThread(BrowserProcessSubThread::BACKGROUND_X11));
-             if (NS_UNLIKELY(!x11Thread->Start())) {
-               NS_ERROR("Failed to create chromium's X11 thread!");
-               return NS_ERROR_FAILURE;
-             }
-#endif
-#ifdef MOZ_IPC
-            scoped_ptr<base::Thread> ipcThread(
-              new BrowserProcessSubThread(BrowserProcessSubThread::IO));
-            base::Thread::Options options;
-            options.message_loop_type = MessageLoop::TYPE_IO;
-            if (NS_UNLIKELY(!ipcThread->StartWithOptions(options))) {
-              NS_ERROR("Failed to create chromium's IO thread!");
-              return NS_ERROR_FAILURE;
-            }
-#endif
-
             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;
             }
           }
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -37,17 +37,16 @@
 
 #include "nsXULAppAPI.h"
 
 #include <stdlib.h>
 
 #include "prenv.h"
 
 #include "nsIAppShell.h"
-#include "nsIAppStartup.h"
 #include "nsIAppStartupNotifier.h"
 #include "nsIDirectoryService.h"
 #include "nsILocalFile.h"
 #include "nsIToolkitChromeRegistry.h"
 #include "nsIToolkitProfile.h"
 
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsAppRunner.h"
@@ -59,42 +58,42 @@
 #include "nsWidgetsCID.h"
 #include "nsXPFEComponentsCID.h"
 #include "nsXREDirProvider.h"
 
 #ifdef MOZ_IPC
 #include "base/at_exit.h"
 #include "base/command_line.h"
 #include "base/message_loop.h"
-#include "base/thread.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 "ContentProcessThread.h"
 #include "ContentProcessParent.h"
+#include "ContentProcessChild.h"
 
 #include "mozilla/ipc/TestShellParent.h"
 #include "mozilla/ipc/XPCShellEnvironment.h"
 #include "mozilla/test/TestParent.h"
 #include "mozilla/test/TestProcessParent.h"
 #include "mozilla/test/TestThreadChild.h"
 #include "mozilla/Monitor.h"
 
-using mozilla::ipc::BrowserProcessSubThread;
 using mozilla::ipc::GeckoChildProcessHost;
 using mozilla::ipc::GeckoThread;
 using mozilla::ipc::ScopedXREEmbed;
 
 using mozilla::plugins::PluginThreadChild;
 using mozilla::dom::ContentProcessThread;
 using mozilla::dom::ContentProcessParent;
+using mozilla::dom::ContentProcessChild;
 using mozilla::ipc::TestShellParent;
 using mozilla::ipc::XPCShellEnvironment;
 
 using mozilla::test::TestParent;
 using mozilla::test::TestProcessParent;
 using mozilla::test::TestThreadChild;
 
 using mozilla::Monitor;
@@ -332,42 +331,21 @@ 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]);
 
-  base::AtExitManager exitManager;
   CommandLine::Init(aArgc, aArgv);
-  MessageLoopForUI mainMessageLoop;
+
   ScopedXREEmbed embed;
 
   {
-    // Make chromium's IPC thread
-#if defined(OS_LINUX)
-    // The lifetime of the BACKGROUND_X11 thread is a subset of the IO thread so
-    // we start it now.
-    scoped_ptr<base::Thread> x11Thread(
-      new BrowserProcessSubThread(BrowserProcessSubThread::BACKGROUND_X11));
-    if (NS_UNLIKELY(!x11Thread->Start())) {
-      NS_ERROR("Failed to create chromium's X11 thread!");
-      return NS_ERROR_FAILURE;
-    }
-#endif
-    scoped_ptr<base::Thread> ipcThread(
-      new BrowserProcessSubThread(BrowserProcessSubThread::IO));
-    base::Thread::Options options;
-    options.message_loop_type = MessageLoop::TYPE_IO;
-    if (NS_UNLIKELY(!ipcThread->StartWithOptions(options))) {
-      NS_ERROR("Failed to create chromium's IO thread!");
-      return NS_ERROR_FAILURE;
-    }
-
     embed.Start();
 
     nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
     NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
 
     if (aMainFunction) {
       nsCOMPtr<nsIRunnable> runnable =
         new MainFunctionRunnable(aMainFunction, aMainFunctionData);
@@ -494,18 +472,64 @@ XRE_RunIPCTestHarness(int aArgc, char* a
 {
     nsresult rv =
         XRE_InitParentProcess(
             aArgc, aArgv, IPCTestHarnessMain, NULL);
     NS_ENSURE_SUCCESS(rv, 1);
     return 0;
 }
 
-void
-XRE_ShutdownChildProcess()
+nsresult
+XRE_RunAppShell()
+{
+    nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
+    NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
+
+    return appShell->Run();
+}
+
+template<>
+struct RunnableMethodTraits<ContentProcessChild>
 {
-    nsCOMPtr<nsIAppStartup> appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID));
-    if (appStartup) {
-        appStartup->Quit(nsIAppStartup::eForceQuit);
+    static void RetainCallee(ContentProcessChild* obj) { }
+    static void ReleaseCallee(ContentProcessChild* obj) { }
+};
+
+void
+XRE_ShutdownChildProcess(MessageLoop* aUILoop)
+{
+    if (aUILoop) {
+        NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+        aUILoop->PostTask(FROM_HERE,
+            NewRunnableMethod(ContentProcessChild::GetSingleton(),
+                              &ContentProcessChild::Quit));
+        return;
+    }
+
+    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+    nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
+    if (appShell) {
+        appShell->Exit();
     }
 }
 
+ContentProcessParent*
+XRE_GetContentProcessParent()
+{
+    if (XRE_GetProcessType() == GeckoProcessType_Default) {
+        return ContentProcessParent::GetSingleton();
+    }
+    NS_WARNING("Called XRE_GetContentProcessParent in child process!");
+    return nsnull;
+}
+
+ContentProcessChild*
+XRE_GetContentProcessChild()
+{
+    if (XRE_GetProcessType() != GeckoProcessType_Default) {
+        return ContentProcessChild::GetSingleton();
+    }
+    NS_WARNING("Called XRE_GetContentProcessChild in parent process!");
+    return nsnull;
+}
+
 #endif
--- 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/ipdl ipc/chromium ipc/glue
+endif
--- a/xpcom/build/nsXPComInit.cpp
+++ b/xpcom/build/nsXPComInit.cpp
@@ -145,23 +145,27 @@ NS_DECL_CLASSINFO(nsStringInputStream)
 
 #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
@@ -582,16 +586,28 @@ NS_InitXPCOM3(nsIServiceManager* *result
         CommandLine::Init(1, &argv);
 #endif
     }
 
     if (!MessageLoop::current()) {
         sMessageLoop = new MessageLoopForUI();
         NS_ENSURE_STATE(sMessageLoop);
     }
+
+    if (!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);
 
@@ -957,16 +973,20 @@ ShutdownXPCOM(nsIServiceManager* servMgr
     NS_LogTerm();
 
 #ifdef GC_LEAK_DETECTOR
     // Shutdown the Leak detector.
     NS_ShutdownLeakDetector();
 #endif
 
 #ifdef MOZ_IPC
+    if (sIOThread) {
+        delete sIOThread;
+        sIOThread = nsnull;
+    }
     if (sMessageLoop) {
         delete sMessageLoop;
         sMessageLoop = nsnull;
     }
     if (sCommandLineWasInitialized) {
         CommandLine::Terminate();
         sCommandLineWasInitialized = false;
     }
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -468,12 +468,29 @@ XRE_API(nsresult,
 XRE_API(int,
         XRE_RunTestShell, (int aArgc,
                            char* aArgv[]))
 
 XRE_API(int,
         XRE_RunIPCTestHarness, (int aArgc,
                                 char* aArgv[]))
 
+XRE_API(nsresult,
+        XRE_RunAppShell, ())
+
+class MessageLoop;
+
 XRE_API(void,
-        XRE_ShutdownChildProcess, ())
+        XRE_ShutdownChildProcess, (MessageLoop* aUILoop = 0))
+
+namespace mozilla {
+namespace dom {
+class ContentProcessParent;
+class ContentProcessChild;
+}
+}
+
+XRE_API(mozilla::dom::ContentProcessParent*,
+        XRE_GetContentProcessParent, ())
+XRE_API(mozilla::dom::ContentProcessChild*,
+        XRE_GetContentProcessChild, ())
 
 #endif // _nsXULAppAPI_h__