michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* vim:set ts=4 sw=4 sts=4 ci et: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "base/basictypes.h" michael@0: michael@0: #include "mozilla/Atomics.h" michael@0: #include "mozilla/Poison.h" michael@0: #include "mozilla/Preferences.h" michael@0: #include "mozilla/XPCOM.h" michael@0: #include "nsXULAppAPI.h" michael@0: michael@0: #include "nsXPCOMPrivate.h" michael@0: #include "nsXPCOMCIDInternal.h" michael@0: michael@0: #include "mozilla/layers/ImageBridgeChild.h" michael@0: #include "mozilla/layers/CompositorParent.h" michael@0: michael@0: #include "prlink.h" michael@0: michael@0: #include "nsCycleCollector.h" michael@0: #include "nsObserverList.h" michael@0: #include "nsObserverService.h" michael@0: #include "nsProperties.h" michael@0: #include "nsPersistentProperties.h" michael@0: #include "nsScriptableInputStream.h" michael@0: #include "nsBinaryStream.h" michael@0: #include "nsStorageStream.h" michael@0: #include "nsPipe.h" michael@0: #include "nsScriptableBase64Encoder.h" michael@0: michael@0: #include "nsMemoryImpl.h" michael@0: #include "nsDebugImpl.h" michael@0: #include "nsTraceRefcnt.h" michael@0: #include "nsErrorService.h" michael@0: michael@0: #include "nsSupportsArray.h" michael@0: #include "nsArray.h" michael@0: #include "nsINIParserImpl.h" michael@0: #include "nsSupportsPrimitives.h" michael@0: #include "nsConsoleService.h" michael@0: michael@0: #include "nsIJSRuntimeService.h" michael@0: michael@0: #include "nsComponentManager.h" michael@0: #include "nsCategoryManagerUtils.h" michael@0: #include "nsIServiceManager.h" michael@0: michael@0: #include "nsThreadManager.h" michael@0: #include "nsThreadPool.h" michael@0: michael@0: #include "xptinfo.h" michael@0: #include "nsIInterfaceInfoManager.h" michael@0: #include "xptiprivate.h" michael@0: #include "mozilla/XPTInterfaceInfoManager.h" michael@0: michael@0: #include "nsTimerImpl.h" michael@0: #include "TimerThread.h" michael@0: michael@0: #include "nsThread.h" michael@0: #include "nsProcess.h" michael@0: #include "nsEnvironment.h" michael@0: #include "nsVersionComparatorImpl.h" michael@0: michael@0: #include "nsIFile.h" michael@0: #include "nsLocalFile.h" michael@0: #if defined(XP_UNIX) michael@0: #include "nsNativeCharsetUtils.h" michael@0: #endif michael@0: #include "nsDirectoryService.h" michael@0: #include "nsDirectoryServiceDefs.h" michael@0: #include "nsCategoryManager.h" michael@0: #include "nsICategoryManager.h" michael@0: #include "nsMultiplexInputStream.h" michael@0: michael@0: #include "nsStringStream.h" michael@0: extern nsresult nsStringInputStreamConstructor(nsISupports *, REFNSIID, void **); michael@0: michael@0: #include "nsAtomService.h" michael@0: #include "nsAtomTable.h" michael@0: #include "nsISupportsImpl.h" michael@0: michael@0: #include "nsHashPropertyBag.h" michael@0: michael@0: #include "nsUnicharInputStream.h" michael@0: #include "nsVariant.h" michael@0: michael@0: #include "nsUUIDGenerator.h" michael@0: michael@0: #include "nsIOUtil.h" michael@0: michael@0: #include "SpecialSystemDirectory.h" michael@0: michael@0: #if defined(XP_WIN) michael@0: #include "nsWindowsRegKey.h" michael@0: #endif michael@0: michael@0: #ifdef MOZ_WIDGET_COCOA michael@0: #include "nsMacUtilsImpl.h" michael@0: #endif michael@0: michael@0: #include "nsSystemInfo.h" michael@0: #include "nsMemoryReporterManager.h" michael@0: #include "nsMemoryInfoDumper.h" michael@0: #include "nsSecurityConsoleMessage.h" michael@0: #include "nsMessageLoop.h" michael@0: michael@0: #include "nsStatusReporterManager.h" michael@0: michael@0: #include michael@0: #include "mozilla/Services.h" michael@0: #include "mozilla/Omnijar.h" michael@0: #include "mozilla/HangMonitor.h" michael@0: #include "mozilla/Telemetry.h" michael@0: #include "mozilla/BackgroundHangMonitor.h" michael@0: michael@0: #include "nsChromeRegistry.h" michael@0: #include "nsChromeProtocolHandler.h" michael@0: #include "mozilla/PoisonIOInterposer.h" michael@0: #include "mozilla/LateWriteChecks.h" michael@0: michael@0: #include "mozilla/scache/StartupCache.h" michael@0: michael@0: #include "base/at_exit.h" michael@0: #include "base/command_line.h" michael@0: #include "base/message_loop.h" michael@0: michael@0: #include "mozilla/ipc/BrowserProcessSubThread.h" michael@0: #include "mozilla/AvailableMemoryTracker.h" michael@0: #include "mozilla/ClearOnShutdown.h" michael@0: #include "mozilla/SystemMemoryReporter.h" michael@0: michael@0: #ifdef MOZ_VISUAL_EVENT_TRACER michael@0: #include "mozilla/VisualEventTracer.h" michael@0: #endif michael@0: michael@0: #include "ogg/ogg.h" michael@0: #if defined(MOZ_VPX) && !defined(MOZ_VPX_NO_MEM_REPORTING) michael@0: #include "vpx_mem/vpx_mem.h" michael@0: #endif michael@0: #ifdef MOZ_WEBM michael@0: #include "nestegg/nestegg.h" michael@0: #endif michael@0: michael@0: #include "GeckoProfiler.h" michael@0: michael@0: #include "jsapi.h" michael@0: michael@0: using namespace mozilla; michael@0: using base::AtExitManager; michael@0: using mozilla::ipc::BrowserProcessSubThread; michael@0: #ifdef MOZ_VISUAL_EVENT_TRACER michael@0: using mozilla::eventtracer::VisualEventTracer; michael@0: #endif michael@0: michael@0: namespace { michael@0: michael@0: static AtExitManager* sExitManager; michael@0: static MessageLoop* sMessageLoop; michael@0: static bool sCommandLineWasInitialized; michael@0: static BrowserProcessSubThread* sIOThread; michael@0: static BackgroundHangMonitor* sMainHangMonitor; michael@0: michael@0: } /* anonymous namespace */ michael@0: michael@0: // Registry Factory creation function defined in nsRegistry.cpp michael@0: // We hook into this function locally to create and register the registry michael@0: // Since noone outside xpcom needs to know about this and nsRegistry.cpp michael@0: // does not have a local include file, we are putting this definition michael@0: // here rather than in nsIRegistry.h michael@0: extern nsresult NS_RegistryGetFactory(nsIFactory** aFactory); michael@0: extern nsresult NS_CategoryManagerGetFactory( nsIFactory** ); michael@0: michael@0: #ifdef XP_WIN michael@0: extern nsresult CreateAnonTempFileRemover(); michael@0: #endif michael@0: michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsProcess) michael@0: michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsIDImpl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsStringImpl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsCStringImpl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRBoolImpl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint8Impl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint16Impl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint32Impl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint64Impl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRTimeImpl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsCharImpl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt16Impl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt32Impl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt64Impl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsFloatImpl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsDoubleImpl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsVoidImpl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsInterfacePointerImpl) michael@0: michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsConsoleService, Init) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsAtomService) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimerImpl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsBinaryOutputStream) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsBinaryInputStream) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsStorageStream) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsVersionComparatorImpl) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsScriptableBase64Encoder) michael@0: #ifdef MOZ_VISUAL_EVENT_TRACER michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(VisualEventTracer) michael@0: #endif michael@0: michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsVariant) michael@0: michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsHashPropertyBag) michael@0: michael@0: NS_GENERIC_AGGREGATED_CONSTRUCTOR(nsProperties) michael@0: michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsUUIDGenerator, Init) michael@0: michael@0: #ifdef MOZ_WIDGET_COCOA michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacUtilsImpl) michael@0: #endif michael@0: michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemInfo, Init) michael@0: michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMemoryReporterManager, Init) michael@0: michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsMemoryInfoDumper) michael@0: michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStatusReporterManager, Init) michael@0: michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsIOUtil) michael@0: michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsSecurityConsoleMessage) michael@0: michael@0: static nsresult michael@0: nsThreadManagerGetSingleton(nsISupports* outer, michael@0: const nsIID& aIID, michael@0: void* *aInstancePtr) michael@0: { michael@0: NS_ASSERTION(aInstancePtr, "null outptr"); michael@0: if (NS_WARN_IF(outer)) michael@0: return NS_ERROR_NO_AGGREGATION; michael@0: michael@0: return nsThreadManager::get()->QueryInterface(aIID, aInstancePtr); michael@0: } michael@0: michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsThreadPool) michael@0: michael@0: static nsresult michael@0: nsXPTIInterfaceInfoManagerGetSingleton(nsISupports* outer, michael@0: const nsIID& aIID, michael@0: void* *aInstancePtr) michael@0: { michael@0: NS_ASSERTION(aInstancePtr, "null outptr"); michael@0: if (NS_WARN_IF(outer)) michael@0: return NS_ERROR_NO_AGGREGATION; michael@0: michael@0: nsCOMPtr iim michael@0: (XPTInterfaceInfoManager::GetSingleton()); michael@0: if (!iim) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: return iim->QueryInterface(aIID, aInstancePtr); michael@0: } michael@0: michael@0: nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = nullptr; michael@0: bool gXPCOMShuttingDown = false; michael@0: bool gXPCOMThreadsShutDown = false; michael@0: michael@0: static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID); michael@0: static NS_DEFINE_CID(kINIParserFactoryCID, NS_INIPARSERFACTORY_CID); michael@0: static NS_DEFINE_CID(kSimpleUnicharStreamFactoryCID, NS_SIMPLE_UNICHAR_STREAM_FACTORY_CID); michael@0: michael@0: NS_DEFINE_NAMED_CID(NS_CHROMEREGISTRY_CID); michael@0: NS_DEFINE_NAMED_CID(NS_CHROMEPROTOCOLHANDLER_CID); michael@0: michael@0: NS_DEFINE_NAMED_CID(NS_SECURITY_CONSOLE_MESSAGE_CID); michael@0: michael@0: NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsChromeRegistry, michael@0: nsChromeRegistry::GetSingleton) michael@0: NS_GENERIC_FACTORY_CONSTRUCTOR(nsChromeProtocolHandler) michael@0: michael@0: #define NS_PERSISTENTPROPERTIES_CID NS_IPERSISTENTPROPERTIES_CID /* sigh */ michael@0: michael@0: static already_AddRefed michael@0: CreateINIParserFactory(const mozilla::Module& module, michael@0: const mozilla::Module::CIDEntry& entry) michael@0: { michael@0: nsCOMPtr f = new nsINIParserFactory(); michael@0: return f.forget(); michael@0: } michael@0: michael@0: static already_AddRefed michael@0: CreateUnicharStreamFactory(const mozilla::Module& module, michael@0: const mozilla::Module::CIDEntry& entry) michael@0: { michael@0: return already_AddRefed( michael@0: nsSimpleUnicharStreamFactory::GetInstance()); michael@0: } michael@0: michael@0: #define COMPONENT(NAME, Ctor) static NS_DEFINE_CID(kNS_##NAME##_CID, NS_##NAME##_CID); michael@0: #include "XPCOMModule.inc" michael@0: #undef COMPONENT michael@0: michael@0: #define COMPONENT(NAME, Ctor) { &kNS_##NAME##_CID, false, nullptr, Ctor }, michael@0: const mozilla::Module::CIDEntry kXPCOMCIDEntries[] = { michael@0: { &kComponentManagerCID, true, nullptr, nsComponentManagerImpl::Create }, michael@0: { &kINIParserFactoryCID, false, CreateINIParserFactory }, michael@0: { &kSimpleUnicharStreamFactoryCID, false, CreateUnicharStreamFactory }, michael@0: #include "XPCOMModule.inc" michael@0: { &kNS_CHROMEREGISTRY_CID, false, nullptr, nsChromeRegistryConstructor }, michael@0: { &kNS_CHROMEPROTOCOLHANDLER_CID, false, nullptr, nsChromeProtocolHandlerConstructor }, michael@0: { &kNS_SECURITY_CONSOLE_MESSAGE_CID, false, nullptr, nsSecurityConsoleMessageConstructor }, michael@0: { nullptr } michael@0: }; michael@0: #undef COMPONENT michael@0: michael@0: #define COMPONENT(NAME, Ctor) { NS_##NAME##_CONTRACTID, &kNS_##NAME##_CID }, michael@0: const mozilla::Module::ContractIDEntry kXPCOMContracts[] = { michael@0: #include "XPCOMModule.inc" michael@0: { NS_CHROMEREGISTRY_CONTRACTID, &kNS_CHROMEREGISTRY_CID }, michael@0: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "chrome", &kNS_CHROMEPROTOCOLHANDLER_CID }, michael@0: { NS_INIPARSERFACTORY_CONTRACTID, &kINIParserFactoryCID }, michael@0: { NS_SECURITY_CONSOLE_MESSAGE_CONTRACTID, &kNS_SECURITY_CONSOLE_MESSAGE_CID }, michael@0: { nullptr } michael@0: }; michael@0: #undef COMPONENT michael@0: michael@0: const mozilla::Module kXPCOMModule = { mozilla::Module::kVersion, kXPCOMCIDEntries, kXPCOMContracts }; michael@0: michael@0: // gDebug will be freed during shutdown. michael@0: static nsIDebug* gDebug = nullptr; michael@0: michael@0: EXPORT_XPCOM_API(nsresult) michael@0: NS_GetDebug(nsIDebug** result) michael@0: { michael@0: return nsDebugImpl::Create(nullptr, michael@0: NS_GET_IID(nsIDebug), michael@0: (void**) result); michael@0: } michael@0: michael@0: EXPORT_XPCOM_API(nsresult) michael@0: NS_InitXPCOM(nsIServiceManager* *result, michael@0: nsIFile* binDirectory) michael@0: { michael@0: return NS_InitXPCOM2(result, binDirectory, nullptr); michael@0: } michael@0: michael@0: class ICUReporter MOZ_FINAL : public nsIMemoryReporter, michael@0: public CountingAllocatorBase michael@0: { michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: michael@0: static void* Alloc(const void*, size_t size) michael@0: { michael@0: return CountingMalloc(size); michael@0: } michael@0: michael@0: static void* Realloc(const void*, void* p, size_t size) michael@0: { michael@0: return CountingRealloc(p, size); michael@0: } michael@0: michael@0: static void Free(const void*, void* p) michael@0: { michael@0: return CountingFree(p); michael@0: } michael@0: michael@0: private: michael@0: NS_IMETHODIMP michael@0: CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData) michael@0: { michael@0: return MOZ_COLLECT_REPORT( michael@0: "explicit/icu", KIND_HEAP, UNITS_BYTES, MemoryAllocated(), michael@0: "Memory used by ICU, a Unicode and globalization support library."); michael@0: } michael@0: }; michael@0: michael@0: NS_IMPL_ISUPPORTS(ICUReporter, nsIMemoryReporter) michael@0: michael@0: /* static */ template<> Atomic CountingAllocatorBase::sAmount(0); michael@0: michael@0: class OggReporter MOZ_FINAL : public nsIMemoryReporter, michael@0: public CountingAllocatorBase michael@0: { michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: michael@0: private: michael@0: NS_IMETHODIMP michael@0: CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData) michael@0: { michael@0: return MOZ_COLLECT_REPORT( michael@0: "explicit/media/libogg", KIND_HEAP, UNITS_BYTES, MemoryAllocated(), michael@0: "Memory allocated through libogg for Ogg, Theora, and related media files."); michael@0: } michael@0: }; michael@0: michael@0: NS_IMPL_ISUPPORTS(OggReporter, nsIMemoryReporter) michael@0: michael@0: /* static */ template<> Atomic CountingAllocatorBase::sAmount(0); michael@0: michael@0: #ifdef MOZ_VPX michael@0: class VPXReporter MOZ_FINAL : public nsIMemoryReporter, michael@0: public CountingAllocatorBase michael@0: { michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: michael@0: private: michael@0: NS_IMETHODIMP michael@0: CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData) michael@0: { michael@0: return MOZ_COLLECT_REPORT( michael@0: "explicit/media/libvpx", KIND_HEAP, UNITS_BYTES, MemoryAllocated(), michael@0: "Memory allocated through libvpx for WebM media files."); michael@0: } michael@0: }; michael@0: michael@0: NS_IMPL_ISUPPORTS(VPXReporter, nsIMemoryReporter) michael@0: michael@0: /* static */ template<> Atomic CountingAllocatorBase::sAmount(0); michael@0: #endif /* MOZ_VPX */ michael@0: michael@0: #ifdef MOZ_WEBM michael@0: class NesteggReporter MOZ_FINAL : public nsIMemoryReporter michael@0: , public CountingAllocatorBase michael@0: { michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: michael@0: private: michael@0: NS_IMETHODIMP michael@0: CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData) michael@0: { michael@0: return MOZ_COLLECT_REPORT( michael@0: "explicit/media/libnestegg", KIND_HEAP, UNITS_BYTES, MemoryAllocated(), michael@0: "Memory allocated through libnestegg for WebM media files."); michael@0: } michael@0: }; michael@0: michael@0: NS_IMPL_ISUPPORTS(NesteggReporter, nsIMemoryReporter) michael@0: michael@0: /* static */ template<> Atomic CountingAllocatorBase::sAmount(0); michael@0: #endif /* MOZ_WEBM */ michael@0: michael@0: // Anonymous namespace for customizing the default locale that JavaScript michael@0: // uses, according to the value of the "javascript.default_locale" pref. michael@0: // The current default locale can be detected in JavaScript by calling michael@0: // `Intl.DateTimeFormat().resolvedOptions().locale` michael@0: namespace { michael@0: michael@0: #define DEFAULT_LOCALE_PREF "javascript.default_locale" michael@0: michael@0: static char* sSystemLocale; michael@0: static char* sJSLocale; michael@0: michael@0: // Returns a pointer to the current JS Runtime. michael@0: static michael@0: JSRuntime* GetRuntime() { michael@0: nsresult rv; michael@0: nsCOMPtr rts = do_GetService("@mozilla.org/js/xpc/RuntimeService;1", &rv); michael@0: if (NS_FAILED(rv)) return NULL; michael@0: JSRuntime* rt; michael@0: rts->GetRuntime(&rt); michael@0: return rt; michael@0: } michael@0: michael@0: // Takes the "javascript.default_locale" pref value and applies it. If the locale michael@0: // is empty, we fall back to the default system and JS locales. michael@0: static michael@0: void DefaultLocaleChangedCallback(const char* /* pref */, void* /* closure */) { michael@0: // Get a pointer to the default JS Runtime. michael@0: JSRuntime* rt = GetRuntime(); michael@0: if (rt) { michael@0: // Read the pref, which may contain a custom default locale to be used in JavaScript. michael@0: nsAutoCString prefLocale; michael@0: mozilla::Preferences::GetCString(DEFAULT_LOCALE_PREF, &prefLocale); michael@0: // Set the application-wide C-locale. Needed for Date.toLocaleFormat(). michael@0: setlocale(LC_ALL, prefLocale.IsEmpty() ? sSystemLocale : prefLocale.get()); michael@0: // Now override the JavaScript Runtime Locale that is used by the Intl API michael@0: // as well as Date.toLocaleString, Number.toLocaleString, and String.localeCompare. michael@0: JS_SetDefaultLocale(rt, prefLocale.IsEmpty() ? sJSLocale : prefLocale.get()); michael@0: } michael@0: } michael@0: michael@0: static michael@0: void StartWatchingDefaultLocalePref() { michael@0: // Get the default system locale. To be used if pref is not available. michael@0: sSystemLocale = strdup(setlocale(LC_ALL,NULL)); michael@0: // Store the default JavaScript locale. michael@0: JSRuntime* rt = GetRuntime(); michael@0: if (rt) { michael@0: sJSLocale = strdup(JS_GetDefaultLocale(rt)); michael@0: } michael@0: // Now keep the locale updated with the current pref value. michael@0: mozilla::Preferences::RegisterCallbackAndCall(DefaultLocaleChangedCallback, DEFAULT_LOCALE_PREF); michael@0: } michael@0: michael@0: static michael@0: void StopWatchingDefaultLocalePref() { michael@0: mozilla::Preferences::UnregisterCallback(DefaultLocaleChangedCallback, DEFAULT_LOCALE_PREF); michael@0: if (sSystemLocale) free(sSystemLocale); michael@0: if (sJSLocale) JS_free(nullptr, sJSLocale); michael@0: } michael@0: michael@0: } // anonymous namespace for locale pref michael@0: michael@0: EXPORT_XPCOM_API(nsresult) michael@0: NS_InitXPCOM2(nsIServiceManager* *result, michael@0: nsIFile* binDirectory, michael@0: nsIDirectoryServiceProvider* appFileLocationProvider) michael@0: { michael@0: mozPoisonValueInit(); michael@0: michael@0: char aLocal; michael@0: profiler_init(&aLocal); michael@0: nsresult rv = NS_OK; michael@0: michael@0: // We are not shutting down michael@0: gXPCOMShuttingDown = false; michael@0: michael@0: // Initialize the available memory tracker before other threads have had a michael@0: // chance to start up, because the initialization is not thread-safe. michael@0: mozilla::AvailableMemoryTracker::Init(); michael@0: michael@0: #ifdef XP_UNIX michael@0: // Discover the current value of the umask, and save it where michael@0: // nsSystemInfo::Init can retrieve it when necessary. There is no way michael@0: // to read the umask without changing it, and the setting is process- michael@0: // global, so this must be done while we are still single-threaded; the michael@0: // nsSystemInfo object is typically created much later, when some piece michael@0: // of chrome JS wants it. The system call is specified as unable to fail. michael@0: nsSystemInfo::gUserUmask = ::umask(0777); michael@0: ::umask(nsSystemInfo::gUserUmask); michael@0: #endif michael@0: michael@0: NS_LogInit(); michael@0: michael@0: // Set up chromium libs michael@0: NS_ASSERTION(!sExitManager && !sMessageLoop, "Bad logic!"); michael@0: michael@0: if (!AtExitManager::AlreadyRegistered()) { michael@0: sExitManager = new AtExitManager(); michael@0: } michael@0: michael@0: if (!MessageLoop::current()) { michael@0: sMessageLoop = new MessageLoopForUI(MessageLoop::TYPE_MOZILLA_UI); michael@0: sMessageLoop->set_thread_name("Gecko"); michael@0: // Set experimental values for main thread hangs: michael@0: // 512ms for transient hangs and 8192ms for permanent hangs michael@0: sMessageLoop->set_hang_timeouts(512, 8192); michael@0: } michael@0: michael@0: if (XRE_GetProcessType() == GeckoProcessType_Default && michael@0: !BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO)) { michael@0: scoped_ptr ioThread( michael@0: new BrowserProcessSubThread(BrowserProcessSubThread::IO)); michael@0: michael@0: base::Thread::Options options; michael@0: options.message_loop_type = MessageLoop::TYPE_IO; michael@0: if (NS_WARN_IF(!ioThread->StartWithOptions(options))) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: sIOThread = ioThread.release(); michael@0: } michael@0: michael@0: // Establish the main thread here. michael@0: rv = nsThreadManager::get()->Init(); michael@0: if (NS_WARN_IF(NS_FAILED(rv))) michael@0: return rv; michael@0: michael@0: // Set up the timer globals/timer thread michael@0: rv = nsTimerImpl::Startup(); michael@0: if (NS_WARN_IF(NS_FAILED(rv))) michael@0: return rv; michael@0: michael@0: #ifndef ANDROID michael@0: // If the locale hasn't already been setup by our embedder, michael@0: // get us out of the "C" locale and into the system michael@0: if (strcmp(setlocale(LC_ALL, nullptr), "C") == 0) michael@0: setlocale(LC_ALL, ""); michael@0: #endif michael@0: michael@0: #if defined(XP_UNIX) michael@0: NS_StartupNativeCharsetUtils(); michael@0: #endif michael@0: michael@0: NS_StartupLocalFile(); michael@0: michael@0: StartupSpecialSystemDirectory(); michael@0: michael@0: nsDirectoryService::RealInit(); michael@0: michael@0: bool value; michael@0: michael@0: if (binDirectory) michael@0: { michael@0: rv = binDirectory->IsDirectory(&value); michael@0: michael@0: if (NS_SUCCEEDED(rv) && value) { michael@0: nsDirectoryService::gService->Set(NS_XPCOM_INIT_CURRENT_PROCESS_DIR, binDirectory); michael@0: } michael@0: } michael@0: michael@0: if (appFileLocationProvider) { michael@0: rv = nsDirectoryService::gService->RegisterProvider(appFileLocationProvider); michael@0: if (NS_FAILED(rv)) return rv; michael@0: } michael@0: michael@0: nsCOMPtr xpcomLib; michael@0: michael@0: nsDirectoryService::gService->Get(NS_GRE_DIR, michael@0: NS_GET_IID(nsIFile), michael@0: getter_AddRefs(xpcomLib)); michael@0: michael@0: if (xpcomLib) { michael@0: xpcomLib->AppendNative(nsDependentCString(XPCOM_DLL)); michael@0: nsDirectoryService::gService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib); michael@0: } michael@0: michael@0: if (!mozilla::Omnijar::IsInitialized()) { michael@0: mozilla::Omnijar::Init(); michael@0: } michael@0: michael@0: if ((sCommandLineWasInitialized = !CommandLine::IsInitialized())) { michael@0: #ifdef OS_WIN michael@0: CommandLine::Init(0, nullptr); michael@0: #else michael@0: nsCOMPtr binaryFile; michael@0: nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, michael@0: NS_GET_IID(nsIFile), michael@0: getter_AddRefs(binaryFile)); michael@0: if (NS_WARN_IF(!binaryFile)) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: rv = binaryFile->AppendNative(NS_LITERAL_CSTRING("nonexistent-executable")); michael@0: if (NS_WARN_IF(NS_FAILED(rv))) michael@0: return rv; michael@0: michael@0: nsCString binaryPath; michael@0: rv = binaryFile->GetNativePath(binaryPath); michael@0: if (NS_WARN_IF(NS_FAILED(rv))) michael@0: return rv; michael@0: michael@0: static char const *const argv = { strdup(binaryPath.get()) }; michael@0: CommandLine::Init(1, &argv); michael@0: #endif michael@0: } michael@0: michael@0: NS_ASSERTION(nsComponentManagerImpl::gComponentManager == nullptr, "CompMgr not null at init"); michael@0: michael@0: // Create the Component/Service Manager michael@0: nsComponentManagerImpl::gComponentManager = new nsComponentManagerImpl(); michael@0: NS_ADDREF(nsComponentManagerImpl::gComponentManager); michael@0: michael@0: // Global cycle collector initialization. michael@0: if (!nsCycleCollector_init()) { michael@0: return NS_ERROR_UNEXPECTED; michael@0: } michael@0: michael@0: // And start it up for this thread too. michael@0: nsCycleCollector_startup(); michael@0: michael@0: // Register ICU memory functions. This really shouldn't be necessary: the michael@0: // JS engine should do this on its own inside JS_Init, and memory-reporting michael@0: // code should call a JSAPI function to observe ICU memory usage. But we michael@0: // can't define the alloc/free functions in the JS engine, because it can't michael@0: // depend on the XPCOM-based memory reporting goop. So for now, we have michael@0: // this oddness. michael@0: mozilla::SetICUMemoryFunctions(); michael@0: michael@0: // Do the same for libogg. michael@0: ogg_set_mem_functions(OggReporter::CountingMalloc, michael@0: OggReporter::CountingCalloc, michael@0: OggReporter::CountingRealloc, michael@0: OggReporter::CountingFree); michael@0: michael@0: #if defined(MOZ_VPX) && !defined(MOZ_VPX_NO_MEM_REPORTING) michael@0: // And for VPX. michael@0: vpx_mem_set_functions(VPXReporter::CountingMalloc, michael@0: VPXReporter::CountingCalloc, michael@0: VPXReporter::CountingRealloc, michael@0: VPXReporter::CountingFree, michael@0: memcpy, michael@0: memset, michael@0: memmove); michael@0: #endif michael@0: michael@0: #ifdef MOZ_WEBM michael@0: // And for libnestegg. michael@0: nestegg_set_halloc_func(NesteggReporter::CountingRealloc); michael@0: #endif michael@0: michael@0: // Initialize the JS engine. michael@0: if (!JS_Init()) { michael@0: NS_RUNTIMEABORT("JS_Init failed"); michael@0: } michael@0: michael@0: rv = nsComponentManagerImpl::gComponentManager->Init(); michael@0: if (NS_FAILED(rv)) michael@0: { michael@0: NS_RELEASE(nsComponentManagerImpl::gComponentManager); michael@0: return rv; michael@0: } michael@0: michael@0: if (result) { michael@0: NS_ADDREF(*result = nsComponentManagerImpl::gComponentManager); michael@0: } michael@0: michael@0: // The iimanager constructor searches and registers XPT files. michael@0: // (We trigger the singleton's lazy construction here to make that happen.) michael@0: (void) XPTInterfaceInfoManager::GetSingleton(); michael@0: michael@0: // After autoreg, but before we actually instantiate any components, michael@0: // add any services listed in the "xpcom-directory-providers" category michael@0: // to the directory service. michael@0: nsDirectoryService::gService->RegisterCategoryProviders(); michael@0: michael@0: // Force layout to spin up so that nsContentUtils is available for cx stack michael@0: // munging. michael@0: nsCOMPtr componentLoader = do_GetService("@mozilla.org/moz/jsloader;1"); michael@0: michael@0: mozilla::scache::StartupCache::GetSingleton(); michael@0: mozilla::AvailableMemoryTracker::Activate(); michael@0: michael@0: // Notify observers of xpcom autoregistration start michael@0: NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_CATEGORY, michael@0: nullptr, michael@0: NS_XPCOM_STARTUP_OBSERVER_ID); michael@0: #ifdef XP_WIN michael@0: CreateAnonTempFileRemover(); michael@0: #endif michael@0: michael@0: // We only want the SystemMemoryReporter running in one process, because it michael@0: // profiles the entire system. The main process is the obvious place for michael@0: // it. michael@0: if (XRE_GetProcessType() == GeckoProcessType_Default) { michael@0: mozilla::SystemMemoryReporter::Init(); michael@0: } michael@0: michael@0: // The memory reporter manager is up and running -- register our reporters. michael@0: RegisterStrongMemoryReporter(new ICUReporter()); michael@0: RegisterStrongMemoryReporter(new OggReporter()); michael@0: #ifdef MOZ_VPX michael@0: RegisterStrongMemoryReporter(new VPXReporter()); michael@0: #endif michael@0: #ifdef MOZ_WEBM michael@0: RegisterStrongMemoryReporter(new NesteggReporter()); michael@0: #endif michael@0: michael@0: mozilla::Telemetry::Init(); michael@0: michael@0: mozilla::HangMonitor::Startup(); michael@0: mozilla::BackgroundHangMonitor::Startup(); michael@0: michael@0: const MessageLoop* const loop = MessageLoop::current(); michael@0: sMainHangMonitor = new mozilla::BackgroundHangMonitor( michael@0: loop->thread_name().c_str(), michael@0: loop->transient_hang_timeout(), michael@0: loop->permanent_hang_timeout()); michael@0: michael@0: #ifdef MOZ_VISUAL_EVENT_TRACER michael@0: mozilla::eventtracer::Init(); michael@0: #endif michael@0: michael@0: // Start watching the javascript.default_locale pref. michael@0: StartWatchingDefaultLocalePref(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: // michael@0: // NS_ShutdownXPCOM() michael@0: // michael@0: // The shutdown sequence for xpcom would be michael@0: // michael@0: // - Notify "xpcom-shutdown" for modules to release primary (root) references michael@0: // - Shutdown XPCOM timers michael@0: // - Notify "xpcom-shutdown-threads" for thread joins michael@0: // - Shutdown the event queues michael@0: // - Release the Global Service Manager michael@0: // - Release all service instances held by the global service manager michael@0: // - Release the Global Service Manager itself michael@0: // - Release the Component Manager michael@0: // - Release all factories cached by the Component Manager michael@0: // - Notify module loaders to shut down michael@0: // - Unload Libraries michael@0: // - Release Contractid Cache held by Component Manager michael@0: // - Release dll abstraction held by Component Manager michael@0: // - Release the Registry held by Component Manager michael@0: // - Finally, release the component manager itself michael@0: // michael@0: EXPORT_XPCOM_API(nsresult) michael@0: NS_ShutdownXPCOM(nsIServiceManager* servMgr) michael@0: { michael@0: return mozilla::ShutdownXPCOM(servMgr); michael@0: } michael@0: michael@0: namespace mozilla { michael@0: michael@0: void michael@0: SetICUMemoryFunctions() michael@0: { michael@0: static bool sICUReporterInitialized = false; michael@0: if (!sICUReporterInitialized) { michael@0: if (!JS_SetICUMemoryFunctions(ICUReporter::Alloc, ICUReporter::Realloc, michael@0: ICUReporter::Free)) { michael@0: NS_RUNTIMEABORT("JS_SetICUMemoryFunctions failed."); michael@0: } michael@0: sICUReporterInitialized = true; michael@0: } michael@0: } michael@0: michael@0: nsresult michael@0: ShutdownXPCOM(nsIServiceManager* servMgr) michael@0: { michael@0: // Make sure the hang monitor is enabled for shutdown. michael@0: HangMonitor::NotifyActivity(); michael@0: michael@0: if (!NS_IsMainThread()) { michael@0: NS_RUNTIMEABORT("Shutdown on wrong thread"); michael@0: } michael@0: michael@0: nsresult rv; michael@0: nsCOMPtr moduleLoaders; michael@0: michael@0: // Notify observers of xpcom shutting down michael@0: { michael@0: // Block it so that the COMPtr will get deleted before we hit michael@0: // servicemanager shutdown michael@0: michael@0: nsCOMPtr thread = do_GetCurrentThread(); michael@0: if (NS_WARN_IF(!thread)) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: nsRefPtr observerService; michael@0: CallGetService("@mozilla.org/observer-service;1", michael@0: (nsObserverService**) getter_AddRefs(observerService)); michael@0: michael@0: if (observerService) michael@0: { michael@0: (void) observerService-> michael@0: NotifyObservers(nullptr, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID, michael@0: nullptr); michael@0: michael@0: nsCOMPtr mgr; michael@0: rv = NS_GetServiceManager(getter_AddRefs(mgr)); michael@0: if (NS_SUCCEEDED(rv)) michael@0: { michael@0: (void) observerService-> michael@0: NotifyObservers(mgr, NS_XPCOM_SHUTDOWN_OBSERVER_ID, michael@0: nullptr); michael@0: } michael@0: } michael@0: michael@0: // This must happen after the shutdown of media and widgets, which michael@0: // are triggered by the NS_XPCOM_SHUTDOWN_OBSERVER_ID notification. michael@0: layers::ImageBridgeChild::ShutDown(); michael@0: michael@0: NS_ProcessPendingEvents(thread); michael@0: mozilla::scache::StartupCache::DeleteSingleton(); michael@0: if (observerService) michael@0: (void) observerService-> michael@0: NotifyObservers(nullptr, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, michael@0: nullptr); michael@0: michael@0: layers::CompositorParent::ShutDown(); michael@0: michael@0: gXPCOMThreadsShutDown = true; michael@0: NS_ProcessPendingEvents(thread); michael@0: michael@0: // Shutdown the timer thread and all timers that might still be alive before michael@0: // shutting down the component manager michael@0: nsTimerImpl::Shutdown(); michael@0: michael@0: NS_ProcessPendingEvents(thread); michael@0: michael@0: // Shutdown all remaining threads. This method does not return until michael@0: // all threads created using the thread manager (with the exception of michael@0: // the main thread) have exited. michael@0: nsThreadManager::get()->Shutdown(); michael@0: michael@0: NS_ProcessPendingEvents(thread); michael@0: michael@0: HangMonitor::NotifyActivity(); michael@0: michael@0: // Late-write checks needs to find the profile directory, so it has to michael@0: // be initialized before mozilla::services::Shutdown or (because of michael@0: // xpcshell tests replacing the service) modules being unloaded. michael@0: mozilla::InitLateWriteChecks(); michael@0: michael@0: // We save the "xpcom-shutdown-loaders" observers to notify after michael@0: // the observerservice is gone. michael@0: if (observerService) { michael@0: observerService-> michael@0: EnumerateObservers(NS_XPCOM_SHUTDOWN_LOADERS_OBSERVER_ID, michael@0: getter_AddRefs(moduleLoaders)); michael@0: michael@0: observerService->Shutdown(); michael@0: } michael@0: } michael@0: michael@0: // Free ClearOnShutdown()'ed smart pointers. This needs to happen *after* michael@0: // we've finished notifying observers of XPCOM shutdown, because shutdown michael@0: // observers themselves might call ClearOnShutdown(). michael@0: mozilla::KillClearOnShutdown(); michael@0: michael@0: // XPCOM is officially in shutdown mode NOW michael@0: // Set this only after the observers have been notified as this michael@0: // will cause servicemanager to become inaccessible. michael@0: mozilla::services::Shutdown(); michael@0: michael@0: #ifdef DEBUG_dougt michael@0: fprintf(stderr, "* * * * XPCOM shutdown. Access will be denied * * * * \n"); michael@0: #endif michael@0: // We may have AddRef'd for the caller of NS_InitXPCOM, so release it michael@0: // here again: michael@0: NS_IF_RELEASE(servMgr); michael@0: michael@0: // Shutdown global servicemanager michael@0: if (nsComponentManagerImpl::gComponentManager) { michael@0: nsComponentManagerImpl::gComponentManager->FreeServices(); michael@0: } michael@0: michael@0: // Release the directory service michael@0: NS_IF_RELEASE(nsDirectoryService::gService); michael@0: michael@0: if (moduleLoaders) { michael@0: bool more; michael@0: nsCOMPtr el; michael@0: while (NS_SUCCEEDED(moduleLoaders->HasMoreElements(&more)) && michael@0: more) { michael@0: moduleLoaders->GetNext(getter_AddRefs(el)); michael@0: michael@0: // Don't worry about weak-reference observers here: there is michael@0: // no reason for weak-ref observers to register for michael@0: // xpcom-shutdown-loaders michael@0: michael@0: // FIXME: This can cause harmless writes from sqlite committing michael@0: // log files. We have to ignore them before we can move michael@0: // the mozilla::PoisonWrite call before this point. See bug michael@0: // 834945 for the details. michael@0: nsCOMPtr obs(do_QueryInterface(el)); michael@0: if (obs) michael@0: (void) obs->Observe(nullptr, michael@0: NS_XPCOM_SHUTDOWN_LOADERS_OBSERVER_ID, michael@0: nullptr); michael@0: } michael@0: michael@0: moduleLoaders = nullptr; michael@0: } michael@0: michael@0: nsCycleCollector_shutdown(); michael@0: michael@0: PROFILER_MARKER("Shutdown xpcom"); michael@0: // If we are doing any shutdown checks, poison writes. michael@0: if (gShutdownChecks != SCM_NOTHING) { michael@0: #ifdef XP_MACOSX michael@0: mozilla::OnlyReportDirtyWrites(); michael@0: #endif /* XP_MACOSX */ michael@0: mozilla::BeginLateWriteChecks(); michael@0: } michael@0: michael@0: // Shutdown nsLocalFile string conversion michael@0: NS_ShutdownLocalFile(); michael@0: #ifdef XP_UNIX michael@0: NS_ShutdownNativeCharsetUtils(); michael@0: #endif michael@0: michael@0: // Shutdown xpcom. This will release all loaders and cause others holding michael@0: // a refcount to the component manager to release it. michael@0: if (nsComponentManagerImpl::gComponentManager) { michael@0: rv = (nsComponentManagerImpl::gComponentManager)->Shutdown(); michael@0: NS_ASSERTION(NS_SUCCEEDED(rv), "Component Manager shutdown failed."); michael@0: } else { michael@0: NS_WARNING("Component Manager was never created ..."); michael@0: } michael@0: michael@0: #ifdef MOZ_ENABLE_PROFILER_SPS michael@0: // In optimized builds we don't do shutdown collections by default, so michael@0: // uncollected (garbage) objects may keep the nsXPConnect singleton alive, michael@0: // and its XPCJSRuntime along with it. However, we still destroy various michael@0: // bits of state in JS_ShutDown(), so we need to make sure the profiler michael@0: // can't access them when it shuts down. This call nulls out the michael@0: // JS pseudo-stack's internal reference to the main thread JSRuntime, michael@0: // duplicating the call in XPCJSRuntime::~XPCJSRuntime() in case that michael@0: // never fired. michael@0: if (PseudoStack *stack = mozilla_get_pseudo_stack()) { michael@0: stack->sampleRuntime(nullptr); michael@0: } michael@0: #endif michael@0: michael@0: // Shut down the JS engine. michael@0: JS_ShutDown(); michael@0: michael@0: // Release our own singletons michael@0: // Do this _after_ shutting down the component manager, because the michael@0: // JS component loader will use XPConnect to call nsIModule::canUnload, michael@0: // and that will spin up the InterfaceInfoManager again -- bad mojo michael@0: XPTInterfaceInfoManager::FreeInterfaceInfoManager(); michael@0: michael@0: // Finally, release the component manager last because it unloads the michael@0: // libraries: michael@0: if (nsComponentManagerImpl::gComponentManager) { michael@0: nsrefcnt cnt; michael@0: NS_RELEASE2(nsComponentManagerImpl::gComponentManager, cnt); michael@0: NS_ASSERTION(cnt == 0, "Component Manager being held past XPCOM shutdown."); michael@0: } michael@0: nsComponentManagerImpl::gComponentManager = nullptr; michael@0: nsCategoryManager::Destroy(); michael@0: michael@0: NS_PurgeAtomTable(); michael@0: michael@0: NS_IF_RELEASE(gDebug); michael@0: michael@0: if (sIOThread) { michael@0: delete sIOThread; michael@0: sIOThread = nullptr; michael@0: } michael@0: if (sMessageLoop) { michael@0: delete sMessageLoop; michael@0: sMessageLoop = nullptr; michael@0: } michael@0: if (sCommandLineWasInitialized) { michael@0: CommandLine::Terminate(); michael@0: sCommandLineWasInitialized = false; michael@0: } michael@0: if (sExitManager) { michael@0: delete sExitManager; michael@0: sExitManager = nullptr; michael@0: } michael@0: michael@0: StopWatchingDefaultLocalePref(); michael@0: michael@0: Omnijar::CleanUp(); michael@0: michael@0: HangMonitor::Shutdown(); michael@0: michael@0: if (sMainHangMonitor) { michael@0: delete sMainHangMonitor; michael@0: sMainHangMonitor = nullptr; michael@0: } michael@0: BackgroundHangMonitor::Shutdown(); michael@0: michael@0: #ifdef MOZ_VISUAL_EVENT_TRACER michael@0: eventtracer::Shutdown(); michael@0: #endif michael@0: michael@0: profiler_shutdown(); michael@0: michael@0: NS_LogTerm(); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: } // namespace mozilla