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.
371 loadChromeManifests
= false;
374 // XXX The check this code replaced implicitly let through all of these
375 // process types, but presumably only the default (parent) and content
376 // processes really need chrome manifests...?
377 case GeckoProcessType_Default
:
378 case GeckoProcessType_Content
:
379 loadChromeManifests
= true;
383 if (loadChromeManifests
) {
384 // This needs to be called very early, before anything in nsLayoutModule is
385 // used, and before any calls are made into the JS engine.
386 nsLayoutModuleInitialize();
388 mJSLoaderReady
= true;
390 // The overall order in which chrome.manifests are expected to be treated
392 // - greDir's omni.ja or greDir
393 // - appDir's omni.ja or appDir
395 InitializeModuleLocations();
396 ComponentLocation
* cl
= sModuleLocations
->AppendElement();
397 cl
->type
= NS_APP_LOCATION
;
398 RefPtr
<nsZipArchive
> greOmnijar
=
399 mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE
);
401 cl
->location
.Init(greOmnijar
, "chrome.manifest");
403 nsCOMPtr
<nsIFile
> lf
= CloneAndAppend(greDir
, "chrome.manifest"_ns
);
404 cl
->location
.Init(lf
);
407 RefPtr
<nsZipArchive
> appOmnijar
=
408 mozilla::Omnijar::GetReader(mozilla::Omnijar::APP
);
410 cl
= sModuleLocations
->AppendElement();
411 cl
->type
= NS_APP_LOCATION
;
412 cl
->location
.Init(appOmnijar
, "chrome.manifest");
415 appDir
->Equals(greDir
, &equals
);
417 cl
= sModuleLocations
->AppendElement();
418 cl
->type
= NS_APP_LOCATION
;
419 nsCOMPtr
<nsIFile
> lf
= CloneAndAppend(appDir
, "chrome.manifest"_ns
);
420 cl
->location
.Init(lf
);
424 RereadChromeManifests(false);
427 nsCategoryManager::GetSingleton()->SuppressNotifications(false);
429 RegisterWeakMemoryReporter(this);
431 // NB: The logging preference watcher needs to be registered late enough in
432 // startup that it's okay to use the preference system, but also as soon as
433 // possible so that log modules enabled via preferences are turned on as
434 // early as possible.
436 // We can't initialize the preference watcher when the log module manager is
437 // initialized, as a number of things attempt to start logging before the
438 // preference system is initialized.
440 // The preference system is registered as a component so at this point during
441 // component manager initialization we know it is setup and we can register
442 // for notifications.
443 LogModulePrefWatcher::RegisterPrefWatcher();
445 // Unfortunately, we can't register the nsCategoryManager memory reporter
446 // in its constructor (which is triggered by the GetSingleton() call
447 // above) because the memory reporter manager isn't initialized at that
448 // point. So we wait until now.
449 nsCategoryManager::GetSingleton()->InitMemoryReporter();
451 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
452 ("nsComponentManager: Initialized."));
456 MOZ_ASSERT(!XRE_IsContentProcess() ||
457 CONTRACTID_HASHTABLE_INITIAL_LENGTH
<= 8 ||
458 mFactories
.Count() > CONTRACTID_HASHTABLE_INITIAL_LENGTH
/ 3,
459 "Initial component hashtable size is too large");
464 template <typename T
>
465 static void AssertNotMallocAllocated(T
* aPtr
) {
466 #if defined(DEBUG) && defined(MOZ_MEMORY)
467 jemalloc_ptr_info_t info
;
468 jemalloc_ptr_info((void*)aPtr
, &info
);
469 MOZ_ASSERT(info
.tag
== TagUnknown
);
473 template <typename T
>
474 static void AssertNotStackAllocated(T
* aPtr
) {
475 // On all of our supported platforms, the stack grows down. Any address
476 // located below the address of our argument is therefore guaranteed not to be
477 // stack-allocated by the caller.
479 // For addresses above our argument, things get trickier. The main thread
480 // stack is traditionally placed at the top of the program's address space,
481 // but that is becoming less reliable as more and more systems adopt address
482 // space layout randomization strategies, so we have to guess how much space
483 // above our argument pointer we need to care about.
485 // On most systems, we're guaranteed at least several KiB at the top of each
486 // stack for TLS. We'd probably be safe assuming at least 4KiB in the stack
487 // segment above our argument address, but safer is... well, safer.
489 // For threads with huge stacks, it's theoretically possible that we could
490 // wind up being passed a stack-allocated string from farther up the stack,
491 // but this is a best-effort thing, so we'll assume we only care about the
492 // immediate caller. For that case, max 2KiB per stack frame is probably a
493 // reasonable guess most of the time, and is less than the ~4KiB that we
494 // expect for TLS, so go with that to avoid the risk of bumping into heap
495 // data just above the stack.
497 static constexpr size_t kFuzz
= 2048;
499 MOZ_ASSERT(uintptr_t(aPtr
) < uintptr_t(&aPtr
) ||
500 uintptr_t(aPtr
) > uintptr_t(&aPtr
) + kFuzz
);
504 static void DoRegisterManifest(NSLocationType aType
, FileLocation
& aFile
,
506 auto result
= URLPreloader::Read(aFile
);
508 nsCString
buf(result
.unwrap());
509 ParseManifest(aType
, aFile
, buf
.BeginWriting(), aChromeOnly
);
510 } else if (NS_BOOTSTRAPPED_LOCATION
!= aType
) {
512 aFile
.GetURIString(uri
);
513 LogMessage("Could not read chrome manifest '%s'.", uri
.get());
517 void nsComponentManagerImpl::RegisterManifest(NSLocationType aType
,
520 DoRegisterManifest(aType
, aFile
, aChromeOnly
);
523 void nsComponentManagerImpl::ManifestManifest(ManifestProcessingContext
& aCx
,
524 int aLineNo
, char* const* aArgv
) {
525 char* file
= aArgv
[0];
526 FileLocation
f(aCx
.mFile
, file
);
527 RegisterManifest(aCx
.mType
, f
, aCx
.mChromeOnly
);
530 void nsComponentManagerImpl::ManifestCategory(ManifestProcessingContext
& aCx
,
531 int aLineNo
, char* const* aArgv
) {
532 char* category
= aArgv
[0];
533 char* key
= aArgv
[1];
534 char* value
= aArgv
[2];
536 nsCategoryManager::GetSingleton()->AddCategoryEntry(
537 nsDependentCString(category
), nsDependentCString(key
),
538 nsDependentCString(value
));
541 void nsComponentManagerImpl::RereadChromeManifests(bool aChromeOnly
) {
542 for (uint32_t i
= 0; i
< sModuleLocations
->Length(); ++i
) {
543 ComponentLocation
& l
= sModuleLocations
->ElementAt(i
);
544 RegisterManifest(l
.type
, l
.location
, aChromeOnly
);
547 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
549 obs
->NotifyObservers(nullptr, "chrome-manifests-loaded", nullptr);
553 nsresult
nsComponentManagerImpl::Shutdown(void) {
554 MOZ_ASSERT(NORMAL
== mStatus
);
556 mStatus
= SHUTDOWN_IN_PROGRESS
;
558 // Shutdown the component manager
559 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
560 ("nsComponentManager: Beginning Shutdown."));
562 UnregisterWeakMemoryReporter(this);
564 // Release all cached factories
565 mContractIDs
.Clear();
566 mFactories
.Clear(); // XXX release the objects, don't just clear
568 StaticComponents::Shutdown();
570 delete sModuleLocations
;
572 mStatus
= SHUTDOWN_COMPLETE
;
574 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
575 ("nsComponentManager: Shutdown complete."));
580 nsComponentManagerImpl::~nsComponentManagerImpl() {
581 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
582 ("nsComponentManager: Beginning destruction."));
584 if (SHUTDOWN_COMPLETE
!= mStatus
) {
588 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
589 ("nsComponentManager: Destroyed."));
592 NS_IMPL_ISUPPORTS(nsComponentManagerImpl
, nsIComponentManager
,
593 nsIServiceManager
, nsIComponentRegistrar
,
594 nsISupportsWeakReference
, nsIInterfaceRequestor
,
597 nsresult
nsComponentManagerImpl::GetInterface(const nsIID
& aUuid
,
599 NS_WARNING("This isn't supported");
600 // fall through to QI as anything QIable is a superset of what can be
601 // got via the GetInterface()
602 return QueryInterface(aUuid
, aResult
);
605 Maybe
<EntryWrapper
> nsComponentManagerImpl::LookupByCID(const nsID
& aCID
) {
606 return LookupByCID(MonitorAutoLock(mLock
), aCID
);
609 Maybe
<EntryWrapper
> nsComponentManagerImpl::LookupByCID(const MonitorAutoLock
&,
611 if (const StaticModule
* module
= StaticComponents::LookupByCID(aCID
)) {
612 return Some(EntryWrapper(module
));
614 if (nsFactoryEntry
* entry
= mFactories
.Get(&aCID
)) {
615 return Some(EntryWrapper(entry
));
620 Maybe
<EntryWrapper
> nsComponentManagerImpl::LookupByContractID(
621 const nsACString
& aContractID
) {
622 return LookupByContractID(MonitorAutoLock(mLock
), aContractID
);
625 Maybe
<EntryWrapper
> nsComponentManagerImpl::LookupByContractID(
626 const MonitorAutoLock
&, const nsACString
& aContractID
) {
627 if (const StaticModule
* module
=
628 StaticComponents::LookupByContractID(aContractID
)) {
629 return Some(EntryWrapper(module
));
631 if (nsFactoryEntry
* entry
= mContractIDs
.Get(aContractID
)) {
632 // UnregisterFactory might have left a stale nsFactoryEntry in
633 // mContractIDs, so we should check to see whether this entry has
635 if (entry
->mFactory
|| entry
->mServiceObject
) {
636 return Some(EntryWrapper(entry
));
642 already_AddRefed
<nsIFactory
> nsComponentManagerImpl::FindFactory(
643 const nsCID
& aClass
) {
644 Maybe
<EntryWrapper
> e
= LookupByCID(aClass
);
649 return e
->GetFactory();
652 already_AddRefed
<nsIFactory
> nsComponentManagerImpl::FindFactory(
653 const char* aContractID
, uint32_t aContractIDLen
) {
654 Maybe
<EntryWrapper
> entry
=
655 LookupByContractID(nsDependentCString(aContractID
, aContractIDLen
));
660 return entry
->GetFactory();
666 * Given a classID, this finds the singleton ClassObject that implements the
667 * CID. Returns an interface of type aIID off the singleton classobject.
670 nsComponentManagerImpl::GetClassObject(const nsCID
& aClass
, const nsIID
& aIID
,
674 if (MOZ_LOG_TEST(nsComponentManagerLog
, LogLevel::Debug
)) {
675 char buf
[NSID_LENGTH
];
676 aClass
.ToProvidedString(buf
);
677 PR_LogPrint("nsComponentManager: GetClassObject(%s)", buf
);
680 MOZ_ASSERT(aResult
!= nullptr);
682 nsCOMPtr
<nsIFactory
> factory
= FindFactory(aClass
);
684 return NS_ERROR_FACTORY_NOT_REGISTERED
;
687 rv
= factory
->QueryInterface(aIID
, aResult
);
690 nsComponentManagerLog
, LogLevel::Warning
,
691 ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
697 nsComponentManagerImpl::GetClassObjectByContractID(const char* aContractID
,
700 if (NS_WARN_IF(!aResult
) || NS_WARN_IF(!aContractID
)) {
701 return NS_ERROR_INVALID_ARG
;
706 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
707 ("nsComponentManager: GetClassObjectByContractID(%s)", aContractID
));
709 nsCOMPtr
<nsIFactory
> factory
= FindFactory(aContractID
, strlen(aContractID
));
711 return NS_ERROR_FACTORY_NOT_REGISTERED
;
714 rv
= factory
->QueryInterface(aIID
, aResult
);
716 MOZ_LOG(nsComponentManagerLog
, LogLevel::Warning
,
717 ("\t\tGetClassObjectByContractID() %s",
718 NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
726 * Create an instance of an object that implements an interface and belongs
727 * to the implementation aClass using the factory. The factory is immediately
728 * released and not held onto for any longer.
731 nsComponentManagerImpl::CreateInstance(const nsCID
& aClass
, const nsIID
& aIID
,
733 // test this first, since there's no point in creating a component during
734 // shutdown -- whether it's available or not would depend on the order it
735 // occurs in the list
736 if (gXPCOMShuttingDown
) {
737 // When processing shutdown, don't process new GetService() requests
738 #ifdef SHOW_DENIED_ON_SHUTDOWN
740 "Creating new instance on shutdown. Denied.\n"
741 " CID: %s\n IID: %s\n",
742 AutoIDString(aClass
).get(), AutoIDString(aIID
).get());
743 #endif /* SHOW_DENIED_ON_SHUTDOWN */
744 return NS_ERROR_UNEXPECTED
;
748 return NS_ERROR_NULL_POINTER
;
752 Maybe
<EntryWrapper
> entry
= LookupByCID(aClass
);
755 return NS_ERROR_FACTORY_NOT_REGISTERED
;
758 #ifdef SHOW_CI_ON_EXISTING_SERVICE
759 if (entry
->ServiceInstance()) {
760 nsAutoCString message
;
761 message
= "You are calling CreateInstance \""_ns
+ AutoIDString(aClass
) +
762 "\" when a service for this CID already exists!"_ns
;
763 NS_ERROR(message
.get());
768 nsCOMPtr
<nsIFactory
> factory
= entry
->GetFactory();
770 rv
= factory
->CreateInstance(aIID
, aResult
);
771 if (NS_SUCCEEDED(rv
) && !*aResult
) {
772 NS_ERROR("Factory did not return an object but returned success!");
773 rv
= NS_ERROR_SERVICE_NOT_AVAILABLE
;
776 // Translate error values
777 rv
= NS_ERROR_FACTORY_NOT_REGISTERED
;
780 if (MOZ_LOG_TEST(nsComponentManagerLog
, LogLevel::Warning
)) {
781 char buf
[NSID_LENGTH
];
782 aClass
.ToProvidedString(buf
);
783 MOZ_LOG(nsComponentManagerLog
, LogLevel::Warning
,
784 ("nsComponentManager: CreateInstance(%s) %s", buf
,
785 NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
792 * CreateInstanceByContractID()
794 * A variant of CreateInstance() that creates an instance of the object that
795 * implements the interface aIID and whose implementation has a contractID
798 * This is only a convenience routine that turns around can calls the
799 * CreateInstance() with classid and iid.
802 nsComponentManagerImpl::CreateInstanceByContractID(const char* aContractID
,
805 if (NS_WARN_IF(!aContractID
)) {
806 return NS_ERROR_INVALID_ARG
;
809 // test this first, since there's no point in creating a component during
810 // shutdown -- whether it's available or not would depend on the order it
811 // occurs in the list
812 if (gXPCOMShuttingDown
) {
813 // When processing shutdown, don't process new GetService() requests
814 #ifdef SHOW_DENIED_ON_SHUTDOWN
816 "Creating new instance on shutdown. Denied.\n"
817 " ContractID: %s\n IID: %s\n",
818 aContractID
, AutoIDString(aIID
).get());
819 #endif /* SHOW_DENIED_ON_SHUTDOWN */
820 return NS_ERROR_UNEXPECTED
;
824 return NS_ERROR_NULL_POINTER
;
828 Maybe
<EntryWrapper
> entry
=
829 LookupByContractID(nsDependentCString(aContractID
));
832 return NS_ERROR_FACTORY_NOT_REGISTERED
;
835 #ifdef SHOW_CI_ON_EXISTING_SERVICE
836 if (entry
->ServiceInstance()) {
837 nsAutoCString message
;
839 "You are calling CreateInstance \""_ns
+
840 nsDependentCString(aContractID
) +
842 "\" when a service for this CID already exists! "
843 "Add it to abusedContracts to track down the service consumer.");
844 NS_ERROR(message
.get());
849 nsCOMPtr
<nsIFactory
> factory
= entry
->GetFactory();
851 rv
= factory
->CreateInstance(aIID
, aResult
);
852 if (NS_SUCCEEDED(rv
) && !*aResult
) {
853 NS_ERROR("Factory did not return an object but returned success!");
854 rv
= NS_ERROR_SERVICE_NOT_AVAILABLE
;
857 // Translate error values
858 rv
= NS_ERROR_FACTORY_NOT_REGISTERED
;
861 MOZ_LOG(nsComponentManagerLog
, LogLevel::Warning
,
862 ("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID
,
863 NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
868 nsresult
nsComponentManagerImpl::FreeServices() {
869 NS_ASSERTION(gXPCOMShuttingDown
,
870 "Must be shutting down in order to free all services");
872 if (!gXPCOMShuttingDown
) {
873 return NS_ERROR_FAILURE
;
876 for (nsFactoryEntry
* entry
: mFactories
.Values()) {
877 entry
->mFactory
= nullptr;
878 entry
->mServiceObject
= nullptr;
881 for (const auto& module
: gStaticModules
) {
882 module
.SetServiceInstance(nullptr);
888 // This should only ever be called within the monitor!
889 nsComponentManagerImpl::PendingServiceInfo
*
890 nsComponentManagerImpl::AddPendingService(const nsCID
& aServiceCID
,
892 PendingServiceInfo
* newInfo
= mPendingServices
.AppendElement();
894 newInfo
->cid
= &aServiceCID
;
895 newInfo
->thread
= aThread
;
900 // This should only ever be called within the monitor!
901 void nsComponentManagerImpl::RemovePendingService(MonitorAutoLock
& aLock
,
902 const nsCID
& aServiceCID
) {
903 uint32_t pendingCount
= mPendingServices
.Length();
904 for (uint32_t index
= 0; index
< pendingCount
; ++index
) {
905 const PendingServiceInfo
& info
= mPendingServices
.ElementAt(index
);
906 if (info
.cid
->Equals(aServiceCID
)) {
907 mPendingServices
.RemoveElementAt(index
);
914 // This should only ever be called within the monitor!
915 PRThread
* nsComponentManagerImpl::GetPendingServiceThread(
916 const nsCID
& aServiceCID
) const {
917 uint32_t pendingCount
= mPendingServices
.Length();
918 for (uint32_t index
= 0; index
< pendingCount
; ++index
) {
919 const PendingServiceInfo
& info
= mPendingServices
.ElementAt(index
);
920 if (info
.cid
->Equals(aServiceCID
)) {
927 nsresult
nsComponentManagerImpl::GetServiceLocked(Maybe
<MonitorAutoLock
>& aLock
,
928 EntryWrapper
& aEntry
,
931 MOZ_ASSERT(aLock
.isSome());
932 if (!aLock
.isSome()) {
933 return NS_ERROR_INVALID_ARG
;
936 if (auto* service
= aEntry
.ServiceInstance()) {
938 return service
->QueryInterface(aIID
, aResult
);
941 PRThread
* currentPRThread
= PR_GetCurrentThread();
942 MOZ_ASSERT(currentPRThread
, "This should never be null!");
944 PRThread
* pendingPRThread
;
945 while ((pendingPRThread
= GetPendingServiceThread(aEntry
.CID()))) {
946 if (pendingPRThread
== currentPRThread
) {
947 NS_ERROR("Recursive GetService!");
948 return NS_ERROR_NOT_AVAILABLE
;
954 // It's still possible that the other thread failed to create the
955 // service so we're not guaranteed to have an entry or service yet.
956 if (auto* service
= aEntry
.ServiceInstance()) {
958 return service
->QueryInterface(aIID
, aResult
);
961 DebugOnly
<PendingServiceInfo
*> newInfo
=
962 AddPendingService(aEntry
.CID(), currentPRThread
);
963 NS_ASSERTION(newInfo
, "Failed to add info to the array!");
965 // We need to not be holding the service manager's lock while calling
966 // CreateInstance, because it invokes user code which could try to re-enter
967 // the service manager:
969 nsCOMPtr
<nsISupports
> service
;
970 auto cleanup
= MakeScopeExit([&]() {
971 // `service` must be released after the lock is released, so if we fail and
972 // still have a reference, release the lock before releasing it.
974 MOZ_ASSERT(aLock
.isSome());
980 mLock
.AssertCurrentThreadOwns();
982 MonitorAutoUnlock
unlock(mLock
);
983 AUTO_PROFILER_MARKER_TEXT(
984 "GetService", OTHER
, MarkerStack::Capture(),
985 nsDependentCString(nsIDToCString(aEntry
.CID()).get()));
986 rv
= aEntry
.CreateInstance(aIID
, getter_AddRefs(service
));
988 if (NS_SUCCEEDED(rv
) && !service
) {
989 NS_ERROR("Factory did not return an object but returned success");
990 return NS_ERROR_SERVICE_NOT_AVAILABLE
;
994 pendingPRThread
= GetPendingServiceThread(aEntry
.CID());
995 MOZ_ASSERT(pendingPRThread
== currentPRThread
,
996 "Pending service array has been changed!");
998 MOZ_ASSERT(aLock
.isSome());
999 RemovePendingService(*aLock
, aEntry
.CID());
1001 if (NS_FAILED(rv
)) {
1005 NS_ASSERTION(!aEntry
.ServiceInstance(),
1006 "Created two instances of a service!");
1008 aEntry
.SetServiceInstance(service
.forget());
1012 *aResult
= do_AddRef(aEntry
.ServiceInstance()).take();
1017 nsComponentManagerImpl::GetService(const nsCID
& aClass
, const nsIID
& aIID
,
1019 // test this first, since there's no point in returning a service during
1020 // shutdown -- whether it's available or not would depend on the order it
1021 // occurs in the list
1022 if (gXPCOMShuttingDown
) {
1023 // When processing shutdown, don't process new GetService() requests
1024 #ifdef SHOW_DENIED_ON_SHUTDOWN
1026 "Getting service on shutdown. Denied.\n"
1027 " CID: %s\n IID: %s\n",
1028 AutoIDString(aClass
).get(), AutoIDString(aIID
).get());
1029 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1030 return NS_ERROR_UNEXPECTED
;
1033 Maybe
<MonitorAutoLock
> lock(std::in_place
, mLock
);
1035 Maybe
<EntryWrapper
> entry
= LookupByCID(*lock
, aClass
);
1037 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1040 return GetServiceLocked(lock
, *entry
, aIID
, aResult
);
1043 nsresult
nsComponentManagerImpl::GetService(ModuleID aId
, const nsIID
& aIID
,
1045 const auto& entry
= gStaticModules
[size_t(aId
)];
1047 // test this first, since there's no point in returning a service during
1048 // shutdown -- whether it's available or not would depend on the order it
1049 // occurs in the list
1050 if (gXPCOMShuttingDown
) {
1051 // When processing shutdown, don't process new GetService() requests
1052 #ifdef SHOW_DENIED_ON_SHUTDOWN
1054 "Getting service on shutdown. Denied.\n"
1055 " CID: %s\n IID: %s\n",
1056 AutoIDString(entry
.CID()).get(), AutoIDString(aIID
).get());
1057 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1058 return NS_ERROR_UNEXPECTED
;
1061 Maybe
<MonitorAutoLock
> lock(std::in_place
, mLock
);
1063 Maybe
<EntryWrapper
> wrapper
;
1064 if (entry
.Overridable()) {
1065 // If we expect this service to be overridden by test code, we need to look
1066 // it up by contract ID every time.
1067 wrapper
= LookupByContractID(*lock
, entry
.ContractID());
1069 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1071 } else if (!entry
.Active()) {
1072 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1074 wrapper
.emplace(&entry
);
1076 return GetServiceLocked(lock
, *wrapper
, aIID
, aResult
);
1080 nsComponentManagerImpl::IsServiceInstantiated(const nsCID
& aClass
,
1083 // Now we want to get the service if we already got it. If not, we don't want
1084 // to create an instance of it. mmh!
1086 // test this first, since there's no point in returning a service during
1087 // shutdown -- whether it's available or not would depend on the order it
1088 // occurs in the list
1089 if (gXPCOMShuttingDown
) {
1090 // When processing shutdown, don't process new GetService() requests
1091 #ifdef SHOW_DENIED_ON_SHUTDOWN
1093 "Checking for service on shutdown. Denied.\n"
1094 " CID: %s\n IID: %s\n",
1095 AutoIDString(aClass
).get(), AutoIDString(aIID
).get());
1096 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1097 return NS_ERROR_UNEXPECTED
;
1100 if (Maybe
<EntryWrapper
> entry
= LookupByCID(aClass
)) {
1101 if (auto* service
= entry
->ServiceInstance()) {
1102 nsCOMPtr
<nsISupports
> instance
;
1103 nsresult rv
= service
->QueryInterface(aIID
, getter_AddRefs(instance
));
1104 *aResult
= (instance
!= nullptr);
1114 nsComponentManagerImpl::IsServiceInstantiatedByContractID(
1115 const char* aContractID
, const nsIID
& aIID
, bool* aResult
) {
1116 // Now we want to get the service if we already got it. If not, we don't want
1117 // to create an instance of it. mmh!
1119 // test this first, since there's no point in returning a service during
1120 // shutdown -- whether it's available or not would depend on the order it
1121 // occurs in the list
1122 if (gXPCOMShuttingDown
) {
1123 // When processing shutdown, don't process new GetService() requests
1124 #ifdef SHOW_DENIED_ON_SHUTDOWN
1126 "Checking for service on shutdown. Denied.\n"
1127 " ContractID: %s\n IID: %s\n",
1128 aContractID
, AutoIDString(aIID
).get());
1129 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1130 return NS_ERROR_UNEXPECTED
;
1133 if (Maybe
<EntryWrapper
> entry
=
1134 LookupByContractID(nsDependentCString(aContractID
))) {
1135 if (auto* service
= entry
->ServiceInstance()) {
1136 nsCOMPtr
<nsISupports
> instance
;
1137 nsresult rv
= service
->QueryInterface(aIID
, getter_AddRefs(instance
));
1138 *aResult
= (instance
!= nullptr);
1148 nsComponentManagerImpl::GetServiceByContractID(const char* aContractID
,
1151 // test this first, since there's no point in returning a service during
1152 // shutdown -- whether it's available or not would depend on the order it
1153 // occurs in the list
1154 if (gXPCOMShuttingDown
) {
1155 // When processing shutdown, don't process new GetService() requests
1156 #ifdef SHOW_DENIED_ON_SHUTDOWN
1158 "Getting service on shutdown. Denied.\n"
1159 " ContractID: %s\n IID: %s\n",
1160 aContractID
, AutoIDString(aIID
).get());
1161 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1162 return NS_ERROR_UNEXPECTED
;
1165 AUTO_PROFILER_LABEL_DYNAMIC_CSTR_NONSENSITIVE("GetServiceByContractID", OTHER
,
1167 Maybe
<MonitorAutoLock
> lock(std::in_place
, mLock
);
1169 Maybe
<EntryWrapper
> entry
=
1170 LookupByContractID(*lock
, nsDependentCString(aContractID
));
1172 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1175 return GetServiceLocked(lock
, *entry
, aIID
, aResult
);
1179 nsComponentManagerImpl::RegisterFactory(const nsCID
& aClass
, const char* aName
,
1180 const char* aContractID
,
1181 nsIFactory
* aFactory
) {
1183 // If a null factory is passed in, this call just wants to reset
1184 // the contract ID to point to an existing CID entry.
1186 return NS_ERROR_INVALID_ARG
;
1189 nsDependentCString
contractID(aContractID
);
1191 MonitorAutoLock
lock(mLock
);
1192 nsFactoryEntry
* oldf
= mFactories
.Get(&aClass
);
1194 StaticComponents::InvalidateContractID(contractID
);
1195 mContractIDs
.InsertOrUpdate(contractID
, oldf
);
1199 if (StaticComponents::LookupByCID(aClass
)) {
1200 // If this is the CID of a static module, just reset the invalid bit of
1201 // the static entry for this contract ID, and assume it points to the
1203 if (StaticComponents::InvalidateContractID(contractID
, false)) {
1204 mContractIDs
.Remove(contractID
);
1208 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1211 auto f
= MakeUnique
<nsFactoryEntry
>(aClass
, aFactory
);
1213 MonitorAutoLock
lock(mLock
);
1214 return mFactories
.WithEntryHandle(&f
->mCID
, [&](auto&& entry
) {
1216 return NS_ERROR_FACTORY_EXISTS
;
1218 if (StaticComponents::LookupByCID(f
->mCID
)) {
1219 return NS_ERROR_FACTORY_EXISTS
;
1222 nsDependentCString
contractID(aContractID
);
1223 mContractIDs
.InsertOrUpdate(contractID
, f
.get());
1224 // We allow dynamically-registered contract IDs to override static
1225 // entries, so invalidate any static entry for this contract ID.
1226 StaticComponents::InvalidateContractID(contractID
);
1228 entry
.Insert(f
.release());
1235 nsComponentManagerImpl::UnregisterFactory(const nsCID
& aClass
,
1236 nsIFactory
* aFactory
) {
1237 // Don't release the dying factory or service object until releasing
1238 // the component manager monitor.
1239 nsCOMPtr
<nsIFactory
> dyingFactory
;
1240 nsCOMPtr
<nsISupports
> dyingServiceObject
;
1243 MonitorAutoLock
lock(mLock
);
1244 auto entry
= mFactories
.Lookup(&aClass
);
1245 nsFactoryEntry
* f
= entry
? entry
.Data() : nullptr;
1246 if (!f
|| f
->mFactory
!= aFactory
) {
1247 // Note: We do not support unregistering static factories.
1248 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1253 // This might leave a stale contractid -> factory mapping in
1254 // place, so null out the factory entry (see
1255 // nsFactoryEntry::GetFactory)
1256 f
->mFactory
.swap(dyingFactory
);
1257 f
->mServiceObject
.swap(dyingServiceObject
);
1264 nsComponentManagerImpl::AutoRegister(nsIFile
* aLocation
) {
1265 XRE_AddManifestLocation(NS_EXTENSION_LOCATION
, aLocation
);
1270 nsComponentManagerImpl::IsCIDRegistered(const nsCID
& aClass
, bool* aResult
) {
1271 *aResult
= LookupByCID(aClass
).isSome();
1276 nsComponentManagerImpl::IsContractIDRegistered(const char* aClass
,
1278 if (NS_WARN_IF(!aClass
)) {
1279 return NS_ERROR_INVALID_ARG
;
1282 Maybe
<EntryWrapper
> entry
= LookupByContractID(nsDependentCString(aClass
));
1284 *aResult
= entry
.isSome();
1289 nsComponentManagerImpl::GetContractIDs(nsTArray
<nsCString
>& aResult
) {
1290 aResult
= ToTArray
<nsTArray
<nsCString
>>(mContractIDs
.Keys());
1292 for (const auto& entry
: gContractEntries
) {
1293 if (!entry
.Invalid()) {
1294 aResult
.AppendElement(entry
.ContractID());
1302 nsComponentManagerImpl::ContractIDToCID(const char* aContractID
,
1305 MonitorAutoLock
lock(mLock
);
1306 Maybe
<EntryWrapper
> entry
=
1307 LookupByContractID(lock
, nsDependentCString(aContractID
));
1309 *aResult
= (nsCID
*)moz_xmalloc(sizeof(nsCID
));
1310 **aResult
= entry
->CID();
1315 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1318 MOZ_DEFINE_MALLOC_SIZE_OF(ComponentManagerMallocSizeOf
)
1321 nsComponentManagerImpl::CollectReports(nsIHandleReportCallback
* aHandleReport
,
1322 nsISupports
* aData
, bool aAnonymize
) {
1323 MOZ_COLLECT_REPORT("explicit/xpcom/component-manager", KIND_HEAP
, UNITS_BYTES
,
1324 SizeOfIncludingThis(ComponentManagerMallocSizeOf
),
1325 "Memory used for the XPCOM component manager.");
1330 size_t nsComponentManagerImpl::SizeOfIncludingThis(
1331 mozilla::MallocSizeOf aMallocSizeOf
) const {
1332 size_t n
= aMallocSizeOf(this);
1334 n
+= mFactories
.ShallowSizeOfExcludingThis(aMallocSizeOf
);
1335 for (const auto& data
: mFactories
.Values()) {
1336 n
+= data
->SizeOfIncludingThis(aMallocSizeOf
);
1339 n
+= mContractIDs
.ShallowSizeOfExcludingThis(aMallocSizeOf
);
1340 for (const auto& key
: mContractIDs
.Keys()) {
1341 // We don't measure the nsFactoryEntry data because it's owned by
1342 // mFactories (which is measured above).
1343 n
+= key
.SizeOfExcludingThisIfUnshared(aMallocSizeOf
);
1346 if (sModuleLocations
) {
1347 n
+= sModuleLocations
->ShallowSizeOfIncludingThis(aMallocSizeOf
);
1350 n
+= mPendingServices
.ShallowSizeOfExcludingThis(aMallocSizeOf
);
1352 // Measurement of the following members may be added later if DMD finds it is
1355 // - sModuleLocations' entries
1360 ////////////////////////////////////////////////////////////////////////////////
1362 ////////////////////////////////////////////////////////////////////////////////
1364 nsFactoryEntry::nsFactoryEntry(const nsCID
& aCID
, nsIFactory
* aFactory
)
1365 : mCID(aCID
), mFactory(aFactory
) {}
1367 already_AddRefed
<nsIFactory
> nsFactoryEntry::GetFactory() {
1368 nsComponentManagerImpl::gComponentManager
->mLock
.AssertNotCurrentThreadOwns();
1370 nsCOMPtr
<nsIFactory
> factory
= mFactory
;
1371 return factory
.forget();
1374 nsresult
nsFactoryEntry::CreateInstance(const nsIID
& aIID
, void** aResult
) {
1375 nsCOMPtr
<nsIFactory
> factory
= GetFactory();
1376 NS_ENSURE_TRUE(factory
, NS_ERROR_FAILURE
);
1377 return factory
->CreateInstance(aIID
, aResult
);
1380 size_t nsFactoryEntry::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf
) {
1381 size_t n
= aMallocSizeOf(this);
1383 // Measurement of the following members may be added later if DMD finds it is
1387 // - mServiceObject;
1392 ////////////////////////////////////////////////////////////////////////////////
1393 // Static Access Functions
1394 ////////////////////////////////////////////////////////////////////////////////
1396 nsresult
NS_GetComponentManager(nsIComponentManager
** aResult
) {
1397 if (!nsComponentManagerImpl::gComponentManager
) {
1398 return NS_ERROR_NOT_INITIALIZED
;
1401 NS_ADDREF(*aResult
= nsComponentManagerImpl::gComponentManager
);
1405 nsresult
NS_GetServiceManager(nsIServiceManager
** aResult
) {
1406 if (!nsComponentManagerImpl::gComponentManager
) {
1407 return NS_ERROR_NOT_INITIALIZED
;
1410 NS_ADDREF(*aResult
= nsComponentManagerImpl::gComponentManager
);
1414 nsresult
NS_GetComponentRegistrar(nsIComponentRegistrar
** aResult
) {
1415 if (!nsComponentManagerImpl::gComponentManager
) {
1416 return NS_ERROR_NOT_INITIALIZED
;
1419 NS_ADDREF(*aResult
= nsComponentManagerImpl::gComponentManager
);
1424 nsComponentManagerImpl::AddBootstrappedManifestLocation(nsIFile
* aLocation
) {
1425 NS_ENSURE_ARG_POINTER(aLocation
);
1428 nsresult rv
= aLocation
->GetPath(path
);
1429 if (NS_FAILED(rv
)) {
1433 if (Substring(path
, path
.Length() - 4).EqualsLiteral(".xpi")) {
1434 return XRE_AddJarManifestLocation(NS_BOOTSTRAPPED_LOCATION
, aLocation
);
1437 nsCOMPtr
<nsIFile
> manifest
= CloneAndAppend(aLocation
, "chrome.manifest"_ns
);
1438 return XRE_AddManifestLocation(NS_BOOTSTRAPPED_LOCATION
, manifest
);
1442 nsComponentManagerImpl::RemoveBootstrappedManifestLocation(nsIFile
* aLocation
) {
1443 NS_ENSURE_ARG_POINTER(aLocation
);
1445 nsCOMPtr
<nsIChromeRegistry
> cr
= mozilla::services::GetChromeRegistry();
1447 return NS_ERROR_FAILURE
;
1451 nsresult rv
= aLocation
->GetPath(path
);
1452 if (NS_FAILED(rv
)) {
1456 nsComponentManagerImpl::ComponentLocation elem
;
1457 elem
.type
= NS_BOOTSTRAPPED_LOCATION
;
1459 if (Substring(path
, path
.Length() - 4).EqualsLiteral(".xpi")) {
1460 elem
.location
.Init(aLocation
, "chrome.manifest");
1462 nsCOMPtr
<nsIFile
> lf
= CloneAndAppend(aLocation
, "chrome.manifest"_ns
);
1463 elem
.location
.Init(lf
);
1466 // Remove reference.
1467 nsComponentManagerImpl::sModuleLocations
->RemoveElement(
1468 elem
, ComponentLocationComparator());
1470 rv
= cr
->CheckForNewChrome();
1475 nsComponentManagerImpl::GetComponentJSMs(nsIUTF8StringEnumerator
** aJSMs
) {
1476 nsCOMPtr
<nsIUTF8StringEnumerator
> result
=
1477 StaticComponents::GetComponentJSMs();
1478 result
.forget(aJSMs
);
1483 nsComponentManagerImpl::GetComponentESModules(
1484 nsIUTF8StringEnumerator
** aESModules
) {
1485 nsCOMPtr
<nsIUTF8StringEnumerator
> result
=
1486 StaticComponents::GetComponentESModules();
1487 result
.forget(aESModules
);
1492 nsComponentManagerImpl::GetManifestLocations(nsIArray
** aLocations
) {
1493 NS_ENSURE_ARG_POINTER(aLocations
);
1494 *aLocations
= nullptr;
1496 if (!sModuleLocations
) {
1497 return NS_ERROR_NOT_INITIALIZED
;
1500 nsCOMPtr
<nsIMutableArray
> locations
= nsArray::Create();
1502 for (uint32_t i
= 0; i
< sModuleLocations
->Length(); ++i
) {
1503 ComponentLocation
& l
= sModuleLocations
->ElementAt(i
);
1504 FileLocation loc
= l
.location
;
1505 nsCString uriString
;
1506 loc
.GetURIString(uriString
);
1507 nsCOMPtr
<nsIURI
> uri
;
1508 rv
= NS_NewURI(getter_AddRefs(uri
), uriString
);
1509 if (NS_SUCCEEDED(rv
)) {
1510 locations
->AppendElement(uri
);
1514 locations
.forget(aLocations
);
1518 EXPORT_XPCOM_API(nsresult
)
1519 XRE_AddManifestLocation(NSLocationType aType
, nsIFile
* aLocation
) {
1520 nsComponentManagerImpl::InitializeModuleLocations();
1521 nsComponentManagerImpl::ComponentLocation
* c
=
1522 nsComponentManagerImpl::sModuleLocations
->AppendElement();
1524 c
->location
.Init(aLocation
);
1526 if (nsComponentManagerImpl::gComponentManager
&&
1527 nsComponentManagerImpl::NORMAL
==
1528 nsComponentManagerImpl::gComponentManager
->mStatus
) {
1529 nsComponentManagerImpl::gComponentManager
->RegisterManifest(
1530 aType
, c
->location
, false);
1536 EXPORT_XPCOM_API(nsresult
)
1537 XRE_AddJarManifestLocation(NSLocationType aType
, nsIFile
* aLocation
) {
1538 nsComponentManagerImpl::InitializeModuleLocations();
1539 nsComponentManagerImpl::ComponentLocation
* c
=
1540 nsComponentManagerImpl::sModuleLocations
->AppendElement();
1543 c
->location
.Init(aLocation
, "chrome.manifest");
1545 if (nsComponentManagerImpl::gComponentManager
&&
1546 nsComponentManagerImpl::NORMAL
==
1547 nsComponentManagerImpl::gComponentManager
->mStatus
) {
1548 nsComponentManagerImpl::gComponentManager
->RegisterManifest(
1549 aType
, c
->location
, false);
1555 // Expose some important global interfaces to rust for the rust xpcom API. These
1556 // methods return a non-owning reference to the component manager, which should
1557 // live for the lifetime of XPCOM.
1560 const nsIComponentManager
* Gecko_GetComponentManager() {
1561 return nsComponentManagerImpl::gComponentManager
;
1564 const nsIServiceManager
* Gecko_GetServiceManager() {
1565 return nsComponentManagerImpl::gComponentManager
;
1568 const nsIComponentRegistrar
* Gecko_GetComponentRegistrar() {
1569 return nsComponentManagerImpl::gComponentManager
;
1572 // FFI-compatible version of `GetServiceHelper::operator()`.
1573 nsresult
Gecko_GetServiceByModuleID(ModuleID aId
, const nsIID
* aIID
,
1575 return nsComponentManagerImpl::gComponentManager
->GetService(aId
, *aIID
,
1579 // FFI-compatible version of `CreateInstanceHelper::operator()`.
1580 nsresult
Gecko_CreateInstanceByModuleID(ModuleID aId
, const nsIID
* aIID
,
1582 const auto& entry
= gStaticModules
[size_t(aId
)];
1583 if (!entry
.Active()) {
1584 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1587 nsresult rv
= entry
.CreateInstance(*aIID
, aResult
);