void
PluginProcessParent::Delete()
{
  MessageLoop* currentLoop = MessageLoop::current();
  MessageLoop* ioLoop = XRE_GetIOMessageLoop();

  if (currentLoop == ioLoop) {
      delete this;
      return;
  }

  ioLoop->PostTask(FROM_HERE,
                   NewRunnableMethod(this, &PluginProcessParent::Delete));
}
Exemplo n.º 2
0
mozilla::ipc::IPCResult
GPUParent::RecvNewWidgetCompositor(Endpoint<layers::PCompositorBridgeParent>&& aEndpoint,
                                   const CSSToLayoutDeviceScale& aScale,
                                   const TimeDuration& aVsyncRate,
                                   const bool& aUseExternalSurfaceSize,
                                   const IntSize& aSurfaceSize)
{
  RefPtr<CompositorBridgeParent> cbp =
    new CompositorBridgeParent(aScale, aVsyncRate, aUseExternalSurfaceSize, aSurfaceSize);

  MessageLoop* loop = CompositorThreadHolder::Loop();
  loop->PostTask(NewRunnableFunction(OpenParent, cbp, Move(aEndpoint)));
  return IPC_OK();
}
bool
GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts, int aTimeoutMs, base::ProcessArchitecture arch)
{
  PrepareLaunch();

  MessageLoop* ioLoop = XRE_GetIOMessageLoop();
  NS_ASSERTION(MessageLoop::current() != ioLoop, "sync launch from the IO thread NYI");

  ioLoop->PostTask(NewNonOwningRunnableMethod
                   <std::vector<std::string>, base::ProcessArchitecture>
                   (this, &GeckoChildProcessHost::RunPerformAsyncLaunch,
                    aExtraOpts, arch));

  return WaitUntilConnected(aTimeoutMs);
}
Exemplo n.º 4
0
void TexturePoolOGL::MaybeFillTextures()
{
  if (sTextures->GetSize() < TEXTURE_REFILL_THRESHOLD &&
      !sHasPendingFillTask) {
    LOG("need to refill the texture pool.");
    sHasPendingFillTask = true;
    MessageLoop* loop = mozilla::layers::CompositorThreadHolder::Loop();
    MOZ_ASSERT(loop);
    loop->PostTask(
      NS_NewRunnableFunction(
        "TexturePoolOGL::MaybeFillTextures",
        [] () {
          TexturePoolOGL::Fill(sActiveContext);
    }));
  }
}
Exemplo n.º 5
0
/*static*/ PImageBridgeParent*
ImageBridgeParent::Create(Transport* aTransport, ProcessId aChildProcessId)
{
  base::ProcessHandle processHandle;
  if (!base::OpenProcessHandle(aChildProcessId, &processHandle)) {
    return nullptr;
  }

  MessageLoop* loop = CompositorParent::CompositorLoop();
  nsRefPtr<ImageBridgeParent> bridge = new ImageBridgeParent(loop, aTransport, aChildProcessId);
  bridge->mSelfRef = bridge;
  loop->PostTask(FROM_HERE,
                 NewRunnableFunction(ConnectImageBridgeInParentProcess,
                                     bridge.get(), aTransport, processHandle));
  return bridge.get();
}
Exemplo n.º 6
0
/*static*/ bool
ImageBridgeParent::Create(Transport* aTransport, ProcessId aOtherProcess)
{
  ProcessHandle processHandle;
  if (!base::OpenProcessHandle(aOtherProcess, &processHandle)) {
    return false;
  }

  MessageLoop* loop = CompositorParent::CompositorLoop();
  nsRefPtr<ImageBridgeParent> bridge = new ImageBridgeParent(loop, aTransport);
  bridge->mSelfRef = bridge;
  loop->PostTask(FROM_HERE,
                 NewRunnableFunction(ConnectImageBridgeInParentProcess,
                                     bridge.get(), aTransport, processHandle));
  return true;
}
Exemplo n.º 7
0
NS_IMETHODIMP
DoWorkRunnable::Run()
{
  MessageLoop* loop = MessageLoop::current();
  MOZ_ASSERT(loop);

  bool nestableTasksAllowed = loop->NestableTasksAllowed();

  // MessageLoop::RunTask() disallows nesting, but our Frankenventloop will
  // always dispatch DoWork() below from what looks to MessageLoop like a nested
  // context.  So we unconditionally allow nesting here.
  loop->SetNestableTasksAllowed(true);
  loop->DoWork();
  loop->SetNestableTasksAllowed(nestableTasksAllowed);

  return NS_OK;
}
Exemplo n.º 8
0
void SfDelegate::initiateConnection(
        const char *uri,
        const KeyedVector<String8, String8> *headers,
        off64_t offset) {
    GURL url(uri);

    MessageLoop *loop = gNetworkThread->message_loop();
    loop->PostTask(
            FROM_HERE,
            NewRunnableFunction(
                &SfDelegate::OnInitiateConnectionWrapper,
                this,
                url,
                headers,
                offset));

}
Exemplo n.º 9
0
NS_IMETHODIMP
DoWorkRunnable::Run()
{
  MessageLoop* loop = MessageLoop::current();
  NS_ASSERTION(loop, "Shouldn't be null!");
  if (loop) {
    bool nestableTasksAllowed = loop->NestableTasksAllowed();

    // MessageLoop::RunTask() disallows nesting, but our Frankenventloop
    // will always dispatch DoWork() below from what looks to
    // MessageLoop like a nested context.  So we unconditionally allow
    // nesting here.
    loop->SetNestableTasksAllowed(true);
    loop->DoWork();
    loop->SetNestableTasksAllowed(nestableTasksAllowed);
  }
  return NS_OK;
}
Exemplo n.º 10
0
GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
                                             base::WaitableEventWatcher::Delegate* aDelegate)
  : ChildProcessHost(RENDER_PROCESS), // FIXME/cjones: we should own this enum
    mProcessType(aProcessType),
    mMonitor("mozilla.ipc.GeckChildProcessHost.mMonitor"),
    mLaunched(false),
    mChannelInitialized(false),
    mDelegate(aDelegate),
    mChildProcessHandle(0)
{
    MOZ_COUNT_CTOR(GeckoChildProcessHost);
    
    MessageLoop* ioLoop = 
      BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO);
    ioLoop->PostTask(FROM_HERE,
                     NewRunnableMethod(this,
                                       &GeckoChildProcessHost::InitializeChannel));
}
Exemplo n.º 11
0
void
MessagePumpForChildProcess::Run(MessagePump::Delegate* aDelegate)
{
  if (mFirstRun) {
#ifdef DEBUG
    NS_ASSERTION(aDelegate && gFirstDelegate == nullptr, "Huh?!");
    gFirstDelegate = aDelegate;
#endif
    mFirstRun = false;
    if (NS_FAILED(XRE_RunAppShell())) {
        NS_WARNING("Failed to run app shell?!");
    }
#ifdef DEBUG
    NS_ASSERTION(aDelegate && aDelegate == gFirstDelegate, "Huh?!");
    gFirstDelegate = nullptr;
#endif
    return;
  }

#ifdef DEBUG
  NS_ASSERTION(aDelegate && aDelegate == gFirstDelegate, "Huh?!");
#endif

  // We can get to this point in startup with Tasks in our loop's
  // incoming_queue_ or pending_queue_, but without a matching
  // DoWorkRunnable().  In MessagePump::Run() above, we sensitively
  // depend on *not* directly calling delegate->DoWork(), because that
  // prioritizes Tasks above XPCOM events.  However, from this point
  // forward, any Task posted to our loop is guaranteed to have a
  // DoWorkRunnable enqueued for it.
  //
  // So we just flush the pending work here and move on.
  MessageLoop* loop = MessageLoop::current();
  bool nestableTasksAllowed = loop->NestableTasksAllowed();
  loop->SetNestableTasksAllowed(true);

  while (aDelegate->DoWork());

  loop->SetNestableTasksAllowed(nestableTasksAllowed);


  // Really run.
  mozilla::ipc::MessagePump::Run(aDelegate);
}
bool
GeckoChildProcessHost::LaunchAndWaitForProcessHandle(StringVector aExtraOpts)
{
  PrepareLaunch();

  MessageLoop* ioLoop = XRE_GetIOMessageLoop();
  ioLoop->PostTask(FROM_HERE,
                   NewRunnableMethod(this,
                                     &GeckoChildProcessHost::RunPerformAsyncLaunch,
                                     aExtraOpts, base::GetCurrentProcessArchitecture()));

  MonitorAutoLock lock(mMonitor);
  while (mProcessState < PROCESS_CREATED) {
    lock.Wait();
  }
  MOZ_ASSERT(mProcessState == PROCESS_ERROR || mChildProcessHandle);

  return mProcessState < PROCESS_ERROR;
}
bool
GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts, int aTimeoutMs, base::ProcessArchitecture arch)
{
  PrepareLaunch();

  PRIntervalTime timeoutTicks = (aTimeoutMs > 0) ? 
    PR_MillisecondsToInterval(aTimeoutMs) : PR_INTERVAL_NO_TIMEOUT;
  MessageLoop* ioLoop = XRE_GetIOMessageLoop();
  NS_ASSERTION(MessageLoop::current() != ioLoop, "sync launch from the IO thread NYI");

  ioLoop->PostTask(FROM_HERE,
                   NewRunnableMethod(this,
                                     &GeckoChildProcessHost::RunPerformAsyncLaunch,
                                     aExtraOpts, arch));
  // NB: this uses a different mechanism than the chromium parent
  // class.
  MonitorAutoLock lock(mMonitor);
  PRIntervalTime waitStart = PR_IntervalNow();
  PRIntervalTime current;

  // We'll receive several notifications, we need to exit when we
  // have either successfully launched or have timed out.
  while (mProcessState != PROCESS_CONNECTED) {
    // If there was an error then return it, don't wait out the timeout.
    if (mProcessState == PROCESS_ERROR) {
      break;
    }

    lock.Wait(timeoutTicks);

    if (timeoutTicks != PR_INTERVAL_NO_TIMEOUT) {
      current = PR_IntervalNow();
      PRIntervalTime elapsed = current - waitStart;
      if (elapsed > timeoutTicks) {
        break;
      }
      timeoutTicks = timeoutTicks - elapsed;
      waitStart = current;
    }
  }

  return mProcessState == PROCESS_CONNECTED;
}
Exemplo n.º 14
0
bool
GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts)
{
  MessageLoop* ioLoop = 
    BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO);
  ioLoop->PostTask(FROM_HERE,
                   NewRunnableMethod(this,
                                     &GeckoChildProcessHost::PerformAsyncLaunch,
                                     aExtraOpts));

  // This may look like the sync launch wait, but we only delay as
  // long as it takes to create the channel.
  MonitorAutoEnter mon(mMonitor);
  while (!mChannelInitialized) {
    mon.Wait();
  }

  return true;
}
nsresult
BluetoothDaemonConnection::ConnectSocket(BluetoothDaemonPDUConsumer* aConsumer)
{
  MOZ_ASSERT(NS_IsMainThread());

  if (mIO) {
    CHROMIUM_LOG("Bluetooth daemon already connecting/connected!");
    return NS_ERROR_FAILURE;
  }

  SetConnectionStatus(SOCKET_CONNECTING);

  MessageLoop* ioLoop = XRE_GetIOMessageLoop();
  mIO = new BluetoothDaemonConnectionIO(
    ioLoop, -1, UnixSocketWatcher::SOCKET_IS_CONNECTING, this, aConsumer);
  ioLoop->PostTask(FROM_HERE, new BluetoothDaemonConnectTask(mIO));

  return NS_OK;
}
bool
GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts)
{
  PrepareLaunch();

  MessageLoop* ioLoop = XRE_GetIOMessageLoop();
  ioLoop->PostTask(FROM_HERE,
                   NewRunnableMethod(this,
                                     &GeckoChildProcessHost::RunPerformAsyncLaunch,
                                     aExtraOpts, base::GetCurrentProcessArchitecture()));

  // This may look like the sync launch wait, but we only delay as
  // long as it takes to create the channel.
  MonitorAutoLock lock(mMonitor);
  while (mProcessState < CHANNEL_INITIALIZED) {
    lock.Wait();
  }

  return true;
}
GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
                                             base::WaitableEventWatcher::Delegate* aDelegate)
  : ChildProcessHost(RENDER_PROCESS), // FIXME/cjones: we should own this enum
    mProcessType(aProcessType),
    mMonitor("mozilla.ipc.GeckChildProcessHost.mMonitor"),
    mLaunched(false),
    mChannelInitialized(false),
    mDelegate(aDelegate),
    mChildProcessHandle(0)
#if defined(MOZ_WIDGET_COCOA)
  , mChildTask(MACH_PORT_NULL)
#endif
{
    MOZ_COUNT_CTOR(GeckoChildProcessHost);
    
    MessageLoop* ioLoop = XRE_GetIOMessageLoop();
    ioLoop->PostTask(FROM_HERE,
                     NewRunnableMethod(this,
                                       &GeckoChildProcessHost::InitializeChannel));
}
GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
                                             ChildPrivileges aPrivileges)
  : ChildProcessHost(RENDER_PROCESS), // FIXME/cjones: we should own this enum
    mProcessType(aProcessType),
    mPrivileges(aPrivileges),
    mMonitor("mozilla.ipc.GeckChildProcessHost.mMonitor"),
    mProcessState(CREATING_CHANNEL),
    mDelegate(nullptr),
    mChildProcessHandle(0)
#if defined(MOZ_WIDGET_COCOA)
  , mChildTask(MACH_PORT_NULL)
#endif
{
    MOZ_COUNT_CTOR(GeckoChildProcessHost);
    
    MessageLoop* ioLoop = XRE_GetIOMessageLoop();
    ioLoop->PostTask(FROM_HERE,
                     NewRunnableMethod(this,
                                       &GeckoChildProcessHost::InitializeChannel));
}
Exemplo n.º 19
0
bool
GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts)
{
  MessageLoop* ioLoop = 
    BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO);
  NS_ASSERTION(MessageLoop::current() != ioLoop, "sync launch from the IO thread NYI");

  ioLoop->PostTask(FROM_HERE,
                   NewRunnableMethod(this,
                                     &GeckoChildProcessHost::PerformAsyncLaunch,
                                     aExtraOpts));

  // NB: this uses a different mechanism than the chromium parent
  // class.
  MonitorAutoEnter mon(mMonitor);
  while (!mLaunched) {
    mon.Wait();
  }

  return true;
}
bool
GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts)
{
#ifdef XP_WIN
  InitWindowsGroupID();
#endif

  MessageLoop* ioLoop = XRE_GetIOMessageLoop();
  ioLoop->PostTask(FROM_HERE,
                   NewRunnableMethod(this,
                                     &GeckoChildProcessHost::PerformAsyncLaunch,
                                     aExtraOpts, base::GetCurrentProcessArchitecture()));

  // This may look like the sync launch wait, but we only delay as
  // long as it takes to create the channel.
  MonitorAutoLock lock(mMonitor);
  while (!mChannelInitialized) {
    lock.Wait();
  }

  return true;
}
Exemplo n.º 21
0
nsresult
XRE_RunAppShell()
{
    nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
    NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
#if defined(XP_MACOSX)
    {
      // In content processes that want XPCOM (and hence want
      // AppShell), we usually run our hybrid event loop through
      // MessagePump::Run(), by way of nsBaseAppShell::Run().  The
      // Cocoa nsAppShell impl, however, implements its own Run()
      // that's unaware of MessagePump.  That's all rather suboptimal,
      // but oddly enough not a problem... usually.
      // 
      // The problem with this setup comes during startup.
      // XPCOM-in-subprocesses depends on IPC, e.g. to init the pref
      // service, so we have to init IPC first.  But, IPC also
      // indirectly kinda-depends on XPCOM, because MessagePump
      // schedules work from off-main threads (e.g. IO thread) by
      // using NS_DispatchToMainThread().  If the IO thread receives a
      // Message from the parent before nsThreadManager is
      // initialized, then DispatchToMainThread() will fail, although
      // MessagePump will remember the task.  This race condition
      // isn't a problem when appShell->Run() ends up in
      // MessagePump::Run(), because MessagePump will immediate see it
      // has work to do.  It *is* a problem when we end up in [NSApp
      // run], because it's not aware that MessagePump has work that
      // needs to be processed; that was supposed to be signaled by
      // nsIRunnable(s).
      // 
      // So instead of hacking Cocoa nsAppShell or rewriting the
      // event-loop system, we compromise here by processing any tasks
      // that might have been enqueued on MessagePump, *before*
      // MessagePump::ScheduleWork was able to successfully
      // DispatchToMainThread().
      MessageLoop* loop = MessageLoop::current();
      bool couldNest = loop->NestableTasksAllowed();

      loop->SetNestableTasksAllowed(true);
      RefPtr<Runnable> task = new MessageLoop::QuitTask();
      loop->PostTask(task.forget());
      loop->Run();

      loop->SetNestableTasksAllowed(couldNest);
    }
#endif  // XP_MACOSX
    return appShell->Run();
}
Exemplo n.º 22
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();
  }

  MessageLoop* messageLoop = MessageLoop::current();
  if (!messageLoop) {
    sMessageLoop = new MessageLoopForUI(MessageLoop::TYPE_MOZILLA_PARENT);
    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);
  } else if (messageLoop->type() == MessageLoop::TYPE_MOZILLA_CHILD) {
    messageLoop->set_thread_name("Gecko_Child");
    messageLoop->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;
}