LCOV - code coverage report
Current view: directory - toolkit/xre - nsEmbedFunctions.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 187 48 25.7 %
Date: 2012-06-02 Functions: 22 5 22.7 %

       1                 : /* ***** BEGIN LICENSE BLOCK *****
       2                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       3                 :  *
       4                 :  * The contents of this file are subject to the Mozilla Public License Version
       5                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       6                 :  * the License. You may obtain a copy of the License at
       7                 :  * http://www.mozilla.org/MPL/
       8                 :  *
       9                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      10                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      11                 :  * for the specific language governing rights and limitations under the
      12                 :  * License.
      13                 :  *
      14                 :  * The Original Code is Mozilla libXUL embedding.
      15                 :  *
      16                 :  * The Initial Developer of the Original Code is
      17                 :  * Benjamin Smedberg <benjamin@smedbergs.us>
      18                 :  *
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2005
      20                 :  * the Mozilla Foundation. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      26                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : #if defined(MOZ_WIDGET_QT)
      39                 : #include "nsQAppInstance.h"
      40                 : #endif
      41                 : 
      42                 : #include "base/basictypes.h"
      43                 : 
      44                 : #include "nsXULAppAPI.h"
      45                 : 
      46                 : #include <stdlib.h>
      47                 : #if defined(MOZ_WIDGET_GTK2)
      48                 : #include <glib.h>
      49                 : #endif
      50                 : 
      51                 : #include "prenv.h"
      52                 : 
      53                 : #include "nsIAppShell.h"
      54                 : #include "nsIAppStartupNotifier.h"
      55                 : #include "nsIDirectoryService.h"
      56                 : #include "nsILocalFile.h"
      57                 : #include "nsIToolkitChromeRegistry.h"
      58                 : #include "nsIToolkitProfile.h"
      59                 : 
      60                 : #if defined(OS_LINUX)
      61                 : #  define XP_LINUX
      62                 : #endif
      63                 : 
      64                 : #ifdef XP_WIN
      65                 : #include <process.h>
      66                 : #endif
      67                 : 
      68                 : #include "nsAppDirectoryServiceDefs.h"
      69                 : #include "nsAppRunner.h"
      70                 : #include "nsAutoRef.h"
      71                 : #include "nsDirectoryServiceDefs.h"
      72                 : #include "nsExceptionHandler.h"
      73                 : #include "nsString.h"
      74                 : #include "nsThreadUtils.h"
      75                 : #include "nsJSUtils.h"
      76                 : #include "nsWidgetsCID.h"
      77                 : #include "nsXREDirProvider.h"
      78                 : 
      79                 : #include "mozilla/Omnijar.h"
      80                 : #if defined(XP_MACOSX)
      81                 : #include "nsVersionComparator.h"
      82                 : #include "chrome/common/mach_ipc_mac.h"
      83                 : #endif
      84                 : #include "nsX11ErrorHandler.h"
      85                 : #include "base/at_exit.h"
      86                 : #include "base/command_line.h"
      87                 : #include "base/message_loop.h"
      88                 : #include "base/process_util.h"
      89                 : #include "chrome/common/child_process.h"
      90                 : #include "chrome/common/notification_service.h"
      91                 : 
      92                 : #include "mozilla/ipc/BrowserProcessSubThread.h"
      93                 : #include "mozilla/ipc/GeckoChildProcessHost.h"
      94                 : #include "mozilla/ipc/IOThreadChild.h"
      95                 : #include "mozilla/ipc/ProcessChild.h"
      96                 : #include "ScopedXREEmbed.h"
      97                 : 
      98                 : #include "mozilla/plugins/PluginProcessChild.h"
      99                 : #include "mozilla/dom/ContentProcess.h"
     100                 : #include "mozilla/dom/ContentParent.h"
     101                 : #include "mozilla/dom/ContentChild.h"
     102                 : 
     103                 : #include "mozilla/jsipc/ContextWrapperParent.h"
     104                 : 
     105                 : #include "mozilla/ipc/TestShellParent.h"
     106                 : #include "mozilla/ipc/XPCShellEnvironment.h"
     107                 : 
     108                 : #include "mozilla/Util.h" // for DebugOnly
     109                 : 
     110                 : #ifdef MOZ_IPDL_TESTS
     111                 : #include "mozilla/_ipdltest/IPDLUnitTests.h"
     112                 : #include "mozilla/_ipdltest/IPDLUnitTestProcessChild.h"
     113                 : 
     114                 : using mozilla::_ipdltest::IPDLUnitTestProcessChild;
     115                 : #endif  // ifdef MOZ_IPDL_TESTS
     116                 : 
     117                 : using namespace mozilla;
     118                 : 
     119                 : using mozilla::ipc::BrowserProcessSubThread;
     120                 : using mozilla::ipc::GeckoChildProcessHost;
     121                 : using mozilla::ipc::IOThreadChild;
     122                 : using mozilla::ipc::ProcessChild;
     123                 : using mozilla::ipc::ScopedXREEmbed;
     124                 : 
     125                 : using mozilla::plugins::PluginProcessChild;
     126                 : using mozilla::dom::ContentProcess;
     127                 : using mozilla::dom::ContentParent;
     128                 : using mozilla::dom::ContentChild;
     129                 : 
     130                 : using mozilla::jsipc::PContextWrapperParent;
     131                 : using mozilla::jsipc::ContextWrapperParent;
     132                 : 
     133                 : using mozilla::ipc::TestShellParent;
     134                 : using mozilla::ipc::TestShellCommandParent;
     135                 : using mozilla::ipc::XPCShellEnvironment;
     136                 : 
     137                 : using mozilla::startup::sChildProcessType;
     138                 : 
     139                 : static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
     140                 : 
     141                 : #ifdef XP_WIN
     142                 : static const PRUnichar kShellLibraryName[] =  L"shell32.dll";
     143                 : #endif
     144                 : 
     145                 : nsresult
     146               0 : XRE_LockProfileDirectory(nsILocalFile* aDirectory,
     147                 :                          nsISupports* *aLockObject)
     148                 : {
     149               0 :   nsCOMPtr<nsIProfileLock> lock;
     150                 : 
     151                 :   nsresult rv = NS_LockProfilePath(aDirectory, nsnull, nsnull,
     152               0 :                                    getter_AddRefs(lock));
     153               0 :   if (NS_SUCCEEDED(rv))
     154               0 :     NS_ADDREF(*aLockObject = lock);
     155                 : 
     156               0 :   return rv;
     157                 : }
     158                 : 
     159                 : static PRInt32 sInitCounter;
     160                 : 
     161                 : nsresult
     162               0 : XRE_InitEmbedding2(nsILocalFile *aLibXULDirectory,
     163                 :                    nsILocalFile *aAppDirectory,
     164                 :                    nsIDirectoryServiceProvider *aAppDirProvider)
     165                 : {
     166                 :   // Initialize some globals to make nsXREDirProvider happy
     167                 :   static char* kNullCommandLine[] = { nsnull };
     168               0 :   gArgv = kNullCommandLine;
     169               0 :   gArgc = 0;
     170                 : 
     171               0 :   NS_ENSURE_ARG(aLibXULDirectory);
     172                 : 
     173               0 :   if (++sInitCounter > 1) // XXXbsmedberg is this really the right solution?
     174               0 :     return NS_OK;
     175                 : 
     176               0 :   if (!aAppDirectory)
     177               0 :     aAppDirectory = aLibXULDirectory;
     178                 : 
     179                 :   nsresult rv;
     180                 : 
     181               0 :   new nsXREDirProvider; // This sets gDirServiceProvider
     182               0 :   if (!gDirServiceProvider)
     183               0 :     return NS_ERROR_OUT_OF_MEMORY;
     184                 : 
     185                 :   rv = gDirServiceProvider->Initialize(aAppDirectory, aLibXULDirectory,
     186               0 :                                        aAppDirProvider);
     187               0 :   if (NS_FAILED(rv))
     188               0 :     return rv;
     189                 : 
     190               0 :   rv = NS_InitXPCOM2(nsnull, aAppDirectory, gDirServiceProvider);
     191               0 :   if (NS_FAILED(rv))
     192               0 :     return rv;
     193                 : 
     194                 :   // We do not need to autoregister components here. The CheckCompatibility()
     195                 :   // bits in nsAppRunner.cpp check for an invalidation flag in
     196                 :   // compatibility.ini.
     197                 :   // If the app wants to autoregister every time (for instance, if it's debug),
     198                 :   // it can do so after we return from this function.
     199                 : 
     200                 :   nsCOMPtr<nsIObserver> startupNotifier
     201               0 :     (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID));
     202               0 :   if (!startupNotifier)
     203               0 :     return NS_ERROR_FAILURE;
     204                 : 
     205               0 :   startupNotifier->Observe(nsnull, APPSTARTUP_TOPIC, nsnull);
     206                 : 
     207               0 :   return NS_OK;
     208                 : }
     209                 : 
     210                 : void
     211               0 : XRE_NotifyProfile()
     212                 : {
     213               0 :   NS_ASSERTION(gDirServiceProvider, "XRE_InitEmbedding was not called!");
     214               0 :   gDirServiceProvider->DoStartup();
     215               0 : }
     216                 : 
     217                 : void
     218               0 : XRE_TermEmbedding()
     219                 : {
     220               0 :   if (--sInitCounter != 0)
     221               0 :     return;
     222                 : 
     223               0 :   NS_ASSERTION(gDirServiceProvider,
     224                 :                "XRE_TermEmbedding without XRE_InitEmbedding");
     225                 : 
     226               0 :   gDirServiceProvider->DoShutdown();
     227               0 :   NS_ShutdownXPCOM(nsnull);
     228               0 :   delete gDirServiceProvider;
     229                 : }
     230                 : 
     231                 : const char*
     232            1409 : XRE_ChildProcessTypeToString(GeckoProcessType aProcessType)
     233                 : {
     234                 :   return (aProcessType < GeckoProcessType_End) ?
     235            1409 :     kGeckoProcessTypeString[aProcessType] : nsnull;
     236                 : }
     237                 : 
     238                 : GeckoProcessType
     239               1 : XRE_StringToChildProcessType(const char* aProcessTypeString)
     240                 : {
     241               6 :   for (int i = 0;
     242               3 :        i < (int) ArrayLength(kGeckoProcessTypeString);
     243                 :        ++i) {
     244               3 :     if (!strcmp(kGeckoProcessTypeString[i], aProcessTypeString)) {
     245               1 :       return static_cast<GeckoProcessType>(i);
     246                 :     }
     247                 :   }
     248               0 :   return GeckoProcessType_Invalid;
     249                 : }
     250                 : 
     251                 : namespace mozilla {
     252                 : namespace startup {
     253                 : GeckoProcessType sChildProcessType = GeckoProcessType_Default;
     254                 : }
     255                 : }
     256                 : 
     257                 : #if defined(MOZ_CRASHREPORTER)
     258                 : // FIXME/bug 539522: this out-of-place function is stuck here because
     259                 : // IPDL wants access to this crashreporter interface, and
     260                 : // crashreporter is built in such a way to make that awkward
     261                 : bool
     262               0 : XRE_TakeMinidumpForChild(PRUint32 aChildPid, nsILocalFile** aDump)
     263                 : {
     264               0 :   return CrashReporter::TakeMinidumpForChild(aChildPid, aDump);
     265                 : }
     266                 : 
     267                 : bool
     268               1 : XRE_SetRemoteExceptionHandler(const char* aPipe/*= 0*/)
     269                 : {
     270                 : #if defined(XP_WIN) || defined(XP_MACOSX)
     271                 :   return CrashReporter::SetRemoteExceptionHandler(nsDependentCString(aPipe));
     272                 : #elif defined(OS_LINUX)
     273               1 :   return CrashReporter::SetRemoteExceptionHandler();
     274                 : #else
     275                 : #  error "OOP crash reporter unsupported on this platform"
     276                 : #endif
     277                 : }
     278                 : #endif // if defined(MOZ_CRASHREPORTER)
     279                 : 
     280                 : #if defined(XP_WIN)
     281                 : void
     282                 : SetTaskbarGroupId(const nsString& aId)
     283                 : {
     284                 :     typedef HRESULT (WINAPI * SetCurrentProcessExplicitAppUserModelIDPtr)(PCWSTR AppID);
     285                 : 
     286                 :     SetCurrentProcessExplicitAppUserModelIDPtr funcAppUserModelID = nsnull;
     287                 : 
     288                 :     HMODULE hDLL = ::LoadLibraryW(kShellLibraryName);
     289                 : 
     290                 :     funcAppUserModelID = (SetCurrentProcessExplicitAppUserModelIDPtr)
     291                 :                           GetProcAddress(hDLL, "SetCurrentProcessExplicitAppUserModelID");
     292                 : 
     293                 :     if (!funcAppUserModelID) {
     294                 :         ::FreeLibrary(hDLL);
     295                 :         return;
     296                 :     }
     297                 : 
     298                 :     if (FAILED(funcAppUserModelID(aId.get()))) {
     299                 :         NS_WARNING("SetCurrentProcessExplicitAppUserModelID failed for child process.");
     300                 :     }
     301                 : 
     302                 :     if (hDLL)
     303                 :         ::FreeLibrary(hDLL);
     304                 : }
     305                 : #endif
     306                 : 
     307                 : nsresult
     308               1 : XRE_InitChildProcess(int aArgc,
     309                 :                      char* aArgv[],
     310                 :                      GeckoProcessType aProcess)
     311                 : {
     312               1 :   NS_ENSURE_ARG_MIN(aArgc, 2);
     313               1 :   NS_ENSURE_ARG_POINTER(aArgv);
     314               1 :   NS_ENSURE_ARG_POINTER(aArgv[0]);
     315                 : 
     316               1 :   sChildProcessType = aProcess;
     317                 : 
     318                 :   // Complete 'task_t' exchange for Mac OS X. This structure has the same size
     319                 :   // regardless of architecture so we don't have any cross-arch issues here.
     320                 : #ifdef XP_MACOSX
     321                 :   if (aArgc < 1)
     322                 :     return 1;
     323                 :   const char* const mach_port_name = aArgv[--aArgc];
     324                 : 
     325                 :   const int kTimeoutMs = 1000;
     326                 : 
     327                 :   MachSendMessage child_message(0);
     328                 :   if (!child_message.AddDescriptor(mach_task_self())) {
     329                 :     NS_WARNING("child AddDescriptor(mach_task_self()) failed.");
     330                 :     return 1;
     331                 :   }
     332                 : 
     333                 :   ReceivePort child_recv_port;
     334                 :   mach_port_t raw_child_recv_port = child_recv_port.GetPort();
     335                 :   if (!child_message.AddDescriptor(raw_child_recv_port)) {
     336                 :     NS_WARNING("Adding descriptor to message failed");
     337                 :     return 1;
     338                 :   }
     339                 : 
     340                 :   MachPortSender child_sender(mach_port_name);
     341                 :   kern_return_t err = child_sender.SendMessage(child_message, kTimeoutMs);
     342                 :   if (err != KERN_SUCCESS) {
     343                 :     NS_WARNING("child SendMessage() failed");
     344                 :     return 1;
     345                 :   }
     346                 : 
     347                 :   MachReceiveMessage parent_message;
     348                 :   err = child_recv_port.WaitForMessage(&parent_message, kTimeoutMs);
     349                 :   if (err != KERN_SUCCESS) {
     350                 :     NS_WARNING("child WaitForMessage() failed");
     351                 :     return 1;
     352                 :   }
     353                 : 
     354                 :   if (parent_message.GetTranslatedPort(0) == MACH_PORT_NULL) {
     355                 :     NS_WARNING("child GetTranslatedPort(0) failed");
     356                 :     return 1;
     357                 :   }
     358                 :   err = task_set_bootstrap_port(mach_task_self(),
     359                 :                                 parent_message.GetTranslatedPort(0));
     360                 :   if (err != KERN_SUCCESS) {
     361                 :     NS_WARNING("child task_set_bootstrap_port() failed");
     362                 :     return 1;
     363                 :   }
     364                 : #endif
     365                 : 
     366               1 :   SetupErrorHandling(aArgv[0]);  
     367                 : 
     368                 : #if defined(MOZ_CRASHREPORTER)
     369               1 :   if (aArgc < 1)
     370               0 :     return 1;
     371               1 :   const char* const crashReporterArg = aArgv[--aArgc];
     372                 :   
     373                 : #  if defined(XP_WIN) || defined(XP_MACOSX)
     374                 :   // on windows and mac, |crashReporterArg| is the named pipe on which the
     375                 :   // server is listening for requests, or "-" if crash reporting is
     376                 :   // disabled.
     377                 :   if (0 != strcmp("-", crashReporterArg) && 
     378                 :       !XRE_SetRemoteExceptionHandler(crashReporterArg)) {
     379                 :     // Bug 684322 will add better visibility into this condition
     380                 :     NS_WARNING("Could not setup crash reporting\n");
     381                 :   }
     382                 : #  elif defined(OS_LINUX)
     383                 :   // on POSIX, |crashReporterArg| is "true" if crash reporting is
     384                 :   // enabled, false otherwise
     385               2 :   if (0 != strcmp("false", crashReporterArg) && 
     386               1 :       !XRE_SetRemoteExceptionHandler(NULL)) {
     387                 :     // Bug 684322 will add better visibility into this condition
     388               0 :     NS_WARNING("Could not setup crash reporting\n");
     389                 :   }
     390                 : #  else
     391                 : #    error "OOP crash reporting unsupported on this platform"
     392                 : #  endif   
     393                 : #endif // if defined(MOZ_CRASHREPORTER)
     394                 : 
     395               1 :   gArgv = aArgv;
     396               1 :   gArgc = aArgc;
     397                 : 
     398                 : #if defined(MOZ_WIDGET_GTK2)
     399               1 :   g_thread_init(NULL);
     400                 : #endif
     401                 : 
     402                 : #if defined(MOZ_WIDGET_QT)
     403                 :   nsQAppInstance::AddRef();
     404                 : #endif
     405                 : 
     406               1 :   if (PR_GetEnv("MOZ_DEBUG_CHILD_PROCESS")) {
     407                 : #ifdef OS_POSIX
     408               0 :       printf("\n\nCHILDCHILDCHILDCHILD\n  debug me @%d\n\n", getpid());
     409               0 :       sleep(30);
     410                 : #elif defined(OS_WIN)
     411                 :       printf("\n\nCHILDCHILDCHILDCHILD\n  debug me @%d\n\n", _getpid());
     412                 :       Sleep(30000);
     413                 : #endif
     414                 :   }
     415                 : 
     416                 :   // child processes launched by GeckoChildProcessHost get this magic
     417                 :   // argument appended to their command lines
     418               1 :   const char* const parentPIDString = aArgv[aArgc-1];
     419               1 :   NS_ABORT_IF_FALSE(parentPIDString, "NULL parent PID");
     420               1 :   --aArgc;
     421                 : 
     422               1 :   char* end = 0;
     423               1 :   base::ProcessId parentPID = strtol(parentPIDString, &end, 10);
     424               1 :   NS_ABORT_IF_FALSE(!*end, "invalid parent PID");
     425                 : 
     426                 :   base::ProcessHandle parentHandle;
     427               1 :   mozilla::DebugOnly<bool> ok = base::OpenProcessHandle(parentPID, &parentHandle);
     428               1 :   NS_ABORT_IF_FALSE(ok, "can't open handle to parent");
     429                 : 
     430                 : #if defined(XP_WIN)
     431                 :   // On Win7+, register the application user model id passed in by
     432                 :   // parent. This insures windows created by the container properly
     433                 :   // group with the parent app on the Win7 taskbar.
     434                 :   const char* const appModelUserId = aArgv[aArgc-1];
     435                 :   --aArgc;
     436                 :   if (appModelUserId) {
     437                 :     // '-' implies no support
     438                 :     if (*appModelUserId != '-') {
     439                 :       nsString appId;
     440                 :       appId.AssignWithConversion(nsDependentCString(appModelUserId));
     441                 :       // The version string is encased in quotes
     442                 :       appId.Trim(NS_LITERAL_CSTRING("\"").get());
     443                 :       // Set the id
     444                 :       SetTaskbarGroupId(appId);
     445                 :     }
     446                 :   }
     447                 : #endif
     448                 : 
     449               1 :   base::AtExitManager exitManager;
     450               1 :   NotificationService notificationService;
     451                 : 
     452               1 :   NS_LogInit();
     453                 : 
     454               1 :   int rv = XRE_InitCommandLine(aArgc, aArgv);
     455               1 :   if (NS_FAILED(rv)) {
     456               0 :     NS_LogTerm();
     457               0 :     return NS_ERROR_FAILURE;
     458                 :   }
     459                 : 
     460                 :   MessageLoop::Type uiLoopType;
     461               1 :   switch (aProcess) {
     462                 :   case GeckoProcessType_Content:
     463                 :       // Content processes need the XPCOM/chromium frankenventloop
     464               1 :       uiLoopType = MessageLoop::TYPE_MOZILLA_CHILD;
     465               1 :       break;
     466                 :   default:
     467               0 :       uiLoopType = MessageLoop::TYPE_UI;
     468               0 :       break;
     469                 :   }
     470                 : 
     471                 :   {
     472                 :     // This is a lexical scope for the MessageLoop below.  We want it
     473                 :     // to go out of scope before NS_LogTerm() so that we don't get
     474                 :     // spurious warnings about XPCOM objects being destroyed from a
     475                 :     // static context.
     476                 : 
     477                 :     // Associate this thread with a UI MessageLoop
     478               1 :     MessageLoop uiMessageLoop(uiLoopType);
     479                 :     {
     480               1 :       nsAutoPtr<ProcessChild> process;
     481                 : 
     482               1 :       switch (aProcess) {
     483                 :       case GeckoProcessType_Default:
     484               0 :         NS_RUNTIMEABORT("This makes no sense");
     485               0 :         break;
     486                 : 
     487                 :       case GeckoProcessType_Plugin:
     488               0 :         process = new PluginProcessChild(parentHandle);
     489               0 :         break;
     490                 : 
     491                 :       case GeckoProcessType_Content:
     492               1 :         process = new ContentProcess(parentHandle);
     493               1 :         break;
     494                 : 
     495                 :       case GeckoProcessType_IPDLUnitTest:
     496                 : #ifdef MOZ_IPDL_TESTS
     497                 :         process = new IPDLUnitTestProcessChild(parentHandle);
     498                 : #else 
     499               0 :         NS_RUNTIMEABORT("rebuild with --enable-ipdl-tests");
     500                 : #endif
     501               0 :         break;
     502                 : 
     503                 :       default:
     504               0 :         NS_RUNTIMEABORT("Unknown main thread class");
     505                 :       }
     506                 : 
     507               1 :       if (!process->Init()) {
     508               0 :         NS_LogTerm();
     509               0 :         return NS_ERROR_FAILURE;
     510                 :       }
     511                 : 
     512                 :       // Run the UI event loop on the main thread.
     513               0 :       uiMessageLoop.MessageLoop::Run();
     514                 : 
     515                 :       // Allow ProcessChild to clean up after itself before going out of
     516                 :       // scope and being deleted
     517               0 :       process->CleanUp();
     518               0 :       mozilla::Omnijar::CleanUp();
     519                 :     }
     520                 :   }
     521                 : 
     522               0 :   NS_LogTerm();
     523               0 :   return XRE_DeinitCommandLine();
     524                 : }
     525                 : 
     526                 : MessageLoop*
     527               0 : XRE_GetIOMessageLoop()
     528                 : {
     529               0 :   if (sChildProcessType == GeckoProcessType_Default) {
     530               0 :     return BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO);
     531                 :   }
     532               0 :   return IOThreadChild::message_loop();
     533                 : }
     534                 : 
     535                 : namespace {
     536                 : 
     537                 : class MainFunctionRunnable : public nsRunnable
     538               0 : {
     539                 : public:
     540                 :   NS_DECL_NSIRUNNABLE
     541                 : 
     542               0 :   MainFunctionRunnable(MainFunction aFunction,
     543                 :                        void* aData)
     544                 :   : mFunction(aFunction),
     545               0 :     mData(aData)
     546                 :   { 
     547               0 :     NS_ASSERTION(aFunction, "Don't give me a null pointer!");
     548               0 :   }
     549                 : 
     550                 : private:
     551                 :   MainFunction mFunction;
     552                 :   void* mData;
     553                 : };
     554                 : 
     555                 : } /* anonymous namespace */
     556                 : 
     557                 : NS_IMETHODIMP
     558               0 : MainFunctionRunnable::Run()
     559                 : {
     560               0 :   mFunction(mData);
     561               0 :   return NS_OK;
     562                 : }
     563                 : 
     564                 : nsresult
     565               0 : XRE_InitParentProcess(int aArgc,
     566                 :                       char* aArgv[],
     567                 :                       MainFunction aMainFunction,
     568                 :                       void* aMainFunctionData)
     569                 : {
     570               0 :   NS_ENSURE_ARG_MIN(aArgc, 1);
     571               0 :   NS_ENSURE_ARG_POINTER(aArgv);
     572               0 :   NS_ENSURE_ARG_POINTER(aArgv[0]);
     573                 : 
     574               0 :   ScopedXREEmbed embed;
     575                 : 
     576               0 :   gArgc = aArgc;
     577               0 :   gArgv = aArgv;
     578               0 :   int rv = XRE_InitCommandLine(gArgc, gArgv);
     579               0 :   if (NS_FAILED(rv))
     580               0 :       return NS_ERROR_FAILURE;
     581                 : 
     582                 :   {
     583               0 :     embed.Start();
     584                 : 
     585               0 :     nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
     586               0 :     NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
     587                 : 
     588               0 :     if (aMainFunction) {
     589                 :       nsCOMPtr<nsIRunnable> runnable =
     590               0 :         new MainFunctionRunnable(aMainFunction, aMainFunctionData);
     591               0 :       NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
     592                 : 
     593               0 :       nsresult rv = NS_DispatchToCurrentThread(runnable);
     594               0 :       NS_ENSURE_SUCCESS(rv, rv);
     595                 :     }
     596                 : 
     597                 :     // Do event loop
     598               0 :     if (NS_FAILED(appShell->Run())) {
     599               0 :       NS_WARNING("Failed to run appshell");
     600               0 :       return NS_ERROR_FAILURE;
     601                 :     }
     602                 :   }
     603                 : 
     604               0 :   return XRE_DeinitCommandLine();
     605                 : }
     606                 : 
     607                 : #ifdef MOZ_IPDL_TESTS
     608                 : //-----------------------------------------------------------------------------
     609                 : // IPDL unit test
     610                 : 
     611                 : int
     612                 : XRE_RunIPDLTest(int aArgc, char** aArgv)
     613                 : {
     614                 :     if (aArgc < 2) {
     615                 :         fprintf(stderr, "TEST-UNEXPECTED-FAIL | <---> | insufficient #args, need at least 2\n");
     616                 :         return 1;
     617                 :     }
     618                 : 
     619                 :     void* data = reinterpret_cast<void*>(aArgv[aArgc-1]);
     620                 : 
     621                 :     nsresult rv =
     622                 :         XRE_InitParentProcess(
     623                 :             --aArgc, aArgv, mozilla::_ipdltest::IPDLUnitTestMain, data);
     624                 :     NS_ENSURE_SUCCESS(rv, 1);
     625                 : 
     626                 :     return 0;
     627                 : }
     628                 : #endif  // ifdef MOZ_IPDL_TESTS
     629                 : 
     630                 : nsresult
     631               0 : XRE_RunAppShell()
     632                 : {
     633               0 :     nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
     634                 : #if defined(XP_MACOSX)
     635                 :     {
     636                 :       // In content processes that want XPCOM (and hence want
     637                 :       // AppShell), we usually run our hybrid event loop through
     638                 :       // MessagePump::Run(), by way of nsBaseAppShell::Run().  The
     639                 :       // Cocoa nsAppShell impl, however, implements its own Run()
     640                 :       // that's unaware of MessagePump.  That's all rather suboptimal,
     641                 :       // but oddly enough not a problem... usually.
     642                 :       // 
     643                 :       // The problem with this setup comes during startup.
     644                 :       // XPCOM-in-subprocesses depends on IPC, e.g. to init the pref
     645                 :       // service, so we have to init IPC first.  But, IPC also
     646                 :       // indirectly kinda-depends on XPCOM, because MessagePump
     647                 :       // schedules work from off-main threads (e.g. IO thread) by
     648                 :       // using NS_DispatchToMainThread().  If the IO thread receives a
     649                 :       // Message from the parent before nsThreadManager is
     650                 :       // initialized, then DispatchToMainThread() will fail, although
     651                 :       // MessagePump will remember the task.  This race condition
     652                 :       // isn't a problem when appShell->Run() ends up in
     653                 :       // MessagePump::Run(), because MessagePump will immediate see it
     654                 :       // has work to do.  It *is* a problem when we end up in [NSApp
     655                 :       // run], because it's not aware that MessagePump has work that
     656                 :       // needs to be processed; that was supposed to be signaled by
     657                 :       // nsIRunnable(s).
     658                 :       // 
     659                 :       // So instead of hacking Cocoa nsAppShell or rewriting the
     660                 :       // event-loop system, we compromise here by processing any tasks
     661                 :       // that might have been enqueued on MessagePump, *before*
     662                 :       // MessagePump::ScheduleWork was able to successfully
     663                 :       // DispatchToMainThread().
     664                 :       MessageLoop* loop = MessageLoop::current();
     665                 :       bool couldNest = loop->NestableTasksAllowed();
     666                 : 
     667                 :       loop->SetNestableTasksAllowed(true);
     668                 :       loop->PostTask(FROM_HERE, new MessageLoop::QuitTask());
     669                 :       loop->Run();
     670                 : 
     671                 :       loop->SetNestableTasksAllowed(couldNest);
     672                 :     }
     673                 : #endif  // XP_MACOSX
     674               0 :     return appShell->Run();
     675                 : }
     676                 : 
     677                 : template<>
     678                 : struct RunnableMethodTraits<ContentChild>
     679                 : {
     680                 :     static void RetainCallee(ContentChild* obj) { }
     681                 :     static void ReleaseCallee(ContentChild* obj) { }
     682                 : };
     683                 : 
     684                 : void
     685               0 : XRE_ShutdownChildProcess()
     686                 : {
     687               0 :   NS_ABORT_IF_FALSE(MessageLoopForUI::current(), "Wrong thread!");
     688                 : 
     689               0 :   mozilla::DebugOnly<MessageLoop*> ioLoop = XRE_GetIOMessageLoop();
     690               0 :   NS_ABORT_IF_FALSE(!!ioLoop, "Bad shutdown order");
     691                 : 
     692                 :   // Quit() sets off the following chain of events
     693                 :   //  (1) UI loop starts quitting
     694                 :   //  (2) UI loop returns from Run() in XRE_InitChildProcess()
     695                 :   //  (3) ProcessChild goes out of scope and terminates the IO thread
     696                 :   //  (4) ProcessChild joins the IO thread
     697                 :   //  (5) exit()
     698               0 :   MessageLoop::current()->Quit();
     699                 : #if defined(XP_MACOSX)
     700                 :   nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
     701                 :   if (appShell) {
     702                 :       // On Mac, we might be only above nsAppShell::Run(), not
     703                 :       // MessagePump::Run().  See XRE_RunAppShell(). To account for
     704                 :       // that case, we fire off an Exit() here.  If we were indeed
     705                 :       // above MessagePump::Run(), this Exit() is just superfluous.
     706                 :       appShell->Exit();
     707                 :   }
     708                 : #endif // XP_MACOSX
     709               0 : }
     710                 : 
     711                 : namespace {
     712                 : ContentParent* gContentParent; //long-lived, manually refcounted
     713               0 : TestShellParent* GetOrCreateTestShellParent()
     714                 : {
     715               0 :     if (!gContentParent) {
     716               0 :         NS_ADDREF(gContentParent = ContentParent::GetNewOrUsed());
     717               0 :     } else if (!gContentParent->IsAlive()) {
     718               0 :         return nsnull;
     719                 :     }
     720               0 :     TestShellParent* tsp = gContentParent->GetTestShellSingleton();
     721               0 :     if (!tsp) {
     722               0 :         tsp = gContentParent->CreateTestShell();
     723                 :     }
     724               0 :     return tsp;
     725                 : }
     726                 : }
     727                 : 
     728                 : bool
     729               0 : XRE_SendTestShellCommand(JSContext* aCx,
     730                 :                          JSString* aCommand,
     731                 :                          void* aCallback)
     732                 : {
     733               0 :     TestShellParent* tsp = GetOrCreateTestShellParent();
     734               0 :     NS_ENSURE_TRUE(tsp, false);
     735                 : 
     736               0 :     nsDependentJSString command;
     737               0 :     NS_ENSURE_TRUE(command.init(aCx, aCommand), false);
     738                 : 
     739               0 :     if (!aCallback) {
     740               0 :         return tsp->SendExecuteCommand(command);
     741                 :     }
     742                 : 
     743                 :     TestShellCommandParent* callback = static_cast<TestShellCommandParent*>(
     744               0 :         tsp->SendPTestShellCommandConstructor(command));
     745               0 :     NS_ENSURE_TRUE(callback, false);
     746                 : 
     747               0 :     jsval callbackVal = *reinterpret_cast<jsval*>(aCallback);
     748               0 :     NS_ENSURE_TRUE(callback->SetCallback(aCx, callbackVal), false);
     749                 : 
     750               0 :     return true;
     751                 : }
     752                 : 
     753                 : bool
     754               0 : XRE_GetChildGlobalObject(JSContext* aCx, JSObject** aGlobalP)
     755                 : {
     756               0 :     TestShellParent* tsp = GetOrCreateTestShellParent();
     757               0 :     return tsp && tsp->GetGlobalJSObject(aCx, aGlobalP);
     758                 : }
     759                 : 
     760                 : bool
     761            1387 : XRE_ShutdownTestShell()
     762                 : {
     763            1387 :     if (!gContentParent) {
     764            1387 :         return true;
     765                 :     }
     766               0 :     bool ret = true;
     767               0 :     if (gContentParent->IsAlive()) {
     768                 :         ret = gContentParent->DestroyTestShell(
     769               0 :             gContentParent->GetTestShellSingleton());
     770                 :     }
     771               0 :     NS_RELEASE(gContentParent);
     772               0 :     return ret;
     773                 : }
     774                 : 
     775                 : #ifdef MOZ_X11
     776                 : void
     777               0 : XRE_InstallX11ErrorHandler()
     778                 : {
     779               0 :   InstallX11ErrorHandler();
     780               0 : }
     781                 : #endif

Generated by: LCOV version 1.7