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"
61 #include "xpcpublic.h"
64 # include "mozmemory.h"
67 using namespace mozilla
;
68 using namespace mozilla::xpcom
;
70 static LazyLogModule
nsComponentManagerLog("nsComponentManager");
73 # define SHOW_DENIED_ON_SHUTDOWN
74 # define SHOW_CI_ON_EXISTING_SERVICE
79 class AutoIDString
: public nsAutoCStringN
<NSID_LENGTH
> {
81 explicit AutoIDString(const nsID
& aID
) {
82 SetLength(NSID_LENGTH
- 1);
84 *reinterpret_cast<char(*)[NSID_LENGTH
]>(BeginWriting()));
93 using ProcessSelector
= Module::ProcessSelector
;
95 // Note: These must be kept in sync with the ProcessSelector definition in
97 bool ProcessSelectorMatches(ProcessSelector aSelector
) {
98 GeckoProcessType type
= XRE_GetProcessType();
99 if (type
== GeckoProcessType_GPU
) {
100 return !!(aSelector
& Module::ALLOW_IN_GPU_PROCESS
);
103 if (type
== GeckoProcessType_RDD
) {
104 return !!(aSelector
& Module::ALLOW_IN_RDD_PROCESS
);
107 if (type
== GeckoProcessType_Socket
) {
108 return !!(aSelector
& (Module::ALLOW_IN_SOCKET_PROCESS
));
111 if (type
== GeckoProcessType_VR
) {
112 return !!(aSelector
& Module::ALLOW_IN_VR_PROCESS
);
115 if (type
== GeckoProcessType_Utility
) {
116 return !!(aSelector
& Module::ALLOW_IN_UTILITY_PROCESS
);
119 if (type
== GeckoProcessType_GMPlugin
) {
120 return !!(aSelector
& Module::ALLOW_IN_GMPLUGIN_PROCESS
);
123 // Only allow XPCOM modules which can be loaded in all processes to be loaded
124 // in the IPDLUnitTest process.
125 if (type
== GeckoProcessType_IPDLUnitTest
) {
126 return size_t(aSelector
) == Module::kMaxProcessSelector
;
129 if (aSelector
& Module::MAIN_PROCESS_ONLY
) {
130 return type
== GeckoProcessType_Default
;
132 if (aSelector
& Module::CONTENT_PROCESS_ONLY
) {
133 return type
== GeckoProcessType_Content
;
138 static bool gProcessMatchTable
[Module::kMaxProcessSelector
+ 1];
140 bool FastProcessSelectorMatches(ProcessSelector aSelector
) {
141 return gProcessMatchTable
[size_t(aSelector
)];
145 } // namespace mozilla
150 * A wrapper simple wrapper class, which can hold either a dynamic
151 * nsFactoryEntry instance, or a static StaticModule entry, and transparently
152 * forwards method calls to the wrapped object.
154 * This allows the same code to work with either static or dynamic modules
155 * without caring about the difference.
157 class MOZ_STACK_CLASS EntryWrapper final
{
159 explicit EntryWrapper(nsFactoryEntry
* aEntry
) : mEntry(aEntry
) {}
161 explicit EntryWrapper(const StaticModule
* aEntry
) : mEntry(aEntry
) {}
163 #define MATCH(type, ifFactory, ifStatic) \
165 type operator()(nsFactoryEntry* entry) { ifFactory; } \
166 type operator()(const StaticModule* entry) { ifStatic; } \
168 return mEntry.match((Matcher()))
171 MATCH(const nsID
&, return entry
->mCID
, return entry
->CID());
174 already_AddRefed
<nsIFactory
> GetFactory() {
175 MATCH(already_AddRefed
<nsIFactory
>, return entry
->GetFactory(),
176 return entry
->GetFactory());
180 * Creates an instance of the underlying component. This should be used in
181 * preference to GetFactory()->CreateInstance() where appropriate, since it
182 * side-steps the necessity of creating a nsIFactory instance for static
185 nsresult
CreateInstance(const nsIID
& aIID
, void** aResult
) {
186 if (mEntry
.is
<nsFactoryEntry
*>()) {
187 return mEntry
.as
<nsFactoryEntry
*>()->CreateInstance(aIID
, aResult
);
189 return mEntry
.as
<const StaticModule
*>()->CreateInstance(aIID
, aResult
);
193 * Returns the cached service instance for this entry, if any. This should
194 * only be accessed while mLock is held.
196 nsISupports
* ServiceInstance() {
197 MATCH(nsISupports
*, return entry
->mServiceObject
,
198 return entry
->ServiceInstance());
200 void SetServiceInstance(already_AddRefed
<nsISupports
> aInst
) {
201 if (mEntry
.is
<nsFactoryEntry
*>()) {
202 mEntry
.as
<nsFactoryEntry
*>()->mServiceObject
= aInst
;
204 return mEntry
.as
<const StaticModule
*>()->SetServiceInstance(
210 * Returns the description string for the module this entry belongs to.
211 * Currently always returns "<unknown module>".
213 nsCString
ModuleDescription() { 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
= 8;
268 nsComponentManagerImpl::nsComponentManagerImpl()
269 : mFactories(CONTRACTID_HASHTABLE_INITIAL_LENGTH
),
270 mContractIDs(CONTRACTID_HASHTABLE_INITIAL_LENGTH
),
271 mLock("nsComponentManagerImpl.mLock"),
272 mStatus(NOT_INITIALIZED
) {}
274 nsTArray
<nsComponentManagerImpl::ComponentLocation
>*
275 nsComponentManagerImpl::sModuleLocations
;
278 void nsComponentManagerImpl::InitializeModuleLocations() {
279 if (sModuleLocations
) {
283 sModuleLocations
= new nsTArray
<ComponentLocation
>;
286 nsresult
nsComponentManagerImpl::Init() {
288 gProcessMatchTable
[size_t(ProcessSelector::ANY_PROCESS
)] =
289 ProcessSelectorMatches(ProcessSelector::ANY_PROCESS
);
290 gProcessMatchTable
[size_t(ProcessSelector::MAIN_PROCESS_ONLY
)] =
291 ProcessSelectorMatches(ProcessSelector::MAIN_PROCESS_ONLY
);
292 gProcessMatchTable
[size_t(ProcessSelector::CONTENT_PROCESS_ONLY
)] =
293 ProcessSelectorMatches(ProcessSelector::CONTENT_PROCESS_ONLY
);
294 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_GPU_PROCESS
)] =
295 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_PROCESS
);
296 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_VR_PROCESS
)] =
297 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_VR_PROCESS
);
298 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_SOCKET_PROCESS
)] =
299 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_SOCKET_PROCESS
);
300 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_RDD_PROCESS
)] =
301 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_RDD_PROCESS
);
302 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_GMPLUGIN_PROCESS
)] =
303 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GMPLUGIN_PROCESS
);
304 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_GPU_AND_MAIN_PROCESS
)] =
305 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_AND_MAIN_PROCESS
);
306 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_GPU_AND_VR_PROCESS
)] =
307 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_AND_VR_PROCESS
);
308 gProcessMatchTable
[size_t(
309 ProcessSelector::ALLOW_IN_GPU_AND_SOCKET_PROCESS
)] =
310 ProcessSelectorMatches(
311 ProcessSelector::ALLOW_IN_GPU_AND_SOCKET_PROCESS
);
312 gProcessMatchTable
[size_t(
313 ProcessSelector::ALLOW_IN_GPU_VR_AND_SOCKET_PROCESS
)] =
314 ProcessSelectorMatches(
315 ProcessSelector::ALLOW_IN_GPU_VR_AND_SOCKET_PROCESS
);
316 gProcessMatchTable
[size_t(
317 ProcessSelector::ALLOW_IN_RDD_AND_SOCKET_PROCESS
)] =
318 ProcessSelectorMatches(
319 ProcessSelector::ALLOW_IN_RDD_AND_SOCKET_PROCESS
);
320 gProcessMatchTable
[size_t(
321 ProcessSelector::ALLOW_IN_GPU_RDD_AND_SOCKET_PROCESS
)] =
322 ProcessSelectorMatches(
323 ProcessSelector::ALLOW_IN_GPU_RDD_AND_SOCKET_PROCESS
);
324 gProcessMatchTable
[size_t(
325 ProcessSelector::ALLOW_IN_GPU_RDD_SOCKET_AND_UTILITY_PROCESS
)] =
326 ProcessSelectorMatches(
327 ProcessSelector::ALLOW_IN_GPU_RDD_SOCKET_AND_UTILITY_PROCESS
);
328 gProcessMatchTable
[size_t(
329 ProcessSelector::ALLOW_IN_GPU_RDD_VR_AND_SOCKET_PROCESS
)] =
330 ProcessSelectorMatches(
331 ProcessSelector::ALLOW_IN_GPU_RDD_VR_AND_SOCKET_PROCESS
);
332 gProcessMatchTable
[size_t(
333 ProcessSelector::ALLOW_IN_GPU_RDD_VR_SOCKET_AND_UTILITY_PROCESS
)] =
334 ProcessSelectorMatches(
335 ProcessSelector::ALLOW_IN_GPU_RDD_VR_SOCKET_AND_UTILITY_PROCESS
);
336 gProcessMatchTable
[size_t(
338 ALLOW_IN_GPU_RDD_VR_SOCKET_UTILITY_AND_GMPLUGIN_PROCESS
)] =
339 ProcessSelectorMatches(
341 ALLOW_IN_GPU_RDD_VR_SOCKET_UTILITY_AND_GMPLUGIN_PROCESS
);
344 MOZ_ASSERT(NOT_INITIALIZED
== mStatus
);
346 nsCOMPtr
<nsIFile
> greDir
= GetLocationFromDirectoryService(NS_GRE_DIR
);
347 nsCOMPtr
<nsIFile
> appDir
=
348 GetLocationFromDirectoryService(NS_XPCOM_CURRENT_PROCESS_DIR
);
350 nsCategoryManager::GetSingleton()->SuppressNotifications(true);
352 auto* catMan
= nsCategoryManager::GetSingleton();
353 for (const auto& cat
: gStaticCategories
) {
354 for (const auto& entry
: cat
) {
355 if (entry
.Active()) {
356 catMan
->AddCategoryEntry(cat
.Name(), entry
.Entry(), entry
.Value());
361 // This needs to be initialized late enough, so that preferences service can
362 // be accessed but before the IO service, and we want it in all process types.
363 xpc::ReadOnlyPage::Init();
365 bool loadChromeManifests
;
366 switch (XRE_GetProcessType()) {
367 // We are going to assume that only a select few (see below) process types
368 // want to load chrome manifests, and that any new process types will not
369 // want to load them, because they're not going to be executing JS.
370 case GeckoProcessType_RemoteSandboxBroker
:
372 loadChromeManifests
= false;
375 // XXX The check this code replaced implicitly let through all of these
376 // process types, but presumably only the default (parent) and content
377 // processes really need chrome manifests...?
378 case GeckoProcessType_Default
:
379 case GeckoProcessType_Content
:
380 loadChromeManifests
= true;
384 if (loadChromeManifests
) {
385 // This needs to be called very early, before anything in nsLayoutModule is
386 // used, and before any calls are made into the JS engine.
387 nsLayoutModuleInitialize();
389 mJSLoaderReady
= true;
391 // The overall order in which chrome.manifests are expected to be treated
393 // - greDir's omni.ja or greDir
394 // - appDir's omni.ja or appDir
396 InitializeModuleLocations();
397 ComponentLocation
* cl
= sModuleLocations
->AppendElement();
398 cl
->type
= NS_APP_LOCATION
;
399 RefPtr
<nsZipArchive
> greOmnijar
=
400 mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE
);
402 cl
->location
.Init(greOmnijar
, "chrome.manifest");
404 nsCOMPtr
<nsIFile
> lf
= CloneAndAppend(greDir
, "chrome.manifest"_ns
);
405 cl
->location
.Init(lf
);
408 RefPtr
<nsZipArchive
> appOmnijar
=
409 mozilla::Omnijar::GetReader(mozilla::Omnijar::APP
);
411 cl
= sModuleLocations
->AppendElement();
412 cl
->type
= NS_APP_LOCATION
;
413 cl
->location
.Init(appOmnijar
, "chrome.manifest");
416 appDir
->Equals(greDir
, &equals
);
418 cl
= sModuleLocations
->AppendElement();
419 cl
->type
= NS_APP_LOCATION
;
420 nsCOMPtr
<nsIFile
> lf
= CloneAndAppend(appDir
, "chrome.manifest"_ns
);
421 cl
->location
.Init(lf
);
425 RereadChromeManifests(false);
428 nsCategoryManager::GetSingleton()->SuppressNotifications(false);
430 RegisterWeakMemoryReporter(this);
432 // NB: The logging preference watcher needs to be registered late enough in
433 // startup that it's okay to use the preference system, but also as soon as
434 // possible so that log modules enabled via preferences are turned on as
435 // early as possible.
437 // We can't initialize the preference watcher when the log module manager is
438 // initialized, as a number of things attempt to start logging before the
439 // preference system is initialized.
441 // The preference system is registered as a component so at this point during
442 // component manager initialization we know it is setup and we can register
443 // for notifications.
444 LogModulePrefWatcher::RegisterPrefWatcher();
446 // Unfortunately, we can't register the nsCategoryManager memory reporter
447 // in its constructor (which is triggered by the GetSingleton() call
448 // above) because the memory reporter manager isn't initialized at that
449 // point. So we wait until now.
450 nsCategoryManager::GetSingleton()->InitMemoryReporter();
452 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
453 ("nsComponentManager: Initialized."));
457 MOZ_ASSERT(!XRE_IsContentProcess() ||
458 CONTRACTID_HASHTABLE_INITIAL_LENGTH
<= 8 ||
459 mFactories
.Count() > CONTRACTID_HASHTABLE_INITIAL_LENGTH
/ 3,
460 "Initial component hashtable size is too large");
465 template <typename T
>
466 static void AssertNotMallocAllocated(T
* aPtr
) {
467 #if defined(DEBUG) && defined(MOZ_MEMORY)
468 jemalloc_ptr_info_t info
;
469 jemalloc_ptr_info((void*)aPtr
, &info
);
470 MOZ_ASSERT(info
.tag
== TagUnknown
);
474 template <typename T
>
475 static void AssertNotStackAllocated(T
* aPtr
) {
476 // On all of our supported platforms, the stack grows down. Any address
477 // located below the address of our argument is therefore guaranteed not to be
478 // stack-allocated by the caller.
480 // For addresses above our argument, things get trickier. The main thread
481 // stack is traditionally placed at the top of the program's address space,
482 // but that is becoming less reliable as more and more systems adopt address
483 // space layout randomization strategies, so we have to guess how much space
484 // above our argument pointer we need to care about.
486 // On most systems, we're guaranteed at least several KiB at the top of each
487 // stack for TLS. We'd probably be safe assuming at least 4KiB in the stack
488 // segment above our argument address, but safer is... well, safer.
490 // For threads with huge stacks, it's theoretically possible that we could
491 // wind up being passed a stack-allocated string from farther up the stack,
492 // but this is a best-effort thing, so we'll assume we only care about the
493 // immediate caller. For that case, max 2KiB per stack frame is probably a
494 // reasonable guess most of the time, and is less than the ~4KiB that we
495 // expect for TLS, so go with that to avoid the risk of bumping into heap
496 // data just above the stack.
498 static constexpr size_t kFuzz
= 2048;
500 MOZ_ASSERT(uintptr_t(aPtr
) < uintptr_t(&aPtr
) ||
501 uintptr_t(aPtr
) > uintptr_t(&aPtr
) + kFuzz
);
505 static void DoRegisterManifest(NSLocationType aType
, FileLocation
& aFile
,
507 auto result
= URLPreloader::Read(aFile
);
509 nsCString
buf(result
.unwrap());
510 ParseManifest(aType
, aFile
, buf
.BeginWriting(), aChromeOnly
);
511 } else if (NS_BOOTSTRAPPED_LOCATION
!= aType
) {
513 aFile
.GetURIString(uri
);
514 LogMessage("Could not read chrome manifest '%s'.", uri
.get());
518 void nsComponentManagerImpl::RegisterManifest(NSLocationType aType
,
521 DoRegisterManifest(aType
, aFile
, aChromeOnly
);
524 void nsComponentManagerImpl::ManifestManifest(ManifestProcessingContext
& aCx
,
525 int aLineNo
, char* const* aArgv
) {
526 char* file
= aArgv
[0];
527 FileLocation
f(aCx
.mFile
, file
);
528 RegisterManifest(aCx
.mType
, f
, aCx
.mChromeOnly
);
531 void nsComponentManagerImpl::ManifestCategory(ManifestProcessingContext
& aCx
,
532 int aLineNo
, char* const* aArgv
) {
533 char* category
= aArgv
[0];
534 char* key
= aArgv
[1];
535 char* value
= aArgv
[2];
537 nsCategoryManager::GetSingleton()->AddCategoryEntry(
538 nsDependentCString(category
), nsDependentCString(key
),
539 nsDependentCString(value
));
542 void nsComponentManagerImpl::RereadChromeManifests(bool aChromeOnly
) {
543 for (uint32_t i
= 0; i
< sModuleLocations
->Length(); ++i
) {
544 ComponentLocation
& l
= sModuleLocations
->ElementAt(i
);
545 RegisterManifest(l
.type
, l
.location
, aChromeOnly
);
548 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
550 obs
->NotifyObservers(nullptr, "chrome-manifests-loaded", nullptr);
554 nsresult
nsComponentManagerImpl::Shutdown(void) {
555 MOZ_ASSERT(NORMAL
== mStatus
);
557 mStatus
= SHUTDOWN_IN_PROGRESS
;
559 // Shutdown the component manager
560 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
561 ("nsComponentManager: Beginning Shutdown."));
563 UnregisterWeakMemoryReporter(this);
565 // Release all cached factories
566 mContractIDs
.Clear();
567 mFactories
.Clear(); // XXX release the objects, don't just clear
569 StaticComponents::Shutdown();
571 delete sModuleLocations
;
573 mStatus
= SHUTDOWN_COMPLETE
;
575 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
576 ("nsComponentManager: Shutdown complete."));
581 nsComponentManagerImpl::~nsComponentManagerImpl() {
582 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
583 ("nsComponentManager: Beginning destruction."));
585 if (SHUTDOWN_COMPLETE
!= mStatus
) {
589 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
590 ("nsComponentManager: Destroyed."));
593 NS_IMPL_ISUPPORTS(nsComponentManagerImpl
, nsIComponentManager
,
594 nsIServiceManager
, nsIComponentRegistrar
,
595 nsISupportsWeakReference
, nsIInterfaceRequestor
,
598 nsresult
nsComponentManagerImpl::GetInterface(const nsIID
& aUuid
,
600 NS_WARNING("This isn't supported");
601 // fall through to QI as anything QIable is a superset of what can be
602 // got via the GetInterface()
603 return QueryInterface(aUuid
, aResult
);
606 Maybe
<EntryWrapper
> nsComponentManagerImpl::LookupByCID(const nsID
& aCID
) {
607 return LookupByCID(MonitorAutoLock(mLock
), aCID
);
610 Maybe
<EntryWrapper
> nsComponentManagerImpl::LookupByCID(const MonitorAutoLock
&,
612 if (const StaticModule
* module
= StaticComponents::LookupByCID(aCID
)) {
613 return Some(EntryWrapper(module
));
615 if (nsFactoryEntry
* entry
= mFactories
.Get(&aCID
)) {
616 return Some(EntryWrapper(entry
));
621 Maybe
<EntryWrapper
> nsComponentManagerImpl::LookupByContractID(
622 const nsACString
& aContractID
) {
623 return LookupByContractID(MonitorAutoLock(mLock
), aContractID
);
626 Maybe
<EntryWrapper
> nsComponentManagerImpl::LookupByContractID(
627 const MonitorAutoLock
&, const nsACString
& aContractID
) {
628 if (const StaticModule
* module
=
629 StaticComponents::LookupByContractID(aContractID
)) {
630 return Some(EntryWrapper(module
));
632 if (nsFactoryEntry
* entry
= mContractIDs
.Get(aContractID
)) {
633 // UnregisterFactory might have left a stale nsFactoryEntry in
634 // mContractIDs, so we should check to see whether this entry has
636 if (entry
->mFactory
|| entry
->mServiceObject
) {
637 return Some(EntryWrapper(entry
));
643 already_AddRefed
<nsIFactory
> nsComponentManagerImpl::FindFactory(
644 const nsCID
& aClass
) {
645 Maybe
<EntryWrapper
> e
= LookupByCID(aClass
);
650 return e
->GetFactory();
653 already_AddRefed
<nsIFactory
> nsComponentManagerImpl::FindFactory(
654 const char* aContractID
, uint32_t aContractIDLen
) {
655 Maybe
<EntryWrapper
> entry
=
656 LookupByContractID(nsDependentCString(aContractID
, aContractIDLen
));
661 return entry
->GetFactory();
667 * Given a classID, this finds the singleton ClassObject that implements the
668 * CID. Returns an interface of type aIID off the singleton classobject.
671 nsComponentManagerImpl::GetClassObject(const nsCID
& aClass
, const nsIID
& aIID
,
675 if (MOZ_LOG_TEST(nsComponentManagerLog
, LogLevel::Debug
)) {
676 char buf
[NSID_LENGTH
];
677 aClass
.ToProvidedString(buf
);
678 PR_LogPrint("nsComponentManager: GetClassObject(%s)", buf
);
681 MOZ_ASSERT(aResult
!= nullptr);
683 nsCOMPtr
<nsIFactory
> factory
= FindFactory(aClass
);
685 return NS_ERROR_FACTORY_NOT_REGISTERED
;
688 rv
= factory
->QueryInterface(aIID
, aResult
);
691 nsComponentManagerLog
, LogLevel::Warning
,
692 ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
698 nsComponentManagerImpl::GetClassObjectByContractID(const char* aContractID
,
701 if (NS_WARN_IF(!aResult
) || NS_WARN_IF(!aContractID
)) {
702 return NS_ERROR_INVALID_ARG
;
707 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
708 ("nsComponentManager: GetClassObjectByContractID(%s)", aContractID
));
710 nsCOMPtr
<nsIFactory
> factory
= FindFactory(aContractID
, strlen(aContractID
));
712 return NS_ERROR_FACTORY_NOT_REGISTERED
;
715 rv
= factory
->QueryInterface(aIID
, aResult
);
717 MOZ_LOG(nsComponentManagerLog
, LogLevel::Warning
,
718 ("\t\tGetClassObjectByContractID() %s",
719 NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
727 * Create an instance of an object that implements an interface and belongs
728 * to the implementation aClass using the factory. The factory is immediately
729 * released and not held onto for any longer.
732 nsComponentManagerImpl::CreateInstance(const nsCID
& aClass
, const nsIID
& aIID
,
734 // test this first, since there's no point in creating a component during
735 // shutdown -- whether it's available or not would depend on the order it
736 // occurs in the list
737 if (gXPCOMShuttingDown
) {
738 // When processing shutdown, don't process new GetService() requests
739 #ifdef SHOW_DENIED_ON_SHUTDOWN
741 "Creating new instance on shutdown. Denied.\n"
742 " CID: %s\n IID: %s\n",
743 AutoIDString(aClass
).get(), AutoIDString(aIID
).get());
744 #endif /* SHOW_DENIED_ON_SHUTDOWN */
745 return NS_ERROR_UNEXPECTED
;
749 return NS_ERROR_NULL_POINTER
;
753 Maybe
<EntryWrapper
> entry
= LookupByCID(aClass
);
756 return NS_ERROR_FACTORY_NOT_REGISTERED
;
759 #ifdef SHOW_CI_ON_EXISTING_SERVICE
760 if (entry
->ServiceInstance()) {
761 nsAutoCString message
;
762 message
= "You are calling CreateInstance \""_ns
+ AutoIDString(aClass
) +
763 "\" when a service for this CID already exists!"_ns
;
764 NS_ERROR(message
.get());
769 nsCOMPtr
<nsIFactory
> factory
= entry
->GetFactory();
771 rv
= factory
->CreateInstance(aIID
, aResult
);
772 if (NS_SUCCEEDED(rv
) && !*aResult
) {
773 NS_ERROR("Factory did not return an object but returned success!");
774 rv
= NS_ERROR_SERVICE_NOT_AVAILABLE
;
777 // Translate error values
778 rv
= NS_ERROR_FACTORY_NOT_REGISTERED
;
781 if (MOZ_LOG_TEST(nsComponentManagerLog
, LogLevel::Warning
)) {
782 char buf
[NSID_LENGTH
];
783 aClass
.ToProvidedString(buf
);
784 MOZ_LOG(nsComponentManagerLog
, LogLevel::Warning
,
785 ("nsComponentManager: CreateInstance(%s) %s", buf
,
786 NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
793 * CreateInstanceByContractID()
795 * A variant of CreateInstance() that creates an instance of the object that
796 * implements the interface aIID and whose implementation has a contractID
799 * This is only a convenience routine that turns around can calls the
800 * CreateInstance() with classid and iid.
803 nsComponentManagerImpl::CreateInstanceByContractID(const char* aContractID
,
806 if (NS_WARN_IF(!aContractID
)) {
807 return NS_ERROR_INVALID_ARG
;
810 // test this first, since there's no point in creating a component during
811 // shutdown -- whether it's available or not would depend on the order it
812 // occurs in the list
813 if (gXPCOMShuttingDown
) {
814 // When processing shutdown, don't process new GetService() requests
815 #ifdef SHOW_DENIED_ON_SHUTDOWN
817 "Creating new instance on shutdown. Denied.\n"
818 " ContractID: %s\n IID: %s\n",
819 aContractID
, AutoIDString(aIID
).get());
820 #endif /* SHOW_DENIED_ON_SHUTDOWN */
821 return NS_ERROR_UNEXPECTED
;
825 return NS_ERROR_NULL_POINTER
;
829 Maybe
<EntryWrapper
> entry
=
830 LookupByContractID(nsDependentCString(aContractID
));
833 return NS_ERROR_FACTORY_NOT_REGISTERED
;
836 #ifdef SHOW_CI_ON_EXISTING_SERVICE
837 if (entry
->ServiceInstance()) {
838 nsAutoCString message
;
840 "You are calling CreateInstance \""_ns
+
841 nsDependentCString(aContractID
) +
843 "\" when a service for this CID already exists! "
844 "Add it to abusedContracts to track down the service consumer.");
845 NS_ERROR(message
.get());
850 nsCOMPtr
<nsIFactory
> factory
= entry
->GetFactory();
852 rv
= factory
->CreateInstance(aIID
, aResult
);
853 if (NS_SUCCEEDED(rv
) && !*aResult
) {
854 NS_ERROR("Factory did not return an object but returned success!");
855 rv
= NS_ERROR_SERVICE_NOT_AVAILABLE
;
858 // Translate error values
859 rv
= NS_ERROR_FACTORY_NOT_REGISTERED
;
862 MOZ_LOG(nsComponentManagerLog
, LogLevel::Warning
,
863 ("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID
,
864 NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
869 nsresult
nsComponentManagerImpl::FreeServices() {
870 NS_ASSERTION(gXPCOMShuttingDown
,
871 "Must be shutting down in order to free all services");
873 if (!gXPCOMShuttingDown
) {
874 return NS_ERROR_FAILURE
;
877 for (nsFactoryEntry
* entry
: mFactories
.Values()) {
878 entry
->mFactory
= nullptr;
879 entry
->mServiceObject
= nullptr;
882 for (const auto& module
: gStaticModules
) {
883 module
.SetServiceInstance(nullptr);
889 // This should only ever be called within the monitor!
890 nsComponentManagerImpl::PendingServiceInfo
*
891 nsComponentManagerImpl::AddPendingService(const nsCID
& aServiceCID
,
893 PendingServiceInfo
* newInfo
= mPendingServices
.AppendElement();
895 newInfo
->cid
= &aServiceCID
;
896 newInfo
->thread
= aThread
;
901 // This should only ever be called within the monitor!
902 void nsComponentManagerImpl::RemovePendingService(MonitorAutoLock
& aLock
,
903 const nsCID
& aServiceCID
) {
904 uint32_t pendingCount
= mPendingServices
.Length();
905 for (uint32_t index
= 0; index
< pendingCount
; ++index
) {
906 const PendingServiceInfo
& info
= mPendingServices
.ElementAt(index
);
907 if (info
.cid
->Equals(aServiceCID
)) {
908 mPendingServices
.RemoveElementAt(index
);
915 // This should only ever be called within the monitor!
916 PRThread
* nsComponentManagerImpl::GetPendingServiceThread(
917 const nsCID
& aServiceCID
) const {
918 uint32_t pendingCount
= mPendingServices
.Length();
919 for (uint32_t index
= 0; index
< pendingCount
; ++index
) {
920 const PendingServiceInfo
& info
= mPendingServices
.ElementAt(index
);
921 if (info
.cid
->Equals(aServiceCID
)) {
928 nsresult
nsComponentManagerImpl::GetServiceLocked(Maybe
<MonitorAutoLock
>& aLock
,
929 EntryWrapper
& aEntry
,
932 MOZ_ASSERT(aLock
.isSome());
933 if (!aLock
.isSome()) {
934 return NS_ERROR_INVALID_ARG
;
937 if (auto* service
= aEntry
.ServiceInstance()) {
939 return service
->QueryInterface(aIID
, aResult
);
942 PRThread
* currentPRThread
= PR_GetCurrentThread();
943 MOZ_ASSERT(currentPRThread
, "This should never be null!");
945 PRThread
* pendingPRThread
;
946 while ((pendingPRThread
= GetPendingServiceThread(aEntry
.CID()))) {
947 if (pendingPRThread
== currentPRThread
) {
948 NS_ERROR("Recursive GetService!");
949 return NS_ERROR_NOT_AVAILABLE
;
955 // It's still possible that the other thread failed to create the
956 // service so we're not guaranteed to have an entry or service yet.
957 if (auto* service
= aEntry
.ServiceInstance()) {
959 return service
->QueryInterface(aIID
, aResult
);
962 DebugOnly
<PendingServiceInfo
*> newInfo
=
963 AddPendingService(aEntry
.CID(), currentPRThread
);
964 NS_ASSERTION(newInfo
, "Failed to add info to the array!");
966 // We need to not be holding the service manager's lock while calling
967 // CreateInstance, because it invokes user code which could try to re-enter
968 // the service manager:
970 nsCOMPtr
<nsISupports
> service
;
971 auto cleanup
= MakeScopeExit([&]() {
972 // `service` must be released after the lock is released, so if we fail and
973 // still have a reference, release the lock before releasing it.
975 MOZ_ASSERT(aLock
.isSome());
981 mLock
.AssertCurrentThreadOwns();
983 MonitorAutoUnlock
unlock(mLock
);
984 AUTO_PROFILER_MARKER_TEXT(
985 "GetService", OTHER
, MarkerStack::Capture(),
986 nsDependentCString(nsIDToCString(aEntry
.CID()).get()));
987 rv
= aEntry
.CreateInstance(aIID
, getter_AddRefs(service
));
989 if (NS_SUCCEEDED(rv
) && !service
) {
990 NS_ERROR("Factory did not return an object but returned success");
991 return NS_ERROR_SERVICE_NOT_AVAILABLE
;
995 pendingPRThread
= GetPendingServiceThread(aEntry
.CID());
996 MOZ_ASSERT(pendingPRThread
== currentPRThread
,
997 "Pending service array has been changed!");
999 MOZ_ASSERT(aLock
.isSome());
1000 RemovePendingService(*aLock
, aEntry
.CID());
1002 if (NS_FAILED(rv
)) {
1006 NS_ASSERTION(!aEntry
.ServiceInstance(),
1007 "Created two instances of a service!");
1009 aEntry
.SetServiceInstance(service
.forget());
1013 *aResult
= do_AddRef(aEntry
.ServiceInstance()).take();
1018 nsComponentManagerImpl::GetService(const nsCID
& aClass
, const nsIID
& aIID
,
1020 // test this first, since there's no point in returning a service during
1021 // shutdown -- whether it's available or not would depend on the order it
1022 // occurs in the list
1023 if (gXPCOMShuttingDown
) {
1024 // When processing shutdown, don't process new GetService() requests
1025 #ifdef SHOW_DENIED_ON_SHUTDOWN
1027 "Getting service on shutdown. Denied.\n"
1028 " CID: %s\n IID: %s\n",
1029 AutoIDString(aClass
).get(), AutoIDString(aIID
).get());
1030 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1031 return NS_ERROR_UNEXPECTED
;
1034 Maybe
<MonitorAutoLock
> lock(std::in_place
, mLock
);
1036 Maybe
<EntryWrapper
> entry
= LookupByCID(*lock
, aClass
);
1038 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1041 return GetServiceLocked(lock
, *entry
, aIID
, aResult
);
1044 nsresult
nsComponentManagerImpl::GetService(ModuleID aId
, const nsIID
& aIID
,
1046 const auto& entry
= gStaticModules
[size_t(aId
)];
1048 // test this first, since there's no point in returning a service during
1049 // shutdown -- whether it's available or not would depend on the order it
1050 // occurs in the list
1051 if (gXPCOMShuttingDown
) {
1052 // When processing shutdown, don't process new GetService() requests
1053 #ifdef SHOW_DENIED_ON_SHUTDOWN
1055 "Getting service on shutdown. Denied.\n"
1056 " CID: %s\n IID: %s\n",
1057 AutoIDString(entry
.CID()).get(), AutoIDString(aIID
).get());
1058 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1059 return NS_ERROR_UNEXPECTED
;
1062 Maybe
<MonitorAutoLock
> lock(std::in_place
, mLock
);
1064 Maybe
<EntryWrapper
> wrapper
;
1065 if (entry
.Overridable()) {
1066 // If we expect this service to be overridden by test code, we need to look
1067 // it up by contract ID every time.
1068 wrapper
= LookupByContractID(*lock
, entry
.ContractID());
1070 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1072 } else if (!entry
.Active()) {
1073 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1075 wrapper
.emplace(&entry
);
1077 return GetServiceLocked(lock
, *wrapper
, aIID
, aResult
);
1081 nsComponentManagerImpl::IsServiceInstantiated(const nsCID
& aClass
,
1084 // Now we want to get the service if we already got it. If not, we don't want
1085 // to create an instance of it. mmh!
1087 // test this first, since there's no point in returning a service during
1088 // shutdown -- whether it's available or not would depend on the order it
1089 // occurs in the list
1090 if (gXPCOMShuttingDown
) {
1091 // When processing shutdown, don't process new GetService() requests
1092 #ifdef SHOW_DENIED_ON_SHUTDOWN
1094 "Checking for service on shutdown. Denied.\n"
1095 " CID: %s\n IID: %s\n",
1096 AutoIDString(aClass
).get(), AutoIDString(aIID
).get());
1097 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1098 return NS_ERROR_UNEXPECTED
;
1101 if (Maybe
<EntryWrapper
> entry
= LookupByCID(aClass
)) {
1102 if (auto* service
= entry
->ServiceInstance()) {
1103 nsCOMPtr
<nsISupports
> instance
;
1104 nsresult rv
= service
->QueryInterface(aIID
, getter_AddRefs(instance
));
1105 *aResult
= (instance
!= nullptr);
1115 nsComponentManagerImpl::IsServiceInstantiatedByContractID(
1116 const char* aContractID
, const nsIID
& aIID
, bool* aResult
) {
1117 // Now we want to get the service if we already got it. If not, we don't want
1118 // to create an instance of it. mmh!
1120 // test this first, since there's no point in returning a service during
1121 // shutdown -- whether it's available or not would depend on the order it
1122 // occurs in the list
1123 if (gXPCOMShuttingDown
) {
1124 // When processing shutdown, don't process new GetService() requests
1125 #ifdef SHOW_DENIED_ON_SHUTDOWN
1127 "Checking for service on shutdown. Denied.\n"
1128 " ContractID: %s\n IID: %s\n",
1129 aContractID
, AutoIDString(aIID
).get());
1130 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1131 return NS_ERROR_UNEXPECTED
;
1134 if (Maybe
<EntryWrapper
> entry
=
1135 LookupByContractID(nsDependentCString(aContractID
))) {
1136 if (auto* service
= entry
->ServiceInstance()) {
1137 nsCOMPtr
<nsISupports
> instance
;
1138 nsresult rv
= service
->QueryInterface(aIID
, getter_AddRefs(instance
));
1139 *aResult
= (instance
!= nullptr);
1149 nsComponentManagerImpl::GetServiceByContractID(const char* aContractID
,
1152 // test this first, since there's no point in returning a service during
1153 // shutdown -- whether it's available or not would depend on the order it
1154 // occurs in the list
1155 if (gXPCOMShuttingDown
) {
1156 // When processing shutdown, don't process new GetService() requests
1157 #ifdef SHOW_DENIED_ON_SHUTDOWN
1159 "Getting service on shutdown. Denied.\n"
1160 " ContractID: %s\n IID: %s\n",
1161 aContractID
, AutoIDString(aIID
).get());
1162 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1163 return NS_ERROR_UNEXPECTED
;
1166 AUTO_PROFILER_LABEL_DYNAMIC_CSTR_NONSENSITIVE("GetServiceByContractID", OTHER
,
1168 Maybe
<MonitorAutoLock
> lock(std::in_place
, mLock
);
1170 Maybe
<EntryWrapper
> entry
=
1171 LookupByContractID(*lock
, nsDependentCString(aContractID
));
1173 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1176 return GetServiceLocked(lock
, *entry
, aIID
, aResult
);
1180 nsComponentManagerImpl::RegisterFactory(const nsCID
& aClass
, const char* aName
,
1181 const char* aContractID
,
1182 nsIFactory
* aFactory
) {
1184 // If a null factory is passed in, this call just wants to reset
1185 // the contract ID to point to an existing CID entry.
1187 return NS_ERROR_INVALID_ARG
;
1190 nsDependentCString
contractID(aContractID
);
1192 MonitorAutoLock
lock(mLock
);
1193 nsFactoryEntry
* oldf
= mFactories
.Get(&aClass
);
1195 StaticComponents::InvalidateContractID(contractID
);
1196 mContractIDs
.InsertOrUpdate(contractID
, oldf
);
1200 if (StaticComponents::LookupByCID(aClass
)) {
1201 // If this is the CID of a static module, just reset the invalid bit of
1202 // the static entry for this contract ID, and assume it points to the
1204 if (StaticComponents::InvalidateContractID(contractID
, false)) {
1205 mContractIDs
.Remove(contractID
);
1209 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1212 auto f
= MakeUnique
<nsFactoryEntry
>(aClass
, aFactory
);
1214 MonitorAutoLock
lock(mLock
);
1215 return mFactories
.WithEntryHandle(&f
->mCID
, [&](auto&& entry
) {
1217 return NS_ERROR_FACTORY_EXISTS
;
1219 if (StaticComponents::LookupByCID(f
->mCID
)) {
1220 return NS_ERROR_FACTORY_EXISTS
;
1223 nsDependentCString
contractID(aContractID
);
1224 mContractIDs
.InsertOrUpdate(contractID
, f
.get());
1225 // We allow dynamically-registered contract IDs to override static
1226 // entries, so invalidate any static entry for this contract ID.
1227 StaticComponents::InvalidateContractID(contractID
);
1229 entry
.Insert(f
.release());
1236 nsComponentManagerImpl::UnregisterFactory(const nsCID
& aClass
,
1237 nsIFactory
* aFactory
) {
1238 // Don't release the dying factory or service object until releasing
1239 // the component manager monitor.
1240 nsCOMPtr
<nsIFactory
> dyingFactory
;
1241 nsCOMPtr
<nsISupports
> dyingServiceObject
;
1244 MonitorAutoLock
lock(mLock
);
1245 auto entry
= mFactories
.Lookup(&aClass
);
1246 nsFactoryEntry
* f
= entry
? entry
.Data() : nullptr;
1247 if (!f
|| f
->mFactory
!= aFactory
) {
1248 // Note: We do not support unregistering static factories.
1249 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1254 // This might leave a stale contractid -> factory mapping in
1255 // place, so null out the factory entry (see
1256 // nsFactoryEntry::GetFactory)
1257 f
->mFactory
.swap(dyingFactory
);
1258 f
->mServiceObject
.swap(dyingServiceObject
);
1265 nsComponentManagerImpl::AutoRegister(nsIFile
* aLocation
) {
1266 XRE_AddManifestLocation(NS_EXTENSION_LOCATION
, aLocation
);
1271 nsComponentManagerImpl::IsCIDRegistered(const nsCID
& aClass
, bool* aResult
) {
1272 *aResult
= LookupByCID(aClass
).isSome();
1277 nsComponentManagerImpl::IsContractIDRegistered(const char* aClass
,
1279 if (NS_WARN_IF(!aClass
)) {
1280 return NS_ERROR_INVALID_ARG
;
1283 Maybe
<EntryWrapper
> entry
= LookupByContractID(nsDependentCString(aClass
));
1285 *aResult
= entry
.isSome();
1290 nsComponentManagerImpl::GetContractIDs(nsTArray
<nsCString
>& aResult
) {
1291 aResult
= ToTArray
<nsTArray
<nsCString
>>(mContractIDs
.Keys());
1293 for (const auto& entry
: gContractEntries
) {
1294 if (!entry
.Invalid()) {
1295 aResult
.AppendElement(entry
.ContractID());
1303 nsComponentManagerImpl::ContractIDToCID(const char* aContractID
,
1306 MonitorAutoLock
lock(mLock
);
1307 Maybe
<EntryWrapper
> entry
=
1308 LookupByContractID(lock
, nsDependentCString(aContractID
));
1310 *aResult
= (nsCID
*)moz_xmalloc(sizeof(nsCID
));
1311 **aResult
= entry
->CID();
1316 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1319 MOZ_DEFINE_MALLOC_SIZE_OF(ComponentManagerMallocSizeOf
)
1322 nsComponentManagerImpl::CollectReports(nsIHandleReportCallback
* aHandleReport
,
1323 nsISupports
* aData
, bool aAnonymize
) {
1324 MOZ_COLLECT_REPORT("explicit/xpcom/component-manager", KIND_HEAP
, UNITS_BYTES
,
1325 SizeOfIncludingThis(ComponentManagerMallocSizeOf
),
1326 "Memory used for the XPCOM component manager.");
1331 size_t nsComponentManagerImpl::SizeOfIncludingThis(
1332 mozilla::MallocSizeOf aMallocSizeOf
) const {
1333 size_t n
= aMallocSizeOf(this);
1335 n
+= mFactories
.ShallowSizeOfExcludingThis(aMallocSizeOf
);
1336 for (const auto& data
: mFactories
.Values()) {
1337 n
+= data
->SizeOfIncludingThis(aMallocSizeOf
);
1340 n
+= mContractIDs
.ShallowSizeOfExcludingThis(aMallocSizeOf
);
1341 for (const auto& key
: mContractIDs
.Keys()) {
1342 // We don't measure the nsFactoryEntry data because it's owned by
1343 // mFactories (which is measured above).
1344 n
+= key
.SizeOfExcludingThisIfUnshared(aMallocSizeOf
);
1347 if (sModuleLocations
) {
1348 n
+= sModuleLocations
->ShallowSizeOfIncludingThis(aMallocSizeOf
);
1351 n
+= mPendingServices
.ShallowSizeOfExcludingThis(aMallocSizeOf
);
1353 // Measurement of the following members may be added later if DMD finds it is
1356 // - sModuleLocations' entries
1361 ////////////////////////////////////////////////////////////////////////////////
1363 ////////////////////////////////////////////////////////////////////////////////
1365 nsFactoryEntry::nsFactoryEntry(const nsCID
& aCID
, nsIFactory
* aFactory
)
1366 : mCID(aCID
), mFactory(aFactory
) {}
1368 already_AddRefed
<nsIFactory
> nsFactoryEntry::GetFactory() {
1369 nsComponentManagerImpl::gComponentManager
->mLock
.AssertNotCurrentThreadOwns();
1371 nsCOMPtr
<nsIFactory
> factory
= mFactory
;
1372 return factory
.forget();
1375 nsresult
nsFactoryEntry::CreateInstance(const nsIID
& aIID
, void** aResult
) {
1376 nsCOMPtr
<nsIFactory
> factory
= GetFactory();
1377 NS_ENSURE_TRUE(factory
, NS_ERROR_FAILURE
);
1378 return factory
->CreateInstance(aIID
, aResult
);
1381 size_t nsFactoryEntry::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf
) {
1382 size_t n
= aMallocSizeOf(this);
1384 // Measurement of the following members may be added later if DMD finds it is
1388 // - mServiceObject;
1393 ////////////////////////////////////////////////////////////////////////////////
1394 // Static Access Functions
1395 ////////////////////////////////////////////////////////////////////////////////
1397 nsresult
NS_GetComponentManager(nsIComponentManager
** aResult
) {
1398 if (!nsComponentManagerImpl::gComponentManager
) {
1399 return NS_ERROR_NOT_INITIALIZED
;
1402 NS_ADDREF(*aResult
= nsComponentManagerImpl::gComponentManager
);
1406 nsresult
NS_GetServiceManager(nsIServiceManager
** aResult
) {
1407 if (!nsComponentManagerImpl::gComponentManager
) {
1408 return NS_ERROR_NOT_INITIALIZED
;
1411 NS_ADDREF(*aResult
= nsComponentManagerImpl::gComponentManager
);
1415 nsresult
NS_GetComponentRegistrar(nsIComponentRegistrar
** aResult
) {
1416 if (!nsComponentManagerImpl::gComponentManager
) {
1417 return NS_ERROR_NOT_INITIALIZED
;
1420 NS_ADDREF(*aResult
= nsComponentManagerImpl::gComponentManager
);
1425 nsComponentManagerImpl::AddBootstrappedManifestLocation(nsIFile
* aLocation
) {
1426 NS_ENSURE_ARG_POINTER(aLocation
);
1429 nsresult rv
= aLocation
->GetPath(path
);
1430 if (NS_FAILED(rv
)) {
1434 if (Substring(path
, path
.Length() - 4).EqualsLiteral(".xpi")) {
1435 return XRE_AddJarManifestLocation(NS_BOOTSTRAPPED_LOCATION
, aLocation
);
1438 nsCOMPtr
<nsIFile
> manifest
= CloneAndAppend(aLocation
, "chrome.manifest"_ns
);
1439 return XRE_AddManifestLocation(NS_BOOTSTRAPPED_LOCATION
, manifest
);
1443 nsComponentManagerImpl::RemoveBootstrappedManifestLocation(nsIFile
* aLocation
) {
1444 NS_ENSURE_ARG_POINTER(aLocation
);
1446 nsCOMPtr
<nsIChromeRegistry
> cr
= mozilla::services::GetChromeRegistry();
1448 return NS_ERROR_FAILURE
;
1452 nsresult rv
= aLocation
->GetPath(path
);
1453 if (NS_FAILED(rv
)) {
1457 nsComponentManagerImpl::ComponentLocation elem
;
1458 elem
.type
= NS_BOOTSTRAPPED_LOCATION
;
1460 if (Substring(path
, path
.Length() - 4).EqualsLiteral(".xpi")) {
1461 elem
.location
.Init(aLocation
, "chrome.manifest");
1463 nsCOMPtr
<nsIFile
> lf
= CloneAndAppend(aLocation
, "chrome.manifest"_ns
);
1464 elem
.location
.Init(lf
);
1467 // Remove reference.
1468 nsComponentManagerImpl::sModuleLocations
->RemoveElement(
1469 elem
, ComponentLocationComparator());
1471 rv
= cr
->CheckForNewChrome();
1476 nsComponentManagerImpl::GetComponentJSMs(nsIUTF8StringEnumerator
** aJSMs
) {
1477 nsCOMPtr
<nsIUTF8StringEnumerator
> result
=
1478 StaticComponents::GetComponentJSMs();
1479 result
.forget(aJSMs
);
1484 nsComponentManagerImpl::GetComponentESModules(
1485 nsIUTF8StringEnumerator
** aESModules
) {
1486 nsCOMPtr
<nsIUTF8StringEnumerator
> result
=
1487 StaticComponents::GetComponentESModules();
1488 result
.forget(aESModules
);
1493 nsComponentManagerImpl::GetManifestLocations(nsIArray
** aLocations
) {
1494 NS_ENSURE_ARG_POINTER(aLocations
);
1495 *aLocations
= nullptr;
1497 if (!sModuleLocations
) {
1498 return NS_ERROR_NOT_INITIALIZED
;
1501 nsCOMPtr
<nsIMutableArray
> locations
= nsArray::Create();
1503 for (uint32_t i
= 0; i
< sModuleLocations
->Length(); ++i
) {
1504 ComponentLocation
& l
= sModuleLocations
->ElementAt(i
);
1505 FileLocation loc
= l
.location
;
1506 nsCString uriString
;
1507 loc
.GetURIString(uriString
);
1508 nsCOMPtr
<nsIURI
> uri
;
1509 rv
= NS_NewURI(getter_AddRefs(uri
), uriString
);
1510 if (NS_SUCCEEDED(rv
)) {
1511 locations
->AppendElement(uri
);
1515 locations
.forget(aLocations
);
1519 EXPORT_XPCOM_API(nsresult
)
1520 XRE_AddManifestLocation(NSLocationType aType
, nsIFile
* aLocation
) {
1521 nsComponentManagerImpl::InitializeModuleLocations();
1522 nsComponentManagerImpl::ComponentLocation
* c
=
1523 nsComponentManagerImpl::sModuleLocations
->AppendElement();
1525 c
->location
.Init(aLocation
);
1527 if (nsComponentManagerImpl::gComponentManager
&&
1528 nsComponentManagerImpl::NORMAL
==
1529 nsComponentManagerImpl::gComponentManager
->mStatus
) {
1530 nsComponentManagerImpl::gComponentManager
->RegisterManifest(
1531 aType
, c
->location
, false);
1537 EXPORT_XPCOM_API(nsresult
)
1538 XRE_AddJarManifestLocation(NSLocationType aType
, nsIFile
* aLocation
) {
1539 nsComponentManagerImpl::InitializeModuleLocations();
1540 nsComponentManagerImpl::ComponentLocation
* c
=
1541 nsComponentManagerImpl::sModuleLocations
->AppendElement();
1544 c
->location
.Init(aLocation
, "chrome.manifest");
1546 if (nsComponentManagerImpl::gComponentManager
&&
1547 nsComponentManagerImpl::NORMAL
==
1548 nsComponentManagerImpl::gComponentManager
->mStatus
) {
1549 nsComponentManagerImpl::gComponentManager
->RegisterManifest(
1550 aType
, c
->location
, false);
1556 // Expose some important global interfaces to rust for the rust xpcom API. These
1557 // methods return a non-owning reference to the component manager, which should
1558 // live for the lifetime of XPCOM.
1561 const nsIComponentManager
* Gecko_GetComponentManager() {
1562 return nsComponentManagerImpl::gComponentManager
;
1565 const nsIServiceManager
* Gecko_GetServiceManager() {
1566 return nsComponentManagerImpl::gComponentManager
;
1569 const nsIComponentRegistrar
* Gecko_GetComponentRegistrar() {
1570 return nsComponentManagerImpl::gComponentManager
;
1573 // FFI-compatible version of `GetServiceHelper::operator()`.
1574 nsresult
Gecko_GetServiceByModuleID(ModuleID aId
, const nsIID
* aIID
,
1576 return nsComponentManagerImpl::gComponentManager
->GetService(aId
, *aIID
,
1580 // FFI-compatible version of `CreateInstanceHelper::operator()`.
1581 nsresult
Gecko_CreateInstanceByModuleID(ModuleID aId
, const nsIID
* aIID
,
1583 const auto& entry
= gStaticModules
[size_t(aId
)];
1584 if (!entry
.Active()) {
1585 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1588 nsresult rv
= entry
.CreateInstance(*aIID
, aResult
);