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