LCOV - code coverage report
Current view: top level - toolkit/xre - nsEmbedFunctions.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 4 202 2.0 %
Date: 2018-08-07 16:42:27 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Public
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       3             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : #include "mozilla/DebugOnly.h"
       6             : 
       7             : #include "base/basictypes.h"
       8             : 
       9             : #include "nsXULAppAPI.h"
      10             : 
      11             : #include <stdlib.h>
      12             : #if defined(MOZ_WIDGET_GTK)
      13             : #include <glib.h>
      14             : #endif
      15             : 
      16             : #include "prenv.h"
      17             : 
      18             : #include "nsIAppShell.h"
      19             : #include "nsIAppStartupNotifier.h"
      20             : #include "nsIDirectoryService.h"
      21             : #include "nsIFile.h"
      22             : #include "nsIToolkitChromeRegistry.h"
      23             : #include "nsIToolkitProfile.h"
      24             : 
      25             : #ifdef XP_WIN
      26             : #include <process.h>
      27             : #include <shobjidl.h>
      28             : #include "mozilla/ipc/WindowsMessageLoop.h"
      29             : #endif
      30             : 
      31             : #include "nsAppDirectoryServiceDefs.h"
      32             : #include "nsAppRunner.h"
      33             : #include "nsAutoRef.h"
      34             : #include "nsDirectoryServiceDefs.h"
      35             : #include "nsExceptionHandler.h"
      36             : #include "nsString.h"
      37             : #include "nsThreadUtils.h"
      38             : #include "nsJSUtils.h"
      39             : #include "nsWidgetsCID.h"
      40             : #include "nsXREDirProvider.h"
      41             : #include "ThreadAnnotation.h"
      42             : 
      43             : #include "mozilla/Omnijar.h"
      44             : #if defined(XP_MACOSX)
      45             : #include "nsVersionComparator.h"
      46             : #include "chrome/common/mach_ipc_mac.h"
      47             : #endif
      48             : #include "nsX11ErrorHandler.h"
      49             : #include "nsGDKErrorHandler.h"
      50             : #include "base/at_exit.h"
      51             : #include "base/command_line.h"
      52             : #include "base/message_loop.h"
      53             : #include "base/process_util.h"
      54             : #include "chrome/common/child_process.h"
      55             : #if defined(MOZ_WIDGET_ANDROID)
      56             : #include "chrome/common/ipc_channel.h"
      57             : #include "mozilla/jni/Utils.h"
      58             : #endif //  defined(MOZ_WIDGET_ANDROID)
      59             : 
      60             : #include "mozilla/AbstractThread.h"
      61             : #include "mozilla/FilePreferences.h"
      62             : 
      63             : #include "mozilla/ipc/BrowserProcessSubThread.h"
      64             : #include "mozilla/ipc/GeckoChildProcessHost.h"
      65             : #include "mozilla/ipc/IOThreadChild.h"
      66             : #include "mozilla/ipc/ProcessChild.h"
      67             : #include "ScopedXREEmbed.h"
      68             : 
      69             : #include "mozilla/plugins/PluginProcessChild.h"
      70             : #include "mozilla/dom/ContentProcess.h"
      71             : #include "mozilla/dom/ContentParent.h"
      72             : #include "mozilla/dom/ContentChild.h"
      73             : 
      74             : #include "mozilla/ipc/TestShellParent.h"
      75             : #include "mozilla/ipc/XPCShellEnvironment.h"
      76             : #include "mozilla/Scheduler.h"
      77             : #include "mozilla/WindowsDllBlocklist.h"
      78             : 
      79             : #include "GMPProcessChild.h"
      80             : #include "mozilla/gfx/GPUProcessImpl.h"
      81             : 
      82             : #include "GeckoProfiler.h"
      83             : 
      84             : #if defined(MOZ_SANDBOX) && defined(XP_WIN)
      85             : #include "mozilla/sandboxTarget.h"
      86             : #include "mozilla/sandboxing/loggingCallbacks.h"
      87             : #endif
      88             : 
      89             : #if defined(MOZ_CONTENT_SANDBOX)
      90             : #include "mozilla/SandboxSettings.h"
      91             : #include "mozilla/Preferences.h"
      92             : #endif
      93             : 
      94             : #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
      95             : #include "mozilla/Sandbox.h"
      96             : #endif
      97             : 
      98             : #if defined(XP_LINUX)
      99             : #include <sys/prctl.h>
     100             : #ifndef PR_SET_PTRACER
     101             : #define PR_SET_PTRACER 0x59616d61
     102             : #endif
     103             : #ifndef PR_SET_PTRACER_ANY
     104             : #define PR_SET_PTRACER_ANY ((unsigned long)-1)
     105             : #endif
     106             : #endif
     107             : 
     108             : #ifdef MOZ_IPDL_TESTS
     109             : #include "mozilla/_ipdltest/IPDLUnitTests.h"
     110             : #include "mozilla/_ipdltest/IPDLUnitTestProcessChild.h"
     111             : 
     112             : using mozilla::_ipdltest::IPDLUnitTestProcessChild;
     113             : #endif  // ifdef MOZ_IPDL_TESTS
     114             : 
     115             : #ifdef MOZ_JPROF
     116             : #include "jprof.h"
     117             : #endif
     118             : 
     119             : #if defined(XP_WIN) && defined(MOZ_ENABLE_SKIA_PDF)
     120             : #include "mozilla/widget/PDFiumProcessChild.h"
     121             : #endif
     122             : 
     123             : using namespace mozilla;
     124             : 
     125             : using mozilla::ipc::BrowserProcessSubThread;
     126             : using mozilla::ipc::GeckoChildProcessHost;
     127             : using mozilla::ipc::IOThreadChild;
     128             : using mozilla::ipc::ProcessChild;
     129             : using mozilla::ipc::ScopedXREEmbed;
     130             : 
     131             : using mozilla::plugins::PluginProcessChild;
     132             : using mozilla::dom::ContentProcess;
     133             : using mozilla::dom::ContentParent;
     134             : using mozilla::dom::ContentChild;
     135             : 
     136             : using mozilla::gmp::GMPProcessChild;
     137             : 
     138             : using mozilla::ipc::TestShellParent;
     139             : using mozilla::ipc::TestShellCommandParent;
     140             : using mozilla::ipc::XPCShellEnvironment;
     141             : 
     142             : using mozilla::startup::sChildProcessType;
     143             : 
     144             : static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
     145             : 
     146             : nsresult
     147           0 : XRE_LockProfileDirectory(nsIFile* aDirectory,
     148             :                          nsISupports* *aLockObject)
     149             : {
     150           0 :   nsCOMPtr<nsIProfileLock> lock;
     151             : 
     152           0 :   nsresult rv = NS_LockProfilePath(aDirectory, nullptr, nullptr,
     153           0 :                                    getter_AddRefs(lock));
     154           0 :   if (NS_SUCCEEDED(rv))
     155           0 :     NS_ADDREF(*aLockObject = lock);
     156             : 
     157           0 :   return rv;
     158             : }
     159             : 
     160             : static int32_t sInitCounter;
     161             : 
     162             : nsresult
     163           0 : XRE_InitEmbedding2(nsIFile *aLibXULDirectory,
     164             :                    nsIFile *aAppDirectory,
     165             :                    nsIDirectoryServiceProvider *aAppDirProvider)
     166             : {
     167             :   // Initialize some globals to make nsXREDirProvider happy
     168             :   static char* kNullCommandLine[] = { nullptr };
     169           0 :   gArgv = kNullCommandLine;
     170           0 :   gArgc = 0;
     171             : 
     172           0 :   NS_ENSURE_ARG(aLibXULDirectory);
     173             : 
     174           0 :   if (++sInitCounter > 1) // XXXbsmedberg is this really the right solution?
     175             :     return NS_OK;
     176             : 
     177           0 :   if (!aAppDirectory)
     178           0 :     aAppDirectory = aLibXULDirectory;
     179             : 
     180             :   nsresult rv;
     181             : 
     182           0 :   new nsXREDirProvider; // This sets gDirServiceProvider
     183           0 :   if (!gDirServiceProvider)
     184             :     return NS_ERROR_OUT_OF_MEMORY;
     185             : 
     186             :   rv = gDirServiceProvider->Initialize(aAppDirectory, aLibXULDirectory,
     187           0 :                                        aAppDirProvider);
     188           0 :   if (NS_FAILED(rv))
     189             :     return rv;
     190             : 
     191           0 :   rv = NS_InitXPCOM2(nullptr, aAppDirectory, gDirServiceProvider);
     192           0 :   if (NS_FAILED(rv))
     193             :     return rv;
     194             : 
     195             :   // We do not need to autoregister components here. The CheckCompatibility()
     196             :   // bits in nsAppRunner.cpp check for an invalidation flag in
     197             :   // compatibility.ini.
     198             :   // If the app wants to autoregister every time (for instance, if it's debug),
     199             :   // it can do so after we return from this function.
     200             : 
     201             :   nsCOMPtr<nsIObserver> startupNotifier
     202           0 :     (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID));
     203           0 :   if (!startupNotifier)
     204             :     return NS_ERROR_FAILURE;
     205             : 
     206           0 :   startupNotifier->Observe(nullptr, APPSTARTUP_TOPIC, nullptr);
     207             : 
     208           0 :   return NS_OK;
     209             : }
     210             : 
     211             : void
     212           0 : XRE_NotifyProfile()
     213             : {
     214           0 :   NS_ASSERTION(gDirServiceProvider, "XRE_InitEmbedding was not called!");
     215           0 :   gDirServiceProvider->DoStartup();
     216           0 : }
     217             : 
     218             : void
     219           0 : XRE_TermEmbedding()
     220             : {
     221           0 :   if (--sInitCounter != 0)
     222             :     return;
     223             : 
     224           0 :   NS_ASSERTION(gDirServiceProvider,
     225             :                "XRE_TermEmbedding without XRE_InitEmbedding");
     226             : 
     227           0 :   gDirServiceProvider->DoShutdown();
     228           0 :   NS_ShutdownXPCOM(nullptr);
     229           0 :   delete gDirServiceProvider;
     230             : }
     231             : 
     232             : const char*
     233           2 : XRE_ChildProcessTypeToString(GeckoProcessType aProcessType)
     234             : {
     235           0 :   return (aProcessType < GeckoProcessType_End) ?
     236           2 :     kGeckoProcessTypeString[aProcessType] : "invalid";
     237             : }
     238             : 
     239             : namespace mozilla {
     240             : namespace startup {
     241             : GeckoProcessType sChildProcessType = GeckoProcessType_Default;
     242             : } // namespace startup
     243             : } // namespace mozilla
     244             : 
     245             : #if defined(MOZ_WIDGET_ANDROID)
     246             : void
     247             : XRE_SetAndroidChildFds (JNIEnv* env, int prefsFd, int ipcFd, int crashFd, int crashAnnotationFd)
     248             : {
     249             :   mozilla::jni::SetGeckoThreadEnv(env);
     250             :   mozilla::dom::SetPrefsFd(prefsFd);
     251             :   IPC::Channel::SetClientChannelFd(ipcFd);
     252             :   CrashReporter::SetNotificationPipeForChild(crashFd);
     253             :   CrashReporter::SetCrashAnnotationPipeForChild(crashAnnotationFd);
     254             : }
     255             : #endif // defined(MOZ_WIDGET_ANDROID)
     256             : 
     257             : void
     258           0 : XRE_SetProcessType(const char* aProcessTypeString)
     259             : {
     260             :   static bool called = false;
     261           0 :   if (called) {
     262           0 :     MOZ_CRASH();
     263             :   }
     264           0 :   called = true;
     265             : 
     266           0 :   sChildProcessType = GeckoProcessType_Invalid;
     267           0 :   for (int i = 0;
     268             :        i < (int) ArrayLength(kGeckoProcessTypeString);
     269             :        ++i) {
     270           0 :     if (!strcmp(kGeckoProcessTypeString[i], aProcessTypeString)) {
     271           0 :       sChildProcessType = static_cast<GeckoProcessType>(i);
     272           0 :       return;
     273             :     }
     274             :   }
     275             : }
     276             : 
     277             : // FIXME/bug 539522: this out-of-place function is stuck here because
     278             : // IPDL wants access to this crashreporter interface, and
     279             : // crashreporter is built in such a way to make that awkward
     280             : bool
     281           0 : XRE_TakeMinidumpForChild(uint32_t aChildPid, nsIFile** aDump,
     282             :                          uint32_t* aSequence)
     283             : {
     284           0 :   return CrashReporter::TakeMinidumpForChild(aChildPid, aDump, aSequence);
     285             : }
     286             : 
     287             : bool
     288             : #if defined(XP_WIN)
     289             : XRE_SetRemoteExceptionHandler(const char* aPipe /*= 0*/,
     290             :                               uintptr_t aCrashTimeAnnotationFile)
     291             : #else
     292           0 : XRE_SetRemoteExceptionHandler(const char* aPipe /*= 0*/)
     293             : #endif
     294             : {
     295             : #if defined(XP_WIN)
     296             :   return CrashReporter::SetRemoteExceptionHandler(nsDependentCString(aPipe),
     297             :                                                   aCrashTimeAnnotationFile);
     298             : #elif defined(XP_MACOSX)
     299             :   return CrashReporter::SetRemoteExceptionHandler(nsDependentCString(aPipe));
     300             : #else
     301           0 :   return CrashReporter::SetRemoteExceptionHandler();
     302             : #endif
     303             : }
     304             : 
     305             : #if defined(XP_WIN)
     306             : void
     307             : SetTaskbarGroupId(const nsString& aId)
     308             : {
     309             :     if (FAILED(SetCurrentProcessExplicitAppUserModelID(aId.get()))) {
     310             :         NS_WARNING("SetCurrentProcessExplicitAppUserModelID failed for child process.");
     311             :     }
     312             : }
     313             : #endif
     314             : 
     315             : #if defined(MOZ_CONTENT_SANDBOX)
     316             : void
     317             : AddContentSandboxLevelAnnotation()
     318             : {
     319             :   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     320             :     int level = GetEffectiveContentSandboxLevel();
     321             :     nsAutoCString levelString;
     322             :     levelString.AppendInt(level);
     323             :     CrashReporter::AnnotateCrashReport(
     324             :       NS_LITERAL_CSTRING("ContentSandboxLevel"), levelString);
     325             :   }
     326             : }
     327             : #endif /* MOZ_CONTENT_SANDBOX */
     328             : 
     329             : namespace {
     330             : 
     331           0 : int GetDebugChildPauseTime() {
     332           0 :   auto pauseStr = PR_GetEnv("MOZ_DEBUG_CHILD_PAUSE");
     333           0 :   if (pauseStr && *pauseStr) {
     334           0 :     int pause = atoi(pauseStr);
     335           0 :     if (pause != 1) { // must be !=1 since =1 enables the default pause time
     336             : #if defined(OS_WIN)
     337             :       pause *= 1000; // convert to ms
     338             : #endif
     339             :       return pause;
     340             :     }
     341             :   }
     342             : #ifdef OS_POSIX
     343           0 :   return 30; // seconds
     344             : #elif defined(OS_WIN)
     345             :   return 10000; // milliseconds
     346             : #else
     347             :   return 0;
     348             : #endif
     349             : }
     350             : 
     351             : } // namespace
     352             : 
     353             : nsresult
     354           0 : XRE_InitChildProcess(int aArgc,
     355             :                      char* aArgv[],
     356             :                      const XREChildData* aChildData)
     357             : {
     358           0 :   NS_ENSURE_ARG_MIN(aArgc, 2);
     359           0 :   NS_ENSURE_ARG_POINTER(aArgv);
     360           0 :   NS_ENSURE_ARG_POINTER(aArgv[0]);
     361           0 :   MOZ_ASSERT(aChildData);
     362             : 
     363             : #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
     364             :   // This has to happen before glib thread pools are started.
     365             :   mozilla::SandboxEarlyInit();
     366             : #endif
     367             : 
     368             : #ifdef MOZ_JPROF
     369             :   // Call the code to install our handler
     370             :   setupProfilingStuff();
     371             : #endif
     372             : 
     373             : #if defined(XP_WIN)
     374             :   // From the --attach-console support in nsNativeAppSupportWin.cpp, but
     375             :   // here we are a content child process, so we always attempt to attach
     376             :   // to the parent's (ie, the browser's) console.
     377             :   // Try to attach console to the parent process.
     378             :   // It will succeed when the parent process is a command line,
     379             :   // so that stdio will be displayed in it.
     380             :   if (AttachConsole(ATTACH_PARENT_PROCESS)) {
     381             :     // Change std handles to refer to new console handles.
     382             :     // Before doing so, ensure that stdout/stderr haven't been
     383             :     // redirected to a valid file
     384             :     if (_fileno(stdout) == -1 ||
     385             :         _get_osfhandle(fileno(stdout)) == -1)
     386             :         freopen("CONOUT$", "w", stdout);
     387             :     // Merge stderr into CONOUT$ since there isn't any `CONERR$`.
     388             :     // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx
     389             :     if (_fileno(stderr) == -1 ||
     390             :         _get_osfhandle(fileno(stderr)) == -1)
     391             :         freopen("CONOUT$", "w", stderr);
     392             :     if (_fileno(stdin) == -1 || _get_osfhandle(fileno(stdin)) == -1)
     393             :         freopen("CONIN$", "r", stdin);
     394             :   }
     395             : 
     396             : #if defined(MOZ_SANDBOX)
     397             :   if (aChildData->sandboxTargetServices) {
     398             :     SandboxTarget::Instance()->SetTargetServices(aChildData->sandboxTargetServices);
     399             :   }
     400             : #endif
     401             : #endif
     402             : 
     403             :   // NB: This must be called before profiler_init
     404             :   ScopedLogging logger;
     405             : 
     406           0 :   mozilla::LogModule::Init(aArgc, aArgv);
     407             : 
     408           0 :   AUTO_PROFILER_INIT;
     409           0 :   AUTO_PROFILER_LABEL("XRE_InitChildProcess", OTHER);
     410             : 
     411             :   // Ensure AbstractThread is minimally setup, so async IPC messages
     412             :   // work properly.
     413           0 :   AbstractThread::InitTLS();
     414             : 
     415             :   // Complete 'task_t' exchange for Mac OS X. This structure has the same size
     416             :   // regardless of architecture so we don't have any cross-arch issues here.
     417             : #ifdef XP_MACOSX
     418             :   if (aArgc < 1)
     419             :     return NS_ERROR_FAILURE;
     420             :   const char* const mach_port_name = aArgv[--aArgc];
     421             : 
     422             :   const int kTimeoutMs = 1000;
     423             : 
     424             :   MachSendMessage child_message(0);
     425             :   if (!child_message.AddDescriptor(MachMsgPortDescriptor(mach_task_self()))) {
     426             :     NS_WARNING("child AddDescriptor(mach_task_self()) failed.");
     427             :     return NS_ERROR_FAILURE;
     428             :   }
     429             : 
     430             :   ReceivePort child_recv_port;
     431             :   mach_port_t raw_child_recv_port = child_recv_port.GetPort();
     432             :   if (!child_message.AddDescriptor(MachMsgPortDescriptor(raw_child_recv_port))) {
     433             :     NS_WARNING("Adding descriptor to message failed");
     434             :     return NS_ERROR_FAILURE;
     435             :   }
     436             : 
     437             :   ReceivePort* ports_out_receiver = new ReceivePort();
     438             :   if (!child_message.AddDescriptor(MachMsgPortDescriptor(ports_out_receiver->GetPort()))) {
     439             :     NS_WARNING("Adding descriptor to message failed");
     440             :     return NS_ERROR_FAILURE;
     441             :   }
     442             : 
     443             :   ReceivePort* ports_in_receiver = new ReceivePort();
     444             :   if (!child_message.AddDescriptor(MachMsgPortDescriptor(ports_in_receiver->GetPort()))) {
     445             :     NS_WARNING("Adding descriptor to message failed");
     446             :     return NS_ERROR_FAILURE;
     447             :   }
     448             : 
     449             :   MachPortSender child_sender(mach_port_name);
     450             :   kern_return_t err = child_sender.SendMessage(child_message, kTimeoutMs);
     451             :   if (err != KERN_SUCCESS) {
     452             :     NS_WARNING("child SendMessage() failed");
     453             :     return NS_ERROR_FAILURE;
     454             :   }
     455             : 
     456             :   MachReceiveMessage parent_message;
     457             :   err = child_recv_port.WaitForMessage(&parent_message, kTimeoutMs);
     458             :   if (err != KERN_SUCCESS) {
     459             :     NS_WARNING("child WaitForMessage() failed");
     460             :     return NS_ERROR_FAILURE;
     461             :   }
     462             : 
     463             :   if (parent_message.GetTranslatedPort(0) == MACH_PORT_NULL) {
     464             :     NS_WARNING("child GetTranslatedPort(0) failed");
     465             :     return NS_ERROR_FAILURE;
     466             :   }
     467             : 
     468             :   err = task_set_bootstrap_port(mach_task_self(),
     469             :                                 parent_message.GetTranslatedPort(0));
     470             : 
     471             :   if (parent_message.GetTranslatedPort(1) == MACH_PORT_NULL) {
     472             :     NS_WARNING("child GetTranslatedPort(1) failed");
     473             :     return NS_ERROR_FAILURE;
     474             :   }
     475             :   MachPortSender* ports_out_sender = new MachPortSender(parent_message.GetTranslatedPort(1));
     476             : 
     477             :   if (parent_message.GetTranslatedPort(2) == MACH_PORT_NULL) {
     478             :     NS_WARNING("child GetTranslatedPort(2) failed");
     479             :     return NS_ERROR_FAILURE;
     480             :   }
     481             :   MachPortSender* ports_in_sender = new MachPortSender(parent_message.GetTranslatedPort(2));
     482             : 
     483             :   if (err != KERN_SUCCESS) {
     484             :     NS_WARNING("child task_set_bootstrap_port() failed");
     485             :     return NS_ERROR_FAILURE;
     486             :   }
     487             : 
     488             : #endif
     489             : 
     490           0 :   SetupErrorHandling(aArgv[0]);
     491             : 
     492             :   if (!CrashReporter::IsDummy()) {
     493             : #if defined(XP_WIN)
     494             :     if (aArgc < 1) {
     495             :       return NS_ERROR_FAILURE;
     496             :     }
     497             :     const char* const crashTimeAnnotationArg = aArgv[--aArgc];
     498             :     uintptr_t crashTimeAnnotationFile =
     499             :       static_cast<uintptr_t>(std::stoul(std::string(crashTimeAnnotationArg)));
     500             : #endif
     501             : 
     502           0 :     if (aArgc < 1)
     503             :       return NS_ERROR_FAILURE;
     504           0 :     const char* const crashReporterArg = aArgv[--aArgc];
     505             : 
     506             : #if defined(XP_MACOSX)
     507             :     // on windows and mac, |crashReporterArg| is the named pipe on which the
     508             :     // server is listening for requests, or "-" if crash reporting is
     509             :     // disabled.
     510             :     if (0 != strcmp("-", crashReporterArg) &&
     511             :         !XRE_SetRemoteExceptionHandler(crashReporterArg)) {
     512             :       // Bug 684322 will add better visibility into this condition
     513             :       NS_WARNING("Could not setup crash reporting\n");
     514             :     }
     515             : #elif defined(XP_WIN)
     516             :     if (0 != strcmp("-", crashReporterArg) &&
     517             :         !XRE_SetRemoteExceptionHandler(crashReporterArg,
     518             :                                        crashTimeAnnotationFile)) {
     519             :       // Bug 684322 will add better visibility into this condition
     520             :       NS_WARNING("Could not setup crash reporting\n");
     521             :     }
     522             : #else
     523             :     // on POSIX, |crashReporterArg| is "true" if crash reporting is
     524             :     // enabled, false otherwise
     525           0 :     if (0 != strcmp("false", crashReporterArg) &&
     526           0 :         !XRE_SetRemoteExceptionHandler(nullptr)) {
     527             :       // Bug 684322 will add better visibility into this condition
     528           0 :       NS_WARNING("Could not setup crash reporting\n");
     529             :     }
     530             : #endif
     531             :   }
     532             : 
     533             :   // For Init/Shutdown thread name annotations in the crash reporter.
     534           0 :   CrashReporter::InitThreadAnnotationRAII annotation;
     535             : 
     536           0 :   gArgv = aArgv;
     537           0 :   gArgc = aArgc;
     538             : 
     539             : #ifdef MOZ_X11
     540           0 :   XInitThreads();
     541             : #endif
     542             : #ifdef MOZ_WIDGET_GTK
     543             :   // Setting the name here avoids the need to pass this through to gtk_init().
     544           0 :   g_set_prgname(aArgv[0]);
     545             : #endif
     546             : 
     547             : #ifdef OS_POSIX
     548           0 :   if (PR_GetEnv("MOZ_DEBUG_CHILD_PROCESS") ||
     549           0 :       PR_GetEnv("MOZ_DEBUG_CHILD_PAUSE")) {
     550             : #if defined(XP_LINUX) && defined(DEBUG)
     551           0 :     if (prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0) != 0) {
     552           0 :       printf_stderr("Could not allow ptrace from any process.\n");
     553             :     }
     554             : #endif
     555           0 :     printf_stderr("\n\nCHILDCHILDCHILDCHILD (process type %s)\n  debug me @ %d\n\n",
     556             :                   XRE_ChildProcessTypeToString(XRE_GetProcessType()),
     557           0 :                   base::GetCurrentProcId());
     558           0 :     sleep(GetDebugChildPauseTime());
     559             :   }
     560             : #elif defined(OS_WIN)
     561             :   if (PR_GetEnv("MOZ_DEBUG_CHILD_PROCESS")) {
     562             :     NS_DebugBreak(NS_DEBUG_BREAK,
     563             :                   "Invoking NS_DebugBreak() to debug child process",
     564             :                   nullptr, __FILE__, __LINE__);
     565             :   } else if (PR_GetEnv("MOZ_DEBUG_CHILD_PAUSE")) {
     566             :     printf_stderr("\n\nCHILDCHILDCHILDCHILD (process type %s)\n  debug me @ %d\n\n",
     567             :                   XRE_ChildProcessTypeToString(XRE_GetProcessType()),
     568             :                   base::GetCurrentProcId());
     569             :     ::Sleep(GetDebugChildPauseTime());
     570             :   }
     571             : #endif
     572             : 
     573             :   // child processes launched by GeckoChildProcessHost get this magic
     574             :   // argument appended to their command lines
     575           0 :   const char* const parentPIDString = aArgv[aArgc-1];
     576           0 :   MOZ_ASSERT(parentPIDString, "NULL parent PID");
     577           0 :   --aArgc;
     578             : 
     579           0 :   char* end = 0;
     580           0 :   base::ProcessId parentPID = strtol(parentPIDString, &end, 10);
     581           0 :   MOZ_ASSERT(!*end, "invalid parent PID");
     582             : 
     583           0 :   nsCOMPtr<nsIFile> crashReportTmpDir;
     584           0 :   if (XRE_GetProcessType() == GeckoProcessType_GPU) {
     585           0 :     aArgc--;
     586           0 :     if (strlen(aArgv[aArgc])) { // if it's empty, ignore it
     587           0 :       nsresult rv = XRE_GetFileFromPath(aArgv[aArgc], getter_AddRefs(crashReportTmpDir));
     588           0 :       if (NS_FAILED(rv)) {
     589             :         // If we don't have a valid tmp dir we can probably still run ok, but
     590             :         // crash report .extra files might not get picked up by the parent
     591             :         // process. Debug-assert because this shouldn't happen in practice.
     592           0 :         MOZ_ASSERT(false, "GPU process started without valid tmp dir!");
     593             :       }
     594             :     }
     595             :   }
     596             : 
     597             : #ifdef XP_MACOSX
     598             :   mozilla::ipc::SharedMemoryBasic::SetupMachMemory(parentPID, ports_in_receiver, ports_in_sender,
     599             :                                                    ports_out_sender, ports_out_receiver, true);
     600             : #endif
     601             : 
     602             : #if defined(XP_WIN)
     603             :   // On Win7+, register the application user model id passed in by
     604             :   // parent. This insures windows created by the container properly
     605             :   // group with the parent app on the Win7 taskbar.
     606             :   const char* const appModelUserId = aArgv[--aArgc];
     607             :   if (appModelUserId) {
     608             :     // '-' implies no support
     609             :     if (*appModelUserId != '-') {
     610             :       nsString appId;
     611             :       CopyASCIItoUTF16(nsDependentCString(appModelUserId), appId);
     612             :       // The version string is encased in quotes
     613             :       appId.Trim("\"");
     614             :       // Set the id
     615             :       SetTaskbarGroupId(appId);
     616             :     }
     617             :   }
     618             : #endif
     619             : 
     620           0 :   base::AtExitManager exitManager;
     621             : 
     622           0 :   nsresult rv = XRE_InitCommandLine(aArgc, aArgv);
     623           0 :   if (NS_FAILED(rv)) {
     624             :     return NS_ERROR_FAILURE;
     625             :   }
     626             : 
     627             :   MessageLoop::Type uiLoopType;
     628           0 :   switch (XRE_GetProcessType()) {
     629             :   case GeckoProcessType_Content:
     630             :   case GeckoProcessType_GPU:
     631             :       // Content processes need the XPCOM/chromium frankenventloop
     632             :       uiLoopType = MessageLoop::TYPE_MOZILLA_CHILD;
     633             :       break;
     634             :   case GeckoProcessType_GMPlugin:
     635             :   case GeckoProcessType_PDFium:
     636           0 :       uiLoopType = MessageLoop::TYPE_DEFAULT;
     637           0 :       break;
     638             :   default:
     639           0 :       uiLoopType = MessageLoop::TYPE_UI;
     640           0 :       break;
     641             :   }
     642             : 
     643             :   {
     644             :     // This is a lexical scope for the MessageLoop below.  We want it
     645             :     // to go out of scope before NS_LogTerm() so that we don't get
     646             :     // spurious warnings about XPCOM objects being destroyed from a
     647             :     // static context.
     648             : 
     649             :     // Associate this thread with a UI MessageLoop
     650           0 :     MessageLoop uiMessageLoop(uiLoopType);
     651             :     {
     652           0 :       nsAutoPtr<ProcessChild> process;
     653             : 
     654             : #ifdef XP_WIN
     655             :       mozilla::ipc::windows::InitUIThread();
     656             : #endif
     657             : 
     658           0 :       switch (XRE_GetProcessType()) {
     659             :       case GeckoProcessType_Default:
     660           0 :         MOZ_CRASH("This makes no sense");
     661             :         break;
     662             : 
     663             :       case GeckoProcessType_Plugin:
     664           0 :         process = new PluginProcessChild(parentPID);
     665             :         break;
     666             : 
     667             :       case GeckoProcessType_Content:
     668           0 :         process = new ContentProcess(parentPID);
     669             :         break;
     670             : 
     671             :       case GeckoProcessType_IPDLUnitTest:
     672             : #ifdef MOZ_IPDL_TESTS
     673             :         process = new IPDLUnitTestProcessChild(parentPID);
     674             : #else
     675           0 :         MOZ_CRASH("rebuild with --enable-ipdl-tests");
     676             : #endif
     677             :         break;
     678             : 
     679             :       case GeckoProcessType_GMPlugin:
     680           0 :         process = new gmp::GMPProcessChild(parentPID);
     681             :         break;
     682             : 
     683             : #if defined(XP_WIN) && defined(MOZ_ENABLE_SKIA_PDF)
     684             :       case GeckoProcessType_PDFium:
     685             :         process = new widget::PDFiumProcessChild(parentPID);
     686             :         break;
     687             : #endif
     688             :       case GeckoProcessType_GPU:
     689           0 :         process = new gfx::GPUProcessImpl(parentPID);
     690             :         break;
     691             : 
     692             :       default:
     693           0 :         MOZ_CRASH("Unknown main thread class");
     694             :       }
     695             : 
     696           0 :       if (!process->Init(aArgc, aArgv)) {
     697           0 :         return NS_ERROR_FAILURE;
     698             :       }
     699             : 
     700             : #if defined(XP_WIN)
     701             :       // Set child processes up such that they will get killed after the
     702             :       // chrome process is killed in cases where the user shuts the system
     703             :       // down or logs off.
     704             :       ::SetProcessShutdownParameters(0x280 - 1, SHUTDOWN_NORETRY);
     705             : #endif
     706             : 
     707             : #if defined(MOZ_SANDBOX) && defined(XP_WIN)
     708             :       // We need to do this after the process has been initialised, as
     709             :       // InitLoggingIfRequired may need access to prefs.
     710             :       mozilla::sandboxing::InitLoggingIfRequired(aChildData->ProvideLogFunction);
     711             : #endif
     712           0 :       mozilla::FilePreferences::InitDirectoriesWhitelist();
     713           0 :       mozilla::FilePreferences::InitPrefs();
     714             : 
     715           0 :       OverrideDefaultLocaleIfNeeded();
     716             : 
     717             : #if defined(MOZ_CONTENT_SANDBOX)
     718             :       AddContentSandboxLevelAnnotation();
     719             : #endif
     720             : 
     721             :       // Run the UI event loop on the main thread.
     722           0 :       uiMessageLoop.MessageLoop::Run();
     723             : 
     724             :       // Allow ProcessChild to clean up after itself before going out of
     725             :       // scope and being deleted
     726           0 :       process->CleanUp();
     727           0 :       mozilla::Omnijar::CleanUp();
     728             : 
     729             : #if defined(XP_MACOSX)
     730             :       // Everybody should be done using shared memory by now.
     731             :       mozilla::ipc::SharedMemoryBasic::Shutdown();
     732             : #endif
     733             :     }
     734             :   }
     735             : 
     736           0 :   return XRE_DeinitCommandLine();
     737             : }
     738             : 
     739             : MessageLoop*
     740           0 : XRE_GetIOMessageLoop()
     741             : {
     742           0 :   if (sChildProcessType == GeckoProcessType_Default) {
     743          13 :     return BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO);
     744             :   }
     745           0 :   return IOThreadChild::message_loop();
     746             : }
     747             : 
     748             : namespace {
     749             : 
     750           0 : class MainFunctionRunnable : public Runnable
     751             : {
     752             : public:
     753             :   NS_DECL_NSIRUNNABLE
     754             : 
     755           0 :   MainFunctionRunnable(MainFunction aFunction, void* aData)
     756           0 :     : mozilla::Runnable("MainFunctionRunnable")
     757             :     , mFunction(aFunction)
     758           0 :     , mData(aData)
     759             :   {
     760           0 :     NS_ASSERTION(aFunction, "Don't give me a null pointer!");
     761           0 :   }
     762             : 
     763             : private:
     764             :   MainFunction mFunction;
     765             :   void* mData;
     766             : };
     767             : 
     768             : } /* anonymous namespace */
     769             : 
     770             : NS_IMETHODIMP
     771           0 : MainFunctionRunnable::Run()
     772             : {
     773           0 :   mFunction(mData);
     774           0 :   return NS_OK;
     775             : }
     776             : 
     777             : nsresult
     778           0 : XRE_InitParentProcess(int aArgc,
     779             :                       char* aArgv[],
     780             :                       MainFunction aMainFunction,
     781             :                       void* aMainFunctionData)
     782             : {
     783           0 :   NS_ENSURE_ARG_MIN(aArgc, 1);
     784           0 :   NS_ENSURE_ARG_POINTER(aArgv);
     785           0 :   NS_ENSURE_ARG_POINTER(aArgv[0]);
     786             : 
     787             :   // Set main thread before we initialize the profiler
     788           0 :   NS_SetMainThread();
     789             : 
     790           0 :   mozilla::LogModule::Init(aArgc, aArgv);
     791             : 
     792           0 :   AUTO_PROFILER_INIT;
     793             : 
     794           0 :   ScopedXREEmbed embed;
     795             : 
     796           0 :   gArgc = aArgc;
     797           0 :   gArgv = aArgv;
     798           0 :   nsresult rv = XRE_InitCommandLine(gArgc, gArgv);
     799           0 :   if (NS_FAILED(rv))
     800             :       return NS_ERROR_FAILURE;
     801             : 
     802             :   {
     803           0 :     embed.Start();
     804             : 
     805           0 :     nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
     806           0 :     NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
     807             : 
     808           0 :     if (aMainFunction) {
     809             :       nsCOMPtr<nsIRunnable> runnable =
     810           0 :         new MainFunctionRunnable(aMainFunction, aMainFunctionData);
     811           0 :       NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
     812             : 
     813           0 :       nsresult rv = NS_DispatchToCurrentThread(runnable);
     814           0 :       NS_ENSURE_SUCCESS(rv, rv);
     815             :     }
     816             : 
     817             :     // Do event loop
     818           0 :     if (NS_FAILED(appShell->Run())) {
     819           0 :       NS_WARNING("Failed to run appshell");
     820           0 :       return NS_ERROR_FAILURE;
     821             :     }
     822             :   }
     823             : 
     824           0 :   return XRE_DeinitCommandLine();
     825             : }
     826             : 
     827             : #ifdef MOZ_IPDL_TESTS
     828             : //-----------------------------------------------------------------------------
     829             : // IPDL unit test
     830             : 
     831             : int
     832             : XRE_RunIPDLTest(int aArgc, char** aArgv)
     833             : {
     834             :     if (aArgc < 2) {
     835             :         fprintf(stderr, "TEST-UNEXPECTED-FAIL | <---> | insufficient #args, need at least 2\n");
     836             :         return 1;
     837             :     }
     838             : 
     839             :     void* data = reinterpret_cast<void*>(aArgv[aArgc-1]);
     840             : 
     841             :     nsresult rv =
     842             :         XRE_InitParentProcess(
     843             :             --aArgc, aArgv, mozilla::_ipdltest::IPDLUnitTestMain, data);
     844             :     NS_ENSURE_SUCCESS(rv, 1);
     845             : 
     846             :     return 0;
     847             : }
     848             : #endif  // ifdef MOZ_IPDL_TESTS
     849             : 
     850             : nsresult
     851           0 : XRE_RunAppShell()
     852             : {
     853           0 :     nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
     854           0 :     NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
     855             : #if defined(XP_MACOSX)
     856             :     if (XRE_UseNativeEventProcessing()) {
     857             :       // In content processes that want XPCOM (and hence want
     858             :       // AppShell), we usually run our hybrid event loop through
     859             :       // MessagePump::Run(), by way of nsBaseAppShell::Run().  The
     860             :       // Cocoa nsAppShell impl, however, implements its own Run()
     861             :       // that's unaware of MessagePump.  That's all rather suboptimal,
     862             :       // but oddly enough not a problem... usually.
     863             :       //
     864             :       // The problem with this setup comes during startup.
     865             :       // XPCOM-in-subprocesses depends on IPC, e.g. to init the pref
     866             :       // service, so we have to init IPC first.  But, IPC also
     867             :       // indirectly kinda-depends on XPCOM, because MessagePump
     868             :       // schedules work from off-main threads (e.g. IO thread) by
     869             :       // using NS_DispatchToMainThread().  If the IO thread receives a
     870             :       // Message from the parent before nsThreadManager is
     871             :       // initialized, then DispatchToMainThread() will fail, although
     872             :       // MessagePump will remember the task.  This race condition
     873             :       // isn't a problem when appShell->Run() ends up in
     874             :       // MessagePump::Run(), because MessagePump will immediate see it
     875             :       // has work to do.  It *is* a problem when we end up in [NSApp
     876             :       // run], because it's not aware that MessagePump has work that
     877             :       // needs to be processed; that was supposed to be signaled by
     878             :       // nsIRunnable(s).
     879             :       //
     880             :       // So instead of hacking Cocoa nsAppShell or rewriting the
     881             :       // event-loop system, we compromise here by processing any tasks
     882             :       // that might have been enqueued on MessagePump, *before*
     883             :       // MessagePump::ScheduleWork was able to successfully
     884             :       // DispatchToMainThread().
     885             :       MessageLoop* loop = MessageLoop::current();
     886             :       bool couldNest = loop->NestableTasksAllowed();
     887             : 
     888             :       loop->SetNestableTasksAllowed(true);
     889             :       RefPtr<Runnable> task = new MessageLoop::QuitTask();
     890             :       loop->PostTask(task.forget());
     891             :       loop->Run();
     892             : 
     893             :       loop->SetNestableTasksAllowed(couldNest);
     894             :     }
     895             : #endif  // XP_MACOSX
     896           0 :     return appShell->Run();
     897             : }
     898             : 
     899             : void
     900           0 : XRE_ShutdownChildProcess()
     901             : {
     902           0 :   MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
     903             : 
     904           0 :   mozilla::DebugOnly<MessageLoop*> ioLoop = XRE_GetIOMessageLoop();
     905           0 :   MOZ_ASSERT(!!ioLoop, "Bad shutdown order");
     906             : 
     907           0 :   Scheduler::Shutdown();
     908             : 
     909             :   // Quit() sets off the following chain of events
     910             :   //  (1) UI loop starts quitting
     911             :   //  (2) UI loop returns from Run() in XRE_InitChildProcess()
     912             :   //  (3) ProcessChild goes out of scope and terminates the IO thread
     913             :   //  (4) ProcessChild joins the IO thread
     914             :   //  (5) exit()
     915           0 :   MessageLoop::current()->Quit();
     916             : 
     917             : #if defined(XP_MACOSX)
     918             :   nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
     919             :   if (appShell) {
     920             :       // On Mac, we might be only above nsAppShell::Run(), not
     921             :       // MessagePump::Run().  See XRE_RunAppShell(). To account for
     922             :       // that case, we fire off an Exit() here.  If we were indeed
     923             :       // above MessagePump::Run(), this Exit() is just superfluous.
     924             :       appShell->Exit();
     925             :   }
     926             : #endif // XP_MACOSX
     927           0 : }
     928             : 
     929             : namespace {
     930             : ContentParent* gContentParent; //long-lived, manually refcounted
     931           0 : TestShellParent* GetOrCreateTestShellParent()
     932             : {
     933           0 :     if (!gContentParent) {
     934             :         // Use a "web" child process by default.  File a bug if you don't like
     935             :         // this and you're sure you wouldn't be better off writing a "browser"
     936             :         // chrome mochitest where you can have multiple types of content
     937             :         // processes.
     938             :         RefPtr<ContentParent> parent =
     939           0 :             ContentParent::GetNewOrUsedBrowserProcess(
     940           0 :                 NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE));
     941           0 :         parent.forget(&gContentParent);
     942           0 :     } else if (!gContentParent->IsAlive()) {
     943             :         return nullptr;
     944             :     }
     945           0 :     TestShellParent* tsp = gContentParent->GetTestShellSingleton();
     946           0 :     if (!tsp) {
     947           0 :         tsp = gContentParent->CreateTestShell();
     948             :     }
     949             :     return tsp;
     950             : }
     951             : 
     952             : } // namespace
     953             : 
     954             : bool
     955           0 : XRE_SendTestShellCommand(JSContext* aCx,
     956             :                          JSString* aCommand,
     957             :                          void* aCallback)
     958             : {
     959           0 :     JS::RootedString cmd(aCx, aCommand);
     960           0 :     TestShellParent* tsp = GetOrCreateTestShellParent();
     961           0 :     NS_ENSURE_TRUE(tsp, false);
     962             : 
     963           0 :     nsAutoJSString command;
     964           0 :     NS_ENSURE_TRUE(command.init(aCx, cmd), false);
     965             : 
     966           0 :     if (!aCallback) {
     967           0 :         return tsp->SendExecuteCommand(command);
     968             :     }
     969             : 
     970             :     TestShellCommandParent* callback = static_cast<TestShellCommandParent*>(
     971           0 :         tsp->SendPTestShellCommandConstructor(command));
     972           0 :     NS_ENSURE_TRUE(callback, false);
     973             : 
     974           0 :     JS::Value callbackVal = *reinterpret_cast<JS::Value*>(aCallback);
     975           0 :     NS_ENSURE_TRUE(callback->SetCallback(aCx, callbackVal), false);
     976             : 
     977             :     return true;
     978             : }
     979             : 
     980             : bool
     981           0 : XRE_ShutdownTestShell()
     982             : {
     983           0 :     if (!gContentParent) {
     984             :         return true;
     985             :     }
     986           0 :     bool ret = true;
     987           0 :     if (gContentParent->IsAlive()) {
     988           0 :         ret = gContentParent->DestroyTestShell(
     989           0 :             gContentParent->GetTestShellSingleton());
     990             :     }
     991           0 :     NS_RELEASE(gContentParent);
     992           0 :     return ret;
     993             : }
     994             : 
     995             : #ifdef MOZ_X11
     996             : void
     997           0 : XRE_InstallX11ErrorHandler()
     998             : {
     999             : #ifdef MOZ_WIDGET_GTK
    1000           1 :   InstallGdkErrorHandler();
    1001             : #else
    1002             :   InstallX11ErrorHandler();
    1003             : #endif
    1004             : }
    1005             : #endif

Generated by: LCOV version 1.13-14-ga5dd952