1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "base/basictypes.h"
8 
9 #include "mozilla/AbstractThread.h"
10 #include "mozilla/Atomics.h"
11 #include "mozilla/Poison.h"
12 #include "mozilla/SharedThreadPool.h"
13 #include "mozilla/XPCOM.h"
14 #include "nsXULAppAPI.h"
15 
16 #include "nsXPCOMPrivate.h"
17 #include "nsXPCOMCIDInternal.h"
18 
19 #include "mozilla/layers/ImageBridgeChild.h"
20 #include "mozilla/layers/CompositorBridgeParent.h"
21 #include "mozilla/dom/VideoDecoderManagerChild.h"
22 
23 #include "prlink.h"
24 
25 #include "nsCycleCollector.h"
26 #include "nsObserverList.h"
27 #include "nsObserverService.h"
28 #include "nsProperties.h"
29 #include "nsPersistentProperties.h"
30 #include "nsScriptableInputStream.h"
31 #include "nsBinaryStream.h"
32 #include "nsStorageStream.h"
33 #include "nsPipe.h"
34 #include "nsScriptableBase64Encoder.h"
35 
36 #include "nsMemoryImpl.h"
37 #include "nsDebugImpl.h"
38 #include "nsTraceRefcnt.h"
39 #include "nsErrorService.h"
40 
41 // Disable deprecation warnings generated by nsISupportsArray and associated
42 // classes.
43 #if defined(__GNUC__)
44 #pragma GCC diagnostic push
45 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
46 #elif defined(_MSC_VER)
47 #pragma warning (push)
48 #pragma warning (disable : 4996)
49 #endif
50 
51 #include "nsSupportsArray.h"
52 
53 #if defined(__GNUC__)
54 #pragma GCC diagnostic pop
55 #elif defined(_MSC_VER)
56 #pragma warning (pop)
57 #endif
58 
59 #include "nsArray.h"
60 #include "nsINIParserImpl.h"
61 #include "nsSupportsPrimitives.h"
62 #include "nsConsoleService.h"
63 
64 #include "nsComponentManager.h"
65 #include "nsCategoryManagerUtils.h"
plot()66 #include "nsIServiceManager.h"
67 
68 #include "nsThreadManager.h"
69 #include "nsThreadPool.h"
70 
71 #include "xptinfo.h"
72 #include "nsIInterfaceInfoManager.h"
73 #include "xptiprivate.h"
74 #include "mozilla/XPTInterfaceInfoManager.h"
75 
76 #include "nsTimerImpl.h"
77 #include "TimerThread.h"
78 
79 #include "nsThread.h"
80 #include "nsProcess.h"
81 #include "nsEnvironment.h"
82 #include "nsVersionComparatorImpl.h"
83 
84 #include "nsIFile.h"
85 #include "nsLocalFile.h"
86 #if defined(XP_UNIX)
87 #include "nsNativeCharsetUtils.h"
88 #endif
89 #include "nsDirectoryService.h"
90 #include "nsDirectoryServiceDefs.h"
91 #include "nsCategoryManager.h"
92 #include "nsICategoryManager.h"
93 #include "nsMultiplexInputStream.h"
94 
95 #include "nsStringStream.h"
96 extern nsresult nsStringInputStreamConstructor(nsISupports*, REFNSIID, void**);
97 
98 #include "nsAtomService.h"
99 #include "nsAtomTable.h"
100 #include "nsISupportsImpl.h"
101 
102 #include "nsHashPropertyBag.h"
103 
104 #include "nsUnicharInputStream.h"
105 #include "nsVariant.h"
106 
107 #include "nsUUIDGenerator.h"
108 
109 #include "nsIOUtil.h"
110 
111 #include "SpecialSystemDirectory.h"
112 
113 #if defined(XP_WIN)
114 #include "mozilla/WindowsVersion.h"
115 #include "nsWindowsRegKey.h"
116 #endif
117 
118 #ifdef MOZ_WIDGET_COCOA
119 #include "nsMacUtilsImpl.h"
120 #endif
121 
122 #include "nsSystemInfo.h"
123 #include "nsMemoryReporterManager.h"
124 #include "nsMemoryInfoDumper.h"
125 #include "nsSecurityConsoleMessage.h"
126 #include "nsMessageLoop.h"
127 
128 #include "nsStatusReporterManager.h"
129 
130 #include <locale.h>
131 #include "mozilla/Services.h"
132 #include "mozilla/Omnijar.h"
133 #include "mozilla/HangMonitor.h"
134 #include "mozilla/Telemetry.h"
135 #include "mozilla/BackgroundHangMonitor.h"
136 
137 #include "nsChromeRegistry.h"
138 #include "nsChromeProtocolHandler.h"
139 #include "mozilla/PoisonIOInterposer.h"
140 #include "mozilla/LateWriteChecks.h"
141 
142 #include "mozilla/scache/StartupCache.h"
143 
144 #include "base/at_exit.h"
145 #include "base/command_line.h"
146 #include "base/message_loop.h"
147 
148 #include "mozilla/ipc/BrowserProcessSubThread.h"
149 #include "mozilla/AvailableMemoryTracker.h"
150 #include "mozilla/ClearOnShutdown.h"
151 #include "mozilla/CountingAllocatorBase.h"
152 #include "mozilla/SystemMemoryReporter.h"
153 #include "mozilla/UniquePtr.h"
154 
155 #include "mozilla/ipc/GeckoChildProcessHost.h"
156 
157 #ifndef MOZ_OGG_NO_MEM_REPORTING
158 #include "ogg/ogg.h"
159 #endif
160 #if defined(MOZ_VPX) && !defined(MOZ_VPX_NO_MEM_REPORTING)
161 #if defined(HAVE_STDINT_H)
162 // mozilla-config.h defines HAVE_STDINT_H, and then it's defined *again* in
163 // vpx_config.h (which we include via vpx_mem.h, below). This redefinition
164 // triggers a build warning on MSVC, so we have to #undef it first.
165 #undef HAVE_STDINT_H
166 #endif
167 #include "vpx_mem/vpx_mem.h"
168 #endif
169 
170 #include "GeckoProfiler.h"
171 
172 #include "jsapi.h"
173 #include "js/Initialization.h"
174 
175 #include "gfxPlatform.h"
176 
177 #if EXPOSE_INTL_API
178 #include "unicode/putil.h"
179 #endif
180 
181 using namespace mozilla;
182 using base::AtExitManager;
183 using mozilla::ipc::BrowserProcessSubThread;
184 
185 namespace {
186 
187 static AtExitManager* sExitManager;
188 static MessageLoop* sMessageLoop;
189 static bool sCommandLineWasInitialized;
190 static BrowserProcessSubThread* sIOThread;
191 static BackgroundHangMonitor* sMainHangMonitor;
192 
193 } /* anonymous namespace */
194 
195 // Registry Factory creation function defined in nsRegistry.cpp
196 // We hook into this function locally to create and register the registry
197 // Since noone outside xpcom needs to know about this and nsRegistry.cpp
198 // does not have a local include file, we are putting this definition
199 // here rather than in nsIRegistry.h
200 extern nsresult NS_RegistryGetFactory(nsIFactory** aFactory);
201 extern nsresult NS_CategoryManagerGetFactory(nsIFactory**);
202 
203 #ifdef XP_WIN
204 extern nsresult CreateAnonTempFileRemover();
205 #endif
206 
207 NS_GENERIC_FACTORY_CONSTRUCTOR(nsProcess)
208 
209 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsID)
210 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsString)
211 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsCString)
212 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRBool)
213 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint8)
214 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint16)
215 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint32)
216 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint64)
217 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRTime)
218 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsChar)
219 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt16)
220 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt32)
221 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt64)
222 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsFloat)
223 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsDouble)
224 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsVoid)
225 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsInterfacePointer)
226 
227 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsConsoleService, Init)
228 NS_GENERIC_FACTORY_CONSTRUCTOR(nsAtomService)
229 NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimer)
230 NS_GENERIC_FACTORY_CONSTRUCTOR(nsBinaryOutputStream)
231 NS_GENERIC_FACTORY_CONSTRUCTOR(nsBinaryInputStream)
232 NS_GENERIC_FACTORY_CONSTRUCTOR(nsStorageStream)
233 NS_GENERIC_FACTORY_CONSTRUCTOR(nsVersionComparatorImpl)
234 NS_GENERIC_FACTORY_CONSTRUCTOR(nsScriptableBase64Encoder)
235 
236 NS_GENERIC_FACTORY_CONSTRUCTOR(nsVariantCC)
237 
238 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHashPropertyBagCC)
239 
240 NS_GENERIC_AGGREGATED_CONSTRUCTOR(nsProperties)
241 
242 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsUUIDGenerator, Init)
243 
244 #ifdef MOZ_WIDGET_COCOA
245 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacUtilsImpl)
246 #endif
247 
248 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemInfo, Init)
249 
250 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMemoryReporterManager, Init)
251 
252 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMemoryInfoDumper)
253 
254 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStatusReporterManager, Init)
255 
256 NS_GENERIC_FACTORY_CONSTRUCTOR(nsIOUtil)
257 
258 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSecurityConsoleMessage)
259 
260 static nsresult
261 nsThreadManagerGetSingleton(nsISupports* aOuter,
262                             const nsIID& aIID,
263                             void** aInstancePtr)
264 {
265   NS_ASSERTION(aInstancePtr, "null outptr");
266   if (NS_WARN_IF(aOuter)) {
267     return NS_ERROR_NO_AGGREGATION;
268   }
269 
270   return nsThreadManager::get().QueryInterface(aIID, aInstancePtr);
271 }
272 
273 NS_GENERIC_FACTORY_CONSTRUCTOR(nsThreadPool)
274 
275 static nsresult
276 nsXPTIInterfaceInfoManagerGetSingleton(nsISupports* aOuter,
277                                        const nsIID& aIID,
278                                        void** aInstancePtr)
279 {
280   NS_ASSERTION(aInstancePtr, "null outptr");
281   if (NS_WARN_IF(aOuter)) {
282     return NS_ERROR_NO_AGGREGATION;
283   }
284 
285   nsCOMPtr<nsIInterfaceInfoManager> iim(XPTInterfaceInfoManager::GetSingleton());
286   if (!iim) {
287     return NS_ERROR_FAILURE;
288   }
289 
290   return iim->QueryInterface(aIID, aInstancePtr);
291 }
292 
293 nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = nullptr;
294 bool gXPCOMShuttingDown = false;
295 bool gXPCOMThreadsShutDown = false;
296 char16_t* gGREBinPath = nullptr;
297 
298 static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
299 static NS_DEFINE_CID(kINIParserFactoryCID, NS_INIPARSERFACTORY_CID);
300 
301 NS_DEFINE_NAMED_CID(NS_CHROMEREGISTRY_CID);
302 NS_DEFINE_NAMED_CID(NS_CHROMEPROTOCOLHANDLER_CID);
303 
304 NS_DEFINE_NAMED_CID(NS_SECURITY_CONSOLE_MESSAGE_CID);
305 
306 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsChromeRegistry,
307                                          nsChromeRegistry::GetSingleton)
308 NS_GENERIC_FACTORY_CONSTRUCTOR(nsChromeProtocolHandler)
309 
310 #define NS_PERSISTENTPROPERTIES_CID NS_IPERSISTENTPROPERTIES_CID /* sigh */
311 
312 static already_AddRefed<nsIFactory>
313 CreateINIParserFactory(const mozilla::Module& aModule,
314                        const mozilla::Module::CIDEntry& aEntry)
315 {
316   nsCOMPtr<nsIFactory> f = new nsINIParserFactory();
317   return f.forget();
318 }
319 
320 #define COMPONENT(NAME, Ctor) static NS_DEFINE_CID(kNS_##NAME##_CID, NS_##NAME##_CID);
321 #define COMPONENT_M(NAME, Ctor, Selector) static NS_DEFINE_CID(kNS_##NAME##_CID, NS_##NAME##_CID);
322 #include "XPCOMModule.inc"
323 #undef COMPONENT
324 #undef COMPONENT_M
325 
326 #define COMPONENT(NAME, Ctor) { &kNS_##NAME##_CID, false, nullptr, Ctor },
327 #define COMPONENT_M(NAME, Ctor, Selector) { &kNS_##NAME##_CID, false, nullptr, Ctor, Selector },
328 const mozilla::Module::CIDEntry kXPCOMCIDEntries[] = {
329   { &kComponentManagerCID, true, nullptr, nsComponentManagerImpl::Create, Module::ALLOW_IN_GPU_PROCESS },
330   { &kINIParserFactoryCID, false, CreateINIParserFactory },
331 #include "XPCOMModule.inc"
332   { &kNS_CHROMEREGISTRY_CID, false, nullptr, nsChromeRegistryConstructor },
333   { &kNS_CHROMEPROTOCOLHANDLER_CID, false, nullptr, nsChromeProtocolHandlerConstructor },
334   { &kNS_SECURITY_CONSOLE_MESSAGE_CID, false, nullptr, nsSecurityConsoleMessageConstructor },
335   { nullptr }
336 };
337 #undef COMPONENT
338 #undef COMPONENT_M
339 
340 #define COMPONENT(NAME, Ctor) { NS_##NAME##_CONTRACTID, &kNS_##NAME##_CID },
341 #define COMPONENT_M(NAME, Ctor, Selector) { NS_##NAME##_CONTRACTID, &kNS_##NAME##_CID, Selector },
342 const mozilla::Module::ContractIDEntry kXPCOMContracts[] = {
343 #include "XPCOMModule.inc"
344   { NS_CHROMEREGISTRY_CONTRACTID, &kNS_CHROMEREGISTRY_CID },
345   { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "chrome", &kNS_CHROMEPROTOCOLHANDLER_CID },
346   { NS_INIPARSERFACTORY_CONTRACTID, &kINIParserFactoryCID },
347   { NS_SECURITY_CONSOLE_MESSAGE_CONTRACTID, &kNS_SECURITY_CONSOLE_MESSAGE_CID },
348   { nullptr }
349 };
350 #undef COMPONENT
351 #undef COMPONENT_M
352 
353 const mozilla::Module kXPCOMModule = {
354   mozilla::Module::kVersion, kXPCOMCIDEntries, kXPCOMContracts,
355   nullptr,
356   nullptr,
357   nullptr,
358   nullptr,
359   Module::ALLOW_IN_GPU_PROCESS
360 };
361 
362 // gDebug will be freed during shutdown.
363 static nsIDebug2* gDebug = nullptr;
364 
365 EXPORT_XPCOM_API(nsresult)
366 NS_GetDebug(nsIDebug2** aResult)
367 {
368   return nsDebugImpl::Create(nullptr,  NS_GET_IID(nsIDebug2), (void**)aResult);
369 }
370 
371 EXPORT_XPCOM_API(nsresult)
372 NS_InitXPCOM(nsIServiceManager** aResult,
373              nsIFile* aBinDirectory)
374 {
375   return NS_InitXPCOM2(aResult, aBinDirectory, nullptr);
376 }
377 
378 class ICUReporter final
379   : public nsIMemoryReporter
380   , public CountingAllocatorBase<ICUReporter>
381 {
382 public:
383   NS_DECL_ISUPPORTS
384 
385   static void* Alloc(const void*, size_t aSize)
386   {
387     return CountingMalloc(aSize);
388   }
389 
390   static void* Realloc(const void*, void* aPtr, size_t aSize)
391   {
392     return CountingRealloc(aPtr, aSize);
393   }
394 
395   static void Free(const void*, void* aPtr)
396   {
397     return CountingFree(aPtr);
398   }
399 
400 private:
401   NS_IMETHOD
402   CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
403                  bool aAnonymize) override
404   {
405     MOZ_COLLECT_REPORT(
406       "explicit/icu", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
407       "Memory used by ICU, a Unicode and globalization support library.");
408 
409     return NS_OK;
410   }
411 
412   ~ICUReporter() {}
413 };
414 
415 NS_IMPL_ISUPPORTS(ICUReporter, nsIMemoryReporter)
416 
417 /* static */ template<> Atomic<size_t>
418 CountingAllocatorBase<ICUReporter>::sAmount(0);
419 
420 class OggReporter final
421   : public nsIMemoryReporter
422   , public CountingAllocatorBase<OggReporter>
423 {
424 public:
425   NS_DECL_ISUPPORTS
426 
427 private:
428   NS_IMETHOD
429   CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
430                  bool aAnonymize) override
431   {
432     MOZ_COLLECT_REPORT(
433       "explicit/media/libogg", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
434       "Memory allocated through libogg for Ogg, Theora, and related media "
435       "files.");
436 
437     return NS_OK;
438   }
439 
440   ~OggReporter() {}
441 };
442 
443 NS_IMPL_ISUPPORTS(OggReporter, nsIMemoryReporter)
444 
445 /* static */ template<> Atomic<size_t>
446 CountingAllocatorBase<OggReporter>::sAmount(0);
447 
448 #ifdef MOZ_VPX
449 class VPXReporter final
450   : public nsIMemoryReporter
451   , public CountingAllocatorBase<VPXReporter>
452 {
453 public:
454   NS_DECL_ISUPPORTS
455 
456 private:
457   NS_IMETHOD
458   CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
459                  bool aAnonymize) override
460   {
461     MOZ_COLLECT_REPORT(
462       "explicit/media/libvpx", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
463       "Memory allocated through libvpx for WebM media files.");
464 
465     return NS_OK;
466   }
467 
468   ~VPXReporter() {}
469 };
470 
471 NS_IMPL_ISUPPORTS(VPXReporter, nsIMemoryReporter)
472 
473 /* static */ template<> Atomic<size_t>
474 CountingAllocatorBase<VPXReporter>::sAmount(0);
475 #endif /* MOZ_VPX */
476 
477 static double
478 TimeSinceProcessCreation()
479 {
480   bool ignore;
481   return (TimeStamp::Now() - TimeStamp::ProcessCreation(ignore)).ToMilliseconds();
482 }
483 
484 static bool sInitializedJS = false;
485 
486 // Note that on OSX, aBinDirectory will point to .app/Contents/Resources/browser
487 EXPORT_XPCOM_API(nsresult)
488 NS_InitXPCOM2(nsIServiceManager** aResult,
489               nsIFile* aBinDirectory,
490               nsIDirectoryServiceProvider* aAppFileLocationProvider)
491 {
492   static bool sInitialized = false;
493   if (sInitialized) {
494     return NS_ERROR_FAILURE;
495   }
496 
497   sInitialized = true;
498 
499   mozPoisonValueInit();
500 
501   NS_LogInit();
502 
503   NS_InitAtomTable();
504 
505   mozilla::LogModule::Init();
506 
507   JS_SetCurrentEmbedderTimeFunction(TimeSinceProcessCreation);
508 
509   char aLocal;
510   profiler_init(&aLocal);
511   nsresult rv = NS_OK;
512 
513   // We are not shutting down
514   gXPCOMShuttingDown = false;
515 
516   // Initialize the available memory tracker before other threads have had a
517   // chance to start up, because the initialization is not thread-safe.
518   mozilla::AvailableMemoryTracker::Init();
519 
520 #ifdef XP_UNIX
521   // Discover the current value of the umask, and save it where
522   // nsSystemInfo::Init can retrieve it when necessary.  There is no way
523   // to read the umask without changing it, and the setting is process-
524   // global, so this must be done while we are still single-threaded; the
525   // nsSystemInfo object is typically created much later, when some piece
526   // of chrome JS wants it.  The system call is specified as unable to fail.
527   nsSystemInfo::gUserUmask = ::umask(0777);
528   ::umask(nsSystemInfo::gUserUmask);
529 #endif
530 
531   // Set up chromium libs
532   NS_ASSERTION(!sExitManager && !sMessageLoop, "Bad logic!");
533 
534   if (!AtExitManager::AlreadyRegistered()) {
535     sExitManager = new AtExitManager();
536   }
537 
538   MessageLoop* messageLoop = MessageLoop::current();
539   if (!messageLoop) {
540     sMessageLoop = new MessageLoopForUI(MessageLoop::TYPE_MOZILLA_PARENT);
541     sMessageLoop->set_thread_name("Gecko");
542     // Set experimental values for main thread hangs:
543     // 128ms for transient hangs and 8192ms for permanent hangs
544     sMessageLoop->set_hang_timeouts(128, 8192);
545   } else if (messageLoop->type() == MessageLoop::TYPE_MOZILLA_CHILD) {
546     messageLoop->set_thread_name("Gecko_Child");
547     messageLoop->set_hang_timeouts(128, 8192);
548   }
549 
550   if (XRE_IsParentProcess() &&
551       !BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO)) {
552     UniquePtr<BrowserProcessSubThread> ioThread = MakeUnique<BrowserProcessSubThread>(BrowserProcessSubThread::IO);
553 
554     base::Thread::Options options;
555     options.message_loop_type = MessageLoop::TYPE_IO;
556     if (NS_WARN_IF(!ioThread->StartWithOptions(options))) {
557       return NS_ERROR_FAILURE;
558     }
559 
560     sIOThread = ioThread.release();
561   }
562 
563   // Establish the main thread here.
564   rv = nsThreadManager::get().Init();
565   if (NS_WARN_IF(NS_FAILED(rv))) {
566     return rv;
567   }
568 
569   // Set up the timer globals/timer thread
570   rv = nsTimerImpl::Startup();
571   if (NS_WARN_IF(NS_FAILED(rv))) {
572     return rv;
573   }
574 
575 #ifndef ANDROID
576   // If the locale hasn't already been setup by our embedder,
577   // get us out of the "C" locale and into the system
578   if (strcmp(setlocale(LC_ALL, nullptr), "C") == 0) {
579     setlocale(LC_ALL, "");
580   }
581 #endif
582 
583 #if defined(XP_UNIX)
584   NS_StartupNativeCharsetUtils();
585 #endif
586 
587   NS_StartupLocalFile();
588 
589   StartupSpecialSystemDirectory();
590 
591   nsDirectoryService::RealInit();
592 
593   bool value;
594 
595   if (aBinDirectory) {
596     rv = aBinDirectory->IsDirectory(&value);
597 
598     if (NS_SUCCEEDED(rv) && value) {
599       nsDirectoryService::gService->Set(NS_XPCOM_INIT_CURRENT_PROCESS_DIR,
600                                         aBinDirectory);
601     }
602   }
603 
604   if (aAppFileLocationProvider) {
605     rv = nsDirectoryService::gService->RegisterProvider(aAppFileLocationProvider);
606     if (NS_FAILED(rv)) {
607       return rv;
608     }
609   }
610 
611   nsCOMPtr<nsIFile> xpcomLib;
612   nsDirectoryService::gService->Get(NS_GRE_BIN_DIR,
613                                     NS_GET_IID(nsIFile),
614                                     getter_AddRefs(xpcomLib));
615   MOZ_ASSERT(xpcomLib);
616 
617   // set gGREBinPath
618   nsAutoString path;
619   xpcomLib->GetPath(path);
620   gGREBinPath = ToNewUnicode(path);
621 
622   xpcomLib->AppendNative(nsDependentCString(XPCOM_DLL));
623   nsDirectoryService::gService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib);
624 
625   if (!mozilla::Omnijar::IsInitialized()) {
626     mozilla::Omnijar::Init();
627   }
628 
629   if ((sCommandLineWasInitialized = !CommandLine::IsInitialized())) {
630 #ifdef OS_WIN
631     CommandLine::Init(0, nullptr);
632 #else
633     nsCOMPtr<nsIFile> binaryFile;
634     nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
635                                       NS_GET_IID(nsIFile),
636                                       getter_AddRefs(binaryFile));
637     if (NS_WARN_IF(!binaryFile)) {
638       return NS_ERROR_FAILURE;
639     }
640 
641     rv = binaryFile->AppendNative(NS_LITERAL_CSTRING("nonexistent-executable"));
642     if (NS_WARN_IF(NS_FAILED(rv))) {
643       return rv;
644     }
645 
646     nsCString binaryPath;
647     rv = binaryFile->GetNativePath(binaryPath);
648     if (NS_WARN_IF(NS_FAILED(rv))) {
649       return rv;
650     }
651 
652     static char const* const argv = { strdup(binaryPath.get()) };
653     CommandLine::Init(1, &argv);
654 #endif
655   }
656 
657   NS_ASSERTION(nsComponentManagerImpl::gComponentManager == nullptr,
658                "CompMgr not null at init");
659 
660   // Create the Component/Service Manager
661   nsComponentManagerImpl::gComponentManager = new nsComponentManagerImpl();
662   NS_ADDREF(nsComponentManagerImpl::gComponentManager);
663 
664   // Global cycle collector initialization.
665   if (!nsCycleCollector_init()) {
666     return NS_ERROR_UNEXPECTED;
667   }
668 
669   // And start it up for this thread too.
670   nsCycleCollector_startup();
671 
672   // Register ICU memory functions.  This really shouldn't be necessary: the
673   // JS engine should do this on its own inside JS_Init, and memory-reporting
674   // code should call a JSAPI function to observe ICU memory usage.  But we
675   // can't define the alloc/free functions in the JS engine, because it can't
676   // depend on the XPCOM-based memory reporting goop.  So for now, we have
677   // this oddness.
678   mozilla::SetICUMemoryFunctions();
679 
680 #ifndef MOZ_OGG_NO_MEM_REPORTING
681   // Do the same for libogg.
682   ogg_set_mem_functions(OggReporter::CountingMalloc,
683                         OggReporter::CountingCalloc,
684                         OggReporter::CountingRealloc,
685                         OggReporter::CountingFree);
686 #endif
687 
688 #if defined(MOZ_VPX) && !defined(MOZ_VPX_NO_MEM_REPORTING)
689   // And for VPX.
690   vpx_mem_set_functions(VPXReporter::CountingMalloc,
691                         VPXReporter::CountingCalloc,
692                         VPXReporter::CountingRealloc,
693                         VPXReporter::CountingFree,
694                         memcpy,
695                         memset,
696                         memmove);
697 #endif
698 
699 #if EXPOSE_INTL_API && defined(MOZ_ICU_DATA_ARCHIVE)
700   nsCOMPtr<nsIFile> greDir;
701   nsDirectoryService::gService->Get(NS_GRE_DIR,
702                                     NS_GET_IID(nsIFile),
703                                     getter_AddRefs(greDir));
704   MOZ_ASSERT(greDir);
705   nsAutoCString nativeGREPath;
706   greDir->GetNativePath(nativeGREPath);
707   u_setDataDirectory(nativeGREPath.get());
708 #endif
709 
710   // Initialize the JS engine.
711   const char* jsInitFailureReason = JS_InitWithFailureDiagnostic();
712   if (jsInitFailureReason) {
713     NS_RUNTIMEABORT(jsInitFailureReason);
714   }
715   sInitializedJS = true;
716 
717   // Init AbstractThread.
718   AbstractThread::InitStatics();
719 
720   rv = nsComponentManagerImpl::gComponentManager->Init();
721   if (NS_FAILED(rv)) {
722     NS_RELEASE(nsComponentManagerImpl::gComponentManager);
723     return rv;
724   }
725 
726   if (aResult) {
727     NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager);
728   }
729 
730   // The iimanager constructor searches and registers XPT files.
731   // (We trigger the singleton's lazy construction here to make that happen.)
732   (void)XPTInterfaceInfoManager::GetSingleton();
733 
734   // After autoreg, but before we actually instantiate any components,
735   // add any services listed in the "xpcom-directory-providers" category
736   // to the directory service.
737   nsDirectoryService::gService->RegisterCategoryProviders();
738 
739   // Init SharedThreadPool (which needs the service manager).
740   SharedThreadPool::InitStatics();
741 
742   // Force layout to spin up so that nsContentUtils is available for cx stack
743   // munging.  Note that layout registers a number of static atoms, and also
744   // seals the static atom table, so NS_RegisterStaticAtom may not be called
745   // beyond this point.
746   nsCOMPtr<nsISupports> componentLoader =
747     do_GetService("@mozilla.org/moz/jsloader;1");
748 
749   mozilla::scache::StartupCache::GetSingleton();
750   mozilla::AvailableMemoryTracker::Activate();
751 
752   // Notify observers of xpcom autoregistration start
753   NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_CATEGORY,
754                                 nullptr,
755                                 NS_XPCOM_STARTUP_OBSERVER_ID);
756 #ifdef XP_WIN
757   CreateAnonTempFileRemover();
758 #endif
759 
760   // We only want the SystemMemoryReporter running in one process, because it
761   // profiles the entire system.  The main process is the obvious place for
762   // it.
763   if (XRE_IsParentProcess()) {
764     mozilla::SystemMemoryReporter::Init();
765   }
766 
767   // The memory reporter manager is up and running -- register our reporters.
768   RegisterStrongMemoryReporter(new ICUReporter());
769   RegisterStrongMemoryReporter(new OggReporter());
770 #ifdef MOZ_VPX
771   RegisterStrongMemoryReporter(new VPXReporter());
772 #endif
773 
774   mozilla::Telemetry::Init();
775 
776   mozilla::HangMonitor::Startup();
777   mozilla::BackgroundHangMonitor::Startup();
778 
779   const MessageLoop* const loop = MessageLoop::current();
780   sMainHangMonitor = new mozilla::BackgroundHangMonitor(
781     loop->thread_name().c_str(),
782     loop->transient_hang_timeout(),
783     loop->permanent_hang_timeout());
784 
785   return NS_OK;
786 }
787 
788 EXPORT_XPCOM_API(nsresult)
789 NS_InitMinimalXPCOM()
790 {
791   mozPoisonValueInit();
792   NS_SetMainThread();
793   mozilla::TimeStamp::Startup();
794   NS_LogInit();
795   NS_InitAtomTable();
796   mozilla::LogModule::Init();
797 
798   char aLocal;
799   profiler_init(&aLocal);
800 
801   nsresult rv = nsThreadManager::get().Init();
802   if (NS_WARN_IF(NS_FAILED(rv))) {
803     return rv;
804   }
805 
806   // Set up the timer globals/timer thread.
807   rv = nsTimerImpl::Startup();
808   if (NS_WARN_IF(NS_FAILED(rv))) {
809     return rv;
810   }
811 
812   // Create the Component/Service Manager
813   nsComponentManagerImpl::gComponentManager = new nsComponentManagerImpl();
814   NS_ADDREF(nsComponentManagerImpl::gComponentManager);
815 
816   rv = nsComponentManagerImpl::gComponentManager->Init();
817   if (NS_FAILED(rv)) {
818     NS_RELEASE(nsComponentManagerImpl::gComponentManager);
819     return rv;
820   }
821 
822   // Global cycle collector initialization.
823   if (!nsCycleCollector_init()) {
824     return NS_ERROR_UNEXPECTED;
825   }
826 
827   AbstractThread::InitStatics();
828   SharedThreadPool::InitStatics();
829   mozilla::Telemetry::Init();
830   mozilla::HangMonitor::Startup();
831   mozilla::BackgroundHangMonitor::Startup();
832 
833   return NS_OK;
834 }
835 
836 //
837 // NS_ShutdownXPCOM()
838 //
839 // The shutdown sequence for xpcom would be
840 //
841 // - Notify "xpcom-shutdown" for modules to release primary (root) references
842 // - Shutdown XPCOM timers
843 // - Notify "xpcom-shutdown-threads" for thread joins
844 // - Shutdown the event queues
845 // - Release the Global Service Manager
846 //   - Release all service instances held by the global service manager
847 //   - Release the Global Service Manager itself
848 // - Release the Component Manager
849 //   - Release all factories cached by the Component Manager
850 //   - Notify module loaders to shut down
851 //   - Unload Libraries
852 //   - Release Contractid Cache held by Component Manager
853 //   - Release dll abstraction held by Component Manager
854 //   - Release the Registry held by Component Manager
855 //   - Finally, release the component manager itself
856 //
857 EXPORT_XPCOM_API(nsresult)
858 NS_ShutdownXPCOM(nsIServiceManager* aServMgr)
859 {
860   return mozilla::ShutdownXPCOM(aServMgr);
861 }
862 
863 namespace mozilla {
864 
865 void
866 SetICUMemoryFunctions()
867 {
868   static bool sICUReporterInitialized = false;
869   if (!sICUReporterInitialized) {
870     if (!JS_SetICUMemoryFunctions(ICUReporter::Alloc, ICUReporter::Realloc,
871                                   ICUReporter::Free)) {
872       NS_RUNTIMEABORT("JS_SetICUMemoryFunctions failed.");
873     }
874     sICUReporterInitialized = true;
875   }
876 }
877 
878 nsresult
879 ShutdownXPCOM(nsIServiceManager* aServMgr)
880 {
881   // Make sure the hang monitor is enabled for shutdown.
882   HangMonitor::NotifyActivity();
883 
884   if (!NS_IsMainThread()) {
885     NS_RUNTIMEABORT("Shutdown on wrong thread");
886   }
887 
888   nsresult rv;
889   nsCOMPtr<nsISimpleEnumerator> moduleLoaders;
890 
891   // Notify observers of xpcom shutting down
892   {
893     // Block it so that the COMPtr will get deleted before we hit
894     // servicemanager shutdown
895 
896     nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
897     if (NS_WARN_IF(!thread)) {
898       return NS_ERROR_UNEXPECTED;
899     }
900 
901     RefPtr<nsObserverService> observerService;
902     CallGetService("@mozilla.org/observer-service;1",
903                    (nsObserverService**)getter_AddRefs(observerService));
904 
905     if (observerService) {
906       mozilla::KillClearOnShutdown(ShutdownPhase::WillShutdown);
907       observerService->NotifyObservers(nullptr,
908                                        NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID,
909                                        nullptr);
910 
911       nsCOMPtr<nsIServiceManager> mgr;
912       rv = NS_GetServiceManager(getter_AddRefs(mgr));
913       if (NS_SUCCEEDED(rv)) {
914         mozilla::KillClearOnShutdown(ShutdownPhase::Shutdown);
915         observerService->NotifyObservers(mgr, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
916                                          nullptr);
917       }
918     }
919 
920     // This must happen after the shutdown of media and widgets, which
921     // are triggered by the NS_XPCOM_SHUTDOWN_OBSERVER_ID notification.
922     NS_ProcessPendingEvents(thread);
923     gfxPlatform::ShutdownLayersIPC();
924     mozilla::dom::VideoDecoderManagerChild::Shutdown();
925 
926     mozilla::scache::StartupCache::DeleteSingleton();
927     if (observerService)
928     {
929       mozilla::KillClearOnShutdown(ShutdownPhase::ShutdownThreads);
930       observerService->NotifyObservers(nullptr,
931                                        NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID,
932                                        nullptr);
933     }
934 
935     gXPCOMThreadsShutDown = true;
936     NS_ProcessPendingEvents(thread);
937 
938     // Shutdown the timer thread and all timers that might still be alive before
939     // shutting down the component manager
940     nsTimerImpl::Shutdown();
941 
942     NS_ProcessPendingEvents(thread);
943 
944     // Shutdown all remaining threads.  This method does not return until
945     // all threads created using the thread manager (with the exception of
946     // the main thread) have exited.
947     nsThreadManager::get().Shutdown();
948 
949     NS_ProcessPendingEvents(thread);
950 
951     HangMonitor::NotifyActivity();
952 
953     // Late-write checks needs to find the profile directory, so it has to
954     // be initialized before mozilla::services::Shutdown or (because of
955     // xpcshell tests replacing the service) modules being unloaded.
956     mozilla::InitLateWriteChecks();
957 
958     // We save the "xpcom-shutdown-loaders" observers to notify after
959     // the observerservice is gone.
960     if (observerService) {
961       mozilla::KillClearOnShutdown(ShutdownPhase::ShutdownLoaders);
962       observerService->EnumerateObservers(NS_XPCOM_SHUTDOWN_LOADERS_OBSERVER_ID,
963                                           getter_AddRefs(moduleLoaders));
964 
965       observerService->Shutdown();
966     }
967   }
968 
969   // Free ClearOnShutdown()'ed smart pointers.  This needs to happen *after*
970   // we've finished notifying observers of XPCOM shutdown, because shutdown
971   // observers themselves might call ClearOnShutdown().
972   mozilla::KillClearOnShutdown(ShutdownPhase::ShutdownFinal);
973 
974   // XPCOM is officially in shutdown mode NOW
975   // Set this only after the observers have been notified as this
976   // will cause servicemanager to become inaccessible.
977   mozilla::services::Shutdown();
978 
979   // We may have AddRef'd for the caller of NS_InitXPCOM, so release it
980   // here again:
981   NS_IF_RELEASE(aServMgr);
982 
983   // Shutdown global servicemanager
984   if (nsComponentManagerImpl::gComponentManager) {
985     nsComponentManagerImpl::gComponentManager->FreeServices();
986   }
987 
988   // Release the directory service
989   nsDirectoryService::gService = nullptr;
990 
991   free(gGREBinPath);
992   gGREBinPath = nullptr;
993 
994   if (moduleLoaders) {
995     bool more;
996     nsCOMPtr<nsISupports> el;
997     while (NS_SUCCEEDED(moduleLoaders->HasMoreElements(&more)) && more) {
998       moduleLoaders->GetNext(getter_AddRefs(el));
999 
1000       // Don't worry about weak-reference observers here: there is
1001       // no reason for weak-ref observers to register for
1002       // xpcom-shutdown-loaders
1003 
1004       // FIXME: This can cause harmless writes from sqlite committing
1005       // log files. We have to ignore them before we can move
1006       // the mozilla::PoisonWrite call before this point. See bug
1007       // 834945 for the details.
1008       nsCOMPtr<nsIObserver> obs(do_QueryInterface(el));
1009       if (obs) {
1010         obs->Observe(nullptr, NS_XPCOM_SHUTDOWN_LOADERS_OBSERVER_ID, nullptr);
1011       }
1012     }
1013 
1014     moduleLoaders = nullptr;
1015   }
1016 
1017   bool shutdownCollect;
1018 #ifdef NS_FREE_PERMANENT_DATA
1019   shutdownCollect = true;
1020 #else
1021   shutdownCollect = !!PR_GetEnv("MOZ_CC_RUN_DURING_SHUTDOWN");
1022 #endif
1023   nsCycleCollector_shutdown(shutdownCollect);
1024 
1025   PROFILER_MARKER("Shutdown xpcom");
1026   // If we are doing any shutdown checks, poison writes.
1027   if (gShutdownChecks != SCM_NOTHING) {
1028 #ifdef XP_MACOSX
1029     mozilla::OnlyReportDirtyWrites();
1030 #endif /* XP_MACOSX */
1031     mozilla::BeginLateWriteChecks();
1032   }
1033 
1034   // Shutdown nsLocalFile string conversion
1035   NS_ShutdownLocalFile();
1036 #ifdef XP_UNIX
1037   NS_ShutdownNativeCharsetUtils();
1038 #endif
1039 
1040   // Shutdown xpcom. This will release all loaders and cause others holding
1041   // a refcount to the component manager to release it.
1042   if (nsComponentManagerImpl::gComponentManager) {
1043     rv = (nsComponentManagerImpl::gComponentManager)->Shutdown();
1044     NS_ASSERTION(NS_SUCCEEDED(rv), "Component Manager shutdown failed.");
1045   } else {
1046     NS_WARNING("Component Manager was never created ...");
1047   }
1048 
1049 #ifdef MOZ_ENABLE_PROFILER_SPS
1050   // In optimized builds we don't do shutdown collections by default, so
1051   // uncollected (garbage) objects may keep the nsXPConnect singleton alive,
1052   // and its XPCJSContext along with it. However, we still destroy various
1053   // bits of state in JS_ShutDown(), so we need to make sure the profiler
1054   // can't access them when it shuts down. This call nulls out the
1055   // JS pseudo-stack's internal reference to the main thread JSContext,
1056   // duplicating the call in XPCJSContext::~XPCJSContext() in case that
1057   // never fired.
1058   if (PseudoStack* stack = mozilla_get_pseudo_stack()) {
1059     stack->sampleContext(nullptr);
1060   }
1061 #endif
1062 
1063   if (sInitializedJS) {
1064     // Shut down the JS engine.
1065     JS_ShutDown();
1066     sInitializedJS = false;
1067   }
1068 
1069   // Release our own singletons
1070   // Do this _after_ shutting down the component manager, because the
1071   // JS component loader will use XPConnect to call nsIModule::canUnload,
1072   // and that will spin up the InterfaceInfoManager again -- bad mojo
1073   XPTInterfaceInfoManager::FreeInterfaceInfoManager();
1074 
1075   // Finally, release the component manager last because it unloads the
1076   // libraries:
1077   if (nsComponentManagerImpl::gComponentManager) {
1078     nsrefcnt cnt;
1079     NS_RELEASE2(nsComponentManagerImpl::gComponentManager, cnt);
1080     NS_ASSERTION(cnt == 0, "Component Manager being held past XPCOM shutdown.");
1081   }
1082   nsComponentManagerImpl::gComponentManager = nullptr;
1083   nsCategoryManager::Destroy();
1084 
1085   NS_ShutdownAtomTable();
1086 
1087   NS_IF_RELEASE(gDebug);
1088 
1089   delete sIOThread;
1090   sIOThread = nullptr;
1091 
1092   delete sMessageLoop;
1093   sMessageLoop = nullptr;
1094 
1095   if (sCommandLineWasInitialized) {
1096     CommandLine::Terminate();
1097     sCommandLineWasInitialized = false;
1098   }
1099 
1100   delete sExitManager;
1101   sExitManager = nullptr;
1102 
1103   Omnijar::CleanUp();
1104 
1105   HangMonitor::Shutdown();
1106 
1107   delete sMainHangMonitor;
1108   sMainHangMonitor = nullptr;
1109 
1110   BackgroundHangMonitor::Shutdown();
1111 
1112   profiler_shutdown();
1113 
1114   NS_LogTerm();
1115 
1116 #if defined(MOZ_WIDGET_GONK)
1117   // This _exit(0) call is intended to be temporary, to get shutdown leak
1118   // checking working on non-B2G platforms.
1119   // On debug B2G, the child process crashes very late.  Instead, just
1120   // give up so at least we exit cleanly. See bug 1071866.
1121   if (XRE_IsContentProcess()) {
1122       NS_WARNING("Exiting child process early!");
1123       _exit(0);
1124   }
1125 #endif
1126 
1127   return NS_OK;
1128 }
1129 
1130 } // namespace mozilla
1131