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

Generated by: LCOV version 1.13