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/. */
9 #include "nsISupports.h"
11 #include "nsCRT.h" // for atoll
13 #include "StaticComponents.h"
15 #include "nsCategoryManager.h"
17 #include "nsComponentManager.h"
18 #include "nsDirectoryService.h"
19 #include "nsDirectoryServiceDefs.h"
20 #include "nsCategoryManager.h"
21 #include "nsLayoutModule.h"
22 #include "mozilla/MemoryReporting.h"
23 #include "nsIObserverService.h"
24 #include "nsIStringEnumerator.h"
26 #include "nsXPCOMPrivate.h"
27 #include "nsISupportsPrimitives.h"
28 #include "nsLocalFile.h"
29 #include "nsReadableUtils.h"
32 #include "nsThreadManager.h"
33 #include "nsThreadUtils.h"
35 #include "private/pprthred.h"
38 #include "ManifestParser.h"
39 #include "nsNetUtil.h"
40 #include "mozilla/Services.h"
42 #include "mozilla/GenericFactory.h"
43 #include "nsSupportsPrimitives.h"
45 #include "nsIMutableArray.h"
46 #include "mozilla/DebugOnly.h"
47 #include "mozilla/FileUtils.h"
48 #include "mozilla/ProfilerLabels.h"
49 #include "mozilla/ProfilerMarkers.h"
50 #include "mozilla/ScopeExit.h"
51 #include "mozilla/URLPreloader.h"
52 #include "mozilla/UniquePtr.h"
53 #include "mozilla/Variant.h"
55 #include <new> // for placement new
57 #include "mozilla/Omnijar.h"
59 #include "mozilla/Logging.h"
60 #include "LogModulePrefWatcher.h"
63 # include "mozmemory.h"
66 using namespace mozilla
;
67 using namespace mozilla::xpcom
;
69 static LazyLogModule
nsComponentManagerLog("nsComponentManager");
72 # define SHOW_DENIED_ON_SHUTDOWN
73 # define SHOW_CI_ON_EXISTING_SERVICE
78 class AutoIDString
: public nsAutoCStringN
<NSID_LENGTH
> {
80 explicit AutoIDString(const nsID
& aID
) {
81 SetLength(NSID_LENGTH
- 1);
83 *reinterpret_cast<char(*)[NSID_LENGTH
]>(BeginWriting()));
92 using ProcessSelector
= Module::ProcessSelector
;
94 // Note: These must be kept in sync with the ProcessSelector definition in
96 bool ProcessSelectorMatches(ProcessSelector aSelector
) {
97 GeckoProcessType type
= XRE_GetProcessType();
98 if (type
== GeckoProcessType_GPU
) {
99 return !!(aSelector
& Module::ALLOW_IN_GPU_PROCESS
);
102 if (type
== GeckoProcessType_RDD
) {
103 return !!(aSelector
& Module::ALLOW_IN_RDD_PROCESS
);
106 if (type
== GeckoProcessType_Socket
) {
107 return !!(aSelector
& (Module::ALLOW_IN_SOCKET_PROCESS
));
110 if (type
== GeckoProcessType_VR
) {
111 return !!(aSelector
& Module::ALLOW_IN_VR_PROCESS
);
114 if (type
== GeckoProcessType_Utility
) {
115 return !!(aSelector
& Module::ALLOW_IN_UTILITY_PROCESS
);
118 // Only allow XPCOM modules which can be loaded in all processes to be loaded
119 // in the IPDLUnitTest process.
120 if (type
== GeckoProcessType_IPDLUnitTest
) {
121 return size_t(aSelector
) == Module::kMaxProcessSelector
;
124 if (aSelector
& Module::MAIN_PROCESS_ONLY
) {
125 return type
== GeckoProcessType_Default
;
127 if (aSelector
& Module::CONTENT_PROCESS_ONLY
) {
128 return type
== GeckoProcessType_Content
;
133 static bool gProcessMatchTable
[Module::kMaxProcessSelector
+ 1];
135 bool FastProcessSelectorMatches(ProcessSelector aSelector
) {
136 return gProcessMatchTable
[size_t(aSelector
)];
140 } // namespace mozilla
145 * A wrapper simple wrapper class, which can hold either a dynamic
146 * nsFactoryEntry instance, or a static StaticModule entry, and transparently
147 * forwards method calls to the wrapped object.
149 * This allows the same code to work with either static or dynamic modules
150 * without caring about the difference.
152 class MOZ_STACK_CLASS EntryWrapper final
{
154 explicit EntryWrapper(nsFactoryEntry
* aEntry
) : mEntry(aEntry
) {}
156 explicit EntryWrapper(const StaticModule
* aEntry
) : mEntry(aEntry
) {}
158 #define MATCH(type, ifFactory, ifStatic) \
160 type operator()(nsFactoryEntry* entry) { ifFactory; } \
161 type operator()(const StaticModule* entry) { ifStatic; } \
163 return mEntry.match((Matcher()))
166 MATCH(const nsID
&, return *entry
->mCIDEntry
->cid
, return entry
->CID());
169 already_AddRefed
<nsIFactory
> GetFactory() {
170 MATCH(already_AddRefed
<nsIFactory
>, return entry
->GetFactory(),
171 return entry
->GetFactory());
175 * Creates an instance of the underlying component. This should be used in
176 * preference to GetFactory()->CreateInstance() where appropriate, since it
177 * side-steps the necessity of creating a nsIFactory instance for static
180 nsresult
CreateInstance(const nsIID
& aIID
, void** aResult
) {
181 if (mEntry
.is
<nsFactoryEntry
*>()) {
182 return mEntry
.as
<nsFactoryEntry
*>()->CreateInstance(aIID
, aResult
);
184 return mEntry
.as
<const StaticModule
*>()->CreateInstance(aIID
, aResult
);
188 * Returns the cached service instance for this entry, if any. This should
189 * only be accessed while mLock is held.
191 nsISupports
* ServiceInstance() {
192 MATCH(nsISupports
*, return entry
->mServiceObject
,
193 return entry
->ServiceInstance());
195 void SetServiceInstance(already_AddRefed
<nsISupports
> aInst
) {
196 if (mEntry
.is
<nsFactoryEntry
*>()) {
197 mEntry
.as
<nsFactoryEntry
*>()->mServiceObject
= aInst
;
199 return mEntry
.as
<const StaticModule
*>()->SetServiceInstance(
205 * Returns the description string for the module this entry belongs to. For
206 * static entries, always returns "<unknown module>".
208 nsCString
ModuleDescription() {
210 return entry
->mModule
? entry
->mModule
->Description()
211 : "<unknown module>"_ns
,
212 return "<unknown module>"_ns
);
216 Variant
<nsFactoryEntry
*, const StaticModule
*> mEntry
;
221 // this is safe to call during InitXPCOM
222 static already_AddRefed
<nsIFile
> GetLocationFromDirectoryService(
224 nsCOMPtr
<nsIProperties
> directoryService
;
225 nsDirectoryService::Create(NS_GET_IID(nsIProperties
),
226 getter_AddRefs(directoryService
));
228 if (!directoryService
) {
232 nsCOMPtr
<nsIFile
> file
;
234 directoryService
->Get(aProp
, NS_GET_IID(nsIFile
), getter_AddRefs(file
));
239 return file
.forget();
242 static already_AddRefed
<nsIFile
> CloneAndAppend(nsIFile
* aBase
,
243 const nsACString
& aAppend
) {
245 aBase
->Clone(getter_AddRefs(f
));
250 f
->AppendNative(aAppend
);
254 ////////////////////////////////////////////////////////////////////////////////
255 // nsComponentManagerImpl
256 ////////////////////////////////////////////////////////////////////////////////
258 nsresult
nsComponentManagerImpl::Create(REFNSIID aIID
, void** aResult
) {
259 if (!gComponentManager
) {
260 return NS_ERROR_FAILURE
;
263 return gComponentManager
->QueryInterface(aIID
, aResult
);
266 static const int CONTRACTID_HASHTABLE_INITIAL_LENGTH
= 16;
268 nsComponentManagerImpl::nsComponentManagerImpl()
269 : mFactories(CONTRACTID_HASHTABLE_INITIAL_LENGTH
),
270 mContractIDs(CONTRACTID_HASHTABLE_INITIAL_LENGTH
),
271 mLock("nsComponentManagerImpl.mLock"),
272 mStatus(NOT_INITIALIZED
) {}
274 extern const mozilla::Module kPowerManagerModule
;
275 extern const mozilla::Module kContentProcessWidgetModule
;
276 #if defined(MOZ_WIDGET_COCOA) || defined(MOZ_WIDGET_UIKIT)
277 extern const mozilla::Module kWidgetModule
;
280 static nsTArray
<const mozilla::Module
*>* sExtraStaticModules
;
283 void nsComponentManagerImpl::InitializeStaticModules() {
284 if (sExtraStaticModules
) {
288 sExtraStaticModules
= new nsTArray
<const mozilla::Module
*>;
291 nsTArray
<nsComponentManagerImpl::ComponentLocation
>*
292 nsComponentManagerImpl::sModuleLocations
;
295 void nsComponentManagerImpl::InitializeModuleLocations() {
296 if (sModuleLocations
) {
300 sModuleLocations
= new nsTArray
<ComponentLocation
>;
303 nsresult
nsComponentManagerImpl::Init() {
305 gProcessMatchTable
[size_t(ProcessSelector::ANY_PROCESS
)] =
306 ProcessSelectorMatches(ProcessSelector::ANY_PROCESS
);
307 gProcessMatchTable
[size_t(ProcessSelector::MAIN_PROCESS_ONLY
)] =
308 ProcessSelectorMatches(ProcessSelector::MAIN_PROCESS_ONLY
);
309 gProcessMatchTable
[size_t(ProcessSelector::CONTENT_PROCESS_ONLY
)] =
310 ProcessSelectorMatches(ProcessSelector::CONTENT_PROCESS_ONLY
);
311 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_GPU_PROCESS
)] =
312 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_PROCESS
);
313 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_VR_PROCESS
)] =
314 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_VR_PROCESS
);
315 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_SOCKET_PROCESS
)] =
316 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_SOCKET_PROCESS
);
317 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_RDD_PROCESS
)] =
318 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_RDD_PROCESS
);
319 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_GPU_AND_MAIN_PROCESS
)] =
320 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_AND_MAIN_PROCESS
);
321 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_GPU_AND_VR_PROCESS
)] =
322 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_AND_VR_PROCESS
);
323 gProcessMatchTable
[size_t(
324 ProcessSelector::ALLOW_IN_GPU_AND_SOCKET_PROCESS
)] =
325 ProcessSelectorMatches(
326 ProcessSelector::ALLOW_IN_GPU_AND_SOCKET_PROCESS
);
327 gProcessMatchTable
[size_t(
328 ProcessSelector::ALLOW_IN_GPU_VR_AND_SOCKET_PROCESS
)] =
329 ProcessSelectorMatches(
330 ProcessSelector::ALLOW_IN_GPU_VR_AND_SOCKET_PROCESS
);
331 gProcessMatchTable
[size_t(
332 ProcessSelector::ALLOW_IN_RDD_AND_SOCKET_PROCESS
)] =
333 ProcessSelectorMatches(
334 ProcessSelector::ALLOW_IN_RDD_AND_SOCKET_PROCESS
);
335 gProcessMatchTable
[size_t(
336 ProcessSelector::ALLOW_IN_GPU_RDD_AND_SOCKET_PROCESS
)] =
337 ProcessSelectorMatches(
338 ProcessSelector::ALLOW_IN_GPU_RDD_AND_SOCKET_PROCESS
);
339 gProcessMatchTable
[size_t(
340 ProcessSelector::ALLOW_IN_GPU_RDD_SOCKET_AND_UTILITY_PROCESS
)] =
341 ProcessSelectorMatches(
342 ProcessSelector::ALLOW_IN_GPU_RDD_SOCKET_AND_UTILITY_PROCESS
);
343 gProcessMatchTable
[size_t(
344 ProcessSelector::ALLOW_IN_GPU_RDD_VR_AND_SOCKET_PROCESS
)] =
345 ProcessSelectorMatches(
346 ProcessSelector::ALLOW_IN_GPU_RDD_VR_AND_SOCKET_PROCESS
);
347 gProcessMatchTable
[size_t(
348 ProcessSelector::ALLOW_IN_GPU_RDD_VR_SOCKET_AND_UTILITY_PROCESS
)] =
349 ProcessSelectorMatches(
350 ProcessSelector::ALLOW_IN_GPU_RDD_VR_SOCKET_AND_UTILITY_PROCESS
);
353 MOZ_ASSERT(NOT_INITIALIZED
== mStatus
);
355 nsCOMPtr
<nsIFile
> greDir
= GetLocationFromDirectoryService(NS_GRE_DIR
);
356 nsCOMPtr
<nsIFile
> appDir
=
357 GetLocationFromDirectoryService(NS_XPCOM_CURRENT_PROCESS_DIR
);
359 InitializeStaticModules();
361 nsCategoryManager::GetSingleton()->SuppressNotifications(true);
363 RegisterModule(&kPowerManagerModule
);
364 RegisterModule(&kContentProcessWidgetModule
);
365 #if defined(MOZ_WIDGET_COCOA) || defined(MOZ_WIDGET_UIKIT)
366 RegisterModule(&kWidgetModule
);
369 for (uint32_t i
= 0; i
< sExtraStaticModules
->Length(); ++i
) {
370 RegisterModule((*sExtraStaticModules
)[i
]);
373 auto* catMan
= nsCategoryManager::GetSingleton();
374 for (const auto& cat
: gStaticCategories
) {
375 for (const auto& entry
: cat
) {
376 if (entry
.Active()) {
377 catMan
->AddCategoryEntry(cat
.Name(), entry
.Entry(), entry
.Value());
382 bool loadChromeManifests
;
383 switch (XRE_GetProcessType()) {
384 // We are going to assume that only a select few (see below) process types
385 // want to load chrome manifests, and that any new process types will not
386 // want to load them, because they're not going to be executing JS.
387 case GeckoProcessType_RemoteSandboxBroker
:
389 loadChromeManifests
= false;
392 // XXX The check this code replaced implicitly let through all of these
393 // process types, but presumably only the default (parent) and content
394 // processes really need chrome manifests...?
395 case GeckoProcessType_Default
:
396 case GeckoProcessType_Content
:
397 case GeckoProcessType_GMPlugin
:
398 loadChromeManifests
= true;
402 if (loadChromeManifests
) {
403 // This needs to be called very early, before anything in nsLayoutModule is
404 // used, and before any calls are made into the JS engine.
405 nsLayoutModuleInitialize();
407 mJSLoaderReady
= true;
409 // The overall order in which chrome.manifests are expected to be treated
411 // - greDir's omni.ja or greDir
412 // - appDir's omni.ja or appDir
414 InitializeModuleLocations();
415 ComponentLocation
* cl
= sModuleLocations
->AppendElement();
416 cl
->type
= NS_APP_LOCATION
;
417 RefPtr
<nsZipArchive
> greOmnijar
=
418 mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE
);
420 cl
->location
.Init(greOmnijar
, "chrome.manifest");
422 nsCOMPtr
<nsIFile
> lf
= CloneAndAppend(greDir
, "chrome.manifest"_ns
);
423 cl
->location
.Init(lf
);
426 RefPtr
<nsZipArchive
> appOmnijar
=
427 mozilla::Omnijar::GetReader(mozilla::Omnijar::APP
);
429 cl
= sModuleLocations
->AppendElement();
430 cl
->type
= NS_APP_LOCATION
;
431 cl
->location
.Init(appOmnijar
, "chrome.manifest");
434 appDir
->Equals(greDir
, &equals
);
436 cl
= sModuleLocations
->AppendElement();
437 cl
->type
= NS_APP_LOCATION
;
438 nsCOMPtr
<nsIFile
> lf
= CloneAndAppend(appDir
, "chrome.manifest"_ns
);
439 cl
->location
.Init(lf
);
443 RereadChromeManifests(false);
446 nsCategoryManager::GetSingleton()->SuppressNotifications(false);
448 RegisterWeakMemoryReporter(this);
450 // NB: The logging preference watcher needs to be registered late enough in
451 // startup that it's okay to use the preference system, but also as soon as
452 // possible so that log modules enabled via preferences are turned on as
453 // early as possible.
455 // We can't initialize the preference watcher when the log module manager is
456 // initialized, as a number of things attempt to start logging before the
457 // preference system is initialized.
459 // The preference system is registered as a component so at this point during
460 // component manager initialization we know it is setup and we can register
461 // for notifications.
462 LogModulePrefWatcher::RegisterPrefWatcher();
464 // Unfortunately, we can't register the nsCategoryManager memory reporter
465 // in its constructor (which is triggered by the GetSingleton() call
466 // above) because the memory reporter manager isn't initialized at that
467 // point. So we wait until now.
468 nsCategoryManager::GetSingleton()->InitMemoryReporter();
470 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
471 ("nsComponentManager: Initialized."));
475 MOZ_ASSERT(!XRE_IsContentProcess() ||
476 mFactories
.Count() > CONTRACTID_HASHTABLE_INITIAL_LENGTH
/ 3,
477 "Initial component hashtable size is too large");
482 static const int kModuleVersionWithSelector
= 51;
484 template <typename T
>
485 static void AssertNotMallocAllocated(T
* aPtr
) {
486 #if defined(DEBUG) && defined(MOZ_MEMORY)
487 jemalloc_ptr_info_t info
;
488 jemalloc_ptr_info((void*)aPtr
, &info
);
489 MOZ_ASSERT(info
.tag
== TagUnknown
);
493 template <typename T
>
494 static void AssertNotStackAllocated(T
* aPtr
) {
495 // On all of our supported platforms, the stack grows down. Any address
496 // located below the address of our argument is therefore guaranteed not to be
497 // stack-allocated by the caller.
499 // For addresses above our argument, things get trickier. The main thread
500 // stack is traditionally placed at the top of the program's address space,
501 // but that is becoming less reliable as more and more systems adopt address
502 // space layout randomization strategies, so we have to guess how much space
503 // above our argument pointer we need to care about.
505 // On most systems, we're guaranteed at least several KiB at the top of each
506 // stack for TLS. We'd probably be safe assuming at least 4KiB in the stack
507 // segment above our argument address, but safer is... well, safer.
509 // For threads with huge stacks, it's theoretically possible that we could
510 // wind up being passed a stack-allocated string from farther up the stack,
511 // but this is a best-effort thing, so we'll assume we only care about the
512 // immediate caller. For that case, max 2KiB per stack frame is probably a
513 // reasonable guess most of the time, and is less than the ~4KiB that we
514 // expect for TLS, so go with that to avoid the risk of bumping into heap
515 // data just above the stack.
517 static constexpr size_t kFuzz
= 2048;
519 MOZ_ASSERT(uintptr_t(aPtr
) < uintptr_t(&aPtr
) ||
520 uintptr_t(aPtr
) > uintptr_t(&aPtr
) + kFuzz
);
524 static inline nsCString
AsLiteralCString(const char* aStr
) {
525 AssertNotMallocAllocated(aStr
);
526 AssertNotStackAllocated(aStr
);
529 str
.AssignLiteral(aStr
, strlen(aStr
));
533 void nsComponentManagerImpl::RegisterModule(const mozilla::Module
* aModule
) {
534 mLock
.AssertNotCurrentThreadOwns();
536 if (aModule
->mVersion
>= kModuleVersionWithSelector
&&
537 !ProcessSelectorMatches(aModule
->selector
)) {
542 // Scope the monitor so that we don't hold it while calling into the
544 MonitorAutoLock
lock(mLock
);
546 KnownModule
* m
= new KnownModule(aModule
);
547 mKnownStaticModules
.AppendElement(m
);
549 if (aModule
->mCIDs
) {
550 const mozilla::Module::CIDEntry
* entry
;
551 for (entry
= aModule
->mCIDs
; entry
->cid
; ++entry
) {
552 RegisterCIDEntryLocked(entry
, m
);
556 if (aModule
->mContractIDs
) {
557 const mozilla::Module::ContractIDEntry
* entry
;
558 for (entry
= aModule
->mContractIDs
; entry
->contractid
; ++entry
) {
559 RegisterContractIDLocked(entry
);
561 MOZ_ASSERT(!entry
->cid
, "Incorrectly terminated contract list");
565 if (aModule
->mCategoryEntries
) {
566 const mozilla::Module::CategoryEntry
* entry
;
567 for (entry
= aModule
->mCategoryEntries
; entry
->category
; ++entry
)
568 nsCategoryManager::GetSingleton()->AddCategoryEntry(
569 AsLiteralCString(entry
->category
), AsLiteralCString(entry
->entry
),
570 AsLiteralCString(entry
->value
));
574 void nsComponentManagerImpl::RegisterCIDEntryLocked(
575 const mozilla::Module::CIDEntry
* aEntry
, KnownModule
* aModule
) {
576 mLock
.AssertCurrentThreadOwns();
578 if (!ProcessSelectorMatches(aEntry
->processSelector
)) {
583 // If we're still in the static initialization phase, check that we're not
584 // registering something that was already registered.
585 if (mStatus
!= NORMAL
) {
586 if (StaticComponents::LookupByCID(*aEntry
->cid
)) {
587 MOZ_CRASH_UNSAFE_PRINTF(
588 "While registering XPCOM module %s, trying to re-register CID '%s' "
589 "already registered by a static component.",
590 aModule
->Description().get(), AutoIDString(*aEntry
->cid
).get());
595 mFactories
.WithEntryHandle(aEntry
->cid
, [&](auto&& entry
) {
596 mLock
.AssertCurrentThreadOwns();
598 nsFactoryEntry
* f
= entry
.Data();
599 NS_WARNING("Re-registering a CID?");
603 existing
= f
->mModule
->Description();
605 existing
= "<unknown module>";
607 MonitorAutoUnlock
unlock(mLock
);
609 "While registering XPCOM module %s, trying to re-register CID '%s' "
610 "already registered by %s.",
611 aModule
->Description().get(), AutoIDString(*aEntry
->cid
).get(),
614 entry
.Insert(new nsFactoryEntry(aEntry
, aModule
));
619 void nsComponentManagerImpl::RegisterContractIDLocked(
620 const mozilla::Module::ContractIDEntry
* aEntry
) {
621 mLock
.AssertCurrentThreadOwns();
623 if (!ProcessSelectorMatches(aEntry
->processSelector
)) {
628 // If we're still in the static initialization phase, check that we're not
629 // registering something that was already registered.
630 if (mStatus
!= NORMAL
) {
631 if (const StaticModule
* module
= StaticComponents::LookupByContractID(
632 nsAutoCString(aEntry
->contractid
))) {
633 MOZ_CRASH_UNSAFE_PRINTF(
634 "Could not map contract ID '%s' to CID %s because it is already "
636 aEntry
->contractid
, AutoIDString(*aEntry
->cid
).get(),
637 AutoIDString(module
->CID()).get());
642 nsFactoryEntry
* f
= mFactories
.Get(aEntry
->cid
);
644 NS_WARNING("No CID found when attempting to map contract ID");
646 MonitorAutoUnlock
unlock(mLock
);
648 "Could not map contract ID '%s' to CID %s because no implementation of "
649 "the CID is registered.",
650 aEntry
->contractid
, AutoIDString(*aEntry
->cid
).get());
655 mContractIDs
.InsertOrUpdate(AsLiteralCString(aEntry
->contractid
), f
);
658 static void DoRegisterManifest(NSLocationType aType
, FileLocation
& aFile
,
660 auto result
= URLPreloader::Read(aFile
);
662 nsCString
buf(result
.unwrap());
663 ParseManifest(aType
, aFile
, buf
.BeginWriting(), aChromeOnly
);
664 } else if (NS_BOOTSTRAPPED_LOCATION
!= aType
) {
666 aFile
.GetURIString(uri
);
667 LogMessage("Could not read chrome manifest '%s'.", uri
.get());
671 void nsComponentManagerImpl::RegisterManifest(NSLocationType aType
,
674 DoRegisterManifest(aType
, aFile
, aChromeOnly
);
677 void nsComponentManagerImpl::ManifestManifest(ManifestProcessingContext
& aCx
,
678 int aLineNo
, char* const* aArgv
) {
679 char* file
= aArgv
[0];
680 FileLocation
f(aCx
.mFile
, file
);
681 RegisterManifest(aCx
.mType
, f
, aCx
.mChromeOnly
);
684 void nsComponentManagerImpl::ManifestCategory(ManifestProcessingContext
& aCx
,
685 int aLineNo
, char* const* aArgv
) {
686 char* category
= aArgv
[0];
687 char* key
= aArgv
[1];
688 char* value
= aArgv
[2];
690 nsCategoryManager::GetSingleton()->AddCategoryEntry(
691 nsDependentCString(category
), nsDependentCString(key
),
692 nsDependentCString(value
));
695 void nsComponentManagerImpl::RereadChromeManifests(bool aChromeOnly
) {
696 for (uint32_t i
= 0; i
< sModuleLocations
->Length(); ++i
) {
697 ComponentLocation
& l
= sModuleLocations
->ElementAt(i
);
698 RegisterManifest(l
.type
, l
.location
, aChromeOnly
);
701 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
703 obs
->NotifyObservers(nullptr, "chrome-manifests-loaded", nullptr);
707 bool nsComponentManagerImpl::KnownModule::Load() {
713 if (mModule
->loadProc
) {
714 nsresult rv
= mModule
->loadProc();
725 nsCString
nsComponentManagerImpl::KnownModule::Description() const {
726 return "<static module>"_ns
;
729 nsresult
nsComponentManagerImpl::Shutdown(void) {
730 MOZ_ASSERT(NORMAL
== mStatus
);
732 mStatus
= SHUTDOWN_IN_PROGRESS
;
734 // Shutdown the component manager
735 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
736 ("nsComponentManager: Beginning Shutdown."));
738 UnregisterWeakMemoryReporter(this);
740 // Release all cached factories
741 mContractIDs
.Clear();
742 mFactories
.Clear(); // XXX release the objects, don't just clear
743 mKnownStaticModules
.Clear();
745 StaticComponents::Shutdown();
747 delete sExtraStaticModules
;
748 delete sModuleLocations
;
750 mStatus
= SHUTDOWN_COMPLETE
;
752 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
753 ("nsComponentManager: Shutdown complete."));
758 nsComponentManagerImpl::~nsComponentManagerImpl() {
759 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
760 ("nsComponentManager: Beginning destruction."));
762 if (SHUTDOWN_COMPLETE
!= mStatus
) {
766 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
767 ("nsComponentManager: Destroyed."));
770 NS_IMPL_ISUPPORTS(nsComponentManagerImpl
, nsIComponentManager
,
771 nsIServiceManager
, nsIComponentRegistrar
,
772 nsISupportsWeakReference
, nsIInterfaceRequestor
,
775 nsresult
nsComponentManagerImpl::GetInterface(const nsIID
& aUuid
,
777 NS_WARNING("This isn't supported");
778 // fall through to QI as anything QIable is a superset of what can be
779 // got via the GetInterface()
780 return QueryInterface(aUuid
, aResult
);
783 Maybe
<EntryWrapper
> nsComponentManagerImpl::LookupByCID(const nsID
& aCID
) {
784 return LookupByCID(MonitorAutoLock(mLock
), aCID
);
787 Maybe
<EntryWrapper
> nsComponentManagerImpl::LookupByCID(const MonitorAutoLock
&,
789 if (const StaticModule
* module
= StaticComponents::LookupByCID(aCID
)) {
790 return Some(EntryWrapper(module
));
792 if (nsFactoryEntry
* entry
= mFactories
.Get(&aCID
)) {
793 return Some(EntryWrapper(entry
));
798 Maybe
<EntryWrapper
> nsComponentManagerImpl::LookupByContractID(
799 const nsACString
& aContractID
) {
800 return LookupByContractID(MonitorAutoLock(mLock
), aContractID
);
803 Maybe
<EntryWrapper
> nsComponentManagerImpl::LookupByContractID(
804 const MonitorAutoLock
&, const nsACString
& aContractID
) {
805 if (const StaticModule
* module
=
806 StaticComponents::LookupByContractID(aContractID
)) {
807 return Some(EntryWrapper(module
));
809 if (nsFactoryEntry
* entry
= mContractIDs
.Get(aContractID
)) {
810 // UnregisterFactory might have left a stale nsFactoryEntry in
811 // mContractIDs, so we should check to see whether this entry has
813 if (entry
->mModule
|| entry
->mFactory
|| entry
->mServiceObject
) {
814 return Some(EntryWrapper(entry
));
820 already_AddRefed
<nsIFactory
> nsComponentManagerImpl::FindFactory(
821 const nsCID
& aClass
) {
822 Maybe
<EntryWrapper
> e
= LookupByCID(aClass
);
827 return e
->GetFactory();
830 already_AddRefed
<nsIFactory
> nsComponentManagerImpl::FindFactory(
831 const char* aContractID
, uint32_t aContractIDLen
) {
832 Maybe
<EntryWrapper
> entry
=
833 LookupByContractID(nsDependentCString(aContractID
, aContractIDLen
));
838 return entry
->GetFactory();
844 * Given a classID, this finds the singleton ClassObject that implements the
845 * CID. Returns an interface of type aIID off the singleton classobject.
848 nsComponentManagerImpl::GetClassObject(const nsCID
& aClass
, const nsIID
& aIID
,
852 if (MOZ_LOG_TEST(nsComponentManagerLog
, LogLevel::Debug
)) {
853 char* buf
= aClass
.ToString();
854 PR_LogPrint("nsComponentManager: GetClassObject(%s)", buf
);
860 MOZ_ASSERT(aResult
!= nullptr);
862 nsCOMPtr
<nsIFactory
> factory
= FindFactory(aClass
);
864 return NS_ERROR_FACTORY_NOT_REGISTERED
;
867 rv
= factory
->QueryInterface(aIID
, aResult
);
870 nsComponentManagerLog
, LogLevel::Warning
,
871 ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
877 nsComponentManagerImpl::GetClassObjectByContractID(const char* aContractID
,
880 if (NS_WARN_IF(!aResult
) || NS_WARN_IF(!aContractID
)) {
881 return NS_ERROR_INVALID_ARG
;
886 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
887 ("nsComponentManager: GetClassObjectByContractID(%s)", aContractID
));
889 nsCOMPtr
<nsIFactory
> factory
= FindFactory(aContractID
, strlen(aContractID
));
891 return NS_ERROR_FACTORY_NOT_REGISTERED
;
894 rv
= factory
->QueryInterface(aIID
, aResult
);
896 MOZ_LOG(nsComponentManagerLog
, LogLevel::Warning
,
897 ("\t\tGetClassObjectByContractID() %s",
898 NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
906 * Create an instance of an object that implements an interface and belongs
907 * to the implementation aClass using the factory. The factory is immediately
908 * released and not held onto for any longer.
911 nsComponentManagerImpl::CreateInstance(const nsCID
& aClass
, const nsIID
& aIID
,
913 // test this first, since there's no point in creating a component during
914 // shutdown -- whether it's available or not would depend on the order it
915 // occurs in the list
916 if (gXPCOMShuttingDown
) {
917 // When processing shutdown, don't process new GetService() requests
918 #ifdef SHOW_DENIED_ON_SHUTDOWN
920 "Creating new instance on shutdown. Denied.\n"
921 " CID: %s\n IID: %s\n",
922 AutoIDString(aClass
).get(), AutoIDString(aIID
).get());
923 #endif /* SHOW_DENIED_ON_SHUTDOWN */
924 return NS_ERROR_UNEXPECTED
;
928 return NS_ERROR_NULL_POINTER
;
932 Maybe
<EntryWrapper
> entry
= LookupByCID(aClass
);
935 return NS_ERROR_FACTORY_NOT_REGISTERED
;
938 #ifdef SHOW_CI_ON_EXISTING_SERVICE
939 if (entry
->ServiceInstance()) {
940 nsAutoCString message
;
941 message
= "You are calling CreateInstance \""_ns
+ AutoIDString(aClass
) +
942 "\" when a service for this CID already exists!"_ns
;
943 NS_ERROR(message
.get());
948 nsCOMPtr
<nsIFactory
> factory
= entry
->GetFactory();
950 rv
= factory
->CreateInstance(aIID
, aResult
);
951 if (NS_SUCCEEDED(rv
) && !*aResult
) {
952 NS_ERROR("Factory did not return an object but returned success!");
953 rv
= NS_ERROR_SERVICE_NOT_AVAILABLE
;
956 // Translate error values
957 rv
= NS_ERROR_FACTORY_NOT_REGISTERED
;
960 if (MOZ_LOG_TEST(nsComponentManagerLog
, LogLevel::Warning
)) {
961 char* buf
= aClass
.ToString();
962 MOZ_LOG(nsComponentManagerLog
, LogLevel::Warning
,
963 ("nsComponentManager: CreateInstance(%s) %s", buf
,
964 NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
974 * CreateInstanceByContractID()
976 * A variant of CreateInstance() that creates an instance of the object that
977 * implements the interface aIID and whose implementation has a contractID
980 * This is only a convenience routine that turns around can calls the
981 * CreateInstance() with classid and iid.
984 nsComponentManagerImpl::CreateInstanceByContractID(const char* aContractID
,
987 if (NS_WARN_IF(!aContractID
)) {
988 return NS_ERROR_INVALID_ARG
;
991 // test this first, since there's no point in creating a component during
992 // shutdown -- whether it's available or not would depend on the order it
993 // occurs in the list
994 if (gXPCOMShuttingDown
) {
995 // When processing shutdown, don't process new GetService() requests
996 #ifdef SHOW_DENIED_ON_SHUTDOWN
998 "Creating new instance on shutdown. Denied.\n"
999 " ContractID: %s\n IID: %s\n",
1000 aContractID
, AutoIDString(aIID
).get());
1001 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1002 return NS_ERROR_UNEXPECTED
;
1006 return NS_ERROR_NULL_POINTER
;
1010 Maybe
<EntryWrapper
> entry
=
1011 LookupByContractID(nsDependentCString(aContractID
));
1014 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1017 #ifdef SHOW_CI_ON_EXISTING_SERVICE
1018 if (entry
->ServiceInstance()) {
1019 nsAutoCString message
;
1021 "You are calling CreateInstance \""_ns
+
1022 nsDependentCString(aContractID
) +
1024 "\" when a service for this CID already exists! "
1025 "Add it to abusedContracts to track down the service consumer.");
1026 NS_ERROR(message
.get());
1031 nsCOMPtr
<nsIFactory
> factory
= entry
->GetFactory();
1033 rv
= factory
->CreateInstance(aIID
, aResult
);
1034 if (NS_SUCCEEDED(rv
) && !*aResult
) {
1035 NS_ERROR("Factory did not return an object but returned success!");
1036 rv
= NS_ERROR_SERVICE_NOT_AVAILABLE
;
1039 // Translate error values
1040 rv
= NS_ERROR_FACTORY_NOT_REGISTERED
;
1043 MOZ_LOG(nsComponentManagerLog
, LogLevel::Warning
,
1044 ("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID
,
1045 NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
1050 nsresult
nsComponentManagerImpl::FreeServices() {
1051 NS_ASSERTION(gXPCOMShuttingDown
,
1052 "Must be shutting down in order to free all services");
1054 if (!gXPCOMShuttingDown
) {
1055 return NS_ERROR_FAILURE
;
1058 for (nsFactoryEntry
* entry
: mFactories
.Values()) {
1059 entry
->mFactory
= nullptr;
1060 entry
->mServiceObject
= nullptr;
1063 for (const auto& module
: gStaticModules
) {
1064 module
.SetServiceInstance(nullptr);
1070 // This should only ever be called within the monitor!
1071 nsComponentManagerImpl::PendingServiceInfo
*
1072 nsComponentManagerImpl::AddPendingService(const nsCID
& aServiceCID
,
1073 PRThread
* aThread
) {
1074 PendingServiceInfo
* newInfo
= mPendingServices
.AppendElement();
1076 newInfo
->cid
= &aServiceCID
;
1077 newInfo
->thread
= aThread
;
1082 // This should only ever be called within the monitor!
1083 void nsComponentManagerImpl::RemovePendingService(MonitorAutoLock
& aLock
,
1084 const nsCID
& aServiceCID
) {
1085 uint32_t pendingCount
= mPendingServices
.Length();
1086 for (uint32_t index
= 0; index
< pendingCount
; ++index
) {
1087 const PendingServiceInfo
& info
= mPendingServices
.ElementAt(index
);
1088 if (info
.cid
->Equals(aServiceCID
)) {
1089 mPendingServices
.RemoveElementAt(index
);
1096 // This should only ever be called within the monitor!
1097 PRThread
* nsComponentManagerImpl::GetPendingServiceThread(
1098 const nsCID
& aServiceCID
) const {
1099 uint32_t pendingCount
= mPendingServices
.Length();
1100 for (uint32_t index
= 0; index
< pendingCount
; ++index
) {
1101 const PendingServiceInfo
& info
= mPendingServices
.ElementAt(index
);
1102 if (info
.cid
->Equals(aServiceCID
)) {
1109 nsresult
nsComponentManagerImpl::GetServiceLocked(Maybe
<MonitorAutoLock
>& aLock
,
1110 EntryWrapper
& aEntry
,
1113 MOZ_ASSERT(aLock
.isSome());
1114 if (!aLock
.isSome()) {
1115 return NS_ERROR_INVALID_ARG
;
1118 if (auto* service
= aEntry
.ServiceInstance()) {
1120 return service
->QueryInterface(aIID
, aResult
);
1123 PRThread
* currentPRThread
= PR_GetCurrentThread();
1124 MOZ_ASSERT(currentPRThread
, "This should never be null!");
1126 PRThread
* pendingPRThread
;
1127 while ((pendingPRThread
= GetPendingServiceThread(aEntry
.CID()))) {
1128 if (pendingPRThread
== currentPRThread
) {
1129 NS_ERROR("Recursive GetService!");
1130 return NS_ERROR_NOT_AVAILABLE
;
1136 // It's still possible that the other thread failed to create the
1137 // service so we're not guaranteed to have an entry or service yet.
1138 if (auto* service
= aEntry
.ServiceInstance()) {
1140 return service
->QueryInterface(aIID
, aResult
);
1143 DebugOnly
<PendingServiceInfo
*> newInfo
=
1144 AddPendingService(aEntry
.CID(), currentPRThread
);
1145 NS_ASSERTION(newInfo
, "Failed to add info to the array!");
1147 // We need to not be holding the service manager's lock while calling
1148 // CreateInstance, because it invokes user code which could try to re-enter
1149 // the service manager:
1151 nsCOMPtr
<nsISupports
> service
;
1152 auto cleanup
= MakeScopeExit([&]() {
1153 // `service` must be released after the lock is released, so if we fail and
1154 // still have a reference, release the lock before releasing it.
1156 MOZ_ASSERT(aLock
.isSome());
1162 mLock
.AssertCurrentThreadOwns();
1164 MonitorAutoUnlock
unlock(mLock
);
1165 AUTO_PROFILER_MARKER_TEXT(
1166 "GetService", OTHER
, MarkerStack::Capture(),
1167 nsDependentCString(nsIDToCString(aEntry
.CID()).get()));
1168 rv
= aEntry
.CreateInstance(aIID
, getter_AddRefs(service
));
1170 if (NS_SUCCEEDED(rv
) && !service
) {
1171 NS_ERROR("Factory did not return an object but returned success");
1172 return NS_ERROR_SERVICE_NOT_AVAILABLE
;
1176 pendingPRThread
= GetPendingServiceThread(aEntry
.CID());
1177 MOZ_ASSERT(pendingPRThread
== currentPRThread
,
1178 "Pending service array has been changed!");
1180 MOZ_ASSERT(aLock
.isSome());
1181 RemovePendingService(*aLock
, aEntry
.CID());
1183 if (NS_FAILED(rv
)) {
1187 NS_ASSERTION(!aEntry
.ServiceInstance(),
1188 "Created two instances of a service!");
1190 aEntry
.SetServiceInstance(service
.forget());
1194 *aResult
= do_AddRef(aEntry
.ServiceInstance()).take();
1199 nsComponentManagerImpl::GetService(const nsCID
& aClass
, const nsIID
& aIID
,
1201 // test this first, since there's no point in returning a service during
1202 // shutdown -- whether it's available or not would depend on the order it
1203 // occurs in the list
1204 if (gXPCOMShuttingDown
) {
1205 // When processing shutdown, don't process new GetService() requests
1206 #ifdef SHOW_DENIED_ON_SHUTDOWN
1208 "Getting service on shutdown. Denied.\n"
1209 " CID: %s\n IID: %s\n",
1210 AutoIDString(aClass
).get(), AutoIDString(aIID
).get());
1211 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1212 return NS_ERROR_UNEXPECTED
;
1215 Maybe
<MonitorAutoLock
> lock(std::in_place
, mLock
);
1217 Maybe
<EntryWrapper
> entry
= LookupByCID(*lock
, aClass
);
1219 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1222 return GetServiceLocked(lock
, *entry
, aIID
, aResult
);
1225 nsresult
nsComponentManagerImpl::GetService(ModuleID aId
, const nsIID
& aIID
,
1227 const auto& entry
= gStaticModules
[size_t(aId
)];
1229 // test this first, since there's no point in returning a service during
1230 // shutdown -- whether it's available or not would depend on the order it
1231 // occurs in the list
1232 if (gXPCOMShuttingDown
) {
1233 // When processing shutdown, don't process new GetService() requests
1234 #ifdef SHOW_DENIED_ON_SHUTDOWN
1236 "Getting service on shutdown. Denied.\n"
1237 " CID: %s\n IID: %s\n",
1238 AutoIDString(entry
.CID()).get(), AutoIDString(aIID
).get());
1239 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1240 return NS_ERROR_UNEXPECTED
;
1243 Maybe
<MonitorAutoLock
> lock(std::in_place
, mLock
);
1245 Maybe
<EntryWrapper
> wrapper
;
1246 if (entry
.Overridable()) {
1247 // If we expect this service to be overridden by test code, we need to look
1248 // it up by contract ID every time.
1249 wrapper
= LookupByContractID(*lock
, entry
.ContractID());
1251 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1253 } else if (!entry
.Active()) {
1254 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1256 wrapper
.emplace(&entry
);
1258 return GetServiceLocked(lock
, *wrapper
, aIID
, aResult
);
1262 nsComponentManagerImpl::IsServiceInstantiated(const nsCID
& aClass
,
1265 // Now we want to get the service if we already got it. If not, we don't want
1266 // to create an instance of it. mmh!
1268 // test this first, since there's no point in returning a service during
1269 // shutdown -- whether it's available or not would depend on the order it
1270 // occurs in the list
1271 if (gXPCOMShuttingDown
) {
1272 // When processing shutdown, don't process new GetService() requests
1273 #ifdef SHOW_DENIED_ON_SHUTDOWN
1275 "Checking for service on shutdown. Denied.\n"
1276 " CID: %s\n IID: %s\n",
1277 AutoIDString(aClass
).get(), AutoIDString(aIID
).get());
1278 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1279 return NS_ERROR_UNEXPECTED
;
1282 if (Maybe
<EntryWrapper
> entry
= LookupByCID(aClass
)) {
1283 if (auto* service
= entry
->ServiceInstance()) {
1284 nsCOMPtr
<nsISupports
> instance
;
1285 nsresult rv
= service
->QueryInterface(aIID
, getter_AddRefs(instance
));
1286 *aResult
= (instance
!= nullptr);
1296 nsComponentManagerImpl::IsServiceInstantiatedByContractID(
1297 const char* aContractID
, const nsIID
& aIID
, bool* aResult
) {
1298 // Now we want to get the service if we already got it. If not, we don't want
1299 // to create an instance of it. mmh!
1301 // test this first, since there's no point in returning a service during
1302 // shutdown -- whether it's available or not would depend on the order it
1303 // occurs in the list
1304 if (gXPCOMShuttingDown
) {
1305 // When processing shutdown, don't process new GetService() requests
1306 #ifdef SHOW_DENIED_ON_SHUTDOWN
1308 "Checking for service on shutdown. Denied.\n"
1309 " ContractID: %s\n IID: %s\n",
1310 aContractID
, AutoIDString(aIID
).get());
1311 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1312 return NS_ERROR_UNEXPECTED
;
1315 if (Maybe
<EntryWrapper
> entry
=
1316 LookupByContractID(nsDependentCString(aContractID
))) {
1317 if (auto* service
= entry
->ServiceInstance()) {
1318 nsCOMPtr
<nsISupports
> instance
;
1319 nsresult rv
= service
->QueryInterface(aIID
, getter_AddRefs(instance
));
1320 *aResult
= (instance
!= nullptr);
1330 nsComponentManagerImpl::GetServiceByContractID(const char* aContractID
,
1333 // test this first, since there's no point in returning a service during
1334 // shutdown -- whether it's available or not would depend on the order it
1335 // occurs in the list
1336 if (gXPCOMShuttingDown
) {
1337 // When processing shutdown, don't process new GetService() requests
1338 #ifdef SHOW_DENIED_ON_SHUTDOWN
1340 "Getting service on shutdown. Denied.\n"
1341 " ContractID: %s\n IID: %s\n",
1342 aContractID
, AutoIDString(aIID
).get());
1343 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1344 return NS_ERROR_UNEXPECTED
;
1347 AUTO_PROFILER_LABEL_DYNAMIC_CSTR_NONSENSITIVE("GetServiceByContractID", OTHER
,
1349 Maybe
<MonitorAutoLock
> lock(std::in_place
, mLock
);
1351 Maybe
<EntryWrapper
> entry
=
1352 LookupByContractID(*lock
, nsDependentCString(aContractID
));
1354 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1357 return GetServiceLocked(lock
, *entry
, aIID
, aResult
);
1361 nsComponentManagerImpl::RegisterFactory(const nsCID
& aClass
, const char* aName
,
1362 const char* aContractID
,
1363 nsIFactory
* aFactory
) {
1365 // If a null factory is passed in, this call just wants to reset
1366 // the contract ID to point to an existing CID entry.
1368 return NS_ERROR_INVALID_ARG
;
1371 nsDependentCString
contractID(aContractID
);
1373 MonitorAutoLock
lock(mLock
);
1374 nsFactoryEntry
* oldf
= mFactories
.Get(&aClass
);
1376 StaticComponents::InvalidateContractID(contractID
);
1377 mContractIDs
.InsertOrUpdate(contractID
, oldf
);
1381 if (StaticComponents::LookupByCID(aClass
)) {
1382 // If this is the CID of a static module, just reset the invalid bit of
1383 // the static entry for this contract ID, and assume it points to the
1385 if (StaticComponents::InvalidateContractID(contractID
, false)) {
1386 mContractIDs
.Remove(contractID
);
1390 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1393 auto f
= MakeUnique
<nsFactoryEntry
>(aClass
, aFactory
);
1395 MonitorAutoLock
lock(mLock
);
1396 return mFactories
.WithEntryHandle(f
->mCIDEntry
->cid
, [&](auto&& entry
) {
1398 return NS_ERROR_FACTORY_EXISTS
;
1400 if (StaticComponents::LookupByCID(*f
->mCIDEntry
->cid
)) {
1401 return NS_ERROR_FACTORY_EXISTS
;
1404 nsDependentCString
contractID(aContractID
);
1405 mContractIDs
.InsertOrUpdate(contractID
, f
.get());
1406 // We allow dynamically-registered contract IDs to override static
1407 // entries, so invalidate any static entry for this contract ID.
1408 StaticComponents::InvalidateContractID(contractID
);
1410 entry
.Insert(f
.release());
1417 nsComponentManagerImpl::UnregisterFactory(const nsCID
& aClass
,
1418 nsIFactory
* aFactory
) {
1419 // Don't release the dying factory or service object until releasing
1420 // the component manager monitor.
1421 nsCOMPtr
<nsIFactory
> dyingFactory
;
1422 nsCOMPtr
<nsISupports
> dyingServiceObject
;
1425 MonitorAutoLock
lock(mLock
);
1426 auto entry
= mFactories
.Lookup(&aClass
);
1427 nsFactoryEntry
* f
= entry
? entry
.Data() : nullptr;
1428 if (!f
|| f
->mFactory
!= aFactory
) {
1429 // Note: We do not support unregistering static factories.
1430 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1435 // This might leave a stale contractid -> factory mapping in
1436 // place, so null out the factory entry (see
1437 // nsFactoryEntry::GetFactory)
1438 f
->mFactory
.swap(dyingFactory
);
1439 f
->mServiceObject
.swap(dyingServiceObject
);
1446 nsComponentManagerImpl::AutoRegister(nsIFile
* aLocation
) {
1447 XRE_AddManifestLocation(NS_EXTENSION_LOCATION
, aLocation
);
1452 nsComponentManagerImpl::AutoUnregister(nsIFile
* aLocation
) {
1453 NS_ERROR("AutoUnregister not implemented.");
1454 return NS_ERROR_NOT_IMPLEMENTED
;
1458 nsComponentManagerImpl::RegisterFactoryLocation(
1459 const nsCID
& aCID
, const char* aClassName
, const char* aContractID
,
1460 nsIFile
* aFile
, const char* aLoaderStr
, const char* aType
) {
1461 NS_ERROR("RegisterFactoryLocation not implemented.");
1462 return NS_ERROR_NOT_IMPLEMENTED
;
1466 nsComponentManagerImpl::UnregisterFactoryLocation(const nsCID
& aCID
,
1468 NS_ERROR("UnregisterFactoryLocation not implemented.");
1469 return NS_ERROR_NOT_IMPLEMENTED
;
1473 nsComponentManagerImpl::IsCIDRegistered(const nsCID
& aClass
, bool* aResult
) {
1474 *aResult
= LookupByCID(aClass
).isSome();
1479 nsComponentManagerImpl::IsContractIDRegistered(const char* aClass
,
1481 if (NS_WARN_IF(!aClass
)) {
1482 return NS_ERROR_INVALID_ARG
;
1485 Maybe
<EntryWrapper
> entry
= LookupByContractID(nsDependentCString(aClass
));
1487 *aResult
= entry
.isSome();
1492 nsComponentManagerImpl::GetContractIDs(nsTArray
<nsCString
>& aResult
) {
1493 aResult
= ToTArray
<nsTArray
<nsCString
>>(mContractIDs
.Keys());
1495 for (const auto& entry
: gContractEntries
) {
1496 if (!entry
.Invalid()) {
1497 aResult
.AppendElement(entry
.ContractID());
1505 nsComponentManagerImpl::CIDToContractID(const nsCID
& aClass
, char** aResult
) {
1506 NS_ERROR("CIDTOContractID not implemented");
1507 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1511 nsComponentManagerImpl::ContractIDToCID(const char* aContractID
,
1514 MonitorAutoLock
lock(mLock
);
1515 Maybe
<EntryWrapper
> entry
=
1516 LookupByContractID(lock
, nsDependentCString(aContractID
));
1518 *aResult
= (nsCID
*)moz_xmalloc(sizeof(nsCID
));
1519 **aResult
= entry
->CID();
1524 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1527 MOZ_DEFINE_MALLOC_SIZE_OF(ComponentManagerMallocSizeOf
)
1530 nsComponentManagerImpl::CollectReports(nsIHandleReportCallback
* aHandleReport
,
1531 nsISupports
* aData
, bool aAnonymize
) {
1532 MOZ_COLLECT_REPORT("explicit/xpcom/component-manager", KIND_HEAP
, UNITS_BYTES
,
1533 SizeOfIncludingThis(ComponentManagerMallocSizeOf
),
1534 "Memory used for the XPCOM component manager.");
1539 size_t nsComponentManagerImpl::SizeOfIncludingThis(
1540 mozilla::MallocSizeOf aMallocSizeOf
) const {
1541 size_t n
= aMallocSizeOf(this);
1543 n
+= mFactories
.ShallowSizeOfExcludingThis(aMallocSizeOf
);
1544 for (const auto& data
: mFactories
.Values()) {
1545 n
+= data
->SizeOfIncludingThis(aMallocSizeOf
);
1548 n
+= mContractIDs
.ShallowSizeOfExcludingThis(aMallocSizeOf
);
1549 for (const auto& key
: mContractIDs
.Keys()) {
1550 // We don't measure the nsFactoryEntry data because it's owned by
1551 // mFactories (which is measured above).
1552 n
+= key
.SizeOfExcludingThisIfUnshared(aMallocSizeOf
);
1555 n
+= sExtraStaticModules
->ShallowSizeOfIncludingThis(aMallocSizeOf
);
1556 if (sModuleLocations
) {
1557 n
+= sModuleLocations
->ShallowSizeOfIncludingThis(aMallocSizeOf
);
1560 n
+= mKnownStaticModules
.ShallowSizeOfExcludingThis(aMallocSizeOf
);
1562 n
+= mPendingServices
.ShallowSizeOfExcludingThis(aMallocSizeOf
);
1564 // Measurement of the following members may be added later if DMD finds it is
1567 // - sModuleLocations' entries
1568 // - mKnownStaticModules' entries?
1573 ////////////////////////////////////////////////////////////////////////////////
1575 ////////////////////////////////////////////////////////////////////////////////
1577 nsFactoryEntry::nsFactoryEntry(const mozilla::Module::CIDEntry
* aEntry
,
1578 nsComponentManagerImpl::KnownModule
* aModule
)
1579 : mCIDEntry(aEntry
), mModule(aModule
) {}
1581 nsFactoryEntry::nsFactoryEntry(const nsCID
& aCID
, nsIFactory
* aFactory
)
1582 : mCIDEntry(nullptr), mModule(nullptr), mFactory(aFactory
) {
1583 auto* e
= new mozilla::Module::CIDEntry();
1584 auto* cid
= new nsCID
;
1590 nsFactoryEntry::~nsFactoryEntry() {
1591 // If this was a RegisterFactory entry, we own the CIDEntry/CID
1593 delete mCIDEntry
->cid
;
1598 already_AddRefed
<nsIFactory
> nsFactoryEntry::GetFactory() {
1599 nsComponentManagerImpl::gComponentManager
->mLock
.AssertNotCurrentThreadOwns();
1602 // RegisterFactory then UnregisterFactory can leave an entry in mContractIDs
1603 // pointing to an unusable nsFactoryEntry.
1608 if (!mModule
->Load()) {
1612 // Don't set mFactory directly, it needs to be locked
1613 nsCOMPtr
<nsIFactory
> factory
;
1615 if (mModule
->Module()->getFactoryProc
) {
1617 mModule
->Module()->getFactoryProc(*mModule
->Module(), *mCIDEntry
);
1618 } else if (mCIDEntry
->getFactoryProc
) {
1619 factory
= mCIDEntry
->getFactoryProc(*mModule
->Module(), *mCIDEntry
);
1621 NS_ASSERTION(mCIDEntry
->constructorProc
, "no getfactory or constructor");
1622 factory
= new mozilla::GenericFactory(mCIDEntry
->constructorProc
);
1628 MonitorAutoLock
lock(nsComponentManagerImpl::gComponentManager
->mLock
);
1629 // Threads can race to set mFactory
1631 factory
.swap(mFactory
);
1634 nsCOMPtr
<nsIFactory
> factory
= mFactory
;
1635 return factory
.forget();
1638 nsresult
nsFactoryEntry::CreateInstance(const nsIID
& aIID
, void** aResult
) {
1639 nsCOMPtr
<nsIFactory
> factory
= GetFactory();
1640 NS_ENSURE_TRUE(factory
, NS_ERROR_FAILURE
);
1641 return factory
->CreateInstance(aIID
, aResult
);
1644 size_t nsFactoryEntry::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf
) {
1645 size_t n
= aMallocSizeOf(this);
1647 // Measurement of the following members may be added later if DMD finds it is
1652 // - mServiceObject;
1657 ////////////////////////////////////////////////////////////////////////////////
1658 // Static Access Functions
1659 ////////////////////////////////////////////////////////////////////////////////
1661 nsresult
NS_GetComponentManager(nsIComponentManager
** aResult
) {
1662 if (!nsComponentManagerImpl::gComponentManager
) {
1663 return NS_ERROR_NOT_INITIALIZED
;
1666 NS_ADDREF(*aResult
= nsComponentManagerImpl::gComponentManager
);
1670 nsresult
NS_GetServiceManager(nsIServiceManager
** aResult
) {
1671 if (!nsComponentManagerImpl::gComponentManager
) {
1672 return NS_ERROR_NOT_INITIALIZED
;
1675 NS_ADDREF(*aResult
= nsComponentManagerImpl::gComponentManager
);
1679 nsresult
NS_GetComponentRegistrar(nsIComponentRegistrar
** aResult
) {
1680 if (!nsComponentManagerImpl::gComponentManager
) {
1681 return NS_ERROR_NOT_INITIALIZED
;
1684 NS_ADDREF(*aResult
= nsComponentManagerImpl::gComponentManager
);
1688 EXPORT_XPCOM_API(nsresult
)
1689 XRE_AddStaticComponent(const mozilla::Module
* aComponent
) {
1690 nsComponentManagerImpl::InitializeStaticModules();
1691 sExtraStaticModules
->AppendElement(aComponent
);
1693 if (nsComponentManagerImpl::gComponentManager
&&
1694 nsComponentManagerImpl::NORMAL
==
1695 nsComponentManagerImpl::gComponentManager
->mStatus
) {
1696 nsComponentManagerImpl::gComponentManager
->RegisterModule(aComponent
);
1703 nsComponentManagerImpl::AddBootstrappedManifestLocation(nsIFile
* aLocation
) {
1704 NS_ENSURE_ARG_POINTER(aLocation
);
1707 nsresult rv
= aLocation
->GetPath(path
);
1708 if (NS_FAILED(rv
)) {
1712 if (Substring(path
, path
.Length() - 4).EqualsLiteral(".xpi")) {
1713 return XRE_AddJarManifestLocation(NS_BOOTSTRAPPED_LOCATION
, aLocation
);
1716 nsCOMPtr
<nsIFile
> manifest
= CloneAndAppend(aLocation
, "chrome.manifest"_ns
);
1717 return XRE_AddManifestLocation(NS_BOOTSTRAPPED_LOCATION
, manifest
);
1721 nsComponentManagerImpl::RemoveBootstrappedManifestLocation(nsIFile
* aLocation
) {
1722 NS_ENSURE_ARG_POINTER(aLocation
);
1724 nsCOMPtr
<nsIChromeRegistry
> cr
= mozilla::services::GetChromeRegistry();
1726 return NS_ERROR_FAILURE
;
1730 nsresult rv
= aLocation
->GetPath(path
);
1731 if (NS_FAILED(rv
)) {
1735 nsComponentManagerImpl::ComponentLocation elem
;
1736 elem
.type
= NS_BOOTSTRAPPED_LOCATION
;
1738 if (Substring(path
, path
.Length() - 4).EqualsLiteral(".xpi")) {
1739 elem
.location
.Init(aLocation
, "chrome.manifest");
1741 nsCOMPtr
<nsIFile
> lf
= CloneAndAppend(aLocation
, "chrome.manifest"_ns
);
1742 elem
.location
.Init(lf
);
1745 // Remove reference.
1746 nsComponentManagerImpl::sModuleLocations
->RemoveElement(
1747 elem
, ComponentLocationComparator());
1749 rv
= cr
->CheckForNewChrome();
1754 nsComponentManagerImpl::GetComponentJSMs(nsIUTF8StringEnumerator
** aJSMs
) {
1755 nsCOMPtr
<nsIUTF8StringEnumerator
> result
=
1756 StaticComponents::GetComponentJSMs();
1757 result
.forget(aJSMs
);
1762 nsComponentManagerImpl::GetComponentESModules(
1763 nsIUTF8StringEnumerator
** aESModules
) {
1764 nsCOMPtr
<nsIUTF8StringEnumerator
> result
=
1765 StaticComponents::GetComponentESModules();
1766 result
.forget(aESModules
);
1771 nsComponentManagerImpl::GetManifestLocations(nsIArray
** aLocations
) {
1772 NS_ENSURE_ARG_POINTER(aLocations
);
1773 *aLocations
= nullptr;
1775 if (!sModuleLocations
) {
1776 return NS_ERROR_NOT_INITIALIZED
;
1779 nsCOMPtr
<nsIMutableArray
> locations
= nsArray::Create();
1781 for (uint32_t i
= 0; i
< sModuleLocations
->Length(); ++i
) {
1782 ComponentLocation
& l
= sModuleLocations
->ElementAt(i
);
1783 FileLocation loc
= l
.location
;
1784 nsCString uriString
;
1785 loc
.GetURIString(uriString
);
1786 nsCOMPtr
<nsIURI
> uri
;
1787 rv
= NS_NewURI(getter_AddRefs(uri
), uriString
);
1788 if (NS_SUCCEEDED(rv
)) {
1789 locations
->AppendElement(uri
);
1793 locations
.forget(aLocations
);
1797 EXPORT_XPCOM_API(nsresult
)
1798 XRE_AddManifestLocation(NSLocationType aType
, nsIFile
* aLocation
) {
1799 nsComponentManagerImpl::InitializeModuleLocations();
1800 nsComponentManagerImpl::ComponentLocation
* c
=
1801 nsComponentManagerImpl::sModuleLocations
->AppendElement();
1803 c
->location
.Init(aLocation
);
1805 if (nsComponentManagerImpl::gComponentManager
&&
1806 nsComponentManagerImpl::NORMAL
==
1807 nsComponentManagerImpl::gComponentManager
->mStatus
) {
1808 nsComponentManagerImpl::gComponentManager
->RegisterManifest(
1809 aType
, c
->location
, false);
1815 EXPORT_XPCOM_API(nsresult
)
1816 XRE_AddJarManifestLocation(NSLocationType aType
, nsIFile
* aLocation
) {
1817 nsComponentManagerImpl::InitializeModuleLocations();
1818 nsComponentManagerImpl::ComponentLocation
* c
=
1819 nsComponentManagerImpl::sModuleLocations
->AppendElement();
1822 c
->location
.Init(aLocation
, "chrome.manifest");
1824 if (nsComponentManagerImpl::gComponentManager
&&
1825 nsComponentManagerImpl::NORMAL
==
1826 nsComponentManagerImpl::gComponentManager
->mStatus
) {
1827 nsComponentManagerImpl::gComponentManager
->RegisterManifest(
1828 aType
, c
->location
, false);
1834 // Expose some important global interfaces to rust for the rust xpcom API. These
1835 // methods return a non-owning reference to the component manager, which should
1836 // live for the lifetime of XPCOM.
1839 const nsIComponentManager
* Gecko_GetComponentManager() {
1840 return nsComponentManagerImpl::gComponentManager
;
1843 const nsIServiceManager
* Gecko_GetServiceManager() {
1844 return nsComponentManagerImpl::gComponentManager
;
1847 const nsIComponentRegistrar
* Gecko_GetComponentRegistrar() {
1848 return nsComponentManagerImpl::gComponentManager
;