LCOV - code coverage report
Current view: directory - xpcom/components - nsComponentManager.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 762 554 72.7 %
Date: 2012-06-02 Functions: 79 64 81.0 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK *****
      37                 :  *
      38                 :  * This Original Code has been modified by IBM Corporation.
      39                 :  * Modifications made by IBM described herein are
      40                 :  * Copyright (c) International Business Machines
      41                 :  * Corporation, 2000
      42                 :  *
      43                 :  * Modifications to Mozilla code or documentation
      44                 :  * identified per MPL Section 3.3
      45                 :  *
      46                 :  * Date             Modified by     Description of modification
      47                 :  * 04/20/2000       IBM Corp.      Added PR_CALLBACK for Optlink use in OS2
      48                 :  */
      49                 : 
      50                 : #include <stdlib.h>
      51                 : #include "nscore.h"
      52                 : #include "nsISupports.h"
      53                 : #include "nspr.h"
      54                 : #include "nsCRT.h" // for atoll
      55                 : 
      56                 : // Arena used by component manager for storing contractid string, dll
      57                 : // location strings and small objects
      58                 : // CAUTION: Arena align mask needs to be defined before including plarena.h
      59                 : //          currently from nsComponentManager.h
      60                 : #define PL_ARENA_CONST_ALIGN_MASK 7
      61                 : #define NS_CM_BLOCK_SIZE (1024 * 8)
      62                 : 
      63                 : #include "nsCategoryManager.h"
      64                 : #include "nsCOMPtr.h"
      65                 : #include "nsComponentManager.h"
      66                 : #include "nsDirectoryService.h"
      67                 : #include "nsDirectoryServiceDefs.h"
      68                 : #include "nsCategoryManager.h"
      69                 : #include "nsCategoryManagerUtils.h"
      70                 : #include "nsIEnumerator.h"
      71                 : #include "xptiprivate.h"
      72                 : #include "nsIConsoleService.h"
      73                 : #include "nsIObserverService.h"
      74                 : #include "nsISimpleEnumerator.h"
      75                 : #include "nsIStringEnumerator.h"
      76                 : #include "nsXPCOM.h"
      77                 : #include "nsXPCOMPrivate.h"
      78                 : #include "nsISupportsPrimitives.h"
      79                 : #include "nsIClassInfo.h"
      80                 : #include "nsLocalFile.h"
      81                 : #include "nsReadableUtils.h"
      82                 : #include "nsStaticComponents.h"
      83                 : #include "nsString.h"
      84                 : #include "nsXPIDLString.h"
      85                 : #include "prcmon.h"
      86                 : #include "xptinfo.h" // this after nsISupports, to pick up IID so that xpt stuff doesn't try to define it itself...
      87                 : #include "nsThreadUtils.h"
      88                 : #include "prthread.h"
      89                 : #include "private/pprthred.h"
      90                 : #include "nsTArray.h"
      91                 : #include "prio.h"
      92                 : #include "mozilla/FunctionTimer.h"
      93                 : #include "ManifestParser.h"
      94                 : #include "mozilla/Services.h"
      95                 : 
      96                 : #include "nsManifestLineReader.h"
      97                 : #include "mozilla/GenericFactory.h"
      98                 : #include "nsSupportsPrimitives.h"
      99                 : #include "nsArrayEnumerator.h"
     100                 : #include "nsStringEnumerator.h"
     101                 : #include "mozilla/FileUtils.h"
     102                 : 
     103                 : #include NEW_H     // for placement new
     104                 : 
     105                 : #include "mozilla/Omnijar.h"
     106                 : 
     107                 : #include "prlog.h"
     108                 : 
     109                 : using namespace mozilla;
     110                 : 
     111                 : PRLogModuleInfo* nsComponentManagerLog = nsnull;
     112                 : 
     113                 : #if 0 || defined (DEBUG_timeless)
     114                 :  #define SHOW_DENIED_ON_SHUTDOWN
     115                 :  #define SHOW_CI_ON_EXISTING_SERVICE
     116                 : #endif
     117                 : 
     118                 : // Bloated registry buffer size to improve startup performance -- needs to
     119                 : // be big enough to fit the entire file into memory or it'll thrash.
     120                 : // 512K is big enough to allow for some future growth in the registry.
     121                 : #define BIG_REGISTRY_BUFLEN   (512*1024)
     122                 : 
     123                 : // Common Key Names
     124                 : const char classIDKeyName[]="classID";
     125                 : const char classesKeyName[]="contractID";
     126                 : const char componentsKeyName[]="components";
     127                 : const char xpcomComponentsKeyName[]="software/mozilla/XPCOM/components";
     128                 : const char xpcomKeyName[]="software/mozilla/XPCOM";
     129                 : 
     130                 : // Common Value Names
     131                 : const char classIDValueName[]="ClassID";
     132                 : const char classNameValueName[]="ClassName";
     133                 : const char componentCountValueName[]="ComponentsCount";
     134                 : const char componentTypeValueName[]="ComponentType";
     135                 : const char contractIDValueName[]="ContractID";
     136                 : const char fileSizeValueName[]="FileSize";
     137                 : const char inprocServerValueName[]="InprocServer";
     138                 : const char lastModValueName[]="LastModTimeStamp";
     139                 : const char nativeComponentType[]="application/x-mozilla-native";
     140                 : const char staticComponentType[]="application/x-mozilla-static";
     141                 : const char jarComponentType[]="application/x-mozilla-jarjs";
     142                 : const char versionValueName[]="VersionString";
     143                 : 
     144                 : const static char XPCOM_ABSCOMPONENT_PREFIX[] = "abs:";
     145                 : const static char XPCOM_RELCOMPONENT_PREFIX[] = "rel:";
     146                 : const static char XPCOM_GRECOMPONENT_PREFIX[] = "gre:";
     147                 : 
     148                 : static const char gIDFormat[] =
     149                 :   "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}";
     150                 : 
     151                 : 
     152                 : #define NS_EMPTY_IID                                 \
     153                 : {                                                    \
     154                 :     0x00000000,                                      \
     155                 :     0x0000,                                          \
     156                 :     0x0000,                                          \
     157                 :     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} \
     158                 : }
     159                 : 
     160                 : NS_DEFINE_CID(kEmptyCID, NS_EMPTY_IID);
     161                 : NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID);
     162                 : 
     163                 : #define UID_STRING_LENGTH 39
     164                 : 
     165                 : #ifdef NS_FUNCTION_TIMER
     166                 : #define COMPMGR_TIME_FUNCTION_CID(cid)                                          \
     167                 :   char cid_buf__[NSID_LENGTH] = { '\0' };                                      \
     168                 :   cid.ToProvidedString(cid_buf__);                                             \
     169                 :   NS_TIME_FUNCTION_MIN_FMT(5, "%s (line %d) (cid: %s)", MOZ_FUNCTION_NAME, \
     170                 :                            __LINE__, cid_buf__)
     171                 : #define COMPMGR_TIME_FUNCTION_CONTRACTID(cid)                                  \
     172                 :   NS_TIME_FUNCTION_MIN_FMT(5, "%s (line %d) (contractid: %s)", MOZ_FUNCTION_NAME, \
     173                 :                            __LINE__, (cid))
     174                 : #else
     175                 : #define COMPMGR_TIME_FUNCTION_CID(cid) do {} while (0)
     176                 : #define COMPMGR_TIME_FUNCTION_CONTRACTID(cid) do {} while (0)
     177                 : #endif
     178                 : 
     179                 : nsresult
     180             759 : nsGetServiceFromCategory::operator()(const nsIID& aIID, void** aInstancePtr) const
     181                 : {
     182                 :     nsresult rv;
     183            1518 :     nsXPIDLCString value;
     184            1518 :     nsCOMPtr<nsICategoryManager> catman;
     185             759 :     nsComponentManagerImpl *compMgr = nsComponentManagerImpl::gComponentManager;
     186             759 :     if (!compMgr) {
     187               0 :         rv = NS_ERROR_NOT_INITIALIZED;
     188               0 :         goto error;
     189                 :     }
     190                 : 
     191             759 :     if (!mCategory || !mEntry) {
     192                 :         // when categories have defaults, use that for null mEntry
     193               0 :         rv = NS_ERROR_NULL_POINTER;
     194               0 :         goto error;
     195                 :     }
     196                 : 
     197                 :     rv = compMgr->nsComponentManagerImpl::GetService(kCategoryManagerCID,
     198                 :                                                      NS_GET_IID(nsICategoryManager),
     199             759 :                                                      getter_AddRefs(catman));
     200             759 :     if (NS_FAILED(rv)) goto error;
     201                 : 
     202                 :     /* find the contractID for category.entry */
     203             759 :     rv = catman->GetCategoryEntry(mCategory, mEntry,
     204             759 :                                   getter_Copies(value));
     205             759 :     if (NS_FAILED(rv)) goto error;
     206             759 :     if (!value) {
     207               0 :         rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
     208               0 :         goto error;
     209                 :     }
     210                 : 
     211                 :     rv = compMgr->
     212                 :         nsComponentManagerImpl::GetServiceByContractID(value,
     213             759 :                                                        aIID, aInstancePtr);
     214             759 :     if (NS_FAILED(rv)) {
     215                 :     error:
     216               0 :         *aInstancePtr = 0;
     217                 :     }
     218             759 :     if (mErrorPtr)
     219               0 :         *mErrorPtr = rv;
     220             759 :     return rv;
     221                 : }
     222                 : 
     223                 : ////////////////////////////////////////////////////////////////////////////////
     224                 : // Arena helper functions
     225                 : ////////////////////////////////////////////////////////////////////////////////
     226                 : char *
     227          885860 : ArenaStrndup(const char *s, PRUint32 len, PLArenaPool *arena)
     228                 : {
     229                 :     void *mem;
     230                 :     // Include trailing null in the len
     231          885860 :     PL_ARENA_ALLOCATE(mem, arena, len+1);
     232          885860 :     if (mem)
     233          885860 :         memcpy(mem, s, len+1);
     234          885860 :     return static_cast<char *>(mem);
     235                 : }
     236                 : 
     237                 : char*
     238          885860 : ArenaStrdup(const char *s, PLArenaPool *arena)
     239                 : {
     240          885860 :     return ArenaStrndup(s, strlen(s), arena);
     241                 : }
     242                 : 
     243                 : // this is safe to call during InitXPCOM
     244                 : static already_AddRefed<nsILocalFile>
     245            2838 : GetLocationFromDirectoryService(const char* prop)
     246                 : {
     247            5676 :     nsCOMPtr<nsIProperties> directoryService;
     248                 :     nsDirectoryService::Create(nsnull,
     249                 :                                NS_GET_IID(nsIProperties),
     250            2838 :                                getter_AddRefs(directoryService));
     251                 : 
     252            2838 :     if (!directoryService)
     253               0 :         return NULL;
     254                 : 
     255            5676 :     nsCOMPtr<nsILocalFile> file;
     256            2838 :     nsresult rv = directoryService->Get(prop,
     257                 :                                         NS_GET_IID(nsILocalFile),
     258            2838 :                                         getter_AddRefs(file));
     259            2838 :     if (NS_FAILED(rv))
     260               0 :         return NULL;
     261                 : 
     262            2838 :     return file.forget();
     263                 : }
     264                 : 
     265                 : static already_AddRefed<nsILocalFile>
     266            1617 : CloneAndAppend(nsILocalFile* aBase, const nsACString& append)
     267                 : {
     268            3234 :     nsCOMPtr<nsIFile> f;
     269            1617 :     aBase->Clone(getter_AddRefs(f));
     270            1617 :     if (!f)
     271               0 :         return NULL;
     272                 : 
     273            3234 :     nsCOMPtr<nsILocalFile> lf = do_QueryInterface(f);
     274            1617 :     f->AppendNative(append);
     275            1617 :     return lf.forget();
     276                 : }
     277                 : 
     278                 : ////////////////////////////////////////////////////////////////////////////////
     279                 : // nsComponentManagerImpl
     280                 : ////////////////////////////////////////////////////////////////////////////////
     281                 : 
     282                 : nsresult
     283               0 : nsComponentManagerImpl::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult)
     284                 : {
     285               0 :     if (aOuter)
     286               0 :         return NS_ERROR_NO_AGGREGATION;
     287                 : 
     288               0 :     if (!gComponentManager)
     289               0 :         return NS_ERROR_FAILURE;
     290                 : 
     291               0 :     return gComponentManager->QueryInterface(aIID, aResult);
     292                 : }
     293                 : 
     294            1419 : nsComponentManagerImpl::nsComponentManagerImpl()
     295                 :     : mMon("nsComponentManagerImpl.mMon")
     296            1419 :     , mStatus(NOT_INITIALIZED)
     297                 : {
     298            1419 : }
     299                 : 
     300                 : #define CONTRACTID_HASHTABLE_INITIAL_SIZE   2048
     301                 : 
     302                 : nsTArray<const mozilla::Module*>* nsComponentManagerImpl::sStaticModules;
     303                 : 
     304                 : /* static */ void
     305            1419 : nsComponentManagerImpl::InitializeStaticModules()
     306                 : {
     307            1419 :     if (sStaticModules)
     308               0 :         return;
     309                 : 
     310            1419 :     sStaticModules = new nsTArray<const mozilla::Module*>;
     311           78045 :     for (const mozilla::Module *const *const *staticModules = kPStaticModules;
     312                 :          *staticModules; ++staticModules)
     313           76626 :         sStaticModules->AppendElement(**staticModules);
     314                 : }
     315                 : 
     316                 : nsTArray<nsComponentManagerImpl::ComponentLocation>*
     317                 : nsComponentManagerImpl::sModuleLocations;
     318                 : 
     319                 : /* static */ void
     320            3034 : nsComponentManagerImpl::InitializeModuleLocations()
     321                 : {
     322            3034 :     if (sModuleLocations)
     323            1615 :         return;
     324                 : 
     325            1419 :     sModuleLocations = new nsTArray<ComponentLocation>;
     326                 : }
     327                 : 
     328            1419 : nsresult nsComponentManagerImpl::Init()
     329                 : {
     330                 :     NS_TIME_FUNCTION;
     331                 : 
     332            1419 :     PR_ASSERT(NOT_INITIALIZED == mStatus);
     333                 : 
     334            1419 :     if (nsComponentManagerLog == nsnull)
     335                 :     {
     336            1419 :         nsComponentManagerLog = PR_NewLogModule("nsComponentManager");
     337                 :     }
     338                 : 
     339                 :     // Initialize our arena
     340                 :     NS_TIME_FUNCTION_MARK("Next: init component manager arena");
     341            1419 :     PL_INIT_ARENA_POOL(&mArena, "ComponentManagerArena", NS_CM_BLOCK_SIZE);
     342                 : 
     343            1419 :     mFactories.Init(CONTRACTID_HASHTABLE_INITIAL_SIZE);
     344            1419 :     mContractIDs.Init(CONTRACTID_HASHTABLE_INITIAL_SIZE);
     345            1419 :     mLoaderMap.Init();
     346            1419 :     mKnownModules.Init();
     347                 : 
     348                 :     nsCOMPtr<nsILocalFile> greDir =
     349            2838 :         GetLocationFromDirectoryService(NS_GRE_DIR);
     350                 :     nsCOMPtr<nsILocalFile> appDir =
     351            2838 :         GetLocationFromDirectoryService(NS_XPCOM_CURRENT_PROCESS_DIR);
     352                 : 
     353            1419 :     InitializeStaticModules();
     354            1419 :     InitializeModuleLocations();
     355                 : 
     356            1419 :     ComponentLocation* cl = sModuleLocations->InsertElementAt(0);
     357            2838 :     nsCOMPtr<nsILocalFile> lf = CloneAndAppend(appDir, NS_LITERAL_CSTRING("chrome.manifest"));
     358            1419 :     cl->type = NS_COMPONENT_LOCATION;
     359            1419 :     cl->location.Init(lf);
     360                 : 
     361            1419 :     bool equals = false;
     362            1419 :     appDir->Equals(greDir, &equals);
     363            1419 :     if (!equals) {
     364               0 :         cl = sModuleLocations->InsertElementAt(0);
     365               0 :         cl->type = NS_COMPONENT_LOCATION;
     366               0 :         lf = CloneAndAppend(greDir, NS_LITERAL_CSTRING("chrome.manifest"));
     367               0 :         cl->location.Init(lf);
     368                 :     }
     369                 : 
     370            1419 :     PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
     371                 :            ("nsComponentManager: Initialized."));
     372                 : 
     373                 :     NS_TIME_FUNCTION_MARK("Next: init native module loader");
     374            1419 :     nsresult rv = mNativeModuleLoader.Init();
     375            1419 :     if (NS_FAILED(rv))
     376               0 :         return rv;
     377                 : 
     378            1419 :     nsCategoryManager::GetSingleton()->SuppressNotifications(true);
     379                 : 
     380            1419 :     RegisterModule(&kXPCOMModule, NULL);
     381                 : 
     382           78045 :     for (PRUint32 i = 0; i < sStaticModules->Length(); ++i)
     383           76626 :         RegisterModule((*sStaticModules)[i], NULL);
     384                 : 
     385            2838 :     nsRefPtr<nsZipArchive> appOmnijar = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP);
     386            1419 :     if (appOmnijar) {
     387               0 :         cl = sModuleLocations->InsertElementAt(1); // Insert after greDir
     388               0 :         cl->type = NS_COMPONENT_LOCATION;
     389               0 :         cl->location.Init(appOmnijar, "chrome.manifest");
     390                 :     }
     391            2838 :     nsRefPtr<nsZipArchive> greOmnijar = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
     392            1419 :     if (greOmnijar) {
     393               0 :         cl = sModuleLocations->InsertElementAt(0);
     394               0 :         cl->type = NS_COMPONENT_LOCATION;
     395               0 :         cl->location.Init(greOmnijar, "chrome.manifest");
     396                 :     }
     397                 : 
     398            1419 :     RereadChromeManifests(false);
     399                 : 
     400            1419 :     nsCategoryManager::GetSingleton()->SuppressNotifications(false);
     401                 : 
     402            1419 :     mStatus = NORMAL;
     403                 : 
     404            1419 :     return NS_OK;
     405                 : }
     406                 : 
     407                 : void
     408           83724 : nsComponentManagerImpl::RegisterModule(const mozilla::Module* aModule,
     409                 :                                        FileLocation* aFile)
     410                 : {
     411          167448 :     ReentrantMonitorAutoEnter mon(mMon);
     412                 : 
     413                 :     KnownModule* m;
     414           83724 :     if (aFile) {
     415           11358 :         nsCString uri;
     416            5679 :         aFile->GetURIString(uri);
     417            5679 :         NS_ASSERTION(!mKnownModules.Get(uri),
     418                 :                      "Must not register a binary module twice.");
     419                 : 
     420            5679 :         m = new KnownModule(aModule, *aFile);
     421            5679 :         mKnownModules.Put(uri, m);
     422                 :     } else {
     423           78045 :         m = new KnownModule(aModule);
     424           78045 :         mKnownStaticModules.AppendElement(m);
     425                 :     }
     426                 : 
     427           83724 :     if (aModule->mCIDs) {
     428                 :         const mozilla::Module::CIDEntry* entry;
     429         1082707 :         for (entry = aModule->mCIDs; entry->cid; ++entry)
     430          998983 :             RegisterCIDEntry(entry, m);
     431                 :     }
     432                 : 
     433           83724 :     if (aModule->mContractIDs) {
     434                 :         const mozilla::Module::ContractIDEntry* entry;
     435         1142303 :         for (entry = aModule->mContractIDs; entry->contractid; ++entry)
     436         1058580 :             RegisterContractID(entry);
     437           83723 :         NS_ASSERTION(!entry->cid, "Incorrectly terminated contract list");
     438                 :     }
     439                 :             
     440           83724 :     if (aModule->mCategoryEntries) {
     441                 :         const mozilla::Module::CategoryEntry* entry;
     442          394482 :         for (entry = aModule->mCategoryEntries; entry->category; ++entry)
     443                 :             nsCategoryManager::GetSingleton()->
     444                 :                 AddCategoryEntry(entry->category,
     445                 :                                  entry->entry,
     446          368940 :                                  entry->value);
     447                 :     }
     448           83724 : }
     449                 : 
     450                 : void
     451          998983 : nsComponentManagerImpl::RegisterCIDEntry(const mozilla::Module::CIDEntry* aEntry,
     452                 :                                          KnownModule* aModule)
     453                 : {
     454          998983 :     mMon.AssertCurrentThreadIn();
     455                 : 
     456          998983 :     nsFactoryEntry* f = mFactories.Get(*aEntry->cid);
     457          998983 :     if (f) {
     458               0 :         NS_WARNING("Re-registering a CID?");
     459                 : 
     460                 :         char idstr[NSID_LENGTH];
     461               0 :         aEntry->cid->ToProvidedString(idstr);
     462                 : 
     463               0 :         nsCString existing;
     464               0 :         if (f->mModule)
     465               0 :             existing = f->mModule->Description();
     466                 :         else
     467               0 :             existing = "<unknown module>";
     468                 : 
     469                 :         LogMessage("While registering XPCOM module %s, trying to re-register CID '%s' already registered by %s.",
     470               0 :                    aModule->Description().get(),
     471                 :                    idstr,
     472               0 :                    existing.get());
     473                 :         return;
     474                 :     }
     475                 : 
     476          998983 :     f = new nsFactoryEntry(aEntry, aModule);
     477          998983 :     mFactories.Put(*aEntry->cid, f);
     478                 : }
     479                 : 
     480                 : void
     481         1058580 : nsComponentManagerImpl::RegisterContractID(const mozilla::Module::ContractIDEntry* aEntry)
     482                 : {
     483         1058580 :     mMon.AssertCurrentThreadIn();
     484                 : 
     485         1058580 :     nsFactoryEntry* f = mFactories.Get(*aEntry->cid);
     486         1058580 :     if (!f) {
     487               0 :         NS_ERROR("No CID found when attempting to map contract ID");
     488                 : 
     489                 :         char idstr[NSID_LENGTH];
     490               0 :         aEntry->cid->ToProvidedString(idstr);
     491                 : 
     492                 :         LogMessage("Could not map contract ID '%s' to CID %s because no implementation of the CID is registered.",
     493                 :                    aEntry->contractid,
     494               0 :                    idstr);
     495                 :                    
     496               0 :         return;
     497                 :     }
     498                 : 
     499         1058580 :     mContractIDs.Put(nsDependentCString(aEntry->contractid), f);
     500                 : }
     501                 : 
     502                 : static void
     503            2063 : CutExtension(nsCString& path)
     504                 : {
     505            2063 :     PRInt32 dotPos = path.RFindChar('.');
     506            2063 :     if (kNotFound == dotPos)
     507               0 :         path.Truncate();
     508                 :     else
     509            2063 :         path.Cut(0, dotPos + 1);
     510            2063 : }
     511                 : 
     512                 : void
     513           99294 : nsComponentManagerImpl::RegisterManifest(NSLocationType aType,
     514                 :                                          FileLocation &aFile,
     515                 :                                          bool aChromeOnly)
     516                 : {
     517                 :     PRUint32 len;
     518          198588 :     FileLocation::Data data;
     519          198588 :     nsAutoArrayPtr<char> buf;
     520           99294 :     nsresult rv = aFile.GetData(data);
     521           99294 :     if (NS_SUCCEEDED(rv)) {
     522           99082 :         rv = data.GetSize(&len);
     523                 :     }
     524           99294 :     if (NS_SUCCEEDED(rv)) {
     525          198164 :         buf = new char[len + 1];
     526           99082 :         rv = data.Copy(buf, len);
     527                 :     }
     528           99294 :     if (NS_SUCCEEDED(rv)) {
     529           99082 :         buf[len] = '\0';
     530           99082 :         ParseManifest(aType, aFile, buf, aChromeOnly);
     531             212 :     } else if (NS_BOOTSTRAPPED_LOCATION != aType) {
     532               0 :         nsCString uri;
     533               0 :         aFile.GetURIString(uri);
     534               0 :         LogMessage("Could not read chrome manifest '%s'.", uri.get());
     535                 :     }
     536           99294 : }
     537                 : 
     538                 : void
     539           95819 : nsComponentManagerImpl::ManifestManifest(ManifestProcessingContext& cx, int lineno, char *const * argv)
     540                 : {
     541           95819 :     char* file = argv[0];
     542          191638 :     FileLocation f(cx.mFile, file);
     543           95819 :     RegisterManifest(cx.mType, f, cx.mChromeOnly);
     544           95819 : }
     545                 : 
     546                 : void
     547            5682 : nsComponentManagerImpl::ManifestBinaryComponent(ManifestProcessingContext& cx, int lineno, char *const * argv)
     548                 : {
     549            5682 :     if (cx.mFile.IsZip()) {
     550               0 :         NS_WARNING("Cannot load binary components from a jar.");
     551                 :         LogMessageWithContext(cx.mFile, lineno,
     552               0 :                               "Cannot load binary components from a jar.");
     553               0 :         return;
     554                 :     }
     555                 : 
     556           11364 :     FileLocation f(cx.mFile, argv[0]);
     557           11364 :     nsCString uri;
     558            5682 :     f.GetURIString(uri);
     559                 : 
     560            5682 :     if (mKnownModules.Get(uri)) {
     561               2 :         NS_WARNING("Attempting to register a binary component twice.");
     562                 :         LogMessageWithContext(cx.mFile, lineno,
     563               2 :                               "Attempting to register a binary component twice.");
     564                 :         return;
     565                 :     }
     566                 : 
     567            5680 :     const mozilla::Module* m = mNativeModuleLoader.LoadModule(f);
     568                 :     // The native module loader should report an error here, we don't have to
     569            5680 :     if (!m)
     570                 :         return;
     571                 : 
     572           11361 :     RegisterModule(m, &f);
     573                 : }
     574                 : 
     575                 : void
     576          218497 : nsComponentManagerImpl::ManifestXPT(ManifestProcessingContext& cx, int lineno, char *const * argv)
     577                 : {
     578          436994 :     FileLocation f(cx.mFile, argv[0]);
     579                 :     PRUint32 len;
     580          436994 :     FileLocation::Data data;
     581          436994 :     nsAutoArrayPtr<char> buf;
     582          218497 :     nsresult rv = f.GetData(data);
     583          218497 :     if (NS_SUCCEEDED(rv)) {
     584          218497 :         rv = data.GetSize(&len);
     585                 :     }
     586          218497 :     if (NS_SUCCEEDED(rv)) {
     587          436994 :         buf = new char[len];
     588          218497 :         rv = data.Copy(buf, len);
     589                 :     }
     590          218497 :     if (NS_SUCCEEDED(rv)) {
     591                 :         xptiInterfaceInfoManager::GetSingleton()
     592          218497 :             ->RegisterBuffer(buf, len);
     593                 :     } else {
     594               0 :         nsCString uri;
     595               0 :         f.GetURIString(uri);
     596               0 :         LogMessage("Could not read '%s'.", uri.get());
     597                 :     }
     598          218497 : }
     599                 : 
     600                 : void
     601          136220 : nsComponentManagerImpl::ManifestComponent(ManifestProcessingContext& cx, int lineno, char *const * argv)
     602                 : {
     603          136220 :     char* id = argv[0];
     604          136220 :     char* file = argv[1];
     605                 : 
     606                 :     nsID cid;
     607          136220 :     if (!cid.Parse(id)) {
     608                 :         LogMessageWithContext(cx.mFile, lineno,
     609               1 :                               "Malformed CID: '%s'.", id);
     610               1 :         return;
     611                 :     }
     612                 : 
     613          272438 :     ReentrantMonitorAutoEnter mon(mMon);
     614          136219 :     nsFactoryEntry* f = mFactories.Get(cid);
     615          136219 :     if (f) {
     616                 :         char idstr[NSID_LENGTH];
     617            1387 :         cid.ToProvidedString(idstr);
     618                 : 
     619            2774 :         nsCString existing;
     620            1387 :         if (f->mModule)
     621            1387 :             existing = f->mModule->Description();
     622                 :         else
     623               0 :             existing = "<unknown module>";
     624                 : 
     625                 :         LogMessageWithContext(cx.mFile, lineno,
     626                 :                               "Trying to re-register CID '%s' already registered by %s.",
     627                 :                               idstr,
     628            1387 :                               existing.get());
     629                 :         return;
     630                 :     }
     631                 : 
     632                 :     KnownModule* km;
     633          269664 :     FileLocation fl(cx.mFile, file);
     634                 : 
     635          269664 :     nsCString hash;
     636          134832 :     fl.GetURIString(hash);
     637          134832 :     km = mKnownModules.Get(hash);
     638          134832 :     if (!km) {
     639          100771 :         km = new KnownModule(fl);
     640          100771 :         mKnownModules.Put(hash, km);
     641                 :     }
     642                 : 
     643                 :     void* place;
     644                 : 
     645          134832 :     PL_ARENA_ALLOCATE(place, &mArena, sizeof(nsCID));
     646          134832 :     nsID* permanentCID = static_cast<nsID*>(place);
     647          134832 :     *permanentCID = cid;
     648                 : 
     649          134832 :     PL_ARENA_ALLOCATE(place, &mArena, sizeof(mozilla::Module::CIDEntry));
     650          134832 :     mozilla::Module::CIDEntry* e = new (place) mozilla::Module::CIDEntry();
     651          134832 :     e->cid = permanentCID;
     652                 : 
     653          134832 :     f = new nsFactoryEntry(e, km);
     654          134832 :     mFactories.Put(cid, f);
     655                 : }
     656                 : 
     657                 : void
     658          137637 : nsComponentManagerImpl::ManifestContract(ManifestProcessingContext& cx, int lineno, char *const * argv)
     659                 : {
     660          137637 :     char* contract = argv[0];
     661          137637 :     char* id = argv[1];
     662                 : 
     663                 :     nsID cid;
     664          137637 :     if (!cid.Parse(id)) {
     665                 :         LogMessageWithContext(cx.mFile, lineno,
     666               0 :                               "Malformed CID: '%s'.", id);
     667               0 :         return;
     668                 :     }
     669                 : 
     670          275274 :     ReentrantMonitorAutoEnter mon(mMon);
     671          137637 :     nsFactoryEntry* f = mFactories.Get(cid);
     672          137637 :     if (!f) {
     673                 :         LogMessageWithContext(cx.mFile, lineno,
     674                 :                               "Could not map contract ID '%s' to CID %s because no implementation of the CID is registered.",
     675               1 :                               contract, id);
     676                 :         return;
     677                 :     }
     678                 : 
     679          137636 :     mContractIDs.Put(nsDependentCString(contract), f);
     680                 : }
     681                 : 
     682                 : void
     683           49675 : nsComponentManagerImpl::ManifestCategory(ManifestProcessingContext& cx, int lineno, char *const * argv)
     684                 : {
     685           49675 :     char* category = argv[0];
     686           49675 :     char* key = argv[1];
     687           49675 :     char* value = argv[2];
     688                 : 
     689                 :     nsCategoryManager::GetSingleton()->
     690           49675 :         AddCategoryEntry(category, key, value);
     691           49675 : }
     692                 : 
     693                 : void
     694            1624 : nsComponentManagerImpl::RereadChromeManifests(bool aChromeOnly)
     695                 : {
     696            4873 :     for (PRUint32 i = 0; i < sModuleLocations->Length(); ++i) {
     697            3249 :         ComponentLocation& l = sModuleLocations->ElementAt(i);
     698            3249 :         RegisterManifest(l.type, l.location, aChromeOnly);
     699                 :     }
     700            1624 : }
     701                 : 
     702                 : bool
     703            2063 : nsComponentManagerImpl::KnownModule::EnsureLoader()
     704                 : {
     705            2063 :     if (!mLoader) {
     706            4126 :         nsCString extension;
     707            2063 :         mFile.GetURIString(extension);
     708            2063 :         CutExtension(extension);
     709            2063 :         mLoader = nsComponentManagerImpl::gComponentManager->LoaderForExtension(extension);
     710                 :     }
     711            2063 :     return !!mLoader;
     712                 : }
     713                 : 
     714                 : bool
     715          101897 : nsComponentManagerImpl::KnownModule::Load()
     716                 : {
     717          101897 :     if (mFailed)
     718               0 :         return false;
     719          101897 :     if (!mModule) {
     720            2063 :         if (!EnsureLoader())
     721               0 :             return false;
     722                 : 
     723            2063 :         mModule = mLoader->LoadModule(mFile);
     724                 : 
     725            2063 :         if (!mModule) {
     726               0 :             mFailed = true;
     727               0 :             return false;
     728                 :         }
     729                 :     }
     730          101897 :     if (!mLoaded) {
     731           29864 :         if (mModule->loadProc) {
     732            7817 :             nsresult rv = mModule->loadProc();
     733            7817 :             if (NS_FAILED(rv)) {
     734               0 :                 mFailed = true;
     735               0 :                 return false;
     736                 :             }
     737                 :         }
     738           29864 :         mLoaded = true;
     739                 :     }
     740          101897 :     return true;
     741                 : }
     742                 : 
     743                 : nsCString
     744            1387 : nsComponentManagerImpl::KnownModule::Description() const
     745                 : {
     746            1387 :     nsCString s;
     747            1387 :     if (mFile)
     748            1387 :         mFile.GetURIString(s);
     749                 :     else
     750               0 :         s = "<static module>";
     751                 :     return s;
     752                 : }
     753                 : 
     754            1419 : nsresult nsComponentManagerImpl::Shutdown(void)
     755                 : {
     756                 :     NS_TIME_FUNCTION;
     757                 : 
     758            1419 :     PR_ASSERT(NORMAL == mStatus);
     759                 : 
     760            1419 :     mStatus = SHUTDOWN_IN_PROGRESS;
     761                 : 
     762                 :     // Shutdown the component manager
     763            1419 :     PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning Shutdown."));
     764                 : 
     765                 :     // Release all cached factories
     766            1419 :     mContractIDs.Clear();
     767            1419 :     mFactories.Clear(); // XXX release the objects, don't just clear
     768            1419 :     mLoaderMap.Clear();
     769            1419 :     mKnownModules.Clear();
     770            1419 :     mKnownStaticModules.Clear();
     771                 : 
     772            1419 :     mLoaderData.Clear();
     773                 : 
     774            1419 :     delete sStaticModules;
     775            1419 :     delete sModuleLocations;
     776                 : 
     777                 :     // Unload libraries
     778            1419 :     mNativeModuleLoader.UnloadLibraries();
     779                 : 
     780                 :     // delete arena for strings and small objects
     781            1419 :     PL_FinishArenaPool(&mArena);
     782                 : 
     783            1419 :     mStatus = SHUTDOWN_COMPLETE;
     784                 : 
     785            1419 :     PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Shutdown complete."));
     786                 : 
     787            1419 :     return NS_OK;
     788                 : }
     789                 : 
     790            2838 : nsComponentManagerImpl::~nsComponentManagerImpl()
     791                 : {
     792            1419 :     PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning destruction."));
     793                 : 
     794            1419 :     if (SHUTDOWN_COMPLETE != mStatus)
     795               0 :         Shutdown();
     796                 : 
     797            1419 :     PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Destroyed."));
     798            1419 : }
     799                 : 
     800         2112238 : NS_IMPL_THREADSAFE_ISUPPORTS5(nsComponentManagerImpl,
     801                 :                               nsIComponentManager,
     802                 :                               nsIServiceManager,
     803                 :                               nsIComponentRegistrar,
     804                 :                               nsISupportsWeakReference,
     805                 :                               nsIInterfaceRequestor)
     806                 : 
     807                 : 
     808                 : nsresult
     809               0 : nsComponentManagerImpl::GetInterface(const nsIID & uuid, void **result)
     810                 : {
     811               0 :     NS_WARNING("This isn't supported");
     812                 :     // fall through to QI as anything QIable is a superset of what can be
     813                 :     // got via the GetInterface()
     814               0 :     return  QueryInterface(uuid, result);
     815                 : }
     816                 : 
     817                 : nsFactoryEntry *
     818          479864 : nsComponentManagerImpl::GetFactoryEntry(const char *aContractID,
     819                 :                                         PRUint32 aContractIDLen)
     820                 : {
     821          959728 :     ReentrantMonitorAutoEnter mon(mMon);
     822          479864 :     return mContractIDs.Get(nsDependentCString(aContractID, aContractIDLen));
     823                 : }
     824                 : 
     825                 : 
     826                 : nsFactoryEntry *
     827          121680 : nsComponentManagerImpl::GetFactoryEntry(const nsCID &aClass)
     828                 : {
     829          243360 :     ReentrantMonitorAutoEnter mon(mMon);
     830          121680 :     return mFactories.Get(aClass);
     831                 : }
     832                 : 
     833                 : already_AddRefed<nsIFactory>
     834            2795 : nsComponentManagerImpl::FindFactory(const nsCID& aClass)
     835                 : {
     836            2795 :     nsFactoryEntry* e = GetFactoryEntry(aClass);
     837            2795 :     if (!e)
     838               0 :         return NULL;
     839                 : 
     840            2795 :     return e->GetFactory();
     841                 : }
     842                 : 
     843                 : already_AddRefed<nsIFactory>
     844           14623 : nsComponentManagerImpl::FindFactory(const char *contractID,
     845                 :                                     PRUint32 aContractIDLen)
     846                 : {
     847           14623 :     nsFactoryEntry *entry = GetFactoryEntry(contractID, aContractIDLen);
     848           14623 :     if (!entry)
     849           14623 :         return NULL;
     850                 : 
     851               0 :     return entry->GetFactory();
     852                 : }
     853                 : 
     854                 : /**
     855                 :  * GetClassObject()
     856                 :  *
     857                 :  * Given a classID, this finds the singleton ClassObject that implements the CID.
     858                 :  * Returns an interface of type aIID off the singleton classobject.
     859                 :  */
     860                 : NS_IMETHODIMP
     861            2795 : nsComponentManagerImpl::GetClassObject(const nsCID &aClass, const nsIID &aIID,
     862                 :                                        void **aResult)
     863                 : {
     864                 :     nsresult rv;
     865                 : 
     866                 : #ifdef PR_LOGGING
     867            2795 :     if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_DEBUG))
     868                 :     {
     869               0 :         char *buf = aClass.ToString();
     870               0 :         PR_LogPrint("nsComponentManager: GetClassObject(%s)", buf);
     871               0 :         if (buf)
     872               0 :             NS_Free(buf);
     873                 :     }
     874                 : #endif
     875                 : 
     876            2795 :     PR_ASSERT(aResult != nsnull);
     877                 : 
     878            5590 :     nsCOMPtr<nsIFactory> factory = FindFactory(aClass);
     879            2795 :     if (!factory)
     880               0 :         return NS_ERROR_FACTORY_NOT_REGISTERED;
     881                 : 
     882            2795 :     rv = factory->QueryInterface(aIID, aResult);
     883                 : 
     884            2795 :     PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
     885                 :            ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
     886                 : 
     887            2795 :     return rv;
     888                 : }
     889                 : 
     890                 : 
     891                 : NS_IMETHODIMP
     892           14623 : nsComponentManagerImpl::GetClassObjectByContractID(const char *contractID,
     893                 :                                                    const nsIID &aIID,
     894                 :                                                    void **aResult)
     895                 : {
     896           14623 :     NS_ENSURE_ARG_POINTER(aResult);
     897           14623 :     NS_ENSURE_ARG_POINTER(contractID);
     898                 : 
     899                 :     nsresult rv;
     900                 : 
     901                 : 
     902                 : #ifdef PR_LOGGING
     903           14623 :     if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_DEBUG))
     904                 :     {
     905               0 :         PR_LogPrint("nsComponentManager: GetClassObject(%s)", contractID);
     906                 :     }
     907                 : #endif
     908                 : 
     909           29246 :     nsCOMPtr<nsIFactory> factory = FindFactory(contractID, strlen(contractID));
     910           14623 :     if (!factory)
     911           14623 :         return NS_ERROR_FACTORY_NOT_REGISTERED;
     912                 : 
     913               0 :     rv = factory->QueryInterface(aIID, aResult);
     914                 : 
     915               0 :     PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
     916                 :            ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
     917                 : 
     918               0 :     return rv;
     919                 : }
     920                 : 
     921                 : /**
     922                 :  * CreateInstance()
     923                 :  *
     924                 :  * Create an instance of an object that implements an interface and belongs
     925                 :  * to the implementation aClass using the factory. The factory is immediately
     926                 :  * released and not held onto for any longer.
     927                 :  */
     928                 : NS_IMETHODIMP
     929          118881 : nsComponentManagerImpl::CreateInstance(const nsCID &aClass,
     930                 :                                        nsISupports *aDelegate,
     931                 :                                        const nsIID &aIID,
     932                 :                                        void **aResult)
     933                 : {
     934                 :     COMPMGR_TIME_FUNCTION_CID(aClass);
     935                 : 
     936                 :     // test this first, since there's no point in creating a component during
     937                 :     // shutdown -- whether it's available or not would depend on the order it
     938                 :     // occurs in the list
     939          118881 :     if (gXPCOMShuttingDown) {
     940                 :         // When processing shutdown, don't process new GetService() requests
     941                 : #ifdef SHOW_DENIED_ON_SHUTDOWN
     942                 :         nsXPIDLCString cid, iid;
     943                 :         cid.Adopt(aClass.ToString());
     944                 :         iid.Adopt(aIID.ToString());
     945                 :         fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
     946                 :                "         CID: %s\n         IID: %s\n", cid.get(), iid.get());
     947                 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
     948               0 :         return NS_ERROR_UNEXPECTED;
     949                 :     }
     950                 : 
     951          118881 :     if (aResult == nsnull)
     952                 :     {
     953               0 :         return NS_ERROR_NULL_POINTER;
     954                 :     }
     955          118881 :     *aResult = nsnull;
     956                 : 
     957          118881 :     nsFactoryEntry *entry = GetFactoryEntry(aClass);
     958                 : 
     959          118881 :     if (!entry)
     960               0 :         return NS_ERROR_FACTORY_NOT_REGISTERED;
     961                 : 
     962                 : #ifdef SHOW_CI_ON_EXISTING_SERVICE
     963                 :     if (entry->mServiceObject) {
     964                 :         nsXPIDLCString cid;
     965                 :         cid.Adopt(aClass.ToString());
     966                 :         nsCAutoString message;
     967                 :         message = NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
     968                 :                   cid + NS_LITERAL_CSTRING("\" when a service for this CID already exists!");
     969                 :         NS_ERROR(message.get());
     970                 :     }
     971                 : #endif
     972                 : 
     973                 :     nsresult rv;
     974          237762 :     nsCOMPtr<nsIFactory> factory = entry->GetFactory();
     975          118881 :     if (factory)
     976                 :     {
     977          118881 :         rv = factory->CreateInstance(aDelegate, aIID, aResult);
     978          118881 :         if (NS_SUCCEEDED(rv) && !*aResult) {
     979               0 :             NS_ERROR("Factory did not return an object but returned success!");
     980               0 :             rv = NS_ERROR_SERVICE_NOT_FOUND;
     981                 :         }
     982                 :     }
     983                 :     else {
     984                 :         // Translate error values
     985               0 :         rv = NS_ERROR_FACTORY_NOT_REGISTERED;
     986                 :     }
     987                 : 
     988                 : #ifdef PR_LOGGING
     989          118881 :     if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
     990                 :     {
     991               0 :         char *buf = aClass.ToString();
     992               0 :         PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
     993                 :                ("nsComponentManager: CreateInstance(%s) %s", buf,
     994                 :                 NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
     995               0 :         if (buf)
     996               0 :             NS_Free(buf);
     997                 :     }
     998                 : #endif
     999                 : 
    1000          118881 :     return rv;
    1001                 : }
    1002                 : 
    1003                 : /**
    1004                 :  * CreateInstanceByContractID()
    1005                 :  *
    1006                 :  * A variant of CreateInstance() that creates an instance of the object that
    1007                 :  * implements the interface aIID and whose implementation has a contractID aContractID.
    1008                 :  *
    1009                 :  * This is only a convenience routine that turns around can calls the
    1010                 :  * CreateInstance() with classid and iid.
    1011                 :  */
    1012                 : NS_IMETHODIMP
    1013          465489 : nsComponentManagerImpl::CreateInstanceByContractID(const char *aContractID,
    1014                 :                                                    nsISupports *aDelegate,
    1015                 :                                                    const nsIID &aIID,
    1016                 :                                                    void **aResult)
    1017                 : {
    1018                 :     COMPMGR_TIME_FUNCTION_CONTRACTID(aContractID);
    1019                 : 
    1020          465489 :     NS_ENSURE_ARG_POINTER(aContractID);
    1021                 : 
    1022                 :     // test this first, since there's no point in creating a component during
    1023                 :     // shutdown -- whether it's available or not would depend on the order it
    1024                 :     // occurs in the list
    1025          465489 :     if (gXPCOMShuttingDown) {
    1026                 :         // When processing shutdown, don't process new GetService() requests
    1027                 : #ifdef SHOW_DENIED_ON_SHUTDOWN
    1028                 :         nsXPIDLCString iid;
    1029                 :         iid.Adopt(aIID.ToString());
    1030                 :         fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
    1031                 :                "  ContractID: %s\n         IID: %s\n", aContractID, iid.get());
    1032                 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
    1033             248 :         return NS_ERROR_UNEXPECTED;
    1034                 :     }
    1035                 : 
    1036          465241 :     if (aResult == nsnull)
    1037                 :     {
    1038               0 :         return NS_ERROR_NULL_POINTER;
    1039                 :     }
    1040          465241 :     *aResult = nsnull;
    1041                 : 
    1042          465241 :     nsFactoryEntry *entry = GetFactoryEntry(aContractID, strlen(aContractID));
    1043                 : 
    1044          465241 :     if (!entry)
    1045              24 :         return NS_ERROR_FACTORY_NOT_REGISTERED;
    1046                 : 
    1047                 : #ifdef SHOW_CI_ON_EXISTING_SERVICE
    1048                 :     if (entry->mServiceObject) {
    1049                 :         nsCAutoString message;
    1050                 :         message =
    1051                 :           NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
    1052                 :           nsDependentCString(aContractID) +
    1053                 :           NS_LITERAL_CSTRING("\" when a service for this CID already exists! "
    1054                 :             "Add it to abusedContracts to track down the service consumer.");
    1055                 :         NS_ERROR(message.get());
    1056                 :     }
    1057                 : #endif
    1058                 : 
    1059                 :     nsresult rv;
    1060          930434 :     nsCOMPtr<nsIFactory> factory = entry->GetFactory();
    1061          465217 :     if (factory)
    1062                 :     {
    1063                 : 
    1064          465217 :         rv = factory->CreateInstance(aDelegate, aIID, aResult);
    1065          465217 :         if (NS_SUCCEEDED(rv) && !*aResult) {
    1066               0 :             NS_ERROR("Factory did not return an object but returned success!");
    1067               0 :             rv = NS_ERROR_SERVICE_NOT_FOUND;
    1068                 :         }
    1069                 :     }
    1070                 :     else {
    1071                 :         // Translate error values
    1072               0 :         rv = NS_ERROR_FACTORY_NOT_REGISTERED;
    1073                 :     }
    1074                 : 
    1075          465217 :     PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
    1076                 :            ("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID,
    1077                 :             NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
    1078                 : 
    1079          465217 :     return rv;
    1080                 : }
    1081                 : 
    1082                 : static PLDHashOperator
    1083         1134257 : FreeFactoryEntries(const nsID& aCID,
    1084                 :                    nsFactoryEntry* aEntry,
    1085                 :                    void* arg)
    1086                 : {
    1087         1134257 :     aEntry->mFactory = NULL;
    1088         1134257 :     aEntry->mServiceObject = NULL;
    1089         1134257 :     return PL_DHASH_NEXT;
    1090                 : }
    1091                 : 
    1092                 : nsresult
    1093            1419 : nsComponentManagerImpl::FreeServices()
    1094                 : {
    1095            1419 :     NS_ASSERTION(gXPCOMShuttingDown, "Must be shutting down in order to free all services");
    1096                 : 
    1097            1419 :     if (!gXPCOMShuttingDown)
    1098               0 :         return NS_ERROR_FAILURE;
    1099                 : 
    1100            1419 :     mFactories.EnumerateRead(FreeFactoryEntries, NULL);
    1101            1419 :     return NS_OK;
    1102                 : }
    1103                 : 
    1104                 : // This should only ever be called within the monitor!
    1105                 : nsComponentManagerImpl::PendingServiceInfo*
    1106           77872 : nsComponentManagerImpl::AddPendingService(const nsCID& aServiceCID,
    1107                 :                                           PRThread* aThread)
    1108                 : {
    1109           77872 :   PendingServiceInfo* newInfo = mPendingServices.AppendElement();
    1110           77872 :   if (newInfo) {
    1111           77872 :     newInfo->cid = &aServiceCID;
    1112           77872 :     newInfo->thread = aThread;
    1113                 :   }
    1114           77872 :   return newInfo;
    1115                 : }
    1116                 : 
    1117                 : // This should only ever be called within the monitor!
    1118                 : void
    1119           77872 : nsComponentManagerImpl::RemovePendingService(const nsCID& aServiceCID)
    1120                 : {
    1121           77872 :   PRUint32 pendingCount = mPendingServices.Length();
    1122          109863 :   for (PRUint32 index = 0; index < pendingCount; ++index) {
    1123          109863 :     const PendingServiceInfo& info = mPendingServices.ElementAt(index);
    1124          109863 :     if (info.cid->Equals(aServiceCID)) {
    1125           77872 :       mPendingServices.RemoveElementAt(index);
    1126           77872 :       return;
    1127                 :     }
    1128                 :   }
    1129                 : }
    1130                 : 
    1131                 : // This should only ever be called within the monitor!
    1132                 : PRThread*
    1133          155744 : nsComponentManagerImpl::GetPendingServiceThread(const nsCID& aServiceCID) const
    1134                 : {
    1135          155744 :   PRUint32 pendingCount = mPendingServices.Length();
    1136          219726 :   for (PRUint32 index = 0; index < pendingCount; ++index) {
    1137          141854 :     const PendingServiceInfo& info = mPendingServices.ElementAt(index);
    1138          141854 :     if (info.cid->Equals(aServiceCID)) {
    1139           77872 :       return info.thread;
    1140                 :     }
    1141                 :   }
    1142           77872 :   return nsnull;
    1143                 : }
    1144                 : 
    1145                 : // GetService() wants to manually Exit()/Enter() a monitor which is
    1146                 : // wrapped in ReentrantMonitorAutoEnter, which nsAutoReentrantMonitor used to allow.
    1147                 : // One use is block-scoped Exit()/Enter(), which could be supported
    1148                 : // with something like a MonitoAutoExit, but that's not a well-defined
    1149                 : // operation in general so that helper doesn't exist.  The other use
    1150                 : // is early-Exit() for perf reasons.  This code is probably hot enough
    1151                 : // to warrant special considerations.
    1152                 : //
    1153                 : // We could use bare mozilla::ReentrantMonitor, but that's error prone.
    1154                 : // Instead, we just add a hacky wrapper here that acts like the old
    1155                 : // nsAutoReentrantMonitor.
    1156                 : struct NS_STACK_CLASS AutoReentrantMonitor
    1157                 : {
    1158          834867 :     AutoReentrantMonitor(ReentrantMonitor& aReentrantMonitor) : mReentrantMonitor(&aReentrantMonitor), mEnterCount(0)
    1159                 :     {
    1160          834867 :         Enter();
    1161          834867 :     }
    1162                 : 
    1163          834867 :     ~AutoReentrantMonitor()
    1164                 :     {
    1165          834867 :         if (mEnterCount) {
    1166          101175 :             Exit();
    1167                 :         }
    1168          834867 :     }
    1169                 : 
    1170          912739 :     void Enter()
    1171                 :     {
    1172          912739 :         mReentrantMonitor->Enter();
    1173          912739 :         ++mEnterCount;
    1174          912739 :     }
    1175                 : 
    1176          912739 :     void Exit()
    1177                 :     {
    1178          912739 :         --mEnterCount;
    1179          912739 :         mReentrantMonitor->Exit();
    1180          912739 :     }
    1181                 : 
    1182                 :     ReentrantMonitor* mReentrantMonitor;
    1183                 :     PRInt32 mEnterCount;
    1184                 : };
    1185                 : 
    1186                 : NS_IMETHODIMP
    1187           91250 : nsComponentManagerImpl::GetService(const nsCID& aClass,
    1188                 :                                    const nsIID& aIID,
    1189                 :                                    void* *result)
    1190                 : {
    1191                 :     // test this first, since there's no point in returning a service during
    1192                 :     // shutdown -- whether it's available or not would depend on the order it
    1193                 :     // occurs in the list
    1194           91250 :     if (gXPCOMShuttingDown) {
    1195                 :         // When processing shutdown, don't process new GetService() requests
    1196                 : #ifdef SHOW_DENIED_ON_SHUTDOWN
    1197                 :         nsXPIDLCString cid, iid;
    1198                 :         cid.Adopt(aClass.ToString());
    1199                 :         iid.Adopt(aIID.ToString());
    1200                 :         fprintf(stderr, "Getting service on shutdown. Denied.\n"
    1201                 :                "         CID: %s\n         IID: %s\n", cid.get(), iid.get());
    1202                 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
    1203             281 :         return NS_ERROR_UNEXPECTED;
    1204                 :     }
    1205                 : 
    1206          181938 :     AutoReentrantMonitor mon(mMon);
    1207                 : 
    1208           90969 :     nsFactoryEntry* entry = mFactories.Get(aClass);
    1209           90969 :     if (!entry)
    1210               0 :         return NS_ERROR_FACTORY_NOT_REGISTERED;
    1211                 : 
    1212           90969 :     if (entry->mServiceObject) {
    1213          167870 :         nsCOMPtr<nsISupports> supports = entry->mServiceObject;
    1214           83935 :         mon.Exit();
    1215           83935 :         return supports->QueryInterface(aIID, result);
    1216                 :     }
    1217                 : 
    1218                 :     // We only care about time when we create the service.
    1219                 :     COMPMGR_TIME_FUNCTION_CID(aClass);
    1220                 : 
    1221            7034 :     PRThread* currentPRThread = PR_GetCurrentThread();
    1222            7034 :     NS_ASSERTION(currentPRThread, "This should never be null!");
    1223                 : 
    1224                 :     // Needed to optimize the event loop below.
    1225            7034 :     nsIThread* currentThread = nsnull;
    1226                 : 
    1227                 :     PRThread* pendingPRThread;
    1228           14068 :     while ((pendingPRThread = GetPendingServiceThread(aClass))) {
    1229               0 :         if (pendingPRThread == currentPRThread) {
    1230               0 :             NS_ERROR("Recursive GetService!");
    1231               0 :             return NS_ERROR_NOT_AVAILABLE;
    1232                 :         }
    1233                 : 
    1234               0 :         mon.Exit();
    1235                 : 
    1236               0 :         if (!currentThread) {
    1237               0 :             currentThread = NS_GetCurrentThread();
    1238               0 :             NS_ASSERTION(currentThread, "This should never be null!");
    1239                 :         }
    1240                 : 
    1241                 :         // This will process a single event or yield the thread if no event is
    1242                 :         // pending.
    1243               0 :         if (!NS_ProcessNextEvent(currentThread, false)) {
    1244               0 :             PR_Sleep(PR_INTERVAL_NO_WAIT);
    1245                 :         }
    1246                 : 
    1247               0 :         mon.Enter();
    1248                 :     }
    1249                 : 
    1250                 :     // It's still possible that the other thread failed to create the
    1251                 :     // service so we're not guaranteed to have an entry or service yet.
    1252            7034 :     if (entry->mServiceObject) {
    1253               0 :         nsCOMPtr<nsISupports> supports = entry->mServiceObject;
    1254               0 :         mon.Exit();
    1255               0 :         return supports->QueryInterface(aIID, result);
    1256                 :     }
    1257                 : 
    1258                 : #ifdef DEBUG
    1259                 :     PendingServiceInfo* newInfo =
    1260                 : #endif
    1261            7034 :     AddPendingService(aClass, currentPRThread);
    1262            7034 :     NS_ASSERTION(newInfo, "Failed to add info to the array!");
    1263                 : 
    1264           14068 :     nsCOMPtr<nsISupports> service;
    1265                 :     // We need to not be holding the service manager's monitor while calling
    1266                 :     // CreateInstance, because it invokes user code which could try to re-enter
    1267                 :     // the service manager:
    1268            7034 :     mon.Exit();
    1269                 : 
    1270            7034 :     nsresult rv = CreateInstance(aClass, nsnull, aIID, getter_AddRefs(service));
    1271                 : 
    1272            7034 :     mon.Enter();
    1273                 : 
    1274                 : #ifdef DEBUG
    1275            7034 :     pendingPRThread = GetPendingServiceThread(aClass);
    1276            7034 :     NS_ASSERTION(pendingPRThread == currentPRThread,
    1277                 :                  "Pending service array has been changed!");
    1278                 : #endif
    1279            7034 :     RemovePendingService(aClass);
    1280                 : 
    1281            7034 :     if (NS_FAILED(rv))
    1282               1 :         return rv;
    1283                 : 
    1284            7033 :     NS_ASSERTION(!entry->mServiceObject, "Created two instances of a service!");
    1285                 : 
    1286            7033 :     entry->mServiceObject = service;
    1287            7033 :     *result = service.get();
    1288            7033 :     if (!*result) {
    1289               0 :         NS_ERROR("Factory did not return an object but returned success!");
    1290               0 :         return NS_ERROR_SERVICE_NOT_FOUND;
    1291                 :     }
    1292            7033 :     NS_ADDREF(static_cast<nsISupports*>((*result)));
    1293            7033 :     return rv;
    1294                 : }
    1295                 : 
    1296                 : NS_IMETHODIMP
    1297               0 : nsComponentManagerImpl::IsServiceInstantiated(const nsCID & aClass,
    1298                 :                                               const nsIID& aIID,
    1299                 :                                               bool *result)
    1300                 : {
    1301                 :     COMPMGR_TIME_FUNCTION_CID(aClass);
    1302                 : 
    1303                 :     // Now we want to get the service if we already got it. If not, we don't want
    1304                 :     // to create an instance of it. mmh!
    1305                 : 
    1306                 :     // test this first, since there's no point in returning a service during
    1307                 :     // shutdown -- whether it's available or not would depend on the order it
    1308                 :     // occurs in the list
    1309               0 :     if (gXPCOMShuttingDown) {
    1310                 :         // When processing shutdown, don't process new GetService() requests
    1311                 : #ifdef SHOW_DENIED_ON_SHUTDOWN
    1312                 :         nsXPIDLCString cid, iid;
    1313                 :         cid.Adopt(aClass.ToString());
    1314                 :         iid.Adopt(aIID.ToString());
    1315                 :         fprintf(stderr, "Checking for service on shutdown. Denied.\n"
    1316                 :                "         CID: %s\n         IID: %s\n", cid.get(), iid.get());
    1317                 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
    1318               0 :         return NS_ERROR_UNEXPECTED;
    1319                 :     }
    1320                 : 
    1321               0 :     nsresult rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
    1322                 :     nsFactoryEntry* entry;
    1323                 : 
    1324                 :     {
    1325               0 :         ReentrantMonitorAutoEnter mon(mMon);
    1326               0 :         entry = mFactories.Get(aClass);
    1327                 :     }
    1328                 : 
    1329               0 :     if (entry && entry->mServiceObject) {
    1330               0 :         nsCOMPtr<nsISupports> service;
    1331               0 :         rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service));
    1332               0 :         *result = (service!=nsnull);
    1333                 :     }
    1334                 : 
    1335               0 :     return rv;
    1336                 : }
    1337                 : 
    1338               0 : NS_IMETHODIMP nsComponentManagerImpl::IsServiceInstantiatedByContractID(const char *aContractID,
    1339                 :                                                                         const nsIID& aIID,
    1340                 :                                                                         bool *result)
    1341                 : {
    1342                 :     COMPMGR_TIME_FUNCTION_CONTRACTID(aContractID);
    1343                 : 
    1344                 :     // Now we want to get the service if we already got it. If not, we don't want
    1345                 :     // to create an instance of it. mmh!
    1346                 : 
    1347                 :     // test this first, since there's no point in returning a service during
    1348                 :     // shutdown -- whether it's available or not would depend on the order it
    1349                 :     // occurs in the list
    1350               0 :     if (gXPCOMShuttingDown) {
    1351                 :         // When processing shutdown, don't process new GetService() requests
    1352                 : #ifdef SHOW_DENIED_ON_SHUTDOWN
    1353                 :         nsXPIDLCString iid;
    1354                 :         iid.Adopt(aIID.ToString());
    1355                 :         fprintf(stderr, "Checking for service on shutdown. Denied.\n"
    1356                 :                "  ContractID: %s\n         IID: %s\n", aContractID, iid.get());
    1357                 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
    1358               0 :         return NS_ERROR_UNEXPECTED;
    1359                 :     }
    1360                 : 
    1361               0 :     nsresult rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
    1362                 :     nsFactoryEntry *entry;
    1363                 :     {
    1364               0 :         ReentrantMonitorAutoEnter mon(mMon);
    1365               0 :         entry = mContractIDs.Get(nsDependentCString(aContractID));
    1366                 :     }
    1367                 : 
    1368               0 :     if (entry && entry->mServiceObject) {
    1369               0 :         nsCOMPtr<nsISupports> service;
    1370               0 :         rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service));
    1371               0 :         *result = (service!=nsnull);
    1372                 :     }
    1373               0 :     return rv;
    1374                 : }
    1375                 : 
    1376                 : 
    1377                 : NS_IMETHODIMP
    1378          763695 : nsComponentManagerImpl::GetServiceByContractID(const char* aContractID,
    1379                 :                                                const nsIID& aIID,
    1380                 :                                                void* *result)
    1381                 : {
    1382                 :     // test this first, since there's no point in returning a service during
    1383                 :     // shutdown -- whether it's available or not would depend on the order it
    1384                 :     // occurs in the list
    1385          763695 :     if (gXPCOMShuttingDown) {
    1386                 :         // When processing shutdown, don't process new GetService() requests
    1387                 : #ifdef SHOW_DENIED_ON_SHUTDOWN
    1388                 :         nsXPIDLCString iid;
    1389                 :         iid.Adopt(aIID.ToString());
    1390                 :         fprintf(stderr, "Getting service on shutdown. Denied.\n"
    1391                 :                "  ContractID: %s\n         IID: %s\n", aContractID, iid.get());
    1392                 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
    1393           19797 :         return NS_ERROR_UNEXPECTED;
    1394                 :     }
    1395                 : 
    1396         1487796 :     AutoReentrantMonitor mon(mMon);
    1397                 : 
    1398          743898 :     nsFactoryEntry *entry = mContractIDs.Get(nsDependentCString(aContractID));
    1399          743898 :     if (!entry)
    1400           23303 :         return NS_ERROR_FACTORY_NOT_REGISTERED;
    1401                 : 
    1402          720595 :     if (entry->mServiceObject) {
    1403         1299514 :         nsCOMPtr<nsISupports> serviceObject = entry->mServiceObject;
    1404                 : 
    1405                 :         // We need to not be holding the service manager's monitor while calling
    1406                 :         // QueryInterface, because it invokes user code which could try to re-enter
    1407                 :         // the service manager, or try to grab some other lock/monitor/condvar
    1408                 :         // and deadlock, e.g. bug 282743.
    1409          649757 :         mon.Exit();
    1410          649757 :         return serviceObject->QueryInterface(aIID, result);
    1411                 :     }
    1412                 : 
    1413                 :     // We only care about time when we create the service.
    1414                 :     COMPMGR_TIME_FUNCTION_CONTRACTID(aContractID);
    1415                 : 
    1416           70838 :     PRThread* currentPRThread = PR_GetCurrentThread();
    1417           70838 :     NS_ASSERTION(currentPRThread, "This should never be null!");
    1418                 : 
    1419                 :     // Needed to optimize the event loop below.
    1420           70838 :     nsIThread* currentThread = nsnull;
    1421                 : 
    1422                 :     PRThread* pendingPRThread;
    1423          141676 :     while ((pendingPRThread = GetPendingServiceThread(*entry->mCIDEntry->cid))) {
    1424               0 :         if (pendingPRThread == currentPRThread) {
    1425               0 :             NS_ERROR("Recursive GetService!");
    1426               0 :             return NS_ERROR_NOT_AVAILABLE;
    1427                 :         }
    1428                 : 
    1429               0 :         mon.Exit();
    1430                 : 
    1431               0 :         if (!currentThread) {
    1432               0 :             currentThread = NS_GetCurrentThread();
    1433               0 :             NS_ASSERTION(currentThread, "This should never be null!");
    1434                 :         }
    1435                 : 
    1436                 :         // This will process a single event or yield the thread if no event is
    1437                 :         // pending.
    1438               0 :         if (!NS_ProcessNextEvent(currentThread, false)) {
    1439               0 :             PR_Sleep(PR_INTERVAL_NO_WAIT);
    1440                 :         }
    1441                 : 
    1442               0 :         mon.Enter();
    1443                 :     }
    1444                 : 
    1445           70838 :     if (currentThread && entry->mServiceObject) {
    1446                 :         // If we have a currentThread then we must have waited on another thread
    1447                 :         // to create the service. Grab it now if that succeeded.
    1448               0 :         nsCOMPtr<nsISupports> serviceObject = entry->mServiceObject;
    1449               0 :         mon.Exit();
    1450               0 :         return serviceObject->QueryInterface(aIID, result);
    1451                 :     }
    1452                 : 
    1453                 : #ifdef DEBUG
    1454                 :     PendingServiceInfo* newInfo =
    1455                 : #endif
    1456           70838 :     AddPendingService(*entry->mCIDEntry->cid, currentPRThread);
    1457           70838 :     NS_ASSERTION(newInfo, "Failed to add info to the array!");
    1458                 : 
    1459          141676 :     nsCOMPtr<nsISupports> service;
    1460                 :     // We need to not be holding the service manager's monitor while calling
    1461                 :     // CreateInstance, because it invokes user code which could try to re-enter
    1462                 :     // the service manager:
    1463           70838 :     mon.Exit();
    1464                 : 
    1465                 :     nsresult rv = CreateInstanceByContractID(aContractID, nsnull, aIID,
    1466           70838 :                                              getter_AddRefs(service));
    1467                 : 
    1468           70838 :     mon.Enter();
    1469                 : 
    1470                 : #ifdef DEBUG
    1471           70838 :     pendingPRThread = GetPendingServiceThread(*entry->mCIDEntry->cid);
    1472           70838 :     NS_ASSERTION(pendingPRThread == currentPRThread,
    1473                 :                  "Pending service array has been changed!");
    1474                 : #endif
    1475           70838 :     RemovePendingService(*entry->mCIDEntry->cid);
    1476                 : 
    1477           70838 :     if (NS_FAILED(rv))
    1478            8561 :         return rv;
    1479                 : 
    1480           62277 :     NS_ASSERTION(!entry->mServiceObject, "Created two instances of a service!");
    1481                 : 
    1482           62277 :     entry->mServiceObject = service;
    1483           62277 :     *result = service.get();
    1484           62277 :     NS_ADDREF(static_cast<nsISupports*>(*result));
    1485           62277 :     return rv;
    1486                 : }
    1487                 : 
    1488                 : already_AddRefed<mozilla::ModuleLoader>
    1489            2063 : nsComponentManagerImpl::LoaderForExtension(const nsACString& aExt)
    1490                 : {
    1491            4126 :     nsCOMPtr<mozilla::ModuleLoader> loader = mLoaderMap.Get(aExt);
    1492            2063 :     if (!loader) {
    1493                 :         loader = do_GetServiceFromCategory("module-loader",
    1494             759 :                                            PromiseFlatCString(aExt).get());
    1495             759 :         if (!loader)
    1496               0 :             return NULL;
    1497                 : 
    1498             759 :         mLoaderMap.Put(aExt, loader);
    1499                 :     }
    1500                 : 
    1501            2063 :     return loader.forget();
    1502                 : }
    1503                 : 
    1504                 : NS_IMETHODIMP
    1505            3261 : nsComponentManagerImpl::RegisterFactory(const nsCID& aClass,
    1506                 :                                         const char* aName,
    1507                 :                                         const char* aContractID,
    1508                 :                                         nsIFactory* aFactory)
    1509                 : {
    1510            3261 :     if (!aFactory) {
    1511                 :         // If a null factory is passed in, this call just wants to reset
    1512                 :         // the contract ID to point to an existing CID entry.
    1513               1 :         if (!aContractID)
    1514               0 :             return NS_ERROR_INVALID_ARG;
    1515                 : 
    1516               2 :         ReentrantMonitorAutoEnter mon(mMon);
    1517               1 :         nsFactoryEntry* oldf = mFactories.Get(aClass);
    1518               1 :         if (!oldf)
    1519               0 :             return NS_ERROR_FACTORY_NOT_REGISTERED;
    1520                 : 
    1521               1 :         mContractIDs.Put(nsDependentCString(aContractID), oldf);
    1522               1 :         return NS_OK;
    1523                 :     }
    1524                 : 
    1525            6520 :     nsAutoPtr<nsFactoryEntry> f(new nsFactoryEntry(aClass, aFactory));
    1526                 : 
    1527            6520 :     ReentrantMonitorAutoEnter mon(mMon);
    1528            3260 :     nsFactoryEntry* oldf = mFactories.Get(aClass);
    1529            3260 :     if (oldf)
    1530               0 :         return NS_ERROR_FACTORY_EXISTS;
    1531                 : 
    1532            3260 :     if (aContractID)
    1533            3260 :         mContractIDs.Put(nsDependentCString(aContractID), f);
    1534                 : 
    1535            3260 :     mFactories.Put(aClass, f.forget());
    1536                 : 
    1537            3260 :     return NS_OK;
    1538                 : }
    1539                 : 
    1540                 : NS_IMETHODIMP
    1541            2818 : nsComponentManagerImpl::UnregisterFactory(const nsCID& aClass,
    1542                 :                                           nsIFactory* aFactory)
    1543                 : {
    1544                 :     // Don't release the dying factory or service object until releasing
    1545                 :     // the component manager monitor.
    1546            5636 :     nsCOMPtr<nsIFactory> dyingFactory;
    1547            5636 :     nsCOMPtr<nsISupports> dyingServiceObject;
    1548                 : 
    1549                 :     {
    1550            5636 :         ReentrantMonitorAutoEnter mon(mMon);
    1551            2818 :         nsFactoryEntry* f = mFactories.Get(aClass);
    1552            2818 :         if (!f || f->mFactory != aFactory)
    1553               0 :             return NS_ERROR_FACTORY_NOT_REGISTERED;
    1554                 : 
    1555            2818 :         mFactories.Remove(aClass);
    1556                 : 
    1557                 :         // This might leave a stale contractid -> factory mapping in
    1558                 :         // place, so null out the factory entry (see
    1559                 :         // nsFactoryEntry::GetFactory)
    1560            2818 :         f->mFactory.swap(dyingFactory);
    1561            5636 :         f->mServiceObject.swap(dyingServiceObject);
    1562                 :     }
    1563                 : 
    1564            2818 :     return NS_OK;
    1565                 : }
    1566                 : 
    1567                 : NS_IMETHODIMP
    1568              30 : nsComponentManagerImpl::AutoRegister(nsIFile* aLocation)
    1569                 : {
    1570              60 :     nsCOMPtr<nsILocalFile> lf = do_QueryInterface(aLocation);
    1571              30 :     if (!lf)
    1572               0 :         return NS_ERROR_INVALID_ARG;
    1573                 : 
    1574              30 :     XRE_AddManifestLocation(NS_COMPONENT_LOCATION, lf);
    1575              30 :     return NS_OK;
    1576                 : }
    1577                 : 
    1578                 : NS_IMETHODIMP
    1579               0 : nsComponentManagerImpl::AutoUnregister(nsIFile* aLocation)
    1580                 : {
    1581               0 :     NS_ERROR("AutoUnregister not implemented.");
    1582               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1583                 : }
    1584                 : 
    1585                 : NS_IMETHODIMP
    1586               0 : nsComponentManagerImpl::RegisterFactoryLocation(const nsCID& aCID,
    1587                 :                                                 const char* aClassName,
    1588                 :                                                 const char* aContractID,
    1589                 :                                                 nsIFile* aFile,
    1590                 :                                                 const char* aLoaderStr,
    1591                 :                                                 const char* aType)
    1592                 : {
    1593               0 :     NS_ERROR("RegisterFactoryLocation not implemented.");
    1594               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1595                 : }
    1596                 : 
    1597                 : NS_IMETHODIMP
    1598               0 : nsComponentManagerImpl::UnregisterFactoryLocation(const nsCID& aCID,
    1599                 :                                                   nsIFile* aFile)
    1600                 : {
    1601               0 :     NS_ERROR("UnregisterFactoryLocation not implemented.");
    1602               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1603                 : }
    1604                 : 
    1605                 : NS_IMETHODIMP
    1606               4 : nsComponentManagerImpl::IsCIDRegistered(const nsCID & aClass,
    1607                 :                                         bool *_retval)
    1608                 : {
    1609               4 :     *_retval = (nsnull != GetFactoryEntry(aClass));
    1610               4 :     return NS_OK;
    1611                 : }
    1612                 : 
    1613                 : NS_IMETHODIMP
    1614               0 : nsComponentManagerImpl::IsContractIDRegistered(const char *aClass,
    1615                 :                                                bool *_retval)
    1616                 : {
    1617               0 :     NS_ENSURE_ARG_POINTER(aClass);
    1618               0 :     nsFactoryEntry *entry = GetFactoryEntry(aClass, strlen(aClass));
    1619                 : 
    1620               0 :     if (entry)
    1621               0 :         *_retval = true;
    1622                 :     else
    1623               0 :         *_retval = false;
    1624               0 :     return NS_OK;
    1625                 : }
    1626                 : 
    1627                 : static PLDHashOperator
    1628               0 : EnumerateCIDHelper(const nsID& id, nsFactoryEntry* entry, void* closure)
    1629                 : {
    1630               0 :     nsCOMArray<nsISupports> *array = static_cast<nsCOMArray<nsISupports>*>(closure);
    1631               0 :     nsCOMPtr<nsISupportsID> wrapper = new nsSupportsIDImpl();
    1632               0 :     wrapper->SetData(&id);
    1633               0 :     array->AppendObject(wrapper);
    1634               0 :     return PL_DHASH_NEXT;
    1635                 : }
    1636                 : 
    1637                 : NS_IMETHODIMP
    1638               0 : nsComponentManagerImpl::EnumerateCIDs(nsISimpleEnumerator **aEnumerator)
    1639                 : {
    1640                 :     NS_TIME_FUNCTION;
    1641                 : 
    1642               0 :     nsCOMArray<nsISupports> array;
    1643               0 :     mFactories.EnumerateRead(EnumerateCIDHelper, &array);
    1644                 : 
    1645               0 :     return NS_NewArrayEnumerator(aEnumerator, array);
    1646                 : }
    1647                 : 
    1648                 : static PLDHashOperator
    1649               0 : EnumerateContractsHelper(const nsACString& contract, nsFactoryEntry* entry, void* closure)
    1650                 : {
    1651               0 :     nsTArray<nsCString>* array = static_cast<nsTArray<nsCString>*>(closure);
    1652               0 :     array->AppendElement(contract);
    1653               0 :     return PL_DHASH_NEXT;
    1654                 : }
    1655                 : 
    1656                 : NS_IMETHODIMP
    1657               0 : nsComponentManagerImpl::EnumerateContractIDs(nsISimpleEnumerator **aEnumerator)
    1658                 : {
    1659                 :     NS_TIME_FUNCTION;
    1660                 : 
    1661               0 :     nsTArray<nsCString>* array = new nsTArray<nsCString>;
    1662               0 :     mContractIDs.EnumerateRead(EnumerateContractsHelper, array);
    1663                 : 
    1664               0 :     nsCOMPtr<nsIUTF8StringEnumerator> e;
    1665               0 :     nsresult rv = NS_NewAdoptingUTF8StringEnumerator(getter_AddRefs(e), array);
    1666               0 :     if (NS_FAILED(rv))
    1667               0 :         return rv;
    1668                 : 
    1669               0 :     return CallQueryInterface(e, aEnumerator);
    1670                 : }
    1671                 : 
    1672                 : NS_IMETHODIMP
    1673               0 : nsComponentManagerImpl::CIDToContractID(const nsCID & aClass,
    1674                 :                                         char **_retval)
    1675                 : {
    1676               0 :     NS_ERROR("CIDTOContractID not implemented");
    1677               0 :     return NS_ERROR_FACTORY_NOT_REGISTERED;
    1678                 : }
    1679                 : 
    1680                 : NS_IMETHODIMP
    1681           53359 : nsComponentManagerImpl::ContractIDToCID(const char *aContractID,
    1682                 :                                         nsCID * *_retval)
    1683                 : {
    1684                 :     {
    1685          106718 :         ReentrantMonitorAutoEnter mon(mMon);
    1686           53359 :         nsFactoryEntry* entry = mContractIDs.Get(nsDependentCString(aContractID));
    1687           53359 :         if (entry) {
    1688           51775 :             *_retval = (nsCID*) NS_Alloc(sizeof(nsCID));
    1689           51775 :             **_retval = *entry->mCIDEntry->cid;
    1690           51775 :             return NS_OK;
    1691                 :         }
    1692                 :     }
    1693            1584 :     *_retval = NULL;
    1694            1584 :     return NS_ERROR_FACTORY_NOT_REGISTERED;
    1695                 : }
    1696                 : 
    1697                 : ////////////////////////////////////////////////////////////////////////////////
    1698                 : // nsFactoryEntry
    1699                 : ////////////////////////////////////////////////////////////////////////////////
    1700                 : 
    1701         1133815 : nsFactoryEntry::nsFactoryEntry(const mozilla::Module::CIDEntry* entry,
    1702                 :                                nsComponentManagerImpl::KnownModule* module)
    1703                 :     : mCIDEntry(entry)
    1704         1133815 :     , mModule(module)
    1705                 : {
    1706         1133815 : }
    1707                 : 
    1708            3260 : nsFactoryEntry::nsFactoryEntry(const nsCID& aCID, nsIFactory* factory)
    1709                 :     : mCIDEntry(NULL)
    1710                 :     , mModule(NULL)
    1711            3260 :     , mFactory(factory)
    1712                 : {
    1713            3260 :     mozilla::Module::CIDEntry* e = new mozilla::Module::CIDEntry();
    1714            3260 :     nsCID* cid = new nsCID;
    1715            3260 :     *cid = aCID;
    1716            3260 :     e->cid = cid;
    1717            3260 :     mCIDEntry = e;
    1718            3260 : }        
    1719                 : 
    1720               0 : nsFactoryEntry::~nsFactoryEntry()
    1721                 : {
    1722                 :     // If this was a RegisterFactory entry, we own the CIDEntry/CID
    1723               0 :     if (!mModule) {
    1724               0 :         delete mCIDEntry->cid;
    1725               0 :         delete mCIDEntry;
    1726                 :     }
    1727               0 : }
    1728                 : 
    1729                 : already_AddRefed<nsIFactory>
    1730          586893 : nsFactoryEntry::GetFactory()
    1731                 : {
    1732          586893 :     if (!mFactory) {
    1733                 :         // RegisterFactory then UnregisterFactory can leave an entry in mContractIDs
    1734                 :         // pointing to an unusable nsFactoryEntry.
    1735          101897 :         if (!mModule)
    1736               0 :             return NULL;
    1737                 : 
    1738          101897 :         if (!mModule->Load())
    1739               0 :             return NULL;
    1740                 : 
    1741          101897 :         if (mModule->Module()->getFactoryProc) {
    1742            4236 :             mFactory = mModule->Module()->getFactoryProc(*mModule->Module(),
    1743            4236 :                                                          *mCIDEntry);
    1744                 :         }
    1745           99779 :         else if (mCIDEntry->getFactoryProc) {
    1746             147 :             mFactory = mCIDEntry->getFactoryProc(*mModule->Module(), *mCIDEntry);
    1747                 :         }
    1748                 :         else {
    1749           99632 :             NS_ASSERTION(mCIDEntry->constructorProc, "no getfactory or constructor");
    1750           99632 :             mFactory = new mozilla::GenericFactory(mCIDEntry->constructorProc);
    1751                 :         }
    1752          101897 :         if (!mFactory)
    1753               0 :             return NULL;
    1754                 :     }
    1755          586893 :     nsIFactory* factory = mFactory.get();
    1756          586893 :     NS_ADDREF(factory);
    1757          586893 :     return factory;
    1758                 : }
    1759                 : 
    1760                 : ////////////////////////////////////////////////////////////////////////////////
    1761                 : // Static Access Functions
    1762                 : ////////////////////////////////////////////////////////////////////////////////
    1763                 : 
    1764                 : nsresult
    1765          106679 : NS_GetComponentManager(nsIComponentManager* *result)
    1766                 : {
    1767          106679 :     if (!nsComponentManagerImpl::gComponentManager)
    1768               1 :         return NS_ERROR_NOT_INITIALIZED;
    1769                 : 
    1770          106678 :     NS_ADDREF(*result = nsComponentManagerImpl::gComponentManager);
    1771          106678 :     return NS_OK;
    1772                 : }
    1773                 : 
    1774                 : nsresult
    1775          247707 : NS_GetServiceManager(nsIServiceManager* *result)
    1776                 : {
    1777          247707 :     if (!nsComponentManagerImpl::gComponentManager)
    1778               0 :         return NS_ERROR_NOT_INITIALIZED;
    1779                 : 
    1780          247707 :     NS_ADDREF(*result = nsComponentManagerImpl::gComponentManager);
    1781          247707 :     return NS_OK;
    1782                 : }
    1783                 : 
    1784                 : 
    1785                 : nsresult
    1786           48125 : NS_GetComponentRegistrar(nsIComponentRegistrar* *result)
    1787                 : {
    1788           48125 :     if (!nsComponentManagerImpl::gComponentManager)
    1789               0 :         return NS_ERROR_NOT_INITIALIZED;
    1790                 : 
    1791           48125 :     NS_ADDREF(*result = nsComponentManagerImpl::gComponentManager);
    1792           48125 :     return NS_OK;
    1793                 : }
    1794                 : 
    1795                 : EXPORT_XPCOM_API(nsresult)
    1796               0 : XRE_AddStaticComponent(const mozilla::Module* aComponent)
    1797                 : {
    1798               0 :     nsComponentManagerImpl::InitializeStaticModules();
    1799               0 :     nsComponentManagerImpl::sStaticModules->AppendElement(aComponent);
    1800                 : 
    1801               0 :     if (nsComponentManagerImpl::gComponentManager &&
    1802                 :         nsComponentManagerImpl::NORMAL == nsComponentManagerImpl::gComponentManager->mStatus)
    1803               0 :         nsComponentManagerImpl::gComponentManager->RegisterModule(aComponent, NULL);
    1804                 : 
    1805               0 :     return NS_OK;
    1806                 : }
    1807                 : 
    1808                 : NS_IMETHODIMP
    1809             196 : nsComponentManagerImpl::AddBootstrappedManifestLocation(nsILocalFile* aLocation)
    1810                 : {
    1811             392 :   nsString path;
    1812             196 :   nsresult rv = aLocation->GetPath(path);
    1813             196 :   if (NS_FAILED(rv))
    1814               0 :     return rv;
    1815                 : 
    1816             196 :   if (Substring(path, path.Length() - 4).Equals(NS_LITERAL_STRING(".xpi"))) {
    1817              97 :     return XRE_AddJarManifestLocation(NS_BOOTSTRAPPED_LOCATION, aLocation);
    1818                 :   }
    1819                 : 
    1820                 :   nsCOMPtr<nsILocalFile> manifest =
    1821             198 :     CloneAndAppend(aLocation, NS_LITERAL_CSTRING("chrome.manifest"));
    1822              99 :   return XRE_AddManifestLocation(NS_BOOTSTRAPPED_LOCATION, manifest);
    1823                 : }
    1824                 : 
    1825                 : NS_IMETHODIMP
    1826             196 : nsComponentManagerImpl::RemoveBootstrappedManifestLocation(nsILocalFile* aLocation)
    1827                 : {
    1828             392 :   nsCOMPtr<nsIChromeRegistry> cr = mozilla::services::GetChromeRegistryService();
    1829             196 :   if (!cr)
    1830               0 :     return NS_ERROR_FAILURE;
    1831                 : 
    1832             392 :   nsCOMPtr<nsILocalFile> manifest;
    1833             392 :   nsString path;
    1834             196 :   nsresult rv = aLocation->GetPath(path);
    1835             196 :   if (NS_FAILED(rv))
    1836               0 :     return rv;
    1837                 : 
    1838             392 :   nsComponentManagerImpl::ComponentLocation elem;
    1839             196 :   elem.type = NS_BOOTSTRAPPED_LOCATION;
    1840                 : 
    1841             196 :   if (Substring(path, path.Length() - 4).Equals(NS_LITERAL_STRING(".xpi"))) {
    1842              97 :     elem.location.Init(aLocation, "chrome.manifest");
    1843                 :   } else {
    1844             198 :     nsCOMPtr<nsILocalFile> lf = CloneAndAppend(aLocation, NS_LITERAL_CSTRING("chrome.manifest"));
    1845              99 :     elem.location.Init(lf);
    1846                 :   }
    1847                 : 
    1848                 :   // Remove reference.
    1849             196 :   nsComponentManagerImpl::sModuleLocations->RemoveElement(elem, ComponentLocationComparator());
    1850                 : 
    1851             196 :   rv = cr->CheckForNewChrome();
    1852             196 :   return rv;
    1853                 : }
    1854                 : 
    1855                 : EXPORT_XPCOM_API(nsresult)
    1856            1517 : XRE_AddManifestLocation(NSLocationType aType, nsILocalFile* aLocation)
    1857                 : {
    1858            1517 :     nsComponentManagerImpl::InitializeModuleLocations();
    1859                 :     nsComponentManagerImpl::ComponentLocation* c = 
    1860            1517 :         nsComponentManagerImpl::sModuleLocations->AppendElement();
    1861            1517 :     c->type = aType;
    1862            1517 :     c->location.Init(aLocation);
    1863                 : 
    1864            1517 :     if (nsComponentManagerImpl::gComponentManager &&
    1865                 :         nsComponentManagerImpl::NORMAL == nsComponentManagerImpl::gComponentManager->mStatus)
    1866             129 :         nsComponentManagerImpl::gComponentManager->RegisterManifest(aType, c->location, false);
    1867                 : 
    1868            1517 :     return NS_OK;
    1869                 : }
    1870                 : 
    1871                 : EXPORT_XPCOM_API(nsresult)
    1872              98 : XRE_AddJarManifestLocation(NSLocationType aType, nsILocalFile* aLocation)
    1873                 : {
    1874              98 :     nsComponentManagerImpl::InitializeModuleLocations();
    1875                 :     nsComponentManagerImpl::ComponentLocation* c = 
    1876              98 :         nsComponentManagerImpl::sModuleLocations->AppendElement();
    1877                 : 
    1878              98 :     c->type = aType;
    1879              98 :     c->location.Init(aLocation, "chrome.manifest");
    1880                 : 
    1881              98 :     if (nsComponentManagerImpl::gComponentManager &&
    1882                 :         nsComponentManagerImpl::NORMAL == nsComponentManagerImpl::gComponentManager->mStatus)
    1883              97 :         nsComponentManagerImpl::gComponentManager->RegisterManifest(aType, c->location, false);
    1884                 : 
    1885              98 :     return NS_OK;
    1886                 : }
    1887                 : 

Generated by: LCOV version 1.7