LCOV - code coverage report
Current view: top level - xpcom/components - nsComponentManager.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 505 840 60.1 %
Date: 2017-07-14 16:53:18 Functions: 60 85 70.6 %
Legend: Lines: hit not hit

          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             : 

Generated by: LCOV version 1.13