Bug 1606739 - Initialize the .dynamic section first. r=froydnj
[gecko.git] / xpcom / components / nsComponentManager.cpp
bloba28087b3f0890170b2b5aa6ebd5b61f9431b6503
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/. */
7 #include <stdlib.h>
8 #include "nscore.h"
9 #include "nsISupports.h"
10 #include "nspr.h"
11 #include "nsCRT.h" // for atoll
13 #include "StaticComponents.h"
15 #include "nsCategoryManager.h"
16 #include "nsCOMPtr.h"
17 #include "nsComponentManager.h"
18 #include "nsDirectoryService.h"
19 #include "nsDirectoryServiceDefs.h"
20 #include "nsCategoryManager.h"
21 #include "nsCategoryManagerUtils.h"
22 #include "nsLayoutModule.h"
23 #include "mozilla/MemoryReporting.h"
24 #include "nsIObserverService.h"
25 #include "nsIStringEnumerator.h"
26 #include "nsXPCOM.h"
27 #include "nsXPCOMPrivate.h"
28 #include "nsISupportsPrimitives.h"
29 #include "nsLocalFile.h"
30 #include "nsReadableUtils.h"
31 #include "nsString.h"
32 #include "prcmon.h"
33 #include "nsThreadManager.h"
34 #include "nsThreadUtils.h"
35 #include "prthread.h"
36 #include "private/pprthred.h"
37 #include "nsTArray.h"
38 #include "prio.h"
39 #include "ManifestParser.h"
40 #include "nsNetUtil.h"
41 #include "mozilla/Services.h"
42 #include "mozJSComponentLoader.h"
44 #include "mozilla/GenericFactory.h"
45 #include "nsSupportsPrimitives.h"
46 #include "nsArray.h"
47 #include "nsIMutableArray.h"
48 #include "mozilla/DebugOnly.h"
49 #include "mozilla/FileUtils.h"
50 #include "mozilla/ScopeExit.h"
51 #include "mozilla/URLPreloader.h"
52 #include "mozilla/UniquePtr.h"
53 #include "mozilla/Variant.h"
54 #include "nsDataHashtable.h"
56 #include <new> // for placement new
58 #include "mozilla/Omnijar.h"
60 #include "mozilla/Logging.h"
61 #include "LogModulePrefWatcher.h"
63 #ifdef MOZ_MEMORY
64 # include "mozmemory.h"
65 #endif
67 using namespace mozilla;
68 using namespace mozilla::xpcom;
70 static LazyLogModule nsComponentManagerLog("nsComponentManager");
72 #if 0
73 # define SHOW_DENIED_ON_SHUTDOWN
74 # define SHOW_CI_ON_EXISTING_SERVICE
75 #endif
77 NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID);
79 nsresult nsGetServiceFromCategory::operator()(const nsIID& aIID,
80 void** aInstancePtr) const {
81 nsresult rv;
82 nsCString value;
83 nsCOMPtr<nsICategoryManager> catman;
84 nsComponentManagerImpl* compMgr = nsComponentManagerImpl::gComponentManager;
85 if (!compMgr) {
86 rv = NS_ERROR_NOT_INITIALIZED;
87 goto error;
90 rv = compMgr->nsComponentManagerImpl::GetService(
91 kCategoryManagerCID, NS_GET_IID(nsICategoryManager),
92 getter_AddRefs(catman));
93 if (NS_FAILED(rv)) {
94 goto error;
97 /* find the contractID for category.entry */
98 rv = catman->GetCategoryEntry(mCategory, mEntry, value);
99 if (NS_FAILED(rv)) {
100 goto error;
102 if (value.IsVoid()) {
103 rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
104 goto error;
107 rv = compMgr->nsComponentManagerImpl::GetServiceByContractID(
108 value.get(), aIID, aInstancePtr);
109 if (NS_FAILED(rv)) {
110 error:
111 *aInstancePtr = 0;
113 if (mErrorPtr) {
114 *mErrorPtr = rv;
116 return rv;
119 namespace {
121 class AutoIDString : public nsAutoCStringN<NSID_LENGTH> {
122 public:
123 explicit AutoIDString(const nsID& aID) {
124 SetLength(NSID_LENGTH - 1);
125 aID.ToProvidedString(
126 *reinterpret_cast<char(*)[NSID_LENGTH]>(BeginWriting()));
130 } // namespace
132 namespace mozilla {
133 namespace xpcom {
135 using ProcessSelector = Module::ProcessSelector;
137 // Note: These must be kept in sync with the ProcessSelector definition in
138 // Module.h.
139 bool ProcessSelectorMatches(ProcessSelector aSelector) {
140 GeckoProcessType type = XRE_GetProcessType();
141 if (type == GeckoProcessType_GPU) {
142 return !!(aSelector & Module::ALLOW_IN_GPU_PROCESS);
145 if (type == GeckoProcessType_RDD) {
146 return !!(aSelector & Module::ALLOW_IN_RDD_PROCESS);
149 if (type == GeckoProcessType_Socket) {
150 return !!(aSelector & (Module::ALLOW_IN_SOCKET_PROCESS));
153 if (type == GeckoProcessType_VR) {
154 return !!(aSelector & Module::ALLOW_IN_VR_PROCESS);
157 if (aSelector & Module::MAIN_PROCESS_ONLY) {
158 return type == GeckoProcessType_Default;
160 if (aSelector & Module::CONTENT_PROCESS_ONLY) {
161 return type == GeckoProcessType_Content;
163 return true;
166 static bool gProcessMatchTable[Module::kMaxProcessSelector + 1];
168 bool FastProcessSelectorMatches(ProcessSelector aSelector) {
169 return gProcessMatchTable[size_t(aSelector)];
172 } // namespace xpcom
173 } // namespace mozilla
175 namespace {
178 * A wrapper simple wrapper class, which can hold either a dynamic
179 * nsFactoryEntry instance, or a static StaticModule entry, and transparently
180 * forwards method calls to the wrapped object.
182 * This allows the same code to work with either static or dynamic modules
183 * without caring about the difference.
185 class MOZ_STACK_CLASS EntryWrapper final {
186 public:
187 explicit EntryWrapper(nsFactoryEntry* aEntry) : mEntry(aEntry) {}
189 explicit EntryWrapper(const StaticModule* aEntry) : mEntry(aEntry) {}
191 #define MATCH(type, ifFactory, ifStatic) \
192 struct Matcher { \
193 type operator()(nsFactoryEntry* entry) { ifFactory; } \
194 type operator()(const StaticModule* entry) { ifStatic; } \
195 }; \
196 return mEntry.match((Matcher()))
198 const nsID& CID() {
199 MATCH(const nsID&, return *entry->mCIDEntry->cid, return entry->CID());
202 already_AddRefed<nsIFactory> GetFactory() {
203 MATCH(already_AddRefed<nsIFactory>, return entry->GetFactory(),
204 return entry->GetFactory());
208 * Creates an instance of the underlying component. This should be used in
209 * preference to GetFactory()->CreateInstance() where appropriate, since it
210 * side-steps the necessity of creating a nsIFactory instance for static
211 * modules.
213 nsresult CreateInstance(nsISupports* aOuter, const nsIID& aIID,
214 void** aResult) {
215 if (mEntry.is<nsFactoryEntry*>()) {
216 return mEntry.as<nsFactoryEntry*>()->CreateInstance(aOuter, aIID,
217 aResult);
219 return mEntry.as<const StaticModule*>()->CreateInstance(aOuter, aIID,
220 aResult);
224 * Returns the cached service instance for this entry, if any. This should
225 * only be accessed while mLock is held.
227 nsISupports* ServiceInstance() {
228 MATCH(nsISupports*, return entry->mServiceObject,
229 return entry->ServiceInstance());
231 void SetServiceInstance(already_AddRefed<nsISupports> aInst) {
232 if (mEntry.is<nsFactoryEntry*>()) {
233 mEntry.as<nsFactoryEntry*>()->mServiceObject = aInst;
234 } else {
235 return mEntry.as<const StaticModule*>()->SetServiceInstance(
236 std::move(aInst));
241 * Returns the description string for the module this entry belongs to. For
242 * static entries, always returns "<unknown module>".
244 nsCString ModuleDescription() {
245 MATCH(nsCString,
246 return entry->mModule ? entry->mModule->Description()
247 : NS_LITERAL_CSTRING("<unknown module>"),
248 return NS_LITERAL_CSTRING("<unknown module>"));
251 private:
252 Variant<nsFactoryEntry*, const StaticModule*> mEntry;
255 // GetService and a few other functions need to exit their mutex mid-function
256 // without reentering it later in the block. This class supports that
257 // style of early-exit that MutexAutoUnlock doesn't.
259 class MOZ_STACK_CLASS MutexLock {
260 public:
261 explicit MutexLock(SafeMutex& aMutex) : mMutex(aMutex), mLocked(false) {
262 Lock();
265 ~MutexLock() {
266 if (mLocked) {
267 Unlock();
271 void Lock() {
272 NS_ASSERTION(!mLocked, "Re-entering a mutex");
273 mMutex.Lock();
274 mLocked = true;
277 void Unlock() {
278 NS_ASSERTION(mLocked, "Exiting a mutex that isn't held!");
279 mMutex.Unlock();
280 mLocked = false;
283 private:
284 SafeMutex& mMutex;
285 bool mLocked;
288 } // namespace
290 // this is safe to call during InitXPCOM
291 static already_AddRefed<nsIFile> GetLocationFromDirectoryService(
292 const char* aProp) {
293 nsCOMPtr<nsIProperties> directoryService;
294 nsDirectoryService::Create(nullptr, NS_GET_IID(nsIProperties),
295 getter_AddRefs(directoryService));
297 if (!directoryService) {
298 return nullptr;
301 nsCOMPtr<nsIFile> file;
302 nsresult rv =
303 directoryService->Get(aProp, NS_GET_IID(nsIFile), getter_AddRefs(file));
304 if (NS_FAILED(rv)) {
305 return nullptr;
308 return file.forget();
311 static already_AddRefed<nsIFile> CloneAndAppend(nsIFile* aBase,
312 const nsACString& aAppend) {
313 nsCOMPtr<nsIFile> f;
314 aBase->Clone(getter_AddRefs(f));
315 if (!f) {
316 return nullptr;
319 f->AppendNative(aAppend);
320 return f.forget();
323 ////////////////////////////////////////////////////////////////////////////////
324 // nsComponentManagerImpl
325 ////////////////////////////////////////////////////////////////////////////////
327 nsresult nsComponentManagerImpl::Create(nsISupports* aOuter, REFNSIID aIID,
328 void** aResult) {
329 if (aOuter) {
330 return NS_ERROR_NO_AGGREGATION;
333 if (!gComponentManager) {
334 return NS_ERROR_FAILURE;
337 return gComponentManager->QueryInterface(aIID, aResult);
340 static const int CONTRACTID_HASHTABLE_INITIAL_LENGTH = 32;
342 nsComponentManagerImpl::nsComponentManagerImpl()
343 : mFactories(CONTRACTID_HASHTABLE_INITIAL_LENGTH),
344 mContractIDs(CONTRACTID_HASHTABLE_INITIAL_LENGTH),
345 mLock("nsComponentManagerImpl.mLock"),
346 mStatus(NOT_INITIALIZED) {}
348 extern const mozilla::Module kNeckoModule;
349 extern const mozilla::Module kPowerManagerModule;
350 extern const mozilla::Module kContentProcessWidgetModule;
351 #if defined(MOZ_WIDGET_COCOA) || defined(MOZ_WIDGET_UIKIT)
352 extern const mozilla::Module kWidgetModule;
353 #endif
354 extern const mozilla::Module kLayoutModule;
355 extern const mozilla::Module kKeyValueModule;
356 extern const mozilla::Module kXREModule;
357 extern const mozilla::Module kEmbeddingModule;
359 static nsTArray<const mozilla::Module*>* sExtraStaticModules;
361 /* static */
362 void nsComponentManagerImpl::InitializeStaticModules() {
363 if (sExtraStaticModules) {
364 return;
367 sExtraStaticModules = new nsTArray<const mozilla::Module*>;
370 nsTArray<nsComponentManagerImpl::ComponentLocation>*
371 nsComponentManagerImpl::sModuleLocations;
373 /* static */
374 void nsComponentManagerImpl::InitializeModuleLocations() {
375 if (sModuleLocations) {
376 return;
379 sModuleLocations = new nsTArray<ComponentLocation>;
382 nsresult nsComponentManagerImpl::Init() {
384 gProcessMatchTable[size_t(ProcessSelector::ANY_PROCESS)] =
385 ProcessSelectorMatches(ProcessSelector::ANY_PROCESS);
386 gProcessMatchTable[size_t(ProcessSelector::MAIN_PROCESS_ONLY)] =
387 ProcessSelectorMatches(ProcessSelector::MAIN_PROCESS_ONLY);
388 gProcessMatchTable[size_t(ProcessSelector::CONTENT_PROCESS_ONLY)] =
389 ProcessSelectorMatches(ProcessSelector::CONTENT_PROCESS_ONLY);
390 gProcessMatchTable[size_t(ProcessSelector::ALLOW_IN_GPU_PROCESS)] =
391 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_PROCESS);
392 gProcessMatchTable[size_t(ProcessSelector::ALLOW_IN_VR_PROCESS)] =
393 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_VR_PROCESS);
394 gProcessMatchTable[size_t(ProcessSelector::ALLOW_IN_SOCKET_PROCESS)] =
395 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_SOCKET_PROCESS);
396 gProcessMatchTable[size_t(ProcessSelector::ALLOW_IN_RDD_PROCESS)] =
397 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_RDD_PROCESS);
398 gProcessMatchTable[size_t(ProcessSelector::ALLOW_IN_GPU_AND_VR_PROCESS)] =
399 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_AND_VR_PROCESS);
400 gProcessMatchTable[size_t(
401 ProcessSelector::ALLOW_IN_GPU_AND_SOCKET_PROCESS)] =
402 ProcessSelectorMatches(
403 ProcessSelector::ALLOW_IN_GPU_AND_SOCKET_PROCESS);
404 gProcessMatchTable[size_t(
405 ProcessSelector::ALLOW_IN_GPU_VR_AND_SOCKET_PROCESS)] =
406 ProcessSelectorMatches(
407 ProcessSelector::ALLOW_IN_GPU_VR_AND_SOCKET_PROCESS);
408 gProcessMatchTable[size_t(
409 ProcessSelector::ALLOW_IN_RDD_AND_SOCKET_PROCESS)] =
410 ProcessSelectorMatches(
411 ProcessSelector::ALLOW_IN_RDD_AND_SOCKET_PROCESS);
412 gProcessMatchTable[size_t(
413 ProcessSelector::ALLOW_IN_GPU_RDD_AND_SOCKET_PROCESS)] =
414 ProcessSelectorMatches(
415 ProcessSelector::ALLOW_IN_GPU_RDD_AND_SOCKET_PROCESS);
416 gProcessMatchTable[size_t(
417 ProcessSelector::ALLOW_IN_GPU_RDD_VR_AND_SOCKET_PROCESS)] =
418 ProcessSelectorMatches(
419 ProcessSelector::ALLOW_IN_GPU_RDD_VR_AND_SOCKET_PROCESS);
422 MOZ_ASSERT(NOT_INITIALIZED == mStatus);
424 nsCOMPtr<nsIFile> greDir = GetLocationFromDirectoryService(NS_GRE_DIR);
425 nsCOMPtr<nsIFile> appDir =
426 GetLocationFromDirectoryService(NS_XPCOM_CURRENT_PROCESS_DIR);
428 InitializeStaticModules();
430 nsCategoryManager::GetSingleton()->SuppressNotifications(true);
432 RegisterModule(&kXPCOMModule);
433 RegisterModule(&kNeckoModule);
434 RegisterModule(&kPowerManagerModule);
435 RegisterModule(&kContentProcessWidgetModule);
436 #if defined(MOZ_WIDGET_COCOA) || defined(MOZ_WIDGET_UIKIT)
437 RegisterModule(&kWidgetModule);
438 #endif
439 RegisterModule(&kLayoutModule);
440 RegisterModule(&kKeyValueModule);
441 RegisterModule(&kXREModule);
442 RegisterModule(&kEmbeddingModule);
444 for (uint32_t i = 0; i < sExtraStaticModules->Length(); ++i) {
445 RegisterModule((*sExtraStaticModules)[i]);
448 auto* catMan = nsCategoryManager::GetSingleton();
449 for (const auto& cat : gStaticCategories) {
450 for (const auto& entry : cat) {
451 if (entry.Active()) {
452 catMan->AddCategoryEntry(cat.Name(), entry.Entry(), entry.Value());
457 bool loadChromeManifests;
458 switch (XRE_GetProcessType()) {
459 // We are going to assume that only a select few (see below) process types
460 // want to load chrome manifests, and that any new process types will not
461 // want to load them, because they're not going to be executing JS.
462 case GeckoProcessType_RemoteSandboxBroker:
463 default:
464 loadChromeManifests = false;
465 break;
467 // XXX The check this code replaced implicitly let through all of these
468 // process types, but presumably only the default (parent) and content
469 // processes really need chrome manifests...?
470 case GeckoProcessType_Default:
471 case GeckoProcessType_Plugin:
472 case GeckoProcessType_Content:
473 case GeckoProcessType_IPDLUnitTest:
474 case GeckoProcessType_GMPlugin:
475 loadChromeManifests = true;
476 break;
479 if (loadChromeManifests) {
480 // This needs to be called very early, before anything in nsLayoutModule is
481 // used, and before any calls are made into the JS engine.
482 nsLayoutModuleInitialize();
484 mJSLoaderReady = true;
486 // The overall order in which chrome.manifests are expected to be treated
487 // is the following:
488 // - greDir's omni.ja or greDir
489 // - appDir's omni.ja or appDir
491 InitializeModuleLocations();
492 ComponentLocation* cl = sModuleLocations->AppendElement();
493 cl->type = NS_APP_LOCATION;
494 RefPtr<nsZipArchive> greOmnijar =
495 mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
496 if (greOmnijar) {
497 cl->location.Init(greOmnijar, "chrome.manifest");
498 } else {
499 nsCOMPtr<nsIFile> lf =
500 CloneAndAppend(greDir, NS_LITERAL_CSTRING("chrome.manifest"));
501 cl->location.Init(lf);
504 RefPtr<nsZipArchive> appOmnijar =
505 mozilla::Omnijar::GetReader(mozilla::Omnijar::APP);
506 if (appOmnijar) {
507 cl = sModuleLocations->AppendElement();
508 cl->type = NS_APP_LOCATION;
509 cl->location.Init(appOmnijar, "chrome.manifest");
510 } else {
511 bool equals = false;
512 appDir->Equals(greDir, &equals);
513 if (!equals) {
514 cl = sModuleLocations->AppendElement();
515 cl->type = NS_APP_LOCATION;
516 nsCOMPtr<nsIFile> lf =
517 CloneAndAppend(appDir, NS_LITERAL_CSTRING("chrome.manifest"));
518 cl->location.Init(lf);
522 RereadChromeManifests(false);
525 nsCategoryManager::GetSingleton()->SuppressNotifications(false);
527 RegisterWeakMemoryReporter(this);
529 // NB: The logging preference watcher needs to be registered late enough in
530 // startup that it's okay to use the preference system, but also as soon as
531 // possible so that log modules enabled via preferences are turned on as
532 // early as possible.
534 // We can't initialize the preference watcher when the log module manager is
535 // initialized, as a number of things attempt to start logging before the
536 // preference system is initialized.
538 // The preference system is registered as a component so at this point during
539 // component manager initialization we know it is setup and we can register
540 // for notifications.
541 LogModulePrefWatcher::RegisterPrefWatcher();
543 // Unfortunately, we can't register the nsCategoryManager memory reporter
544 // in its constructor (which is triggered by the GetSingleton() call
545 // above) because the memory reporter manager isn't initialized at that
546 // point. So we wait until now.
547 nsCategoryManager::GetSingleton()->InitMemoryReporter();
549 MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
550 ("nsComponentManager: Initialized."));
552 mStatus = NORMAL;
554 MOZ_ASSERT(!XRE_IsContentProcess() ||
555 mFactories.Count() > CONTRACTID_HASHTABLE_INITIAL_LENGTH / 3,
556 "Initial component hashtable size is too large");
558 return NS_OK;
561 static const int kModuleVersionWithSelector = 51;
563 template <typename T>
564 static void AssertNotMallocAllocated(T* aPtr) {
565 #if defined(DEBUG) && defined(MOZ_MEMORY)
566 jemalloc_ptr_info_t info;
567 jemalloc_ptr_info((void*)aPtr, &info);
568 MOZ_ASSERT(info.tag == TagUnknown);
569 #endif
572 template <typename T>
573 static void AssertNotStackAllocated(T* aPtr) {
574 // On all of our supported platforms, the stack grows down. Any address
575 // located below the address of our argument is therefore guaranteed not to be
576 // stack-allocated by the caller.
578 // For addresses above our argument, things get trickier. The main thread
579 // stack is traditionally placed at the top of the program's address space,
580 // but that is becoming less reliable as more and more systems adopt address
581 // space layout randomization strategies, so we have to guess how much space
582 // above our argument pointer we need to care about.
584 // On most systems, we're guaranteed at least several KiB at the top of each
585 // stack for TLS. We'd probably be safe assuming at least 4KiB in the stack
586 // segment above our argument address, but safer is... well, safer.
588 // For threads with huge stacks, it's theoretically possible that we could
589 // wind up being passed a stack-allocated string from farther up the stack,
590 // but this is a best-effort thing, so we'll assume we only care about the
591 // immediate caller. For that case, max 2KiB per stack frame is probably a
592 // reasonable guess most of the time, and is less than the ~4KiB that we
593 // expect for TLS, so go with that to avoid the risk of bumping into heap
594 // data just above the stack.
595 #ifdef DEBUG
596 static constexpr size_t kFuzz = 2048;
598 MOZ_ASSERT(uintptr_t(aPtr) < uintptr_t(&aPtr) ||
599 uintptr_t(aPtr) > uintptr_t(&aPtr) + kFuzz);
600 #endif
603 static inline nsCString AsLiteralCString(const char* aStr) {
604 AssertNotMallocAllocated(aStr);
605 AssertNotStackAllocated(aStr);
607 nsCString str;
608 str.AssignLiteral(aStr, strlen(aStr));
609 return str;
612 void nsComponentManagerImpl::RegisterModule(const mozilla::Module* aModule) {
613 mLock.AssertNotCurrentThreadOwns();
615 if (aModule->mVersion >= kModuleVersionWithSelector &&
616 !ProcessSelectorMatches(aModule->selector)) {
617 return;
621 // Scope the monitor so that we don't hold it while calling into the
622 // category manager.
623 MutexLock lock(mLock);
625 KnownModule* m = new KnownModule(aModule);
626 mKnownStaticModules.AppendElement(m);
628 if (aModule->mCIDs) {
629 const mozilla::Module::CIDEntry* entry;
630 for (entry = aModule->mCIDs; entry->cid; ++entry) {
631 RegisterCIDEntryLocked(entry, m);
635 if (aModule->mContractIDs) {
636 const mozilla::Module::ContractIDEntry* entry;
637 for (entry = aModule->mContractIDs; entry->contractid; ++entry) {
638 RegisterContractIDLocked(entry);
640 MOZ_ASSERT(!entry->cid, "Incorrectly terminated contract list");
644 if (aModule->mCategoryEntries) {
645 const mozilla::Module::CategoryEntry* entry;
646 for (entry = aModule->mCategoryEntries; entry->category; ++entry)
647 nsCategoryManager::GetSingleton()->AddCategoryEntry(
648 AsLiteralCString(entry->category), AsLiteralCString(entry->entry),
649 AsLiteralCString(entry->value));
653 void nsComponentManagerImpl::RegisterCIDEntryLocked(
654 const mozilla::Module::CIDEntry* aEntry, KnownModule* aModule) {
655 mLock.AssertCurrentThreadOwns();
657 if (!ProcessSelectorMatches(aEntry->processSelector)) {
658 return;
661 #ifdef DEBUG
662 // If we're still in the static initialization phase, check that we're not
663 // registering something that was already registered.
664 if (mStatus != NORMAL) {
665 if (StaticComponents::LookupByCID(*aEntry->cid)) {
666 MOZ_CRASH_UNSAFE_PRINTF(
667 "While registering XPCOM module %s, trying to re-register CID '%s' "
668 "already registered by a static component.",
669 aModule->Description().get(), AutoIDString(*aEntry->cid).get());
672 #endif
674 if (auto entry = mFactories.LookupForAdd(aEntry->cid)) {
675 nsFactoryEntry* f = entry.Data();
676 NS_WARNING("Re-registering a CID?");
678 nsCString existing;
679 if (f->mModule) {
680 existing = f->mModule->Description();
681 } else {
682 existing = "<unknown module>";
684 SafeMutexAutoUnlock unlock(mLock);
685 LogMessage(
686 "While registering XPCOM module %s, trying to re-register CID '%s' "
687 "already registered by %s.",
688 aModule->Description().get(), AutoIDString(*aEntry->cid).get(),
689 existing.get());
690 } else {
691 entry.OrInsert(
692 [aEntry, aModule]() { return new nsFactoryEntry(aEntry, aModule); });
696 void nsComponentManagerImpl::RegisterContractIDLocked(
697 const mozilla::Module::ContractIDEntry* aEntry) {
698 mLock.AssertCurrentThreadOwns();
700 if (!ProcessSelectorMatches(aEntry->processSelector)) {
701 return;
704 #ifdef DEBUG
705 // If we're still in the static initialization phase, check that we're not
706 // registering something that was already registered.
707 if (mStatus != NORMAL) {
708 if (const StaticModule* module = StaticComponents::LookupByContractID(
709 nsAutoCString(aEntry->contractid))) {
710 MOZ_CRASH_UNSAFE_PRINTF(
711 "Could not map contract ID '%s' to CID %s because it is already "
712 "mapped to CID %s.",
713 aEntry->contractid, AutoIDString(*aEntry->cid).get(),
714 AutoIDString(module->CID()).get());
717 #endif
719 nsFactoryEntry* f = mFactories.Get(aEntry->cid);
720 if (!f) {
721 NS_WARNING("No CID found when attempting to map contract ID");
723 SafeMutexAutoUnlock unlock(mLock);
724 LogMessage(
725 "Could not map contract ID '%s' to CID %s because no implementation of "
726 "the CID is registered.",
727 aEntry->contractid, AutoIDString(*aEntry->cid).get());
729 return;
732 mContractIDs.Put(AsLiteralCString(aEntry->contractid), f);
735 static void CutExtension(nsCString& aPath) {
736 int32_t dotPos = aPath.RFindChar('.');
737 if (kNotFound == dotPos) {
738 aPath.Truncate();
739 } else {
740 aPath.Cut(0, dotPos + 1);
744 static void DoRegisterManifest(NSLocationType aType, FileLocation& aFile,
745 bool aChromeOnly) {
746 auto result = URLPreloader::Read(aFile);
747 if (result.isOk()) {
748 nsCString buf(result.unwrap());
749 ParseManifest(aType, aFile, buf.BeginWriting(), aChromeOnly);
750 } else if (NS_BOOTSTRAPPED_LOCATION != aType) {
751 nsCString uri;
752 aFile.GetURIString(uri);
753 LogMessage("Could not read chrome manifest '%s'.", uri.get());
757 void nsComponentManagerImpl::RegisterManifest(NSLocationType aType,
758 FileLocation& aFile,
759 bool aChromeOnly) {
760 DoRegisterManifest(aType, aFile, aChromeOnly);
763 void nsComponentManagerImpl::ManifestManifest(ManifestProcessingContext& aCx,
764 int aLineNo, char* const* aArgv) {
765 char* file = aArgv[0];
766 FileLocation f(aCx.mFile, file);
767 RegisterManifest(aCx.mType, f, aCx.mChromeOnly);
770 void nsComponentManagerImpl::ManifestComponent(ManifestProcessingContext& aCx,
771 int aLineNo,
772 char* const* aArgv) {
773 mLock.AssertNotCurrentThreadOwns();
775 char* id = aArgv[0];
776 char* file = aArgv[1];
778 nsID cid;
779 if (!cid.Parse(id)) {
780 LogMessageWithContext(aCx.mFile, aLineNo, "Malformed CID: '%s'.", id);
781 return;
784 // Precompute the hash/file data outside of the lock
785 FileLocation fl(aCx.mFile, file);
786 nsCString hash;
787 fl.GetURIString(hash);
789 MutexLock lock(mLock);
790 if (Maybe<EntryWrapper> f = LookupByCID(lock, cid)) {
791 nsCString existing(f->ModuleDescription());
793 lock.Unlock();
795 LogMessageWithContext(
796 aCx.mFile, aLineNo,
797 "Trying to re-register CID '%s' already registered by %s.",
798 AutoIDString(cid).get(), existing.get());
799 return;
802 KnownModule* km;
804 km = mKnownModules.Get(hash);
805 if (!km) {
806 km = new KnownModule(fl);
807 mKnownModules.Put(hash, km);
810 void* place = mArena.Allocate(sizeof(nsCID));
811 nsID* permanentCID = static_cast<nsID*>(place);
812 *permanentCID = cid;
814 place = mArena.Allocate(sizeof(mozilla::Module::CIDEntry));
815 auto* e = new (KnownNotNull, place) mozilla::Module::CIDEntry();
816 e->cid = permanentCID;
818 mFactories.Put(permanentCID, new nsFactoryEntry(e, km));
821 void nsComponentManagerImpl::ManifestContract(ManifestProcessingContext& aCx,
822 int aLineNo, char* const* aArgv) {
823 mLock.AssertNotCurrentThreadOwns();
825 char* contract = aArgv[0];
826 char* id = aArgv[1];
828 nsID cid;
829 if (!cid.Parse(id)) {
830 LogMessageWithContext(aCx.mFile, aLineNo, "Malformed CID: '%s'.", id);
831 return;
834 MutexLock lock(mLock);
835 nsFactoryEntry* f = mFactories.Get(&cid);
836 if (!f) {
837 lock.Unlock();
838 LogMessageWithContext(aCx.mFile, aLineNo,
839 "Could not map contract ID '%s' to CID %s because no "
840 "implementation of the CID is registered.",
841 contract, id);
842 return;
845 nsDependentCString contractString(contract);
846 StaticComponents::InvalidateContractID(nsDependentCString(contractString));
847 mContractIDs.Put(contractString, f);
850 void nsComponentManagerImpl::ManifestCategory(ManifestProcessingContext& aCx,
851 int aLineNo, char* const* aArgv) {
852 char* category = aArgv[0];
853 char* key = aArgv[1];
854 char* value = aArgv[2];
856 nsCategoryManager::GetSingleton()->AddCategoryEntry(
857 nsDependentCString(category), nsDependentCString(key),
858 nsDependentCString(value));
861 void nsComponentManagerImpl::RereadChromeManifests(bool aChromeOnly) {
862 for (uint32_t i = 0; i < sModuleLocations->Length(); ++i) {
863 ComponentLocation& l = sModuleLocations->ElementAt(i);
864 RegisterManifest(l.type, l.location, aChromeOnly);
867 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
868 if (obs) {
869 obs->NotifyObservers(nullptr, "chrome-manifests-loaded", nullptr);
873 bool nsComponentManagerImpl::KnownModule::Load() {
874 if (mFailed) {
875 return false;
877 if (!mModule) {
878 nsCString extension;
879 mFile.GetURIString(extension);
880 CutExtension(extension);
881 if (!extension.Equals("js")) {
882 return false;
885 RefPtr<mozJSComponentLoader> loader = mozJSComponentLoader::Get();
886 mModule = loader->LoadModule(mFile);
888 if (!mModule) {
889 mFailed = true;
890 return false;
893 if (!mLoaded) {
894 if (mModule->loadProc) {
895 nsresult rv = mModule->loadProc();
896 if (NS_FAILED(rv)) {
897 mFailed = true;
898 return false;
901 mLoaded = true;
903 return true;
906 nsCString nsComponentManagerImpl::KnownModule::Description() const {
907 nsCString s;
908 if (mFile) {
909 mFile.GetURIString(s);
910 } else {
911 s = "<static module>";
913 return s;
916 nsresult nsComponentManagerImpl::Shutdown(void) {
917 MOZ_ASSERT(NORMAL == mStatus);
919 mStatus = SHUTDOWN_IN_PROGRESS;
921 // Shutdown the component manager
922 MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
923 ("nsComponentManager: Beginning Shutdown."));
925 UnregisterWeakMemoryReporter(this);
927 // Release all cached factories
928 mContractIDs.Clear();
929 mFactories.Clear(); // XXX release the objects, don't just clear
930 mKnownModules.Clear();
931 mKnownStaticModules.Clear();
933 StaticComponents::Shutdown();
935 delete sExtraStaticModules;
936 delete sModuleLocations;
938 mStatus = SHUTDOWN_COMPLETE;
940 MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
941 ("nsComponentManager: Shutdown complete."));
943 return NS_OK;
946 nsComponentManagerImpl::~nsComponentManagerImpl() {
947 MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
948 ("nsComponentManager: Beginning destruction."));
950 if (SHUTDOWN_COMPLETE != mStatus) {
951 Shutdown();
954 MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
955 ("nsComponentManager: Destroyed."));
958 NS_IMPL_ISUPPORTS(nsComponentManagerImpl, nsIComponentManager,
959 nsIServiceManager, nsIComponentRegistrar,
960 nsISupportsWeakReference, nsIInterfaceRequestor,
961 nsIMemoryReporter)
963 nsresult nsComponentManagerImpl::GetInterface(const nsIID& aUuid,
964 void** aResult) {
965 NS_WARNING("This isn't supported");
966 // fall through to QI as anything QIable is a superset of what can be
967 // got via the GetInterface()
968 return QueryInterface(aUuid, aResult);
971 Maybe<EntryWrapper> nsComponentManagerImpl::LookupByCID(const nsID& aCID) {
972 return LookupByCID(MutexLock(mLock), aCID);
975 Maybe<EntryWrapper> nsComponentManagerImpl::LookupByCID(const MutexLock&,
976 const nsID& aCID) {
977 if (const StaticModule* module = StaticComponents::LookupByCID(aCID)) {
978 return Some(EntryWrapper(module));
980 if (nsFactoryEntry* entry = mFactories.Get(&aCID)) {
981 return Some(EntryWrapper(entry));
983 return Nothing();
986 Maybe<EntryWrapper> nsComponentManagerImpl::LookupByContractID(
987 const nsACString& aContractID) {
988 return LookupByContractID(MutexLock(mLock), aContractID);
991 Maybe<EntryWrapper> nsComponentManagerImpl::LookupByContractID(
992 const MutexLock&, const nsACString& aContractID) {
993 if (const StaticModule* module =
994 StaticComponents::LookupByContractID(aContractID)) {
995 return Some(EntryWrapper(module));
997 if (nsFactoryEntry* entry = mContractIDs.Get(aContractID)) {
998 // UnregisterFactory might have left a stale nsFactoryEntry in
999 // mContractIDs, so we should check to see whether this entry has
1000 // anything useful.
1001 if (entry->mModule || entry->mFactory || entry->mServiceObject) {
1002 return Some(EntryWrapper(entry));
1005 return Nothing();
1008 already_AddRefed<nsIFactory> nsComponentManagerImpl::FindFactory(
1009 const nsCID& aClass) {
1010 Maybe<EntryWrapper> e = LookupByCID(aClass);
1011 if (!e) {
1012 return nullptr;
1015 return e->GetFactory();
1018 already_AddRefed<nsIFactory> nsComponentManagerImpl::FindFactory(
1019 const char* aContractID, uint32_t aContractIDLen) {
1020 Maybe<EntryWrapper> entry =
1021 LookupByContractID(nsDependentCString(aContractID, aContractIDLen));
1022 if (!entry) {
1023 return nullptr;
1026 return entry->GetFactory();
1030 * GetClassObject()
1032 * Given a classID, this finds the singleton ClassObject that implements the
1033 * CID. Returns an interface of type aIID off the singleton classobject.
1035 NS_IMETHODIMP
1036 nsComponentManagerImpl::GetClassObject(const nsCID& aClass, const nsIID& aIID,
1037 void** aResult) {
1038 nsresult rv;
1040 if (MOZ_LOG_TEST(nsComponentManagerLog, LogLevel::Debug)) {
1041 char* buf = aClass.ToString();
1042 PR_LogPrint("nsComponentManager: GetClassObject(%s)", buf);
1043 if (buf) {
1044 free(buf);
1048 MOZ_ASSERT(aResult != nullptr);
1050 nsCOMPtr<nsIFactory> factory = FindFactory(aClass);
1051 if (!factory) {
1052 return NS_ERROR_FACTORY_NOT_REGISTERED;
1055 rv = factory->QueryInterface(aIID, aResult);
1057 MOZ_LOG(
1058 nsComponentManagerLog, LogLevel::Warning,
1059 ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
1061 return rv;
1064 NS_IMETHODIMP
1065 nsComponentManagerImpl::GetClassObjectByContractID(const char* aContractID,
1066 const nsIID& aIID,
1067 void** aResult) {
1068 if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aContractID)) {
1069 return NS_ERROR_INVALID_ARG;
1072 nsresult rv;
1074 MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
1075 ("nsComponentManager: GetClassObjectByContractID(%s)", aContractID));
1077 nsCOMPtr<nsIFactory> factory = FindFactory(aContractID, strlen(aContractID));
1078 if (!factory) {
1079 return NS_ERROR_FACTORY_NOT_REGISTERED;
1082 rv = factory->QueryInterface(aIID, aResult);
1084 MOZ_LOG(nsComponentManagerLog, LogLevel::Warning,
1085 ("\t\tGetClassObjectByContractID() %s",
1086 NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
1088 return rv;
1092 * CreateInstance()
1094 * Create an instance of an object that implements an interface and belongs
1095 * to the implementation aClass using the factory. The factory is immediately
1096 * released and not held onto for any longer.
1098 NS_IMETHODIMP
1099 nsComponentManagerImpl::CreateInstance(const nsCID& aClass,
1100 nsISupports* aDelegate,
1101 const nsIID& aIID, void** aResult) {
1102 // test this first, since there's no point in creating a component during
1103 // shutdown -- whether it's available or not would depend on the order it
1104 // occurs in the list
1105 if (gXPCOMShuttingDown) {
1106 // When processing shutdown, don't process new GetService() requests
1107 #ifdef SHOW_DENIED_ON_SHUTDOWN
1108 fprintf(stderr,
1109 "Creating new instance on shutdown. Denied.\n"
1110 " CID: %s\n IID: %s\n",
1111 AutoIDString(aClass).get(), AutoIDString(aIID).get());
1112 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1113 return NS_ERROR_UNEXPECTED;
1116 if (!aResult) {
1117 return NS_ERROR_NULL_POINTER;
1119 *aResult = nullptr;
1121 Maybe<EntryWrapper> entry = LookupByCID(aClass);
1123 if (!entry) {
1124 return NS_ERROR_FACTORY_NOT_REGISTERED;
1127 #ifdef SHOW_CI_ON_EXISTING_SERVICE
1128 if (entry->ServiceInstance()) {
1129 nsAutoCString message;
1130 message =
1131 NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
1132 AutoIDString(aClass) +
1133 NS_LITERAL_CSTRING("\" when a service for this CID already exists!");
1134 NS_ERROR(message.get());
1136 #endif
1138 nsresult rv;
1139 nsCOMPtr<nsIFactory> factory = entry->GetFactory();
1140 if (factory) {
1141 rv = factory->CreateInstance(aDelegate, aIID, aResult);
1142 if (NS_SUCCEEDED(rv) && !*aResult) {
1143 NS_ERROR("Factory did not return an object but returned success!");
1144 rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
1146 } else {
1147 // Translate error values
1148 rv = NS_ERROR_FACTORY_NOT_REGISTERED;
1151 if (MOZ_LOG_TEST(nsComponentManagerLog, LogLevel::Warning)) {
1152 char* buf = aClass.ToString();
1153 MOZ_LOG(nsComponentManagerLog, LogLevel::Warning,
1154 ("nsComponentManager: CreateInstance(%s) %s", buf,
1155 NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
1156 if (buf) {
1157 free(buf);
1161 return rv;
1165 * CreateInstanceByContractID()
1167 * A variant of CreateInstance() that creates an instance of the object that
1168 * implements the interface aIID and whose implementation has a contractID
1169 * aContractID.
1171 * This is only a convenience routine that turns around can calls the
1172 * CreateInstance() with classid and iid.
1174 NS_IMETHODIMP
1175 nsComponentManagerImpl::CreateInstanceByContractID(const char* aContractID,
1176 nsISupports* aDelegate,
1177 const nsIID& aIID,
1178 void** aResult) {
1179 if (NS_WARN_IF(!aContractID)) {
1180 return NS_ERROR_INVALID_ARG;
1183 // test this first, since there's no point in creating a component during
1184 // shutdown -- whether it's available or not would depend on the order it
1185 // occurs in the list
1186 if (gXPCOMShuttingDown) {
1187 // When processing shutdown, don't process new GetService() requests
1188 #ifdef SHOW_DENIED_ON_SHUTDOWN
1189 fprintf(stderr,
1190 "Creating new instance on shutdown. Denied.\n"
1191 " ContractID: %s\n IID: %s\n",
1192 aContractID, AutoIDString(aIID).get());
1193 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1194 return NS_ERROR_UNEXPECTED;
1197 if (!aResult) {
1198 return NS_ERROR_NULL_POINTER;
1200 *aResult = nullptr;
1202 Maybe<EntryWrapper> entry =
1203 LookupByContractID(nsDependentCString(aContractID));
1205 if (!entry) {
1206 return NS_ERROR_FACTORY_NOT_REGISTERED;
1209 #ifdef SHOW_CI_ON_EXISTING_SERVICE
1210 if (entry->ServiceInstance()) {
1211 nsAutoCString message;
1212 message =
1213 NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
1214 nsDependentCString(aContractID) +
1215 NS_LITERAL_CSTRING(
1216 "\" when a service for this CID already exists! "
1217 "Add it to abusedContracts to track down the service consumer.");
1218 NS_ERROR(message.get());
1220 #endif
1222 nsresult rv;
1223 nsCOMPtr<nsIFactory> factory = entry->GetFactory();
1224 if (factory) {
1225 rv = factory->CreateInstance(aDelegate, aIID, aResult);
1226 if (NS_SUCCEEDED(rv) && !*aResult) {
1227 NS_ERROR("Factory did not return an object but returned success!");
1228 rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
1230 } else {
1231 // Translate error values
1232 rv = NS_ERROR_FACTORY_NOT_REGISTERED;
1235 MOZ_LOG(nsComponentManagerLog, LogLevel::Warning,
1236 ("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID,
1237 NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
1239 return rv;
1242 nsresult nsComponentManagerImpl::FreeServices() {
1243 NS_ASSERTION(gXPCOMShuttingDown,
1244 "Must be shutting down in order to free all services");
1246 if (!gXPCOMShuttingDown) {
1247 return NS_ERROR_FAILURE;
1250 for (auto iter = mFactories.Iter(); !iter.Done(); iter.Next()) {
1251 nsFactoryEntry* entry = iter.UserData();
1252 entry->mFactory = nullptr;
1253 entry->mServiceObject = nullptr;
1256 for (const auto& module : gStaticModules) {
1257 module.SetServiceInstance(nullptr);
1260 return NS_OK;
1263 // This should only ever be called within the monitor!
1264 nsComponentManagerImpl::PendingServiceInfo*
1265 nsComponentManagerImpl::AddPendingService(const nsCID& aServiceCID,
1266 PRThread* aThread) {
1267 PendingServiceInfo* newInfo = mPendingServices.AppendElement();
1268 if (newInfo) {
1269 newInfo->cid = &aServiceCID;
1270 newInfo->thread = aThread;
1272 return newInfo;
1275 // This should only ever be called within the monitor!
1276 void nsComponentManagerImpl::RemovePendingService(const nsCID& aServiceCID) {
1277 uint32_t pendingCount = mPendingServices.Length();
1278 for (uint32_t index = 0; index < pendingCount; ++index) {
1279 const PendingServiceInfo& info = mPendingServices.ElementAt(index);
1280 if (info.cid->Equals(aServiceCID)) {
1281 mPendingServices.RemoveElementAt(index);
1282 return;
1287 // This should only ever be called within the monitor!
1288 PRThread* nsComponentManagerImpl::GetPendingServiceThread(
1289 const nsCID& aServiceCID) const {
1290 uint32_t pendingCount = mPendingServices.Length();
1291 for (uint32_t index = 0; index < pendingCount; ++index) {
1292 const PendingServiceInfo& info = mPendingServices.ElementAt(index);
1293 if (info.cid->Equals(aServiceCID)) {
1294 return info.thread;
1297 return nullptr;
1300 nsresult nsComponentManagerImpl::GetServiceLocked(MutexLock& aLock,
1301 EntryWrapper& aEntry,
1302 const nsIID& aIID,
1303 void** aResult) {
1304 if (auto* service = aEntry.ServiceInstance()) {
1305 aLock.Unlock();
1306 return service->QueryInterface(aIID, aResult);
1309 PRThread* currentPRThread = PR_GetCurrentThread();
1310 MOZ_ASSERT(currentPRThread, "This should never be null!");
1312 // Needed to optimize the event loop below.
1313 nsIThread* currentThread = nullptr;
1315 PRThread* pendingPRThread;
1316 while ((pendingPRThread = GetPendingServiceThread(aEntry.CID()))) {
1317 if (pendingPRThread == currentPRThread) {
1318 NS_ERROR("Recursive GetService!");
1319 return NS_ERROR_NOT_AVAILABLE;
1322 SafeMutexAutoUnlock unlockPending(mLock);
1324 // If the current thread doesn't have an associated nsThread, then it's a
1325 // thread that doesn't have an event loop to process, so we'll just try
1326 // to yield to another thread in an attempt to make progress.
1327 if (!nsThreadManager::get().IsNSThread()) {
1328 PR_Sleep(PR_INTERVAL_NO_WAIT);
1329 continue;
1332 if (!currentThread) {
1333 currentThread = NS_GetCurrentThread();
1334 MOZ_ASSERT(currentThread, "This should never be null!");
1337 // This will process a single event or yield the thread if no event is
1338 // pending.
1339 if (!NS_ProcessNextEvent(currentThread, false)) {
1340 PR_Sleep(PR_INTERVAL_NO_WAIT);
1344 // It's still possible that the other thread failed to create the
1345 // service so we're not guaranteed to have an entry or service yet.
1346 if (auto* service = aEntry.ServiceInstance()) {
1347 aLock.Unlock();
1348 return service->QueryInterface(aIID, aResult);
1351 DebugOnly<PendingServiceInfo*> newInfo =
1352 AddPendingService(aEntry.CID(), currentPRThread);
1353 NS_ASSERTION(newInfo, "Failed to add info to the array!");
1355 // We need to not be holding the service manager's lock while calling
1356 // CreateInstance, because it invokes user code which could try to re-enter
1357 // the service manager:
1359 nsCOMPtr<nsISupports> service;
1360 auto cleanup = MakeScopeExit([&]() {
1361 // `service` must be released after the lock is released, so if we fail and
1362 // still have a reference, release the lock before relasing it.
1363 if (service) {
1364 aLock.Unlock();
1365 service = nullptr;
1369 nsresult rv;
1371 SafeMutexAutoUnlock unlock(mLock);
1372 rv = aEntry.CreateInstance(nullptr, aIID, getter_AddRefs(service));
1374 if (NS_SUCCEEDED(rv) && !service) {
1375 NS_ERROR("Factory did not return an object but returned success");
1376 return NS_ERROR_SERVICE_NOT_AVAILABLE;
1379 #ifdef DEBUG
1380 pendingPRThread = GetPendingServiceThread(aEntry.CID());
1381 MOZ_ASSERT(pendingPRThread == currentPRThread,
1382 "Pending service array has been changed!");
1383 #endif
1384 RemovePendingService(aEntry.CID());
1386 if (NS_FAILED(rv)) {
1387 return rv;
1390 NS_ASSERTION(!aEntry.ServiceInstance(),
1391 "Created two instances of a service!");
1393 aEntry.SetServiceInstance(service.forget());
1395 aLock.Unlock();
1396 *aResult = do_AddRef(aEntry.ServiceInstance()).take();
1397 return NS_OK;
1400 NS_IMETHODIMP
1401 nsComponentManagerImpl::GetService(const nsCID& aClass, const nsIID& aIID,
1402 void** aResult) {
1403 // test this first, since there's no point in returning a service during
1404 // shutdown -- whether it's available or not would depend on the order it
1405 // occurs in the list
1406 if (gXPCOMShuttingDown) {
1407 // When processing shutdown, don't process new GetService() requests
1408 #ifdef SHOW_DENIED_ON_SHUTDOWN
1409 fprintf(stderr,
1410 "Getting service on shutdown. Denied.\n"
1411 " CID: %s\n IID: %s\n",
1412 AutoIDString(aClass).get(), AutoIDString(aIID).get());
1413 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1414 return NS_ERROR_UNEXPECTED;
1417 MutexLock lock(mLock);
1419 Maybe<EntryWrapper> entry = LookupByCID(lock, aClass);
1420 if (!entry) {
1421 return NS_ERROR_FACTORY_NOT_REGISTERED;
1424 return GetServiceLocked(lock, *entry, aIID, aResult);
1427 nsresult nsComponentManagerImpl::GetService(ModuleID aId, const nsIID& aIID,
1428 void** aResult) {
1429 const auto& entry = gStaticModules[size_t(aId)];
1431 // test this first, since there's no point in returning a service during
1432 // shutdown -- whether it's available or not would depend on the order it
1433 // occurs in the list
1434 if (gXPCOMShuttingDown) {
1435 // When processing shutdown, don't process new GetService() requests
1436 #ifdef SHOW_DENIED_ON_SHUTDOWN
1437 fprintf(stderr,
1438 "Getting service on shutdown. Denied.\n"
1439 " CID: %s\n IID: %s\n",
1440 AutoIDString(entry.CID()).get(), AutoIDString(aIID).get());
1441 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1442 return NS_ERROR_UNEXPECTED;
1445 MutexLock lock(mLock);
1447 if (!entry.Active()) {
1448 return NS_ERROR_FACTORY_NOT_REGISTERED;
1451 Maybe<EntryWrapper> wrapper;
1452 if (entry.Overridable()) {
1453 // If we expect this service to be overridden by test code, we need to look
1454 // it up by contract ID every time.
1455 wrapper = LookupByContractID(lock, entry.ContractID());
1456 if (!wrapper) {
1457 return NS_ERROR_FACTORY_NOT_REGISTERED;
1459 } else {
1460 wrapper.emplace(&entry);
1462 return GetServiceLocked(lock, *wrapper, aIID, aResult);
1465 NS_IMETHODIMP
1466 nsComponentManagerImpl::IsServiceInstantiated(const nsCID& aClass,
1467 const nsIID& aIID,
1468 bool* aResult) {
1469 // Now we want to get the service if we already got it. If not, we don't want
1470 // to create an instance of it. mmh!
1472 // test this first, since there's no point in returning a service during
1473 // shutdown -- whether it's available or not would depend on the order it
1474 // occurs in the list
1475 if (gXPCOMShuttingDown) {
1476 // When processing shutdown, don't process new GetService() requests
1477 #ifdef SHOW_DENIED_ON_SHUTDOWN
1478 fprintf(stderr,
1479 "Checking for service on shutdown. Denied.\n"
1480 " CID: %s\n IID: %s\n",
1481 AutoIDString(aClass).get(), AutoIDString(aIID).get());
1482 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1483 return NS_ERROR_UNEXPECTED;
1486 if (Maybe<EntryWrapper> entry = LookupByCID(aClass)) {
1487 if (auto* service = entry->ServiceInstance()) {
1488 nsCOMPtr<nsISupports> instance;
1489 nsresult rv = service->QueryInterface(aIID, getter_AddRefs(instance));
1490 *aResult = (instance != nullptr);
1491 return rv;
1495 *aResult = false;
1496 return NS_OK;
1499 NS_IMETHODIMP
1500 nsComponentManagerImpl::IsServiceInstantiatedByContractID(
1501 const char* aContractID, const nsIID& aIID, bool* aResult) {
1502 // Now we want to get the service if we already got it. If not, we don't want
1503 // to create an instance of it. mmh!
1505 // test this first, since there's no point in returning a service during
1506 // shutdown -- whether it's available or not would depend on the order it
1507 // occurs in the list
1508 if (gXPCOMShuttingDown) {
1509 // When processing shutdown, don't process new GetService() requests
1510 #ifdef SHOW_DENIED_ON_SHUTDOWN
1511 fprintf(stderr,
1512 "Checking for service on shutdown. Denied.\n"
1513 " ContractID: %s\n IID: %s\n",
1514 aContractID, AutoIDString(aIID).get());
1515 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1516 return NS_ERROR_UNEXPECTED;
1519 if (Maybe<EntryWrapper> entry =
1520 LookupByContractID(nsDependentCString(aContractID))) {
1521 if (auto* service = entry->ServiceInstance()) {
1522 nsCOMPtr<nsISupports> instance;
1523 nsresult rv = service->QueryInterface(aIID, getter_AddRefs(instance));
1524 *aResult = (instance != nullptr);
1525 return rv;
1529 *aResult = false;
1530 return NS_OK;
1533 NS_IMETHODIMP
1534 nsComponentManagerImpl::GetServiceByContractID(const char* aContractID,
1535 const nsIID& aIID,
1536 void** aResult) {
1537 // test this first, since there's no point in returning a service during
1538 // shutdown -- whether it's available or not would depend on the order it
1539 // occurs in the list
1540 if (gXPCOMShuttingDown) {
1541 // When processing shutdown, don't process new GetService() requests
1542 #ifdef SHOW_DENIED_ON_SHUTDOWN
1543 fprintf(stderr,
1544 "Getting service on shutdown. Denied.\n"
1545 " ContractID: %s\n IID: %s\n",
1546 aContractID, AutoIDString(aIID).get());
1547 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1548 return NS_ERROR_UNEXPECTED;
1551 MutexLock lock(mLock);
1553 Maybe<EntryWrapper> entry =
1554 LookupByContractID(lock, nsDependentCString(aContractID));
1555 if (!entry) {
1556 return NS_ERROR_FACTORY_NOT_REGISTERED;
1559 return GetServiceLocked(lock, *entry, aIID, aResult);
1562 NS_IMETHODIMP
1563 nsComponentManagerImpl::RegisterFactory(const nsCID& aClass, const char* aName,
1564 const char* aContractID,
1565 nsIFactory* aFactory) {
1566 if (!aFactory) {
1567 // If a null factory is passed in, this call just wants to reset
1568 // the contract ID to point to an existing CID entry.
1569 if (!aContractID) {
1570 return NS_ERROR_INVALID_ARG;
1573 nsDependentCString contractID(aContractID);
1575 SafeMutexAutoLock lock(mLock);
1576 nsFactoryEntry* oldf = mFactories.Get(&aClass);
1577 if (oldf) {
1578 StaticComponents::InvalidateContractID(contractID);
1579 mContractIDs.Put(contractID, oldf);
1580 return NS_OK;
1583 if (StaticComponents::LookupByCID(aClass)) {
1584 // If this is the CID of a static module, just reset the invalid bit of
1585 // the static entry for this contract ID, and assume it points to the
1586 // correct class.
1587 if (StaticComponents::InvalidateContractID(contractID, false)) {
1588 mContractIDs.Remove(contractID);
1589 return NS_OK;
1592 return NS_ERROR_FACTORY_NOT_REGISTERED;
1595 auto f = MakeUnique<nsFactoryEntry>(aClass, aFactory);
1597 SafeMutexAutoLock lock(mLock);
1598 if (auto entry = mFactories.LookupForAdd(f->mCIDEntry->cid)) {
1599 return NS_ERROR_FACTORY_EXISTS;
1600 } else {
1601 if (StaticComponents::LookupByCID(*f->mCIDEntry->cid)) {
1602 entry.OrRemove();
1603 return NS_ERROR_FACTORY_EXISTS;
1605 if (aContractID) {
1606 nsDependentCString contractID(aContractID);
1607 mContractIDs.Put(contractID, f.get());
1608 // We allow dynamically-registered contract IDs to override static
1609 // entries, so invalidate any static entry for this contract ID.
1610 StaticComponents::InvalidateContractID(contractID);
1612 entry.OrInsert([&f]() { return f.release(); });
1615 return NS_OK;
1618 NS_IMETHODIMP
1619 nsComponentManagerImpl::UnregisterFactory(const nsCID& aClass,
1620 nsIFactory* aFactory) {
1621 // Don't release the dying factory or service object until releasing
1622 // the component manager monitor.
1623 nsCOMPtr<nsIFactory> dyingFactory;
1624 nsCOMPtr<nsISupports> dyingServiceObject;
1627 SafeMutexAutoLock lock(mLock);
1628 auto entry = mFactories.Lookup(&aClass);
1629 nsFactoryEntry* f = entry ? entry.Data() : nullptr;
1630 if (!f || f->mFactory != aFactory) {
1631 // Note: We do not support unregistering static factories.
1632 return NS_ERROR_FACTORY_NOT_REGISTERED;
1635 entry.Remove();
1637 // This might leave a stale contractid -> factory mapping in
1638 // place, so null out the factory entry (see
1639 // nsFactoryEntry::GetFactory)
1640 f->mFactory.swap(dyingFactory);
1641 f->mServiceObject.swap(dyingServiceObject);
1644 return NS_OK;
1647 NS_IMETHODIMP
1648 nsComponentManagerImpl::AutoRegister(nsIFile* aLocation) {
1649 XRE_AddManifestLocation(NS_EXTENSION_LOCATION, aLocation);
1650 return NS_OK;
1653 NS_IMETHODIMP
1654 nsComponentManagerImpl::AutoUnregister(nsIFile* aLocation) {
1655 NS_ERROR("AutoUnregister not implemented.");
1656 return NS_ERROR_NOT_IMPLEMENTED;
1659 NS_IMETHODIMP
1660 nsComponentManagerImpl::RegisterFactoryLocation(
1661 const nsCID& aCID, const char* aClassName, const char* aContractID,
1662 nsIFile* aFile, const char* aLoaderStr, const char* aType) {
1663 NS_ERROR("RegisterFactoryLocation not implemented.");
1664 return NS_ERROR_NOT_IMPLEMENTED;
1667 NS_IMETHODIMP
1668 nsComponentManagerImpl::UnregisterFactoryLocation(const nsCID& aCID,
1669 nsIFile* aFile) {
1670 NS_ERROR("UnregisterFactoryLocation not implemented.");
1671 return NS_ERROR_NOT_IMPLEMENTED;
1674 NS_IMETHODIMP
1675 nsComponentManagerImpl::IsCIDRegistered(const nsCID& aClass, bool* aResult) {
1676 *aResult = LookupByCID(aClass).isSome();
1677 return NS_OK;
1680 NS_IMETHODIMP
1681 nsComponentManagerImpl::IsContractIDRegistered(const char* aClass,
1682 bool* aResult) {
1683 if (NS_WARN_IF(!aClass)) {
1684 return NS_ERROR_INVALID_ARG;
1687 Maybe<EntryWrapper> entry = LookupByContractID(nsDependentCString(aClass));
1689 *aResult = entry.isSome();
1690 return NS_OK;
1693 NS_IMETHODIMP
1694 nsComponentManagerImpl::GetContractIDs(nsTArray<nsCString>& aResult) {
1695 aResult.Clear();
1697 for (auto iter = mContractIDs.Iter(); !iter.Done(); iter.Next()) {
1698 aResult.AppendElement(iter.Key());
1701 for (const auto& entry : gContractEntries) {
1702 if (!entry.Invalid()) {
1703 aResult.AppendElement(entry.ContractID());
1707 return NS_OK;
1710 NS_IMETHODIMP
1711 nsComponentManagerImpl::CIDToContractID(const nsCID& aClass, char** aResult) {
1712 NS_ERROR("CIDTOContractID not implemented");
1713 return NS_ERROR_FACTORY_NOT_REGISTERED;
1716 NS_IMETHODIMP
1717 nsComponentManagerImpl::ContractIDToCID(const char* aContractID,
1718 nsCID** aResult) {
1720 MutexLock lock(mLock);
1721 Maybe<EntryWrapper> entry =
1722 LookupByContractID(lock, nsDependentCString(aContractID));
1723 if (entry) {
1724 *aResult = (nsCID*)moz_xmalloc(sizeof(nsCID));
1725 **aResult = entry->CID();
1726 return NS_OK;
1729 *aResult = nullptr;
1730 return NS_ERROR_FACTORY_NOT_REGISTERED;
1733 MOZ_DEFINE_MALLOC_SIZE_OF(ComponentManagerMallocSizeOf)
1735 NS_IMETHODIMP
1736 nsComponentManagerImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
1737 nsISupports* aData, bool aAnonymize) {
1738 MOZ_COLLECT_REPORT("explicit/xpcom/component-manager", KIND_HEAP, UNITS_BYTES,
1739 SizeOfIncludingThis(ComponentManagerMallocSizeOf),
1740 "Memory used for the XPCOM component manager.");
1742 return NS_OK;
1745 size_t nsComponentManagerImpl::SizeOfIncludingThis(
1746 mozilla::MallocSizeOf aMallocSizeOf) const {
1747 size_t n = aMallocSizeOf(this);
1749 n += mFactories.ShallowSizeOfExcludingThis(aMallocSizeOf);
1750 for (auto iter = mFactories.ConstIter(); !iter.Done(); iter.Next()) {
1751 n += iter.Data()->SizeOfIncludingThis(aMallocSizeOf);
1754 n += mContractIDs.ShallowSizeOfExcludingThis(aMallocSizeOf);
1755 for (auto iter = mContractIDs.ConstIter(); !iter.Done(); iter.Next()) {
1756 // We don't measure the nsFactoryEntry data because it's owned by
1757 // mFactories (which is measured above).
1758 n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
1761 n += sExtraStaticModules->ShallowSizeOfIncludingThis(aMallocSizeOf);
1762 if (sModuleLocations) {
1763 n += sModuleLocations->ShallowSizeOfIncludingThis(aMallocSizeOf);
1766 n += mKnownStaticModules.ShallowSizeOfExcludingThis(aMallocSizeOf);
1767 n += mKnownModules.ShallowSizeOfExcludingThis(aMallocSizeOf);
1769 n += mArena.SizeOfExcludingThis(aMallocSizeOf);
1771 n += mPendingServices.ShallowSizeOfExcludingThis(aMallocSizeOf);
1773 // Measurement of the following members may be added later if DMD finds it is
1774 // worthwhile:
1775 // - mMon
1776 // - sModuleLocations' entries
1777 // - mKnownStaticModules' entries?
1778 // - mKnownModules' keys and values?
1780 return n;
1783 ////////////////////////////////////////////////////////////////////////////////
1784 // nsFactoryEntry
1785 ////////////////////////////////////////////////////////////////////////////////
1787 nsFactoryEntry::nsFactoryEntry(const mozilla::Module::CIDEntry* aEntry,
1788 nsComponentManagerImpl::KnownModule* aModule)
1789 : mCIDEntry(aEntry), mModule(aModule) {}
1791 nsFactoryEntry::nsFactoryEntry(const nsCID& aCID, nsIFactory* aFactory)
1792 : mCIDEntry(nullptr), mModule(nullptr), mFactory(aFactory) {
1793 auto* e = new mozilla::Module::CIDEntry();
1794 auto* cid = new nsCID;
1795 *cid = aCID;
1796 e->cid = cid;
1797 mCIDEntry = e;
1800 nsFactoryEntry::~nsFactoryEntry() {
1801 // If this was a RegisterFactory entry, we own the CIDEntry/CID
1802 if (!mModule) {
1803 delete mCIDEntry->cid;
1804 delete mCIDEntry;
1808 already_AddRefed<nsIFactory> nsFactoryEntry::GetFactory() {
1809 nsComponentManagerImpl::gComponentManager->mLock.AssertNotCurrentThreadOwns();
1811 if (!mFactory) {
1812 // RegisterFactory then UnregisterFactory can leave an entry in mContractIDs
1813 // pointing to an unusable nsFactoryEntry.
1814 if (!mModule) {
1815 return nullptr;
1818 if (!mModule->Load()) {
1819 return nullptr;
1822 // Don't set mFactory directly, it needs to be locked
1823 nsCOMPtr<nsIFactory> factory;
1825 if (mModule->Module()->getFactoryProc) {
1826 factory =
1827 mModule->Module()->getFactoryProc(*mModule->Module(), *mCIDEntry);
1828 } else if (mCIDEntry->getFactoryProc) {
1829 factory = mCIDEntry->getFactoryProc(*mModule->Module(), *mCIDEntry);
1830 } else {
1831 NS_ASSERTION(mCIDEntry->constructorProc, "no getfactory or constructor");
1832 factory = new mozilla::GenericFactory(mCIDEntry->constructorProc);
1834 if (!factory) {
1835 return nullptr;
1838 SafeMutexAutoLock lock(nsComponentManagerImpl::gComponentManager->mLock);
1839 // Threads can race to set mFactory
1840 if (!mFactory) {
1841 factory.swap(mFactory);
1844 nsCOMPtr<nsIFactory> factory = mFactory;
1845 return factory.forget();
1848 nsresult nsFactoryEntry::CreateInstance(nsISupports* aOuter, const nsIID& aIID,
1849 void** aResult) {
1850 nsCOMPtr<nsIFactory> factory = GetFactory();
1851 NS_ENSURE_TRUE(factory, NS_ERROR_FAILURE);
1852 return factory->CreateInstance(aOuter, aIID, aResult);
1855 size_t nsFactoryEntry::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) {
1856 size_t n = aMallocSizeOf(this);
1858 // Measurement of the following members may be added later if DMD finds it is
1859 // worthwhile:
1860 // - mCIDEntry;
1861 // - mModule;
1862 // - mFactory;
1863 // - mServiceObject;
1865 return n;
1868 ////////////////////////////////////////////////////////////////////////////////
1869 // Static Access Functions
1870 ////////////////////////////////////////////////////////////////////////////////
1872 nsresult NS_GetComponentManager(nsIComponentManager** aResult) {
1873 if (!nsComponentManagerImpl::gComponentManager) {
1874 return NS_ERROR_NOT_INITIALIZED;
1877 NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager);
1878 return NS_OK;
1881 nsresult NS_GetServiceManager(nsIServiceManager** aResult) {
1882 if (!nsComponentManagerImpl::gComponentManager) {
1883 return NS_ERROR_NOT_INITIALIZED;
1886 NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager);
1887 return NS_OK;
1890 nsresult NS_GetComponentRegistrar(nsIComponentRegistrar** aResult) {
1891 if (!nsComponentManagerImpl::gComponentManager) {
1892 return NS_ERROR_NOT_INITIALIZED;
1895 NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager);
1896 return NS_OK;
1899 EXPORT_XPCOM_API(nsresult)
1900 XRE_AddStaticComponent(const mozilla::Module* aComponent) {
1901 nsComponentManagerImpl::InitializeStaticModules();
1902 sExtraStaticModules->AppendElement(aComponent);
1904 if (nsComponentManagerImpl::gComponentManager &&
1905 nsComponentManagerImpl::NORMAL ==
1906 nsComponentManagerImpl::gComponentManager->mStatus) {
1907 nsComponentManagerImpl::gComponentManager->RegisterModule(aComponent);
1910 return NS_OK;
1913 NS_IMETHODIMP
1914 nsComponentManagerImpl::AddBootstrappedManifestLocation(nsIFile* aLocation) {
1915 NS_ENSURE_ARG_POINTER(aLocation);
1917 nsString path;
1918 nsresult rv = aLocation->GetPath(path);
1919 if (NS_FAILED(rv)) {
1920 return rv;
1923 if (Substring(path, path.Length() - 4).EqualsLiteral(".xpi")) {
1924 return XRE_AddJarManifestLocation(NS_BOOTSTRAPPED_LOCATION, aLocation);
1927 nsCOMPtr<nsIFile> manifest =
1928 CloneAndAppend(aLocation, NS_LITERAL_CSTRING("chrome.manifest"));
1929 return XRE_AddManifestLocation(NS_BOOTSTRAPPED_LOCATION, manifest);
1932 NS_IMETHODIMP
1933 nsComponentManagerImpl::RemoveBootstrappedManifestLocation(nsIFile* aLocation) {
1934 NS_ENSURE_ARG_POINTER(aLocation);
1936 nsCOMPtr<nsIChromeRegistry> cr =
1937 mozilla::services::GetChromeRegistryService();
1938 if (!cr) {
1939 return NS_ERROR_FAILURE;
1942 nsString path;
1943 nsresult rv = aLocation->GetPath(path);
1944 if (NS_FAILED(rv)) {
1945 return rv;
1948 nsComponentManagerImpl::ComponentLocation elem;
1949 elem.type = NS_BOOTSTRAPPED_LOCATION;
1951 if (Substring(path, path.Length() - 4).EqualsLiteral(".xpi")) {
1952 elem.location.Init(aLocation, "chrome.manifest");
1953 } else {
1954 nsCOMPtr<nsIFile> lf =
1955 CloneAndAppend(aLocation, NS_LITERAL_CSTRING("chrome.manifest"));
1956 elem.location.Init(lf);
1959 // Remove reference.
1960 nsComponentManagerImpl::sModuleLocations->RemoveElement(
1961 elem, ComponentLocationComparator());
1963 rv = cr->CheckForNewChrome();
1964 return rv;
1967 NS_IMETHODIMP
1968 nsComponentManagerImpl::GetComponentJSMs(nsIUTF8StringEnumerator** aJSMs) {
1969 nsCOMPtr<nsIUTF8StringEnumerator> result =
1970 StaticComponents::GetComponentJSMs();
1971 result.forget(aJSMs);
1972 return NS_OK;
1975 NS_IMETHODIMP
1976 nsComponentManagerImpl::GetManifestLocations(nsIArray** aLocations) {
1977 NS_ENSURE_ARG_POINTER(aLocations);
1978 *aLocations = nullptr;
1980 if (!sModuleLocations) {
1981 return NS_ERROR_NOT_INITIALIZED;
1984 nsCOMPtr<nsIMutableArray> locations = nsArray::Create();
1985 nsresult rv;
1986 for (uint32_t i = 0; i < sModuleLocations->Length(); ++i) {
1987 ComponentLocation& l = sModuleLocations->ElementAt(i);
1988 FileLocation loc = l.location;
1989 nsCString uriString;
1990 loc.GetURIString(uriString);
1991 nsCOMPtr<nsIURI> uri;
1992 rv = NS_NewURI(getter_AddRefs(uri), uriString);
1993 if (NS_SUCCEEDED(rv)) {
1994 locations->AppendElement(uri);
1998 locations.forget(aLocations);
1999 return NS_OK;
2002 EXPORT_XPCOM_API(nsresult)
2003 XRE_AddManifestLocation(NSLocationType aType, nsIFile* aLocation) {
2004 nsComponentManagerImpl::InitializeModuleLocations();
2005 nsComponentManagerImpl::ComponentLocation* c =
2006 nsComponentManagerImpl::sModuleLocations->AppendElement();
2007 c->type = aType;
2008 c->location.Init(aLocation);
2010 if (nsComponentManagerImpl::gComponentManager &&
2011 nsComponentManagerImpl::NORMAL ==
2012 nsComponentManagerImpl::gComponentManager->mStatus) {
2013 nsComponentManagerImpl::gComponentManager->RegisterManifest(
2014 aType, c->location, false);
2017 return NS_OK;
2020 EXPORT_XPCOM_API(nsresult)
2021 XRE_AddJarManifestLocation(NSLocationType aType, nsIFile* aLocation) {
2022 nsComponentManagerImpl::InitializeModuleLocations();
2023 nsComponentManagerImpl::ComponentLocation* c =
2024 nsComponentManagerImpl::sModuleLocations->AppendElement();
2026 c->type = aType;
2027 c->location.Init(aLocation, "chrome.manifest");
2029 if (nsComponentManagerImpl::gComponentManager &&
2030 nsComponentManagerImpl::NORMAL ==
2031 nsComponentManagerImpl::gComponentManager->mStatus) {
2032 nsComponentManagerImpl::gComponentManager->RegisterManifest(
2033 aType, c->location, false);
2036 return NS_OK;
2039 // Expose some important global interfaces to rust for the rust xpcom API. These
2040 // methods return a non-owning reference to the component manager, which should
2041 // live for the lifetime of XPCOM.
2042 extern "C" {
2044 const nsIComponentManager* Gecko_GetComponentManager() {
2045 return nsComponentManagerImpl::gComponentManager;
2048 const nsIServiceManager* Gecko_GetServiceManager() {
2049 return nsComponentManagerImpl::gComponentManager;
2052 const nsIComponentRegistrar* Gecko_GetComponentRegistrar() {
2053 return nsComponentManagerImpl::gComponentManager;