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