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