Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 : *
7 : * This Original Code has been modified by IBM Corporation.
8 : * Modifications made by IBM described herein are
9 : * Copyright (c) International Business Machines
10 : * Corporation, 2000
11 : *
12 : * Modifications to Mozilla code or documentation
13 : * identified per MPL Section 3.3
14 : *
15 : * Date Modified by Description of modification
16 : * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
17 : */
18 :
19 : #include <stdlib.h>
20 : #include "nscore.h"
21 : #include "nsISupports.h"
22 : #include "nspr.h"
23 : #include "nsCRT.h" // for atoll
24 :
25 : #include "nsCategoryManager.h"
26 : #include "nsCOMPtr.h"
27 : #include "nsComponentManager.h"
28 : #include "nsDirectoryService.h"
29 : #include "nsDirectoryServiceDefs.h"
30 : #include "nsCategoryManager.h"
31 : #include "nsCategoryManagerUtils.h"
32 : #include "xptiprivate.h"
33 : #include "mozilla/MemoryReporting.h"
34 : #include "mozilla/XPTInterfaceInfoManager.h"
35 : #include "nsIConsoleService.h"
36 : #include "nsIObserverService.h"
37 : #include "nsISimpleEnumerator.h"
38 : #include "nsIStringEnumerator.h"
39 : #include "nsXPCOM.h"
40 : #include "nsXPCOMPrivate.h"
41 : #include "nsISupportsPrimitives.h"
42 : #include "nsIClassInfo.h"
43 : #include "nsLocalFile.h"
44 : #include "nsReadableUtils.h"
45 : #include "nsString.h"
46 : #include "nsXPIDLString.h"
47 : #include "prcmon.h"
48 : #include "xptinfo.h" // this after nsISupports, to pick up IID so that xpt stuff doesn't try to define it itself...
49 : #include "nsThreadUtils.h"
50 : #include "prthread.h"
51 : #include "private/pprthred.h"
52 : #include "nsTArray.h"
53 : #include "prio.h"
54 : #include "ManifestParser.h"
55 : #include "nsNetUtil.h"
56 : #include "mozilla/Services.h"
57 :
58 : #include "mozilla/GenericFactory.h"
59 : #include "nsSupportsPrimitives.h"
60 : #include "nsArray.h"
61 : #include "nsIMutableArray.h"
62 : #include "nsArrayEnumerator.h"
63 : #include "nsStringEnumerator.h"
64 : #include "mozilla/FileUtils.h"
65 : #include "mozilla/UniquePtr.h"
66 : #include "nsDataHashtable.h"
67 :
68 : #include <new> // for placement new
69 :
70 : #include "mozilla/Omnijar.h"
71 :
72 : #include "mozilla/Logging.h"
73 : #include "LogModulePrefWatcher.h"
74 :
75 : using namespace mozilla;
76 :
77 : static LazyLogModule nsComponentManagerLog("nsComponentManager");
78 :
79 : #if 0 || defined (DEBUG_timeless)
80 : #define SHOW_DENIED_ON_SHUTDOWN
81 : #define SHOW_CI_ON_EXISTING_SERVICE
82 : #endif
83 :
84 : // Bloated registry buffer size to improve startup performance -- needs to
85 : // be big enough to fit the entire file into memory or it'll thrash.
86 : // 512K is big enough to allow for some future growth in the registry.
87 : #define BIG_REGISTRY_BUFLEN (512*1024)
88 :
89 : // Common Key Names
90 : const char xpcomComponentsKeyName[] = "software/mozilla/XPCOM/components";
91 : const char xpcomKeyName[] = "software/mozilla/XPCOM";
92 :
93 : // Common Value Names
94 : const char fileSizeValueName[] = "FileSize";
95 : const char lastModValueName[] = "LastModTimeStamp";
96 : const char nativeComponentType[] = "application/x-mozilla-native";
97 : const char staticComponentType[] = "application/x-mozilla-static";
98 :
99 : NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID);
100 :
101 : #define UID_STRING_LENGTH 39
102 :
103 : nsresult
104 3 : nsGetServiceFromCategory::operator()(const nsIID& aIID,
105 : void** aInstancePtr) const
106 : {
107 : nsresult rv;
108 6 : nsXPIDLCString value;
109 6 : nsCOMPtr<nsICategoryManager> catman;
110 3 : nsComponentManagerImpl* compMgr = nsComponentManagerImpl::gComponentManager;
111 3 : if (!compMgr) {
112 0 : rv = NS_ERROR_NOT_INITIALIZED;
113 0 : goto error;
114 : }
115 :
116 3 : if (!mCategory || !mEntry) {
117 : // when categories have defaults, use that for null mEntry
118 0 : rv = NS_ERROR_NULL_POINTER;
119 0 : goto error;
120 : }
121 :
122 3 : rv = compMgr->nsComponentManagerImpl::GetService(kCategoryManagerCID,
123 : NS_GET_IID(nsICategoryManager),
124 6 : getter_AddRefs(catman));
125 3 : if (NS_FAILED(rv)) {
126 0 : goto error;
127 : }
128 :
129 : /* find the contractID for category.entry */
130 6 : rv = catman->GetCategoryEntry(mCategory, mEntry,
131 6 : getter_Copies(value));
132 3 : if (NS_FAILED(rv)) {
133 0 : goto error;
134 : }
135 3 : if (!value) {
136 0 : rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
137 0 : goto error;
138 : }
139 :
140 3 : rv = compMgr->nsComponentManagerImpl::GetServiceByContractID(value,
141 : aIID,
142 3 : aInstancePtr);
143 3 : if (NS_FAILED(rv)) {
144 : error:
145 0 : *aInstancePtr = 0;
146 : }
147 3 : if (mErrorPtr) {
148 0 : *mErrorPtr = rv;
149 : }
150 6 : return rv;
151 : }
152 :
153 : // GetService and a few other functions need to exit their mutex mid-function
154 : // without reentering it later in the block. This class supports that
155 : // style of early-exit that MutexAutoUnlock doesn't.
156 :
157 : namespace {
158 :
159 : class MOZ_STACK_CLASS MutexLock
160 : {
161 : public:
162 5836 : explicit MutexLock(SafeMutex& aMutex)
163 5836 : : mMutex(aMutex)
164 5836 : , mLocked(false)
165 : {
166 5836 : Lock();
167 5836 : }
168 :
169 5836 : ~MutexLock()
170 5836 : {
171 5836 : if (mLocked) {
172 1078 : Unlock();
173 : }
174 5836 : }
175 :
176 5836 : void Lock()
177 : {
178 5836 : NS_ASSERTION(!mLocked, "Re-entering a mutex");
179 5836 : mMutex.Lock();
180 5836 : mLocked = true;
181 5836 : }
182 :
183 5836 : void Unlock()
184 : {
185 5836 : NS_ASSERTION(mLocked, "Exiting a mutex that isn't held!");
186 5836 : mMutex.Unlock();
187 5836 : mLocked = false;
188 5836 : }
189 :
190 : private:
191 : SafeMutex& mMutex;
192 : bool mLocked;
193 : };
194 :
195 : } // namespace
196 :
197 : // this is safe to call during InitXPCOM
198 : static already_AddRefed<nsIFile>
199 6 : GetLocationFromDirectoryService(const char* aProp)
200 : {
201 12 : nsCOMPtr<nsIProperties> directoryService;
202 6 : nsDirectoryService::Create(nullptr,
203 : NS_GET_IID(nsIProperties),
204 12 : getter_AddRefs(directoryService));
205 :
206 6 : if (!directoryService) {
207 0 : return nullptr;
208 : }
209 :
210 12 : nsCOMPtr<nsIFile> file;
211 12 : nsresult rv = directoryService->Get(aProp,
212 : NS_GET_IID(nsIFile),
213 12 : getter_AddRefs(file));
214 6 : if (NS_FAILED(rv)) {
215 0 : return nullptr;
216 : }
217 :
218 6 : return file.forget();
219 : }
220 :
221 : static already_AddRefed<nsIFile>
222 20 : CloneAndAppend(nsIFile* aBase, const nsACString& aAppend)
223 : {
224 40 : nsCOMPtr<nsIFile> f;
225 20 : aBase->Clone(getter_AddRefs(f));
226 20 : if (!f) {
227 0 : return nullptr;
228 : }
229 :
230 20 : f->AppendNative(aAppend);
231 20 : return f.forget();
232 : }
233 :
234 : ////////////////////////////////////////////////////////////////////////////////
235 : // nsComponentManagerImpl
236 : ////////////////////////////////////////////////////////////////////////////////
237 :
238 : nsresult
239 0 : nsComponentManagerImpl::Create(nsISupports* aOuter, REFNSIID aIID,
240 : void** aResult)
241 : {
242 0 : if (aOuter) {
243 0 : return NS_ERROR_NO_AGGREGATION;
244 : }
245 :
246 0 : if (!gComponentManager) {
247 0 : return NS_ERROR_FAILURE;
248 : }
249 :
250 0 : return gComponentManager->QueryInterface(aIID, aResult);
251 : }
252 :
253 : static const int CONTRACTID_HASHTABLE_INITIAL_LENGTH = 1024;
254 :
255 3 : nsComponentManagerImpl::nsComponentManagerImpl()
256 : : mFactories(CONTRACTID_HASHTABLE_INITIAL_LENGTH)
257 : , mContractIDs(CONTRACTID_HASHTABLE_INITIAL_LENGTH)
258 : , mLock("nsComponentManagerImpl.mLock")
259 3 : , mStatus(NOT_INITIALIZED)
260 : {
261 3 : }
262 :
263 : nsTArray<const mozilla::Module*>* nsComponentManagerImpl::sStaticModules;
264 :
265 : NSMODULE_DEFN(start_kPStaticModules);
266 : NSMODULE_DEFN(end_kPStaticModules);
267 :
268 : /* The content between start_kPStaticModules and end_kPStaticModules is gathered
269 : * by the linker from various objects containing symbols in a specific section.
270 : * ASAN considers (rightfully) the use of this content as a global buffer
271 : * overflow. But this is a deliberate and well-considered choice, with no proper
272 : * way to make ASAN happy. */
273 : MOZ_ASAN_BLACKLIST
274 : /* static */ void
275 3 : nsComponentManagerImpl::InitializeStaticModules()
276 : {
277 3 : if (sStaticModules) {
278 0 : return;
279 : }
280 :
281 3 : sStaticModules = new nsTArray<const mozilla::Module*>;
282 204 : for (const mozilla::Module * const* staticModules =
283 3 : &NSMODULE_NAME(start_kPStaticModules) + 1;
284 207 : staticModules < &NSMODULE_NAME(end_kPStaticModules); ++staticModules)
285 204 : if (*staticModules) { // ASAN adds padding
286 204 : sStaticModules->AppendElement(*staticModules);
287 : }
288 : }
289 :
290 : nsTArray<nsComponentManagerImpl::ComponentLocation>*
291 : nsComponentManagerImpl::sModuleLocations;
292 :
293 : /* static */ void
294 20 : nsComponentManagerImpl::InitializeModuleLocations()
295 : {
296 20 : if (sModuleLocations) {
297 17 : return;
298 : }
299 :
300 3 : sModuleLocations = new nsTArray<ComponentLocation>;
301 : }
302 :
303 : nsresult
304 3 : nsComponentManagerImpl::Init()
305 : {
306 3 : MOZ_ASSERT(NOT_INITIALIZED == mStatus);
307 :
308 : nsCOMPtr<nsIFile> greDir =
309 6 : GetLocationFromDirectoryService(NS_GRE_DIR);
310 : nsCOMPtr<nsIFile> appDir =
311 6 : GetLocationFromDirectoryService(NS_XPCOM_CURRENT_PROCESS_DIR);
312 :
313 3 : InitializeStaticModules();
314 :
315 3 : nsCategoryManager::GetSingleton()->SuppressNotifications(true);
316 :
317 3 : RegisterModule(&kXPCOMModule, nullptr);
318 :
319 207 : for (uint32_t i = 0; i < sStaticModules->Length(); ++i) {
320 204 : RegisterModule((*sStaticModules)[i], nullptr);
321 : }
322 :
323 3 : bool loadChromeManifests = (XRE_GetProcessType() != GeckoProcessType_GPU);
324 3 : if (loadChromeManifests) {
325 : // The overall order in which chrome.manifests are expected to be treated
326 : // is the following:
327 : // - greDir
328 : // - greDir's omni.ja
329 : // - appDir
330 : // - appDir's omni.ja
331 :
332 3 : InitializeModuleLocations();
333 3 : ComponentLocation* cl = sModuleLocations->AppendElement();
334 6 : nsCOMPtr<nsIFile> lf = CloneAndAppend(greDir,
335 12 : NS_LITERAL_CSTRING("chrome.manifest"));
336 3 : cl->type = NS_APP_LOCATION;
337 3 : cl->location.Init(lf);
338 :
339 : RefPtr<nsZipArchive> greOmnijar =
340 6 : mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
341 3 : if (greOmnijar) {
342 0 : cl = sModuleLocations->AppendElement();
343 0 : cl->type = NS_APP_LOCATION;
344 0 : cl->location.Init(greOmnijar, "chrome.manifest");
345 : }
346 :
347 3 : bool equals = false;
348 3 : appDir->Equals(greDir, &equals);
349 3 : if (!equals) {
350 3 : cl = sModuleLocations->AppendElement();
351 3 : cl->type = NS_APP_LOCATION;
352 3 : lf = CloneAndAppend(appDir, NS_LITERAL_CSTRING("chrome.manifest"));
353 3 : cl->location.Init(lf);
354 : }
355 :
356 : RefPtr<nsZipArchive> appOmnijar =
357 6 : mozilla::Omnijar::GetReader(mozilla::Omnijar::APP);
358 3 : if (appOmnijar) {
359 0 : cl = sModuleLocations->AppendElement();
360 0 : cl->type = NS_APP_LOCATION;
361 0 : cl->location.Init(appOmnijar, "chrome.manifest");
362 : }
363 :
364 3 : RereadChromeManifests(false);
365 : }
366 :
367 3 : nsCategoryManager::GetSingleton()->SuppressNotifications(false);
368 :
369 3 : RegisterWeakMemoryReporter(this);
370 :
371 : // NB: The logging preference watcher needs to be registered late enough in
372 : // startup that it's okay to use the preference system, but also as soon as
373 : // possible so that log modules enabled via preferences are turned on as
374 : // early as possible.
375 : //
376 : // We can't initialize the preference watcher when the log module manager is
377 : // initialized, as a number of things attempt to start logging before the
378 : // preference system is initialized.
379 : //
380 : // The preference system is registered as a component so at this point during
381 : // component manager initialization we know it is setup and we can register
382 : // for notifications.
383 3 : LogModulePrefWatcher::RegisterPrefWatcher();
384 :
385 : // Unfortunately, we can't register the nsCategoryManager memory reporter
386 : // in its constructor (which is triggered by the GetSingleton() call
387 : // above) because the memory reporter manager isn't initialized at that
388 : // point. So we wait until now.
389 3 : nsCategoryManager::GetSingleton()->InitMemoryReporter();
390 :
391 3 : MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
392 : ("nsComponentManager: Initialized."));
393 :
394 3 : mStatus = NORMAL;
395 :
396 6 : return NS_OK;
397 : }
398 :
399 : static bool
400 3720 : ProcessSelectorMatches(Module::ProcessSelector aSelector)
401 : {
402 3720 : GeckoProcessType type = XRE_GetProcessType();
403 3720 : if (type == GeckoProcessType_GPU) {
404 0 : return !!(aSelector & Module::ALLOW_IN_GPU_PROCESS);
405 : }
406 :
407 3720 : if (aSelector & Module::MAIN_PROCESS_ONLY) {
408 48 : return type == GeckoProcessType_Default;
409 : }
410 3672 : if (aSelector & Module::CONTENT_PROCESS_ONLY) {
411 45 : return type == GeckoProcessType_Content;
412 : }
413 3627 : return true;
414 : }
415 :
416 : static const int kModuleVersionWithSelector = 51;
417 :
418 : void
419 207 : nsComponentManagerImpl::RegisterModule(const mozilla::Module* aModule,
420 : FileLocation* aFile)
421 : {
422 207 : mLock.AssertNotCurrentThreadOwns();
423 :
424 414 : if (aModule->mVersion >= kModuleVersionWithSelector &&
425 207 : !ProcessSelectorMatches(aModule->selector))
426 : {
427 0 : return;
428 : }
429 :
430 : {
431 : // Scope the monitor so that we don't hold it while calling into the
432 : // category manager.
433 414 : MutexLock lock(mLock);
434 :
435 : KnownModule* m;
436 207 : if (aFile) {
437 0 : nsCString uri;
438 0 : aFile->GetURIString(uri);
439 0 : NS_ASSERTION(!mKnownModules.Get(uri),
440 : "Must not register a binary module twice.");
441 :
442 0 : m = new KnownModule(aModule, *aFile);
443 0 : mKnownModules.Put(uri, m);
444 : } else {
445 207 : m = new KnownModule(aModule);
446 207 : mKnownStaticModules.AppendElement(m);
447 : }
448 :
449 207 : if (aModule->mCIDs) {
450 : const mozilla::Module::CIDEntry* entry;
451 1881 : for (entry = aModule->mCIDs; entry->cid; ++entry) {
452 1674 : RegisterCIDEntryLocked(entry, m);
453 : }
454 : }
455 :
456 207 : if (aModule->mContractIDs) {
457 : const mozilla::Module::ContractIDEntry* entry;
458 2046 : for (entry = aModule->mContractIDs; entry->contractid; ++entry) {
459 1839 : RegisterContractIDLocked(entry);
460 : }
461 207 : MOZ_ASSERT(!entry->cid, "Incorrectly terminated contract list");
462 : }
463 : }
464 :
465 207 : if (aModule->mCategoryEntries) {
466 : const mozilla::Module::CategoryEntry* entry;
467 372 : for (entry = aModule->mCategoryEntries; entry->category; ++entry)
468 297 : nsCategoryManager::GetSingleton()->AddCategoryEntry(entry->category,
469 297 : entry->entry,
470 594 : entry->value);
471 : }
472 : }
473 :
474 : void
475 1674 : nsComponentManagerImpl::RegisterCIDEntryLocked(
476 : const mozilla::Module::CIDEntry* aEntry,
477 : KnownModule* aModule)
478 : {
479 1674 : mLock.AssertCurrentThreadOwns();
480 :
481 1674 : if (!ProcessSelectorMatches(aEntry->processSelector)) {
482 24 : return;
483 : }
484 :
485 3300 : if (auto entry = mFactories.LookupForAdd(*aEntry->cid)) {
486 0 : nsFactoryEntry* f = entry.Data();
487 0 : NS_WARNING("Re-registering a CID?");
488 :
489 : char idstr[NSID_LENGTH];
490 0 : aEntry->cid->ToProvidedString(idstr);
491 :
492 0 : nsCString existing;
493 0 : if (f->mModule) {
494 0 : existing = f->mModule->Description();
495 : } else {
496 0 : existing = "<unknown module>";
497 : }
498 0 : SafeMutexAutoUnlock unlock(mLock);
499 0 : LogMessage("While registering XPCOM module %s, trying to re-register CID '%s' already registered by %s.",
500 0 : aModule->Description().get(),
501 : idstr,
502 0 : existing.get());
503 : } else {
504 4950 : entry.OrInsert([aEntry, aModule] () { return new nsFactoryEntry(aEntry, aModule); });
505 : }
506 : }
507 :
508 : void
509 1839 : nsComponentManagerImpl::RegisterContractIDLocked(
510 : const mozilla::Module::ContractIDEntry* aEntry)
511 : {
512 1839 : mLock.AssertCurrentThreadOwns();
513 :
514 1839 : if (!ProcessSelectorMatches(aEntry->processSelector)) {
515 46 : return;
516 : }
517 :
518 1816 : nsFactoryEntry* f = mFactories.Get(*aEntry->cid);
519 1816 : if (!f) {
520 0 : NS_WARNING("No CID found when attempting to map contract ID");
521 :
522 : char idstr[NSID_LENGTH];
523 0 : aEntry->cid->ToProvidedString(idstr);
524 :
525 0 : SafeMutexAutoUnlock unlock(mLock);
526 : LogMessage("Could not map contract ID '%s' to CID %s because no implementation of the CID is registered.",
527 0 : aEntry->contractid,
528 0 : idstr);
529 :
530 0 : return;
531 : }
532 :
533 1816 : mContractIDs.Put(nsDependentCString(aEntry->contractid), f);
534 : }
535 :
536 : static void
537 49 : CutExtension(nsCString& aPath)
538 : {
539 49 : int32_t dotPos = aPath.RFindChar('.');
540 49 : if (kNotFound == dotPos) {
541 0 : aPath.Truncate();
542 : } else {
543 49 : aPath.Cut(0, dotPos + 1);
544 : }
545 49 : }
546 :
547 : static void
548 315 : DoRegisterManifest(NSLocationType aType,
549 : FileLocation& aFile,
550 : bool aChromeOnly,
551 : bool aXPTOnly)
552 : {
553 315 : MOZ_ASSERT(!aXPTOnly || !nsComponentManagerImpl::gComponentManager);
554 : uint32_t len;
555 630 : FileLocation::Data data;
556 630 : UniquePtr<char[]> buf;
557 315 : nsresult rv = aFile.GetData(data);
558 315 : if (NS_SUCCEEDED(rv)) {
559 311 : rv = data.GetSize(&len);
560 : }
561 315 : if (NS_SUCCEEDED(rv)) {
562 311 : buf = MakeUnique<char[]>(len + 1);
563 311 : rv = data.Copy(buf.get(), len);
564 : }
565 315 : if (NS_SUCCEEDED(rv)) {
566 311 : buf[len] = '\0';
567 311 : ParseManifest(aType, aFile, buf.get(), aChromeOnly, aXPTOnly);
568 4 : } else if (NS_BOOTSTRAPPED_LOCATION != aType) {
569 0 : nsCString uri;
570 0 : aFile.GetURIString(uri);
571 0 : LogMessage("Could not read chrome manifest '%s'.", uri.get());
572 : }
573 315 : }
574 :
575 : void
576 315 : nsComponentManagerImpl::RegisterManifest(NSLocationType aType,
577 : FileLocation& aFile,
578 : bool aChromeOnly)
579 : {
580 315 : DoRegisterManifest(aType, aFile, aChromeOnly, false);
581 315 : }
582 :
583 : void
584 292 : nsComponentManagerImpl::ManifestManifest(ManifestProcessingContext& aCx,
585 : int aLineNo, char* const* aArgv)
586 : {
587 292 : char* file = aArgv[0];
588 584 : FileLocation f(aCx.mFile, file);
589 292 : RegisterManifest(aCx.mType, f, aCx.mChromeOnly);
590 292 : }
591 :
592 : void
593 0 : nsComponentManagerImpl::ManifestBinaryComponent(ManifestProcessingContext& aCx,
594 : int aLineNo,
595 : char* const* aArgv)
596 : {
597 0 : LogMessageWithContext(aCx.mFile, aLineNo,
598 0 : "Binary XPCOM components are no longer supported.");
599 0 : return;
600 : }
601 :
602 : static void
603 522 : DoRegisterXPT(FileLocation& aFile)
604 : {
605 : uint32_t len;
606 1044 : FileLocation::Data data;
607 1044 : UniquePtr<char[]> buf;
608 522 : nsresult rv = aFile.GetData(data);
609 522 : if (NS_SUCCEEDED(rv)) {
610 522 : rv = data.GetSize(&len);
611 : }
612 522 : if (NS_SUCCEEDED(rv)) {
613 522 : buf = MakeUnique<char[]>(len);
614 522 : rv = data.Copy(buf.get(), len);
615 : }
616 522 : if (NS_SUCCEEDED(rv)) {
617 522 : XPTInterfaceInfoManager::GetSingleton()->RegisterBuffer(buf.get(), len);
618 : } else {
619 0 : nsCString uri;
620 0 : aFile.GetURIString(uri);
621 0 : LogMessage("Could not read '%s'.", uri.get());
622 : }
623 522 : }
624 :
625 : void
626 522 : nsComponentManagerImpl::ManifestXPT(ManifestProcessingContext& aCx,
627 : int aLineNo, char* const* aArgv)
628 : {
629 1044 : FileLocation f(aCx.mFile, aArgv[0]);
630 522 : DoRegisterXPT(f);
631 522 : }
632 :
633 : void
634 422 : nsComponentManagerImpl::ManifestComponent(ManifestProcessingContext& aCx,
635 : int aLineNo, char* const* aArgv)
636 : {
637 422 : mLock.AssertNotCurrentThreadOwns();
638 :
639 422 : char* id = aArgv[0];
640 422 : char* file = aArgv[1];
641 :
642 : nsID cid;
643 422 : if (!cid.Parse(id)) {
644 0 : LogMessageWithContext(aCx.mFile, aLineNo,
645 0 : "Malformed CID: '%s'.", id);
646 0 : return;
647 : }
648 :
649 : // Precompute the hash/file data outside of the lock
650 844 : FileLocation fl(aCx.mFile, file);
651 844 : nsCString hash;
652 422 : fl.GetURIString(hash);
653 :
654 844 : MutexLock lock(mLock);
655 844 : auto entry = mFactories.LookupForAdd(cid);
656 422 : if (entry) {
657 0 : nsFactoryEntry* f = entry.Data();
658 : char idstr[NSID_LENGTH];
659 0 : cid.ToProvidedString(idstr);
660 :
661 0 : nsCString existing;
662 0 : if (f->mModule) {
663 0 : existing = f->mModule->Description();
664 : } else {
665 0 : existing = "<unknown module>";
666 : }
667 :
668 0 : lock.Unlock();
669 :
670 0 : LogMessageWithContext(aCx.mFile, aLineNo,
671 : "Trying to re-register CID '%s' already registered by %s.",
672 : idstr,
673 0 : existing.get());
674 0 : return;
675 : }
676 :
677 : KnownModule* km;
678 :
679 422 : km = mKnownModules.Get(hash);
680 422 : if (!km) {
681 310 : km = new KnownModule(fl);
682 310 : mKnownModules.Put(hash, km);
683 : }
684 :
685 422 : void* place = mArena.Allocate(sizeof(nsCID));
686 422 : nsID* permanentCID = static_cast<nsID*>(place);
687 422 : *permanentCID = cid;
688 :
689 422 : place = mArena.Allocate(sizeof(mozilla::Module::CIDEntry));
690 422 : auto* e = new (KnownNotNull, place) mozilla::Module::CIDEntry();
691 422 : e->cid = permanentCID;
692 :
693 1266 : entry.OrInsert([e, km] () { return new nsFactoryEntry(e, km); });
694 : }
695 :
696 : void
697 439 : nsComponentManagerImpl::ManifestContract(ManifestProcessingContext& aCx,
698 : int aLineNo, char* const* aArgv)
699 : {
700 439 : mLock.AssertNotCurrentThreadOwns();
701 :
702 439 : char* contract = aArgv[0];
703 439 : char* id = aArgv[1];
704 :
705 : nsID cid;
706 439 : if (!cid.Parse(id)) {
707 0 : LogMessageWithContext(aCx.mFile, aLineNo,
708 0 : "Malformed CID: '%s'.", id);
709 0 : return;
710 : }
711 :
712 876 : MutexLock lock(mLock);
713 439 : nsFactoryEntry* f = mFactories.Get(cid);
714 439 : if (!f) {
715 2 : lock.Unlock();
716 2 : LogMessageWithContext(aCx.mFile, aLineNo,
717 : "Could not map contract ID '%s' to CID %s because no implementation of the CID is registered.",
718 2 : contract, id);
719 2 : return;
720 : }
721 :
722 437 : mContractIDs.Put(nsDependentCString(contract), f);
723 : }
724 :
725 : void
726 142 : nsComponentManagerImpl::ManifestCategory(ManifestProcessingContext& aCx,
727 : int aLineNo, char* const* aArgv)
728 : {
729 142 : char* category = aArgv[0];
730 142 : char* key = aArgv[1];
731 142 : char* value = aArgv[2];
732 :
733 : nsCategoryManager::GetSingleton()->
734 142 : AddCategoryEntry(category, key, value);
735 142 : }
736 :
737 : void
738 3 : nsComponentManagerImpl::RereadChromeManifests(bool aChromeOnly)
739 : {
740 9 : for (uint32_t i = 0; i < sModuleLocations->Length(); ++i) {
741 6 : ComponentLocation& l = sModuleLocations->ElementAt(i);
742 6 : RegisterManifest(l.type, l.location, aChromeOnly);
743 : }
744 3 : }
745 :
746 : bool
747 49 : nsComponentManagerImpl::KnownModule::EnsureLoader()
748 : {
749 49 : if (!mLoader) {
750 98 : nsCString extension;
751 49 : mFile.GetURIString(extension);
752 49 : CutExtension(extension);
753 : mLoader =
754 49 : nsComponentManagerImpl::gComponentManager->LoaderForExtension(extension);
755 : }
756 49 : return !!mLoader;
757 : }
758 :
759 : bool
760 463 : nsComponentManagerImpl::KnownModule::Load()
761 : {
762 463 : if (mFailed) {
763 0 : return false;
764 : }
765 463 : if (!mModule) {
766 49 : if (!EnsureLoader()) {
767 0 : return false;
768 : }
769 :
770 49 : mModule = mLoader->LoadModule(mFile);
771 :
772 49 : if (!mModule) {
773 0 : mFailed = true;
774 0 : return false;
775 : }
776 : }
777 463 : if (!mLoaded) {
778 135 : if (mModule->loadProc) {
779 18 : nsresult rv = mModule->loadProc();
780 18 : if (NS_FAILED(rv)) {
781 0 : mFailed = true;
782 0 : return false;
783 : }
784 : }
785 135 : mLoaded = true;
786 : }
787 463 : return true;
788 : }
789 :
790 : nsCString
791 0 : nsComponentManagerImpl::KnownModule::Description() const
792 : {
793 0 : nsCString s;
794 0 : if (mFile) {
795 0 : mFile.GetURIString(s);
796 : } else {
797 0 : s = "<static module>";
798 : }
799 0 : return s;
800 : }
801 :
802 0 : nsresult nsComponentManagerImpl::Shutdown(void)
803 : {
804 0 : MOZ_ASSERT(NORMAL == mStatus);
805 :
806 0 : mStatus = SHUTDOWN_IN_PROGRESS;
807 :
808 : // Shutdown the component manager
809 0 : MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
810 : ("nsComponentManager: Beginning Shutdown."));
811 :
812 0 : UnregisterWeakMemoryReporter(this);
813 :
814 : // Release all cached factories
815 0 : mContractIDs.Clear();
816 0 : mFactories.Clear(); // XXX release the objects, don't just clear
817 0 : mLoaderMap.Clear();
818 0 : mKnownModules.Clear();
819 0 : mKnownStaticModules.Clear();
820 :
821 0 : delete sStaticModules;
822 0 : delete sModuleLocations;
823 :
824 0 : mStatus = SHUTDOWN_COMPLETE;
825 :
826 0 : MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
827 : ("nsComponentManager: Shutdown complete."));
828 :
829 0 : return NS_OK;
830 : }
831 :
832 0 : nsComponentManagerImpl::~nsComponentManagerImpl()
833 : {
834 0 : MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
835 : ("nsComponentManager: Beginning destruction."));
836 :
837 0 : if (SHUTDOWN_COMPLETE != mStatus) {
838 0 : Shutdown();
839 : }
840 :
841 0 : MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
842 : ("nsComponentManager: Destroyed."));
843 0 : }
844 :
845 3591 : NS_IMPL_ISUPPORTS(nsComponentManagerImpl,
846 : nsIComponentManager,
847 : nsIServiceManager,
848 : nsIComponentRegistrar,
849 : nsISupportsWeakReference,
850 : nsIInterfaceRequestor,
851 : nsIMemoryReporter)
852 :
853 : nsresult
854 0 : nsComponentManagerImpl::GetInterface(const nsIID& aUuid, void** aResult)
855 : {
856 0 : NS_WARNING("This isn't supported");
857 : // fall through to QI as anything QIable is a superset of what can be
858 : // got via the GetInterface()
859 0 : return QueryInterface(aUuid, aResult);
860 : }
861 :
862 : nsFactoryEntry*
863 1384 : nsComponentManagerImpl::GetFactoryEntry(const char* aContractID,
864 : uint32_t aContractIDLen)
865 : {
866 2768 : SafeMutexAutoLock lock(mLock);
867 2768 : return mContractIDs.Get(nsDependentCString(aContractID, aContractIDLen));
868 : }
869 :
870 :
871 : nsFactoryEntry*
872 439 : nsComponentManagerImpl::GetFactoryEntry(const nsCID& aClass)
873 : {
874 878 : SafeMutexAutoLock lock(mLock);
875 878 : return mFactories.Get(aClass);
876 : }
877 :
878 : already_AddRefed<nsIFactory>
879 3 : nsComponentManagerImpl::FindFactory(const nsCID& aClass)
880 : {
881 3 : nsFactoryEntry* e = GetFactoryEntry(aClass);
882 3 : if (!e) {
883 0 : return nullptr;
884 : }
885 :
886 3 : return e->GetFactory();
887 : }
888 :
889 : already_AddRefed<nsIFactory>
890 12 : nsComponentManagerImpl::FindFactory(const char* aContractID,
891 : uint32_t aContractIDLen)
892 : {
893 12 : nsFactoryEntry* entry = GetFactoryEntry(aContractID, aContractIDLen);
894 12 : if (!entry) {
895 10 : return nullptr;
896 : }
897 :
898 2 : return entry->GetFactory();
899 : }
900 :
901 : /**
902 : * GetClassObject()
903 : *
904 : * Given a classID, this finds the singleton ClassObject that implements the CID.
905 : * Returns an interface of type aIID off the singleton classobject.
906 : */
907 : NS_IMETHODIMP
908 3 : nsComponentManagerImpl::GetClassObject(const nsCID& aClass, const nsIID& aIID,
909 : void** aResult)
910 : {
911 : nsresult rv;
912 :
913 3 : if (MOZ_LOG_TEST(nsComponentManagerLog, LogLevel::Debug)) {
914 0 : char* buf = aClass.ToString();
915 0 : PR_LogPrint("nsComponentManager: GetClassObject(%s)", buf);
916 0 : if (buf) {
917 0 : free(buf);
918 : }
919 : }
920 :
921 3 : MOZ_ASSERT(aResult != nullptr);
922 :
923 6 : nsCOMPtr<nsIFactory> factory = FindFactory(aClass);
924 3 : if (!factory) {
925 0 : return NS_ERROR_FACTORY_NOT_REGISTERED;
926 : }
927 :
928 3 : rv = factory->QueryInterface(aIID, aResult);
929 :
930 3 : MOZ_LOG(nsComponentManagerLog, LogLevel::Warning,
931 : ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
932 :
933 3 : return rv;
934 : }
935 :
936 :
937 : NS_IMETHODIMP
938 12 : nsComponentManagerImpl::GetClassObjectByContractID(const char* aContractID,
939 : const nsIID& aIID,
940 : void** aResult)
941 : {
942 24 : if (NS_WARN_IF(!aResult) ||
943 12 : NS_WARN_IF(!aContractID)) {
944 0 : return NS_ERROR_INVALID_ARG;
945 : }
946 :
947 : nsresult rv;
948 :
949 12 : MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
950 : ("nsComponentManager: GetClassObjectByContractID(%s)", aContractID));
951 :
952 24 : nsCOMPtr<nsIFactory> factory = FindFactory(aContractID, strlen(aContractID));
953 12 : if (!factory) {
954 10 : return NS_ERROR_FACTORY_NOT_REGISTERED;
955 : }
956 :
957 2 : rv = factory->QueryInterface(aIID, aResult);
958 :
959 2 : MOZ_LOG(nsComponentManagerLog, LogLevel::Warning,
960 : ("\t\tGetClassObjectByContractID() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
961 :
962 2 : return rv;
963 : }
964 :
965 : /**
966 : * CreateInstance()
967 : *
968 : * Create an instance of an object that implements an interface and belongs
969 : * to the implementation aClass using the factory. The factory is immediately
970 : * released and not held onto for any longer.
971 : */
972 : NS_IMETHODIMP
973 429 : nsComponentManagerImpl::CreateInstance(const nsCID& aClass,
974 : nsISupports* aDelegate,
975 : const nsIID& aIID,
976 : void** aResult)
977 : {
978 : // test this first, since there's no point in creating a component during
979 : // shutdown -- whether it's available or not would depend on the order it
980 : // occurs in the list
981 429 : if (gXPCOMShuttingDown) {
982 : // When processing shutdown, don't process new GetService() requests
983 : #ifdef SHOW_DENIED_ON_SHUTDOWN
984 : nsXPIDLCString cid, iid;
985 : cid.Adopt(aClass.ToString());
986 : iid.Adopt(aIID.ToString());
987 : fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
988 : " CID: %s\n IID: %s\n", cid.get(), iid.get());
989 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
990 0 : return NS_ERROR_UNEXPECTED;
991 : }
992 :
993 429 : if (!aResult) {
994 0 : return NS_ERROR_NULL_POINTER;
995 : }
996 429 : *aResult = nullptr;
997 :
998 429 : nsFactoryEntry* entry = GetFactoryEntry(aClass);
999 :
1000 429 : if (!entry) {
1001 0 : return NS_ERROR_FACTORY_NOT_REGISTERED;
1002 : }
1003 :
1004 : #ifdef SHOW_CI_ON_EXISTING_SERVICE
1005 : if (entry->mServiceObject) {
1006 : nsXPIDLCString cid;
1007 : cid.Adopt(aClass.ToString());
1008 : nsAutoCString message;
1009 : message = NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
1010 : cid +
1011 : NS_LITERAL_CSTRING("\" when a service for this CID already exists!");
1012 : NS_ERROR(message.get());
1013 : }
1014 : #endif
1015 :
1016 : nsresult rv;
1017 858 : nsCOMPtr<nsIFactory> factory = entry->GetFactory();
1018 429 : if (factory) {
1019 429 : rv = factory->CreateInstance(aDelegate, aIID, aResult);
1020 429 : if (NS_SUCCEEDED(rv) && !*aResult) {
1021 0 : NS_ERROR("Factory did not return an object but returned success!");
1022 0 : rv = NS_ERROR_SERVICE_NOT_FOUND;
1023 : }
1024 : } else {
1025 : // Translate error values
1026 0 : rv = NS_ERROR_FACTORY_NOT_REGISTERED;
1027 : }
1028 :
1029 429 : if (MOZ_LOG_TEST(nsComponentManagerLog, LogLevel::Warning)) {
1030 0 : char* buf = aClass.ToString();
1031 0 : MOZ_LOG(nsComponentManagerLog, LogLevel::Warning,
1032 : ("nsComponentManager: CreateInstance(%s) %s", buf,
1033 : NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
1034 0 : if (buf) {
1035 0 : free(buf);
1036 : }
1037 : }
1038 :
1039 429 : return rv;
1040 : }
1041 :
1042 : /**
1043 : * CreateInstanceByContractID()
1044 : *
1045 : * A variant of CreateInstance() that creates an instance of the object that
1046 : * implements the interface aIID and whose implementation has a contractID aContractID.
1047 : *
1048 : * This is only a convenience routine that turns around can calls the
1049 : * CreateInstance() with classid and iid.
1050 : */
1051 : NS_IMETHODIMP
1052 1372 : nsComponentManagerImpl::CreateInstanceByContractID(const char* aContractID,
1053 : nsISupports* aDelegate,
1054 : const nsIID& aIID,
1055 : void** aResult)
1056 : {
1057 1372 : if (NS_WARN_IF(!aContractID)) {
1058 0 : return NS_ERROR_INVALID_ARG;
1059 : }
1060 :
1061 : // test this first, since there's no point in creating a component during
1062 : // shutdown -- whether it's available or not would depend on the order it
1063 : // occurs in the list
1064 1372 : if (gXPCOMShuttingDown) {
1065 : // When processing shutdown, don't process new GetService() requests
1066 : #ifdef SHOW_DENIED_ON_SHUTDOWN
1067 : nsXPIDLCString iid;
1068 : iid.Adopt(aIID.ToString());
1069 : fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
1070 : " ContractID: %s\n IID: %s\n", aContractID, iid.get());
1071 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
1072 0 : return NS_ERROR_UNEXPECTED;
1073 : }
1074 :
1075 1372 : if (!aResult) {
1076 0 : return NS_ERROR_NULL_POINTER;
1077 : }
1078 1372 : *aResult = nullptr;
1079 :
1080 1372 : nsFactoryEntry* entry = GetFactoryEntry(aContractID, strlen(aContractID));
1081 :
1082 1372 : if (!entry) {
1083 0 : return NS_ERROR_FACTORY_NOT_REGISTERED;
1084 : }
1085 :
1086 : #ifdef SHOW_CI_ON_EXISTING_SERVICE
1087 : if (entry->mServiceObject) {
1088 : nsAutoCString message;
1089 : message =
1090 : NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
1091 : nsDependentCString(aContractID) +
1092 : NS_LITERAL_CSTRING("\" when a service for this CID already exists! "
1093 : "Add it to abusedContracts to track down the service consumer.");
1094 : NS_ERROR(message.get());
1095 : }
1096 : #endif
1097 :
1098 : nsresult rv;
1099 2744 : nsCOMPtr<nsIFactory> factory = entry->GetFactory();
1100 1372 : if (factory) {
1101 :
1102 1372 : rv = factory->CreateInstance(aDelegate, aIID, aResult);
1103 1372 : if (NS_SUCCEEDED(rv) && !*aResult) {
1104 0 : NS_ERROR("Factory did not return an object but returned success!");
1105 0 : rv = NS_ERROR_SERVICE_NOT_FOUND;
1106 : }
1107 : } else {
1108 : // Translate error values
1109 0 : rv = NS_ERROR_FACTORY_NOT_REGISTERED;
1110 : }
1111 :
1112 1372 : MOZ_LOG(nsComponentManagerLog, LogLevel::Warning,
1113 : ("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID,
1114 : NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
1115 :
1116 1372 : return rv;
1117 : }
1118 :
1119 : nsresult
1120 0 : nsComponentManagerImpl::FreeServices()
1121 : {
1122 0 : NS_ASSERTION(gXPCOMShuttingDown,
1123 : "Must be shutting down in order to free all services");
1124 :
1125 0 : if (!gXPCOMShuttingDown) {
1126 0 : return NS_ERROR_FAILURE;
1127 : }
1128 :
1129 0 : for (auto iter = mFactories.Iter(); !iter.Done(); iter.Next()) {
1130 0 : nsFactoryEntry* entry = iter.UserData();
1131 0 : entry->mFactory = nullptr;
1132 0 : entry->mServiceObject = nullptr;
1133 : }
1134 :
1135 0 : return NS_OK;
1136 : }
1137 :
1138 : // This should only ever be called within the monitor!
1139 : nsComponentManagerImpl::PendingServiceInfo*
1140 350 : nsComponentManagerImpl::AddPendingService(const nsCID& aServiceCID,
1141 : PRThread* aThread)
1142 : {
1143 350 : PendingServiceInfo* newInfo = mPendingServices.AppendElement();
1144 350 : if (newInfo) {
1145 350 : newInfo->cid = &aServiceCID;
1146 350 : newInfo->thread = aThread;
1147 : }
1148 350 : return newInfo;
1149 : }
1150 :
1151 : // This should only ever be called within the monitor!
1152 : void
1153 350 : nsComponentManagerImpl::RemovePendingService(const nsCID& aServiceCID)
1154 : {
1155 350 : uint32_t pendingCount = mPendingServices.Length();
1156 452 : for (uint32_t index = 0; index < pendingCount; ++index) {
1157 452 : const PendingServiceInfo& info = mPendingServices.ElementAt(index);
1158 452 : if (info.cid->Equals(aServiceCID)) {
1159 350 : mPendingServices.RemoveElementAt(index);
1160 350 : return;
1161 : }
1162 : }
1163 : }
1164 :
1165 : // This should only ever be called within the monitor!
1166 : PRThread*
1167 700 : nsComponentManagerImpl::GetPendingServiceThread(const nsCID& aServiceCID) const
1168 : {
1169 700 : uint32_t pendingCount = mPendingServices.Length();
1170 904 : for (uint32_t index = 0; index < pendingCount; ++index) {
1171 554 : const PendingServiceInfo& info = mPendingServices.ElementAt(index);
1172 554 : if (info.cid->Equals(aServiceCID)) {
1173 350 : return info.thread;
1174 : }
1175 : }
1176 350 : return nullptr;
1177 : }
1178 :
1179 : NS_IMETHODIMP
1180 368 : nsComponentManagerImpl::GetService(const nsCID& aClass,
1181 : const nsIID& aIID,
1182 : void** aResult)
1183 : {
1184 : // test this first, since there's no point in returning a service during
1185 : // shutdown -- whether it's available or not would depend on the order it
1186 : // occurs in the list
1187 368 : if (gXPCOMShuttingDown) {
1188 : // When processing shutdown, don't process new GetService() requests
1189 : #ifdef SHOW_DENIED_ON_SHUTDOWN
1190 : nsXPIDLCString cid, iid;
1191 : cid.Adopt(aClass.ToString());
1192 : iid.Adopt(aIID.ToString());
1193 : fprintf(stderr, "Getting service on shutdown. Denied.\n"
1194 : " CID: %s\n IID: %s\n", cid.get(), iid.get());
1195 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
1196 0 : return NS_ERROR_UNEXPECTED;
1197 : }
1198 :
1199 : // `service` must be released after the lock is released, so it must be
1200 : // declared before the lock in this C++ block.
1201 736 : nsCOMPtr<nsISupports> service;
1202 736 : MutexLock lock(mLock);
1203 :
1204 368 : nsFactoryEntry* entry = mFactories.Get(aClass);
1205 368 : if (!entry) {
1206 0 : return NS_ERROR_FACTORY_NOT_REGISTERED;
1207 : }
1208 :
1209 368 : if (entry->mServiceObject) {
1210 298 : lock.Unlock();
1211 298 : return entry->mServiceObject->QueryInterface(aIID, aResult);
1212 : }
1213 :
1214 70 : PRThread* currentPRThread = PR_GetCurrentThread();
1215 70 : MOZ_ASSERT(currentPRThread, "This should never be null!");
1216 :
1217 : // Needed to optimize the event loop below.
1218 70 : nsIThread* currentThread = nullptr;
1219 :
1220 : PRThread* pendingPRThread;
1221 70 : while ((pendingPRThread = GetPendingServiceThread(aClass))) {
1222 0 : if (pendingPRThread == currentPRThread) {
1223 0 : NS_ERROR("Recursive GetService!");
1224 0 : return NS_ERROR_NOT_AVAILABLE;
1225 : }
1226 :
1227 :
1228 0 : SafeMutexAutoUnlock unlockPending(mLock);
1229 :
1230 0 : if (!currentThread) {
1231 0 : currentThread = NS_GetCurrentThread();
1232 0 : MOZ_ASSERT(currentThread, "This should never be null!");
1233 : }
1234 :
1235 : // This will process a single event or yield the thread if no event is
1236 : // pending.
1237 0 : if (!NS_ProcessNextEvent(currentThread, false)) {
1238 0 : PR_Sleep(PR_INTERVAL_NO_WAIT);
1239 : }
1240 : }
1241 :
1242 : // It's still possible that the other thread failed to create the
1243 : // service so we're not guaranteed to have an entry or service yet.
1244 70 : if (entry->mServiceObject) {
1245 0 : lock.Unlock();
1246 0 : return entry->mServiceObject->QueryInterface(aIID, aResult);
1247 : }
1248 :
1249 : #ifdef DEBUG
1250 : PendingServiceInfo* newInfo =
1251 : #endif
1252 70 : AddPendingService(aClass, currentPRThread);
1253 70 : NS_ASSERTION(newInfo, "Failed to add info to the array!");
1254 :
1255 : // We need to not be holding the service manager's lock while calling
1256 : // CreateInstance, because it invokes user code which could try to re-enter
1257 : // the service manager:
1258 :
1259 : nsresult rv;
1260 : {
1261 140 : SafeMutexAutoUnlock unlock(mLock);
1262 70 : rv = CreateInstance(aClass, nullptr, aIID, getter_AddRefs(service));
1263 : }
1264 70 : if (NS_SUCCEEDED(rv) && !service) {
1265 0 : NS_ERROR("Factory did not return an object but returned success");
1266 0 : return NS_ERROR_SERVICE_NOT_FOUND;
1267 : }
1268 :
1269 : #ifdef DEBUG
1270 70 : pendingPRThread = GetPendingServiceThread(aClass);
1271 70 : MOZ_ASSERT(pendingPRThread == currentPRThread,
1272 : "Pending service array has been changed!");
1273 : #endif
1274 70 : RemovePendingService(aClass);
1275 :
1276 70 : if (NS_FAILED(rv)) {
1277 0 : return rv;
1278 : }
1279 :
1280 70 : NS_ASSERTION(!entry->mServiceObject, "Created two instances of a service!");
1281 :
1282 70 : entry->mServiceObject = service.forget();
1283 :
1284 70 : lock.Unlock();
1285 70 : nsISupports** sresult = reinterpret_cast<nsISupports**>(aResult);
1286 70 : *sresult = entry->mServiceObject;
1287 70 : (*sresult)->AddRef();
1288 :
1289 70 : return NS_OK;
1290 : }
1291 :
1292 : NS_IMETHODIMP
1293 0 : nsComponentManagerImpl::IsServiceInstantiated(const nsCID& aClass,
1294 : const nsIID& aIID,
1295 : bool* aResult)
1296 : {
1297 : // Now we want to get the service if we already got it. If not, we don't want
1298 : // to create an instance of it. mmh!
1299 :
1300 : // test this first, since there's no point in returning a service during
1301 : // shutdown -- whether it's available or not would depend on the order it
1302 : // occurs in the list
1303 0 : if (gXPCOMShuttingDown) {
1304 : // When processing shutdown, don't process new GetService() requests
1305 : #ifdef SHOW_DENIED_ON_SHUTDOWN
1306 : nsXPIDLCString cid, iid;
1307 : cid.Adopt(aClass.ToString());
1308 : iid.Adopt(aIID.ToString());
1309 : fprintf(stderr, "Checking for service on shutdown. Denied.\n"
1310 : " CID: %s\n IID: %s\n", cid.get(), iid.get());
1311 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
1312 0 : return NS_ERROR_UNEXPECTED;
1313 : }
1314 :
1315 0 : nsresult rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
1316 : nsFactoryEntry* entry;
1317 :
1318 : {
1319 0 : SafeMutexAutoLock lock(mLock);
1320 0 : entry = mFactories.Get(aClass);
1321 : }
1322 :
1323 0 : if (entry && entry->mServiceObject) {
1324 0 : nsCOMPtr<nsISupports> service;
1325 0 : rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service));
1326 0 : *aResult = (service != nullptr);
1327 : }
1328 :
1329 0 : return rv;
1330 : }
1331 :
1332 : NS_IMETHODIMP
1333 2310 : nsComponentManagerImpl::IsServiceInstantiatedByContractID(
1334 : const char* aContractID,
1335 : const nsIID& aIID,
1336 : bool* aResult)
1337 : {
1338 : // Now we want to get the service if we already got it. If not, we don't want
1339 : // to create an instance of it. mmh!
1340 :
1341 : // test this first, since there's no point in returning a service during
1342 : // shutdown -- whether it's available or not would depend on the order it
1343 : // occurs in the list
1344 2310 : if (gXPCOMShuttingDown) {
1345 : // When processing shutdown, don't process new GetService() requests
1346 : #ifdef SHOW_DENIED_ON_SHUTDOWN
1347 : nsXPIDLCString iid;
1348 : iid.Adopt(aIID.ToString());
1349 : fprintf(stderr, "Checking for service on shutdown. Denied.\n"
1350 : " ContractID: %s\n IID: %s\n", aContractID, iid.get());
1351 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
1352 0 : return NS_ERROR_UNEXPECTED;
1353 : }
1354 :
1355 2310 : nsresult rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
1356 : nsFactoryEntry* entry;
1357 : {
1358 4620 : SafeMutexAutoLock lock(mLock);
1359 2310 : entry = mContractIDs.Get(nsDependentCString(aContractID));
1360 : }
1361 :
1362 2310 : if (entry && entry->mServiceObject) {
1363 814 : nsCOMPtr<nsISupports> service;
1364 407 : rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service));
1365 407 : *aResult = (service != nullptr);
1366 : }
1367 2310 : return rv;
1368 : }
1369 :
1370 :
1371 : NS_IMETHODIMP
1372 4400 : nsComponentManagerImpl::GetServiceByContractID(const char* aContractID,
1373 : const nsIID& aIID,
1374 : void** aResult)
1375 : {
1376 : // test this first, since there's no point in returning a service during
1377 : // shutdown -- whether it's available or not would depend on the order it
1378 : // occurs in the list
1379 4400 : if (gXPCOMShuttingDown) {
1380 : // When processing shutdown, don't process new GetService() requests
1381 : #ifdef SHOW_DENIED_ON_SHUTDOWN
1382 : nsXPIDLCString iid;
1383 : iid.Adopt(aIID.ToString());
1384 : fprintf(stderr, "Getting service on shutdown. Denied.\n"
1385 : " ContractID: %s\n IID: %s\n", aContractID, iid.get());
1386 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
1387 0 : return NS_ERROR_UNEXPECTED;
1388 : }
1389 :
1390 : // `service` must be released after the lock is released, so it must be
1391 : // declared before the lock in this C++ block.
1392 8800 : nsCOMPtr<nsISupports> service;
1393 8800 : MutexLock lock(mLock);
1394 :
1395 4400 : nsFactoryEntry* entry = mContractIDs.Get(nsDependentCString(aContractID));
1396 4400 : if (!entry) {
1397 7 : return NS_ERROR_FACTORY_NOT_REGISTERED;
1398 : }
1399 :
1400 4393 : if (entry->mServiceObject) {
1401 : // We need to not be holding the service manager's monitor while calling
1402 : // QueryInterface, because it invokes user code which could try to re-enter
1403 : // the service manager, or try to grab some other lock/monitor/condvar
1404 : // and deadlock, e.g. bug 282743.
1405 : // `entry` is valid until XPCOM shutdown, so we can safely use it after
1406 : // exiting the lock.
1407 4113 : lock.Unlock();
1408 4113 : return entry->mServiceObject->QueryInterface(aIID, aResult);
1409 : }
1410 :
1411 280 : PRThread* currentPRThread = PR_GetCurrentThread();
1412 280 : MOZ_ASSERT(currentPRThread, "This should never be null!");
1413 :
1414 : // Needed to optimize the event loop below.
1415 280 : nsIThread* currentThread = nullptr;
1416 :
1417 : PRThread* pendingPRThread;
1418 280 : while ((pendingPRThread = GetPendingServiceThread(*entry->mCIDEntry->cid))) {
1419 0 : if (pendingPRThread == currentPRThread) {
1420 0 : NS_ERROR("Recursive GetService!");
1421 0 : return NS_ERROR_NOT_AVAILABLE;
1422 : }
1423 :
1424 0 : SafeMutexAutoUnlock unlockPending(mLock);
1425 :
1426 0 : if (!currentThread) {
1427 0 : currentThread = NS_GetCurrentThread();
1428 0 : MOZ_ASSERT(currentThread, "This should never be null!");
1429 : }
1430 :
1431 : // This will process a single event or yield the thread if no event is
1432 : // pending.
1433 0 : if (!NS_ProcessNextEvent(currentThread, false)) {
1434 0 : PR_Sleep(PR_INTERVAL_NO_WAIT);
1435 : }
1436 : }
1437 :
1438 280 : if (currentThread && entry->mServiceObject) {
1439 : // If we have a currentThread then we must have waited on another thread
1440 : // to create the service. Grab it now if that succeeded.
1441 0 : lock.Unlock();
1442 0 : return entry->mServiceObject->QueryInterface(aIID, aResult);
1443 : }
1444 :
1445 : #ifdef DEBUG
1446 : PendingServiceInfo* newInfo =
1447 : #endif
1448 280 : AddPendingService(*entry->mCIDEntry->cid, currentPRThread);
1449 280 : NS_ASSERTION(newInfo, "Failed to add info to the array!");
1450 :
1451 : // We need to not be holding the service manager's lock while calling
1452 : // CreateInstance, because it invokes user code which could try to re-enter
1453 : // the service manager:
1454 :
1455 : nsresult rv;
1456 : {
1457 560 : SafeMutexAutoUnlock unlock(mLock);
1458 280 : rv = CreateInstanceByContractID(aContractID, nullptr, aIID,
1459 560 : getter_AddRefs(service));
1460 : }
1461 280 : if (NS_SUCCEEDED(rv) && !service) {
1462 0 : NS_ERROR("Factory did not return an object but returned success");
1463 0 : return NS_ERROR_SERVICE_NOT_FOUND;
1464 : }
1465 :
1466 : #ifdef DEBUG
1467 280 : pendingPRThread = GetPendingServiceThread(*entry->mCIDEntry->cid);
1468 280 : MOZ_ASSERT(pendingPRThread == currentPRThread,
1469 : "Pending service array has been changed!");
1470 : #endif
1471 280 : RemovePendingService(*entry->mCIDEntry->cid);
1472 :
1473 280 : if (NS_FAILED(rv)) {
1474 5 : return rv;
1475 : }
1476 :
1477 275 : NS_ASSERTION(!entry->mServiceObject, "Created two instances of a service!");
1478 :
1479 275 : entry->mServiceObject = service.forget();
1480 :
1481 275 : lock.Unlock();
1482 :
1483 275 : nsISupports** sresult = reinterpret_cast<nsISupports**>(aResult);
1484 275 : *sresult = entry->mServiceObject;
1485 275 : (*sresult)->AddRef();
1486 :
1487 275 : return NS_OK;
1488 : }
1489 :
1490 : already_AddRefed<mozilla::ModuleLoader>
1491 49 : nsComponentManagerImpl::LoaderForExtension(const nsACString& aExt)
1492 : {
1493 98 : nsCOMPtr<mozilla::ModuleLoader> loader = mLoaderMap.Get(aExt);
1494 49 : if (!loader) {
1495 6 : loader = do_GetServiceFromCategory("module-loader",
1496 9 : PromiseFlatCString(aExt).get());
1497 3 : if (!loader) {
1498 0 : return nullptr;
1499 : }
1500 :
1501 3 : mLoaderMap.Put(aExt, loader);
1502 : }
1503 :
1504 49 : return loader.forget();
1505 : }
1506 :
1507 : NS_IMETHODIMP
1508 23 : nsComponentManagerImpl::RegisterFactory(const nsCID& aClass,
1509 : const char* aName,
1510 : const char* aContractID,
1511 : nsIFactory* aFactory)
1512 : {
1513 23 : if (!aFactory) {
1514 : // If a null factory is passed in, this call just wants to reset
1515 : // the contract ID to point to an existing CID entry.
1516 0 : if (!aContractID) {
1517 0 : return NS_ERROR_INVALID_ARG;
1518 : }
1519 :
1520 0 : SafeMutexAutoLock lock(mLock);
1521 0 : nsFactoryEntry* oldf = mFactories.Get(aClass);
1522 0 : if (!oldf) {
1523 0 : return NS_ERROR_FACTORY_NOT_REGISTERED;
1524 : }
1525 :
1526 0 : mContractIDs.Put(nsDependentCString(aContractID), oldf);
1527 0 : return NS_OK;
1528 : }
1529 :
1530 46 : nsAutoPtr<nsFactoryEntry> f(new nsFactoryEntry(aClass, aFactory));
1531 :
1532 46 : SafeMutexAutoLock lock(mLock);
1533 46 : if (auto entry = mFactories.LookupForAdd(aClass)) {
1534 0 : return NS_ERROR_FACTORY_EXISTS;
1535 : } else {
1536 23 : if (aContractID) {
1537 23 : mContractIDs.Put(nsDependentCString(aContractID), f);
1538 : }
1539 46 : entry.OrInsert([&f] () { return f.forget(); });
1540 : }
1541 :
1542 23 : return NS_OK;
1543 : }
1544 :
1545 : NS_IMETHODIMP
1546 0 : nsComponentManagerImpl::UnregisterFactory(const nsCID& aClass,
1547 : nsIFactory* aFactory)
1548 : {
1549 : // Don't release the dying factory or service object until releasing
1550 : // the component manager monitor.
1551 0 : nsCOMPtr<nsIFactory> dyingFactory;
1552 0 : nsCOMPtr<nsISupports> dyingServiceObject;
1553 :
1554 : {
1555 0 : SafeMutexAutoLock lock(mLock);
1556 0 : auto entry = mFactories.Lookup(aClass);
1557 0 : nsFactoryEntry* f = entry ? entry.Data() : nullptr;
1558 0 : if (!f || f->mFactory != aFactory) {
1559 0 : return NS_ERROR_FACTORY_NOT_REGISTERED;
1560 : }
1561 :
1562 0 : entry.Remove();
1563 :
1564 : // This might leave a stale contractid -> factory mapping in
1565 : // place, so null out the factory entry (see
1566 : // nsFactoryEntry::GetFactory)
1567 0 : f->mFactory.swap(dyingFactory);
1568 0 : f->mServiceObject.swap(dyingServiceObject);
1569 : }
1570 :
1571 0 : return NS_OK;
1572 : }
1573 :
1574 : NS_IMETHODIMP
1575 0 : nsComponentManagerImpl::AutoRegister(nsIFile* aLocation)
1576 : {
1577 0 : XRE_AddManifestLocation(NS_EXTENSION_LOCATION, aLocation);
1578 0 : return NS_OK;
1579 : }
1580 :
1581 : NS_IMETHODIMP
1582 0 : nsComponentManagerImpl::AutoUnregister(nsIFile* aLocation)
1583 : {
1584 0 : NS_ERROR("AutoUnregister not implemented.");
1585 0 : return NS_ERROR_NOT_IMPLEMENTED;
1586 : }
1587 :
1588 : NS_IMETHODIMP
1589 0 : nsComponentManagerImpl::RegisterFactoryLocation(const nsCID& aCID,
1590 : const char* aClassName,
1591 : const char* aContractID,
1592 : nsIFile* aFile,
1593 : const char* aLoaderStr,
1594 : const char* aType)
1595 : {
1596 0 : NS_ERROR("RegisterFactoryLocation not implemented.");
1597 0 : return NS_ERROR_NOT_IMPLEMENTED;
1598 : }
1599 :
1600 : NS_IMETHODIMP
1601 0 : nsComponentManagerImpl::UnregisterFactoryLocation(const nsCID& aCID,
1602 : nsIFile* aFile)
1603 : {
1604 0 : NS_ERROR("UnregisterFactoryLocation not implemented.");
1605 0 : return NS_ERROR_NOT_IMPLEMENTED;
1606 : }
1607 :
1608 : NS_IMETHODIMP
1609 7 : nsComponentManagerImpl::IsCIDRegistered(const nsCID& aClass,
1610 : bool* aResult)
1611 : {
1612 7 : *aResult = (nullptr != GetFactoryEntry(aClass));
1613 7 : return NS_OK;
1614 : }
1615 :
1616 : NS_IMETHODIMP
1617 0 : nsComponentManagerImpl::IsContractIDRegistered(const char* aClass,
1618 : bool* aResult)
1619 : {
1620 0 : if (NS_WARN_IF(!aClass)) {
1621 0 : return NS_ERROR_INVALID_ARG;
1622 : }
1623 :
1624 0 : nsFactoryEntry* entry = GetFactoryEntry(aClass, strlen(aClass));
1625 :
1626 0 : if (entry) {
1627 : // UnregisterFactory might have left a stale nsFactoryEntry in
1628 : // mContractIDs, so we should check to see whether this entry has
1629 : // anything useful.
1630 0 : *aResult = (bool(entry->mModule) ||
1631 0 : bool(entry->mFactory) ||
1632 0 : bool(entry->mServiceObject));
1633 : } else {
1634 0 : *aResult = false;
1635 : }
1636 0 : return NS_OK;
1637 : }
1638 :
1639 : NS_IMETHODIMP
1640 0 : nsComponentManagerImpl::EnumerateCIDs(nsISimpleEnumerator** aEnumerator)
1641 : {
1642 0 : nsCOMArray<nsISupports> array;
1643 0 : for (auto iter = mFactories.Iter(); !iter.Done(); iter.Next()) {
1644 0 : const nsID& id = iter.Key();
1645 0 : nsCOMPtr<nsISupportsID> wrapper = new nsSupportsID();
1646 0 : wrapper->SetData(&id);
1647 0 : array.AppendObject(wrapper);
1648 : }
1649 0 : return NS_NewArrayEnumerator(aEnumerator, array);
1650 : }
1651 :
1652 : NS_IMETHODIMP
1653 3 : nsComponentManagerImpl::EnumerateContractIDs(nsISimpleEnumerator** aEnumerator)
1654 : {
1655 3 : auto* array = new nsTArray<nsCString>;
1656 2313 : for (auto iter = mContractIDs.Iter(); !iter.Done(); iter.Next()) {
1657 2310 : const nsACString& contract = iter.Key();
1658 2310 : array->AppendElement(contract);
1659 : }
1660 :
1661 6 : nsCOMPtr<nsIUTF8StringEnumerator> e;
1662 3 : nsresult rv = NS_NewAdoptingUTF8StringEnumerator(getter_AddRefs(e), array);
1663 3 : if (NS_FAILED(rv)) {
1664 0 : return rv;
1665 : }
1666 :
1667 3 : return CallQueryInterface(e, aEnumerator);
1668 : }
1669 :
1670 : NS_IMETHODIMP
1671 0 : nsComponentManagerImpl::CIDToContractID(const nsCID& aClass,
1672 : char** aResult)
1673 : {
1674 0 : NS_ERROR("CIDTOContractID not implemented");
1675 0 : return NS_ERROR_FACTORY_NOT_REGISTERED;
1676 : }
1677 :
1678 : NS_IMETHODIMP
1679 203 : nsComponentManagerImpl::ContractIDToCID(const char* aContractID,
1680 : nsCID** aResult)
1681 : {
1682 : {
1683 206 : SafeMutexAutoLock lock(mLock);
1684 203 : nsFactoryEntry* entry = mContractIDs.Get(nsDependentCString(aContractID));
1685 203 : if (entry) {
1686 200 : *aResult = (nsCID*)moz_xmalloc(sizeof(nsCID));
1687 200 : **aResult = *entry->mCIDEntry->cid;
1688 200 : return NS_OK;
1689 : }
1690 : }
1691 3 : *aResult = nullptr;
1692 3 : return NS_ERROR_FACTORY_NOT_REGISTERED;
1693 : }
1694 :
1695 0 : MOZ_DEFINE_MALLOC_SIZE_OF(ComponentManagerMallocSizeOf)
1696 :
1697 : NS_IMETHODIMP
1698 0 : nsComponentManagerImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
1699 : nsISupports* aData, bool aAnonymize)
1700 : {
1701 0 : MOZ_COLLECT_REPORT(
1702 : "explicit/xpcom/component-manager", KIND_HEAP, UNITS_BYTES,
1703 : SizeOfIncludingThis(ComponentManagerMallocSizeOf),
1704 0 : "Memory used for the XPCOM component manager.");
1705 :
1706 0 : return NS_OK;
1707 : }
1708 :
1709 : size_t
1710 0 : nsComponentManagerImpl::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
1711 : const
1712 : {
1713 0 : size_t n = aMallocSizeOf(this);
1714 :
1715 0 : n += mLoaderMap.ShallowSizeOfExcludingThis(aMallocSizeOf);
1716 :
1717 0 : n += mFactories.ShallowSizeOfExcludingThis(aMallocSizeOf);
1718 0 : for (auto iter = mFactories.ConstIter(); !iter.Done(); iter.Next()) {
1719 0 : n += iter.Data()->SizeOfIncludingThis(aMallocSizeOf);
1720 : }
1721 :
1722 0 : n += mContractIDs.ShallowSizeOfExcludingThis(aMallocSizeOf);
1723 0 : for (auto iter = mContractIDs.ConstIter(); !iter.Done(); iter.Next()) {
1724 : // We don't measure the nsFactoryEntry data because it's owned by
1725 : // mFactories (which is measured above).
1726 0 : n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
1727 : }
1728 :
1729 0 : n += sStaticModules->ShallowSizeOfIncludingThis(aMallocSizeOf);
1730 0 : if (sModuleLocations) {
1731 0 : n += sModuleLocations->ShallowSizeOfIncludingThis(aMallocSizeOf);
1732 : }
1733 :
1734 0 : n += mKnownStaticModules.ShallowSizeOfExcludingThis(aMallocSizeOf);
1735 0 : n += mKnownModules.ShallowSizeOfExcludingThis(aMallocSizeOf);
1736 :
1737 0 : n += mArena.SizeOfExcludingThis(aMallocSizeOf);
1738 :
1739 0 : n += mPendingServices.ShallowSizeOfExcludingThis(aMallocSizeOf);
1740 :
1741 : // Measurement of the following members may be added later if DMD finds it is
1742 : // worthwhile:
1743 : // - mLoaderMap's keys and values
1744 : // - mMon
1745 : // - sStaticModules' entries
1746 : // - sModuleLocations' entries
1747 : // - mKnownStaticModules' entries?
1748 : // - mKnownModules' keys and values?
1749 :
1750 0 : return n;
1751 : }
1752 :
1753 : ////////////////////////////////////////////////////////////////////////////////
1754 : // nsFactoryEntry
1755 : ////////////////////////////////////////////////////////////////////////////////
1756 :
1757 2072 : nsFactoryEntry::nsFactoryEntry(const mozilla::Module::CIDEntry* aEntry,
1758 2072 : nsComponentManagerImpl::KnownModule* aModule)
1759 : : mCIDEntry(aEntry)
1760 2072 : , mModule(aModule)
1761 : {
1762 2072 : }
1763 :
1764 23 : nsFactoryEntry::nsFactoryEntry(const nsCID& aCID, nsIFactory* aFactory)
1765 : : mCIDEntry(nullptr)
1766 : , mModule(nullptr)
1767 23 : , mFactory(aFactory)
1768 : {
1769 23 : auto* e = new mozilla::Module::CIDEntry();
1770 23 : auto* cid = new nsCID;
1771 23 : *cid = aCID;
1772 23 : e->cid = cid;
1773 23 : mCIDEntry = e;
1774 23 : }
1775 :
1776 0 : nsFactoryEntry::~nsFactoryEntry()
1777 : {
1778 : // If this was a RegisterFactory entry, we own the CIDEntry/CID
1779 0 : if (!mModule) {
1780 0 : delete mCIDEntry->cid;
1781 0 : delete mCIDEntry;
1782 : }
1783 0 : }
1784 :
1785 : already_AddRefed<nsIFactory>
1786 1806 : nsFactoryEntry::GetFactory()
1787 : {
1788 1806 : nsComponentManagerImpl::gComponentManager->mLock.AssertNotCurrentThreadOwns();
1789 :
1790 1806 : if (!mFactory) {
1791 : // RegisterFactory then UnregisterFactory can leave an entry in mContractIDs
1792 : // pointing to an unusable nsFactoryEntry.
1793 463 : if (!mModule) {
1794 0 : return nullptr;
1795 : }
1796 :
1797 463 : if (!mModule->Load()) {
1798 0 : return nullptr;
1799 : }
1800 :
1801 : // Don't set mFactory directly, it needs to be locked
1802 926 : nsCOMPtr<nsIFactory> factory;
1803 :
1804 463 : if (mModule->Module()->getFactoryProc) {
1805 153 : factory = mModule->Module()->getFactoryProc(*mModule->Module(),
1806 102 : *mCIDEntry);
1807 412 : } else if (mCIDEntry->getFactoryProc) {
1808 1 : factory = mCIDEntry->getFactoryProc(*mModule->Module(), *mCIDEntry);
1809 : } else {
1810 411 : NS_ASSERTION(mCIDEntry->constructorProc, "no getfactory or constructor");
1811 411 : factory = new mozilla::GenericFactory(mCIDEntry->constructorProc);
1812 : }
1813 463 : if (!factory) {
1814 0 : return nullptr;
1815 : }
1816 :
1817 926 : SafeMutexAutoLock lock(nsComponentManagerImpl::gComponentManager->mLock);
1818 : // Threads can race to set mFactory
1819 463 : if (!mFactory) {
1820 463 : factory.swap(mFactory);
1821 : }
1822 : }
1823 3612 : nsCOMPtr<nsIFactory> factory = mFactory;
1824 1806 : return factory.forget();
1825 : }
1826 :
1827 : size_t
1828 0 : nsFactoryEntry::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
1829 : {
1830 0 : size_t n = aMallocSizeOf(this);
1831 :
1832 : // Measurement of the following members may be added later if DMD finds it is
1833 : // worthwhile:
1834 : // - mCIDEntry;
1835 : // - mModule;
1836 : // - mFactory;
1837 : // - mServiceObject;
1838 :
1839 0 : return n;
1840 : }
1841 :
1842 : ////////////////////////////////////////////////////////////////////////////////
1843 : // Static Access Functions
1844 : ////////////////////////////////////////////////////////////////////////////////
1845 :
1846 : nsresult
1847 159 : NS_GetComponentManager(nsIComponentManager** aResult)
1848 : {
1849 159 : if (!nsComponentManagerImpl::gComponentManager) {
1850 0 : return NS_ERROR_NOT_INITIALIZED;
1851 : }
1852 :
1853 159 : NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager);
1854 159 : return NS_OK;
1855 : }
1856 :
1857 : nsresult
1858 252 : NS_GetServiceManager(nsIServiceManager** aResult)
1859 : {
1860 252 : if (!nsComponentManagerImpl::gComponentManager) {
1861 0 : return NS_ERROR_NOT_INITIALIZED;
1862 : }
1863 :
1864 252 : NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager);
1865 252 : return NS_OK;
1866 : }
1867 :
1868 :
1869 : nsresult
1870 206 : NS_GetComponentRegistrar(nsIComponentRegistrar** aResult)
1871 : {
1872 206 : if (!nsComponentManagerImpl::gComponentManager) {
1873 0 : return NS_ERROR_NOT_INITIALIZED;
1874 : }
1875 :
1876 206 : NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager);
1877 206 : return NS_OK;
1878 : }
1879 :
1880 : EXPORT_XPCOM_API(nsresult)
1881 0 : XRE_AddStaticComponent(const mozilla::Module* aComponent)
1882 : {
1883 0 : nsComponentManagerImpl::InitializeStaticModules();
1884 0 : nsComponentManagerImpl::sStaticModules->AppendElement(aComponent);
1885 :
1886 0 : if (nsComponentManagerImpl::gComponentManager &&
1887 : nsComponentManagerImpl::NORMAL ==
1888 0 : nsComponentManagerImpl::gComponentManager->mStatus) {
1889 0 : nsComponentManagerImpl::gComponentManager->RegisterModule(aComponent,
1890 0 : nullptr);
1891 : }
1892 :
1893 0 : return NS_OK;
1894 : }
1895 :
1896 : NS_IMETHODIMP
1897 14 : nsComponentManagerImpl::AddBootstrappedManifestLocation(nsIFile* aLocation)
1898 : {
1899 28 : nsString path;
1900 14 : nsresult rv = aLocation->GetPath(path);
1901 14 : if (NS_FAILED(rv)) {
1902 0 : return rv;
1903 : }
1904 :
1905 14 : if (Substring(path, path.Length() - 4).EqualsLiteral(".xpi")) {
1906 0 : return XRE_AddJarManifestLocation(NS_BOOTSTRAPPED_LOCATION, aLocation);
1907 : }
1908 :
1909 : nsCOMPtr<nsIFile> manifest =
1910 28 : CloneAndAppend(aLocation, NS_LITERAL_CSTRING("chrome.manifest"));
1911 14 : return XRE_AddManifestLocation(NS_BOOTSTRAPPED_LOCATION, manifest);
1912 : }
1913 :
1914 : NS_IMETHODIMP
1915 0 : nsComponentManagerImpl::RemoveBootstrappedManifestLocation(nsIFile* aLocation)
1916 : {
1917 0 : nsCOMPtr<nsIChromeRegistry> cr = mozilla::services::GetChromeRegistryService();
1918 0 : if (!cr) {
1919 0 : return NS_ERROR_FAILURE;
1920 : }
1921 :
1922 0 : nsString path;
1923 0 : nsresult rv = aLocation->GetPath(path);
1924 0 : if (NS_FAILED(rv)) {
1925 0 : return rv;
1926 : }
1927 :
1928 0 : nsComponentManagerImpl::ComponentLocation elem;
1929 0 : elem.type = NS_BOOTSTRAPPED_LOCATION;
1930 :
1931 0 : if (Substring(path, path.Length() - 4).EqualsLiteral(".xpi")) {
1932 0 : elem.location.Init(aLocation, "chrome.manifest");
1933 : } else {
1934 : nsCOMPtr<nsIFile> lf =
1935 0 : CloneAndAppend(aLocation, NS_LITERAL_CSTRING("chrome.manifest"));
1936 0 : elem.location.Init(lf);
1937 : }
1938 :
1939 : // Remove reference.
1940 0 : nsComponentManagerImpl::sModuleLocations->RemoveElement(elem,
1941 0 : ComponentLocationComparator());
1942 :
1943 0 : rv = cr->CheckForNewChrome();
1944 0 : return rv;
1945 : }
1946 :
1947 : NS_IMETHODIMP
1948 0 : nsComponentManagerImpl::GetManifestLocations(nsIArray** aLocations)
1949 : {
1950 0 : NS_ENSURE_ARG_POINTER(aLocations);
1951 0 : *aLocations = nullptr;
1952 :
1953 0 : if (!sModuleLocations) {
1954 0 : return NS_ERROR_NOT_INITIALIZED;
1955 : }
1956 :
1957 0 : nsCOMPtr<nsIMutableArray> locations = nsArray::Create();
1958 : nsresult rv;
1959 0 : for (uint32_t i = 0; i < sModuleLocations->Length(); ++i) {
1960 0 : ComponentLocation& l = sModuleLocations->ElementAt(i);
1961 0 : FileLocation loc = l.location;
1962 0 : nsCString uriString;
1963 0 : loc.GetURIString(uriString);
1964 0 : nsCOMPtr<nsIURI> uri;
1965 0 : rv = NS_NewURI(getter_AddRefs(uri), uriString);
1966 0 : if (NS_SUCCEEDED(rv)) {
1967 0 : locations->AppendElement(uri, false);
1968 : }
1969 : }
1970 :
1971 0 : locations.forget(aLocations);
1972 0 : return NS_OK;
1973 : }
1974 :
1975 : EXPORT_XPCOM_API(nsresult)
1976 17 : XRE_AddManifestLocation(NSLocationType aType, nsIFile* aLocation)
1977 : {
1978 17 : nsComponentManagerImpl::InitializeModuleLocations();
1979 : nsComponentManagerImpl::ComponentLocation* c =
1980 17 : nsComponentManagerImpl::sModuleLocations->AppendElement();
1981 17 : c->type = aType;
1982 17 : c->location.Init(aLocation);
1983 :
1984 34 : if (nsComponentManagerImpl::gComponentManager &&
1985 : nsComponentManagerImpl::NORMAL ==
1986 34 : nsComponentManagerImpl::gComponentManager->mStatus) {
1987 17 : nsComponentManagerImpl::gComponentManager->RegisterManifest(aType,
1988 : c->location,
1989 17 : false);
1990 : }
1991 :
1992 17 : return NS_OK;
1993 : }
1994 :
1995 : EXPORT_XPCOM_API(nsresult)
1996 0 : XRE_AddJarManifestLocation(NSLocationType aType, nsIFile* aLocation)
1997 : {
1998 0 : nsComponentManagerImpl::InitializeModuleLocations();
1999 : nsComponentManagerImpl::ComponentLocation* c =
2000 0 : nsComponentManagerImpl::sModuleLocations->AppendElement();
2001 :
2002 0 : c->type = aType;
2003 0 : c->location.Init(aLocation, "chrome.manifest");
2004 :
2005 0 : if (nsComponentManagerImpl::gComponentManager &&
2006 : nsComponentManagerImpl::NORMAL ==
2007 0 : nsComponentManagerImpl::gComponentManager->mStatus) {
2008 0 : nsComponentManagerImpl::gComponentManager->RegisterManifest(aType,
2009 : c->location,
2010 0 : false);
2011 : }
2012 :
2013 0 : return NS_OK;
2014 : }
2015 :
|