Example #1
0
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;
}