NS_InitXPCOM2(nsIServiceManager** aResult, nsIFile* aBinDirectory, nsIDirectoryServiceProvider* aAppFileLocationProvider) { static bool sInitialized = false; if (sInitialized) { return NS_ERROR_FAILURE; } sInitialized = true; mozPoisonValueInit(); NS_LogInit(); mozilla::LogModule::Init(); JS_SetCurrentEmbedderTimeFunction(TimeSinceProcessCreation); char aLocal; profiler_init(&aLocal); nsresult rv = NS_OK; // We are not shutting down gXPCOMShuttingDown = false; // Initialize the available memory tracker before other threads have had a // chance to start up, because the initialization is not thread-safe. mozilla::AvailableMemoryTracker::Init(); #ifdef XP_UNIX // Discover the current value of the umask, and save it where // nsSystemInfo::Init can retrieve it when necessary. There is no way // to read the umask without changing it, and the setting is process- // global, so this must be done while we are still single-threaded; the // nsSystemInfo object is typically created much later, when some piece // of chrome JS wants it. The system call is specified as unable to fail. nsSystemInfo::gUserUmask = ::umask(0777); ::umask(nsSystemInfo::gUserUmask); #endif // Set up chromium libs NS_ASSERTION(!sExitManager && !sMessageLoop, "Bad logic!"); if (!AtExitManager::AlreadyRegistered()) { sExitManager = new AtExitManager(); } if (!MessageLoop::current()) { sMessageLoop = new MessageLoopForUI(MessageLoop::TYPE_MOZILLA_UI); sMessageLoop->set_thread_name("Gecko"); // Set experimental values for main thread hangs: // 128ms for transient hangs and 8192ms for permanent hangs sMessageLoop->set_hang_timeouts(128, 8192); } if (XRE_IsParentProcess() && !BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO)) { UniquePtr<BrowserProcessSubThread> ioThread = MakeUnique<BrowserProcessSubThread>(BrowserProcessSubThread::IO); base::Thread::Options options; options.message_loop_type = MessageLoop::TYPE_IO; if (NS_WARN_IF(!ioThread->StartWithOptions(options))) { return NS_ERROR_FAILURE; } sIOThread = ioThread.release(); } // Establish the main thread here. rv = nsThreadManager::get()->Init(); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } // Set up the timer globals/timer thread rv = nsTimerImpl::Startup(); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } #ifndef ANDROID // If the locale hasn't already been setup by our embedder, // get us out of the "C" locale and into the system if (strcmp(setlocale(LC_ALL, nullptr), "C") == 0) { setlocale(LC_ALL, ""); } #endif #if defined(XP_UNIX) NS_StartupNativeCharsetUtils(); #endif NS_StartupLocalFile(); StartupSpecialSystemDirectory(); nsDirectoryService::RealInit(); bool value; if (aBinDirectory) { rv = aBinDirectory->IsDirectory(&value); if (NS_SUCCEEDED(rv) && value) { nsDirectoryService::gService->Set(NS_XPCOM_INIT_CURRENT_PROCESS_DIR, aBinDirectory); } } if (aAppFileLocationProvider) { rv = nsDirectoryService::gService->RegisterProvider(aAppFileLocationProvider); if (NS_FAILED(rv)) { return rv; } } nsCOMPtr<nsIFile> xpcomLib; nsDirectoryService::gService->Get(NS_GRE_BIN_DIR, NS_GET_IID(nsIFile), getter_AddRefs(xpcomLib)); MOZ_ASSERT(xpcomLib); // set gGREBinPath nsAutoString path; xpcomLib->GetPath(path); gGREBinPath = ToNewUnicode(path); xpcomLib->AppendNative(nsDependentCString(XPCOM_DLL)); nsDirectoryService::gService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib); if (!mozilla::Omnijar::IsInitialized()) { mozilla::Omnijar::Init(); } if ((sCommandLineWasInitialized = !CommandLine::IsInitialized())) { #ifdef OS_WIN CommandLine::Init(0, nullptr); #else nsCOMPtr<nsIFile> binaryFile; nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(binaryFile)); if (NS_WARN_IF(!binaryFile)) { return NS_ERROR_FAILURE; } rv = binaryFile->AppendNative(NS_LITERAL_CSTRING("nonexistent-executable")); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsCString binaryPath; rv = binaryFile->GetNativePath(binaryPath); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } static char const* const argv = { strdup(binaryPath.get()) }; CommandLine::Init(1, &argv); #endif } NS_ASSERTION(nsComponentManagerImpl::gComponentManager == nullptr, "CompMgr not null at init"); // Create the Component/Service Manager nsComponentManagerImpl::gComponentManager = new nsComponentManagerImpl(); NS_ADDREF(nsComponentManagerImpl::gComponentManager); // Global cycle collector initialization. if (!nsCycleCollector_init()) { return NS_ERROR_UNEXPECTED; } // And start it up for this thread too. nsCycleCollector_startup(); // Register ICU memory functions. This really shouldn't be necessary: the // JS engine should do this on its own inside JS_Init, and memory-reporting // code should call a JSAPI function to observe ICU memory usage. But we // can't define the alloc/free functions in the JS engine, because it can't // depend on the XPCOM-based memory reporting goop. So for now, we have // this oddness. mozilla::SetICUMemoryFunctions(); // Do the same for libogg. ogg_set_mem_functions(OggReporter::CountingMalloc, OggReporter::CountingCalloc, OggReporter::CountingRealloc, OggReporter::CountingFree); #if defined(MOZ_VPX) && !defined(MOZ_VPX_NO_MEM_REPORTING) // And for VPX. vpx_mem_set_functions(VPXReporter::CountingMalloc, VPXReporter::CountingCalloc, VPXReporter::CountingRealloc, VPXReporter::CountingFree, memcpy, memset, memmove); #endif #ifdef MOZ_WEBM // And for libnestegg. // libnestegg expects that its realloc implementation will free // the pointer argument when a size of 0 is passed in, so we need // the special version of the counting realloc. nestegg_set_halloc_func(NesteggReporter::CountingFreeingRealloc); #endif // Initialize the JS engine. if (!JS_Init()) { NS_RUNTIMEABORT("JS_Init failed"); } rv = nsComponentManagerImpl::gComponentManager->Init(); if (NS_FAILED(rv)) { NS_RELEASE(nsComponentManagerImpl::gComponentManager); return rv; } if (aResult) { NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager); } // The iimanager constructor searches and registers XPT files. // (We trigger the singleton's lazy construction here to make that happen.) (void)XPTInterfaceInfoManager::GetSingleton(); // After autoreg, but before we actually instantiate any components, // add any services listed in the "xpcom-directory-providers" category // to the directory service. nsDirectoryService::gService->RegisterCategoryProviders(); // Init SharedThreadPool (which needs the service manager). SharedThreadPool::InitStatics(); // Init AbstractThread. AbstractThread::InitStatics(); // Force layout to spin up so that nsContentUtils is available for cx stack // munging. nsCOMPtr<nsISupports> componentLoader = do_GetService("@mozilla.org/moz/jsloader;1"); mozilla::scache::StartupCache::GetSingleton(); mozilla::AvailableMemoryTracker::Activate(); // Notify observers of xpcom autoregistration start NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_CATEGORY, nullptr, NS_XPCOM_STARTUP_OBSERVER_ID); #ifdef XP_WIN CreateAnonTempFileRemover(); #endif // We only want the SystemMemoryReporter running in one process, because it // profiles the entire system. The main process is the obvious place for // it. if (XRE_IsParentProcess()) { mozilla::SystemMemoryReporter::Init(); } // The memory reporter manager is up and running -- register our reporters. RegisterStrongMemoryReporter(new ICUReporter()); RegisterStrongMemoryReporter(new OggReporter()); #ifdef MOZ_VPX RegisterStrongMemoryReporter(new VPXReporter()); #endif #ifdef MOZ_WEBM RegisterStrongMemoryReporter(new NesteggReporter()); #endif mozilla::Telemetry::Init(); mozilla::HangMonitor::Startup(); mozilla::BackgroundHangMonitor::Startup(); const MessageLoop* const loop = MessageLoop::current(); sMainHangMonitor = new mozilla::BackgroundHangMonitor( loop->thread_name().c_str(), loop->transient_hang_timeout(), loop->permanent_hang_timeout()); return NS_OK; }