LCOV - app.info - xpcom/components/nsComponentManager.cpp

LCOV - code coverage report
| Current view: | directory - xpcom/components - nsComponentManager.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 762 | 553 | 72.6 %
| Date: | 2012-04-21 | 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             754 : nsGetServiceFromCategory::operator()(const nsIID& aIID, void** aInstancePtr) const
         181                 : {
         182                 :     nsresult rv;
         183            1508 :     nsXPIDLCString value;
         184            1508 :     nsCOMPtr<nsICategoryManager> catman;
         185             754 :     nsComponentManagerImpl *compMgr = nsComponentManagerImpl::gComponentManager;
         186             754 :     if (!compMgr) {
         187               0 :         rv = NS_ERROR_NOT_INITIALIZED;
         188               0 :         goto error;
         189                 :     }
         190                 :
         191             754 :     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             754 :                                                      getter_AddRefs(catman));
         200             754 :     if (NS_FAILED(rv)) goto error;
         201                 :
         202                 :     /* find the contractID for category.entry */
         203             754 :     rv = catman->GetCategoryEntry(mCategory, mEntry,
         204             754 :                                   getter_Copies(value));
         205             754 :     if (NS_FAILED(rv)) goto error;
         206             754 :     if (!value) {
         207               0 :         rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
         208               0 :         goto error;
         209                 :     }
         210                 :
         211                 :     rv = compMgr->
         212                 :         nsComponentManagerImpl::GetServiceByContractID(value,
         213             754 :                                                        aIID, aInstancePtr);
         214             754 :     if (NS_FAILED(rv)) {
         215                 :     error:
         216               0 :         *aInstancePtr = 0;
         217                 :     }
         218             754 :     if (mErrorPtr)
         219               0 :         *mErrorPtr = rv;
         220             754 :     return rv;
         221                 : }
         222                 :
         223                 : ////////////////////////////////////////////////////////////////////////////////
         224                 : // Arena helper functions
         225                 : ////////////////////////////////////////////////////////////////////////////////
         226                 : char *
         227          852164 : ArenaStrndup(const char *s, PRUint32 len, PLArenaPool *arena)
         228                 : {
         229                 :     void *mem;
         230                 :     // Include trailing null in the len
         231          852164 :     PL_ARENA_ALLOCATE(mem, arena, len+1);
         232          852164 :     if (mem)
         233          852164 :         memcpy(mem, s, len+1);
         234          852164 :     return static_cast<char *>(mem);
         235                 : }
         236                 :
         237                 : char*
         238          852164 : ArenaStrdup(const char *s, PLArenaPool *arena)
         239                 : {
         240          852164 :     return ArenaStrndup(s, strlen(s), arena);
         241                 : }
         242                 :
         243                 : // this is safe to call during InitXPCOM
         244                 : static already_AddRefed<nsILocalFile>
         245            2730 : GetLocationFromDirectoryService(const char* prop)
         246                 : {
         247            5460 :     nsCOMPtr<nsIProperties> directoryService;
         248                 :     nsDirectoryService::Create(nsnull,
         249                 :                                NS_GET_IID(nsIProperties),
         250            2730 :                                getter_AddRefs(directoryService));
         251                 :
         252            2730 :     if (!directoryService)
         253               0 :         return NULL;
         254                 :
         255            5460 :     nsCOMPtr<nsILocalFile> file;
         256            2730 :     nsresult rv = directoryService->Get(prop,
         257                 :                                         NS_GET_IID(nsILocalFile),
         258            2730 :                                         getter_AddRefs(file));
         259            2730 :     if (NS_FAILED(rv))
         260               0 :         return NULL;
         261                 :
         262            2730 :     return file.forget();
         263                 : }
         264                 :
         265                 : static already_AddRefed<nsILocalFile>
         266            1563 : CloneAndAppend(nsILocalFile* aBase, const nsACString& append)
         267                 : {
         268            3126 :     nsCOMPtr<nsIFile> f;
         269            1563 :     aBase->Clone(getter_AddRefs(f));
         270            1563 :     if (!f)
         271               0 :         return NULL;
         272                 :
         273            3126 :     nsCOMPtr<nsILocalFile> lf = do_QueryInterface(f);
         274            1563 :     f->AppendNative(append);
         275            1563 :     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            1365 : nsComponentManagerImpl::nsComponentManagerImpl()
         295                 :     : mMon("nsComponentManagerImpl.mMon")
         296            1365 :     , mStatus(NOT_INITIALIZED)
         297                 : {
         298            1365 : }
         299                 :
         300                 : #define CONTRACTID_HASHTABLE_INITIAL_SIZE   2048
         301                 :
         302                 : nsTArray<const mozilla::Module*>* nsComponentManagerImpl::sStaticModules;
         303                 :
         304                 : /* static */ void
         305            1365 : nsComponentManagerImpl::InitializeStaticModules()
         306                 : {
         307            1365 :     if (sStaticModules)
         308               0 :         return;
         309                 :
         310            1365 :     sStaticModules = new nsTArray<const mozilla::Module*>;
         311           75075 :     for (const mozilla::Module *const *const *staticModules = kPStaticModules;
         312                 :          *staticModules; ++staticModules)
         313           73710 :         sStaticModules->AppendElement(**staticModules);
         314                 : }
         315                 :
         316                 : nsTArray<nsComponentManagerImpl::ComponentLocation>*
         317                 : nsComponentManagerImpl::sModuleLocations;
         318                 :
         319                 : /* static */ void
         320            2957 : nsComponentManagerImpl::InitializeModuleLocations()
         321                 : {
         322            2957 :     if (sModuleLocations)
         323            1592 :         return;
         324                 :
         325            1365 :     sModuleLocations = new nsTArray<ComponentLocation>;
         326                 : }
         327                 :
         328            1365 : nsresult nsComponentManagerImpl::Init()
         329                 : {
         330                 :     NS_TIME_FUNCTION;
         331                 :
         332            1365 :     PR_ASSERT(NOT_INITIALIZED == mStatus);
         333                 :
         334            1365 :     if (nsComponentManagerLog == nsnull)
         335                 :     {
         336            1365 :         nsComponentManagerLog = PR_NewLogModule("nsComponentManager");
         337                 :     }
         338                 :
         339                 :     // Initialize our arena
         340                 :     NS_TIME_FUNCTION_MARK("Next: init component manager arena");
         341            1365 :     PL_INIT_ARENA_POOL(&mArena, "ComponentManagerArena", NS_CM_BLOCK_SIZE);
         342                 :
         343            1365 :     mFactories.Init(CONTRACTID_HASHTABLE_INITIAL_SIZE);
         344            1365 :     mContractIDs.Init(CONTRACTID_HASHTABLE_INITIAL_SIZE);
         345            1365 :     mLoaderMap.Init();
         346            1365 :     mKnownModules.Init();
         347                 :
         348                 :     nsCOMPtr<nsILocalFile> greDir =
         349            2730 :         GetLocationFromDirectoryService(NS_GRE_DIR);
         350                 :     nsCOMPtr<nsILocalFile> appDir =
         351            2730 :         GetLocationFromDirectoryService(NS_XPCOM_CURRENT_PROCESS_DIR);
         352                 :
         353            1365 :     InitializeStaticModules();
         354            1365 :     InitializeModuleLocations();
         355                 :
         356            1365 :     ComponentLocation* cl = sModuleLocations->InsertElementAt(0);
         357            2730 :     nsCOMPtr<nsILocalFile> lf = CloneAndAppend(appDir, NS_LITERAL_CSTRING("chrome.manifest"));
         358            1365 :     cl->type = NS_COMPONENT_LOCATION;
         359            1365 :     cl->location.Init(lf);
         360                 :
         361            1365 :     bool equals = false;
         362            1365 :     appDir->Equals(greDir, &equals);
         363            1365 :     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            1365 :     PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
         371                 :            ("nsComponentManager: Initialized."));
         372                 :
         373                 :     NS_TIME_FUNCTION_MARK("Next: init native module loader");
         374            1365 :     nsresult rv = mNativeModuleLoader.Init();
         375            1365 :     if (NS_FAILED(rv))
         376               0 :         return rv;
         377                 :
         378            1365 :     nsCategoryManager::GetSingleton()->SuppressNotifications(true);
         379                 :
         380            1365 :     RegisterModule(&kXPCOMModule, NULL);
         381                 :
         382           75075 :     for (PRUint32 i = 0; i < sStaticModules->Length(); ++i)
         383           73710 :         RegisterModule((*sStaticModules)[i], NULL);
         384                 :
         385            2730 :     nsRefPtr<nsZipArchive> appOmnijar = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP);
         386            1365 :     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            2730 :     nsRefPtr<nsZipArchive> greOmnijar = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
         392            1365 :     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            1365 :     RereadChromeManifests(false);
         399                 :
         400            1365 :     nsCategoryManager::GetSingleton()->SuppressNotifications(false);
         401                 :
         402            1365 :     mStatus = NORMAL;
         403                 :
         404            1365 :     return NS_OK;
         405                 : }
         406                 :
         407                 : void
         408           80539 : nsComponentManagerImpl::RegisterModule(const mozilla::Module* aModule,
         409                 :                                        FileLocation* aFile)
         410                 : {
         411          161078 :     ReentrantMonitorAutoEnter mon(mMon);
         412                 :
         413                 :     KnownModule* m;
         414           80539 :     if (aFile) {
         415           10928 :         nsCString uri;
         416            5464 :         aFile->GetURIString(uri);
         417            5464 :         NS_ASSERTION(!mKnownModules.Get(uri),
         418                 :                      "Must not register a binary module twice.");
         419                 :
         420            5464 :         m = new KnownModule(aModule, *aFile);
         421            5464 :         mKnownModules.Put(uri, m);
         422                 :     } else {
         423           75075 :         m = new KnownModule(aModule);
         424           75075 :         mKnownStaticModules.AppendElement(m);
         425                 :     }
         426                 :
         427           80539 :     if (aModule->mCIDs) {
         428                 :         const mozilla::Module::CIDEntry* entry;
         429         1041507 :         for (entry = aModule->mCIDs; entry->cid; ++entry)
         430          960968 :             RegisterCIDEntry(entry, m);
         431                 :     }
         432                 :
         433           80539 :     if (aModule->mContractIDs) {
         434                 :         const mozilla::Module::ContractIDEntry* entry;
         435         1098833 :         for (entry = aModule->mContractIDs; entry->contractid; ++entry)
         436         1018296 :             RegisterContractID(entry);
         437           80537 :         NS_ASSERTION(!entry->cid, "Incorrectly terminated contract list");
         438                 :     }
         439                 :
         440           80539 :     if (aModule->mCategoryEntries) {
         441                 :         const mozilla::Module::CategoryEntry* entry;
         442          379470 :         for (entry = aModule->mCategoryEntries; entry->category; ++entry)
         443                 :             nsCategoryManager::GetSingleton()->
         444                 :                 AddCategoryEntry(entry->category,
         445                 :                                  entry->entry,
         446          354900 :                                  entry->value);
         447                 :     }
         448           80539 : }
         449                 :
         450                 : void
         451          960968 : nsComponentManagerImpl::RegisterCIDEntry(const mozilla::Module::CIDEntry* aEntry,
         452                 :                                          KnownModule* aModule)
         453                 : {
         454          960968 :     mMon.AssertCurrentThreadIn();
         455                 :
         456          960968 :     nsFactoryEntry* f = mFactories.Get(*aEntry->cid);
         457          960968 :     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          960968 :     f = new nsFactoryEntry(aEntry, aModule);
         477          960968 :     mFactories.Put(*aEntry->cid, f);
         478                 : }
         479                 :
         480                 : void
         481         1018296 : nsComponentManagerImpl::RegisterContractID(const mozilla::Module::ContractIDEntry* aEntry)
         482                 : {
         483         1018296 :     mMon.AssertCurrentThreadIn();
         484                 :
         485         1018296 :     nsFactoryEntry* f = mFactories.Get(*aEntry->cid);
         486         1018296 :     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         1018296 :     mContractIDs.Put(nsDependentCString(aEntry->contractid), f);
         500                 : }
         501                 :
         502                 : static void
         503            2054 : CutExtension(nsCString& path)
         504                 : {
         505            2054 :     PRInt32 dotPos = path.RFindChar('.');
         506            2054 :     if (kNotFound == dotPos)
         507               0 :         path.Truncate();
         508                 :     else
         509            2054 :         path.Cut(0, dotPos + 1);
         510            2054 : }
         511                 :
         512                 : void
         513           96030 : nsComponentManagerImpl::RegisterManifest(NSLocationType aType,
         514                 :                                          FileLocation &aFile,
         515                 :                                          bool aChromeOnly)
         516                 : {
         517                 :     PRUint32 len;
         518          192060 :     FileLocation::Data data;
         519          192060 :     nsAutoArrayPtr<char> buf;
         520           96030 :     nsresult rv = aFile.GetData(data);
         521           96030 :     if (NS_SUCCEEDED(rv)) {
         522           95818 :         rv = data.GetSize(&len);
         523                 :     }
         524           96030 :     if (NS_SUCCEEDED(rv)) {
         525          191636 :         buf = new char[len + 1];
         526           95818 :         rv = data.Copy(buf, len);
         527                 :     }
         528           96030 :     if (NS_SUCCEEDED(rv)) {
         529           95818 :         buf[len] = '\0';
         530           95818 :         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           96030 : }
         537                 :
         538                 : void
         539           92632 : nsComponentManagerImpl::ManifestManifest(ManifestProcessingContext& cx, int lineno, char *const * argv)
         540                 : {
         541           92632 :     char* file = argv[0];
         542          185264 :     FileLocation f(cx.mFile, file);
         543           92632 :     RegisterManifest(cx.mType, f, cx.mChromeOnly);
         544           92632 : }
         545                 :
         546                 : void
         547            5467 : nsComponentManagerImpl::ManifestBinaryComponent(ManifestProcessingContext& cx, int lineno, char *const * argv)
         548                 : {
         549            5467 :     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           10934 :     FileLocation f(cx.mFile, argv[0]);
         557           10934 :     nsCString uri;
         558            5467 :     f.GetURIString(uri);
         559                 :
         560            5467 :     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            5465 :     const mozilla::Module* m = mNativeModuleLoader.LoadModule(f);
         568                 :     // The native module loader should report an error here, we don't have to
         569            5465 :     if (!m)
         570                 :         return;
         571                 :
         572           10931 :     RegisterModule(m, &f);
         573                 : }
         574                 :
         575                 : void
         576          210214 : nsComponentManagerImpl::ManifestXPT(ManifestProcessingContext& cx, int lineno, char *const * argv)
         577                 : {
         578          420428 :     FileLocation f(cx.mFile, argv[0]);
         579                 :     PRUint32 len;
         580          420428 :     FileLocation::Data data;
         581          420428 :     nsAutoArrayPtr<char> buf;
         582          210214 :     nsresult rv = f.GetData(data);
         583          210214 :     if (NS_SUCCEEDED(rv)) {
         584          210214 :         rv = data.GetSize(&len);
         585                 :     }
         586          210214 :     if (NS_SUCCEEDED(rv)) {
         587          420428 :         buf = new char[len];
         588          210214 :         rv = data.Copy(buf, len);
         589                 :     }
         590          210214 :     if (NS_SUCCEEDED(rv)) {
         591                 :         xptiInterfaceInfoManager::GetSingleton()
         592          210214 :             ->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          210214 : }
         599                 :
         600                 : void
         601          131064 : nsComponentManagerImpl::ManifestComponent(ManifestProcessingContext& cx, int lineno, char *const * argv)
         602                 : {
         603          131064 :     char* id = argv[0];
         604          131064 :     char* file = argv[1];
         605                 :
         606                 :     nsID cid;
         607          131064 :     if (!cid.Parse(id)) {
         608                 :         LogMessageWithContext(cx.mFile, lineno,
         609               1 :                               "Malformed CID: '%s'.", id);
         610               1 :         return;
         611                 :     }
         612                 :
         613          262126 :     ReentrantMonitorAutoEnter mon(mMon);
         614          131063 :     nsFactoryEntry* f = mFactories.Get(cid);
         615          131063 :     if (f) {
         616                 :         char idstr[NSID_LENGTH];
         617            1366 :         cid.ToProvidedString(idstr);
         618                 :
         619            2732 :         nsCString existing;
         620            1366 :         if (f->mModule)
         621            1366 :             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            1366 :                               existing.get());
         629                 :         return;
         630                 :     }
         631                 :
         632                 :     KnownModule* km;
         633          259394 :     FileLocation fl(cx.mFile, file);
         634                 :
         635          259394 :     nsCString hash;
         636          129697 :     fl.GetURIString(hash);
         637          129697 :     km = mKnownModules.Get(hash);
         638          129697 :     if (!km) {
         639           96932 :         km = new KnownModule(fl);
         640           96932 :         mKnownModules.Put(hash, km);
         641                 :     }
         642                 :
         643                 :     void* place;
         644                 :
         645          129697 :     PL_ARENA_ALLOCATE(place, &mArena, sizeof(nsCID));
         646          129697 :     nsID* permanentCID = static_cast<nsID*>(place);
         647          129697 :     *permanentCID = cid;
         648                 :
         649          129697 :     PL_ARENA_ALLOCATE(place, &mArena, sizeof(mozilla::Module::CIDEntry));
         650          129697 :     mozilla::Module::CIDEntry* e = new (place) mozilla::Module::CIDEntry();
         651          129697 :     e->cid = permanentCID;
         652                 :
         653          129697 :     f = new nsFactoryEntry(e, km);
         654          129697 :     mFactories.Put(cid, f);
         655                 : }
         656                 :
         657                 : void
         658          132427 : nsComponentManagerImpl::ManifestContract(ManifestProcessingContext& cx, int lineno, char *const * argv)
         659                 : {
         660          132427 :     char* contract = argv[0];
         661          132427 :     char* id = argv[1];
         662                 :
         663                 :     nsID cid;
         664          132427 :     if (!cid.Parse(id)) {
         665                 :         LogMessageWithContext(cx.mFile, lineno,
         666               0 :                               "Malformed CID: '%s'.", id);
         667               0 :         return;
         668                 :     }
         669                 :
         670          264854 :     ReentrantMonitorAutoEnter mon(mMon);
         671          132427 :     nsFactoryEntry* f = mFactories.Get(cid);
         672          132427 :     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          132426 :     mContractIDs.Put(nsDependentCString(contract), f);
         680                 : }
         681                 :
         682                 : void
         683           47785 : nsComponentManagerImpl::ManifestCategory(ManifestProcessingContext& cx, int lineno, char *const * argv)
         684                 : {
         685           47785 :     char* category = argv[0];
         686           47785 :     char* key = argv[1];
         687           47785 :     char* value = argv[2];
         688                 :
         689                 :     nsCategoryManager::GetSingleton()->
         690           47785 :         AddCategoryEntry(category, key, value);
         691           47785 : }
         692                 :
         693                 : void
         694            1570 : nsComponentManagerImpl::RereadChromeManifests(bool aChromeOnly)
         695                 : {
         696            4741 :     for (PRUint32 i = 0; i < sModuleLocations->Length(); ++i) {
         697            3171 :         ComponentLocation& l = sModuleLocations->ElementAt(i);
         698            3171 :         RegisterManifest(l.type, l.location, aChromeOnly);
         699                 :     }
         700            1570 : }
         701                 :
         702                 : bool
         703            2054 : nsComponentManagerImpl::KnownModule::EnsureLoader()
         704                 : {
         705            2054 :     if (!mLoader) {
         706            4108 :         nsCString extension;
         707            2054 :         mFile.GetURIString(extension);
         708            2054 :         CutExtension(extension);
         709            2054 :         mLoader = nsComponentManagerImpl::gComponentManager->LoaderForExtension(extension);
         710                 :     }
         711            2054 :     return !!mLoader;
         712                 : }
         713                 :
         714                 : bool
         715           99511 : nsComponentManagerImpl::KnownModule::Load()
         716                 : {
         717           99511 :     if (mFailed)
         718               0 :         return false;
         719           99511 :     if (!mModule) {
         720            2054 :         if (!EnsureLoader())
         721               0 :             return false;
         722                 :
         723            2054 :         mModule = mLoader->LoadModule(mFile);
         724                 :
         725            2054 :         if (!mModule) {
         726               0 :             mFailed = true;
         727               0 :             return false;
         728                 :         }
         729                 :     }
         730           99511 :     if (!mLoaded) {
         731           29124 :         if (mModule->loadProc) {
         732            7648 :             nsresult rv = mModule->loadProc();
         733            7648 :             if (NS_FAILED(rv)) {
         734               0 :                 mFailed = true;
         735               0 :                 return false;
         736                 :             }
         737                 :         }
         738           29124 :         mLoaded = true;
         739                 :     }
         740           99511 :     return true;
         741                 : }
         742                 :
         743                 : nsCString
         744            1366 : nsComponentManagerImpl::KnownModule::Description() const
         745                 : {
         746            1366 :     nsCString s;
         747            1366 :     if (mFile)
         748            1366 :         mFile.GetURIString(s);
         749                 :     else
         750               0 :         s = "<static module>";
         751                 :     return s;
         752                 : }
         753                 :
         754            1365 : nsresult nsComponentManagerImpl::Shutdown(void)
         755                 : {
         756                 :     NS_TIME_FUNCTION;
         757                 :
         758            1365 :     PR_ASSERT(NORMAL == mStatus);
         759                 :
         760            1365 :     mStatus = SHUTDOWN_IN_PROGRESS;
         761                 :
         762                 :     // Shutdown the component manager
         763            1365 :     PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning Shutdown."));
         764                 :
         765                 :     // Release all cached factories
         766            1365 :     mContractIDs.Clear();
         767            1365 :     mFactories.Clear(); // XXX release the objects, don't just clear
         768            1365 :     mLoaderMap.Clear();
         769            1365 :     mKnownModules.Clear();
         770            1365 :     mKnownStaticModules.Clear();
         771                 :
         772            1365 :     mLoaderData.Clear();
         773                 :
         774            1365 :     delete sStaticModules;
         775            1365 :     delete sModuleLocations;
         776                 :
         777                 :     // Unload libraries
         778            1365 :     mNativeModuleLoader.UnloadLibraries();
         779                 :
         780                 :     // delete arena for strings and small objects
         781            1365 :     PL_FinishArenaPool(&mArena);
         782                 :
         783            1365 :     mStatus = SHUTDOWN_COMPLETE;
         784                 :
         785            1365 :     PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Shutdown complete."));
         786                 :
         787            1365 :     return NS_OK;
         788                 : }
         789                 :
         790            2730 : nsComponentManagerImpl::~nsComponentManagerImpl()
         791                 : {
         792            1365 :     PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning destruction."));
         793                 :
         794            1365 :     if (SHUTDOWN_COMPLETE != mStatus)
         795               0 :         Shutdown();
         796                 :
         797            1365 :     PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Destroyed."));
         798            1365 : }
         799                 :
         800         1772719 : 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          474474 : nsComponentManagerImpl::GetFactoryEntry(const char *aContractID,
         819                 :                                         PRUint32 aContractIDLen)
         820                 : {
         821          948948 :     ReentrantMonitorAutoEnter mon(mMon);
         822          474474 :     return mContractIDs.Get(nsDependentCString(aContractID, aContractIDLen));
         823                 : }
         824                 :
         825                 :
         826                 : nsFactoryEntry *
         827          117382 : nsComponentManagerImpl::GetFactoryEntry(const nsCID &aClass)
         828                 : {
         829          234764 :     ReentrantMonitorAutoEnter mon(mMon);
         830          117382 :     return mFactories.Get(aClass);
         831                 : }
         832                 :
         833                 : already_AddRefed<nsIFactory>
         834            2734 : nsComponentManagerImpl::FindFactory(const nsCID& aClass)
         835                 : {
         836            2734 :     nsFactoryEntry* e = GetFactoryEntry(aClass);
         837            2734 :     if (!e)
         838               0 :         return NULL;
         839                 :
         840            2734 :     return e->GetFactory();
         841                 : }
         842                 :
         843                 : already_AddRefed<nsIFactory>
         844           15064 : nsComponentManagerImpl::FindFactory(const char *contractID,
         845                 :                                     PRUint32 aContractIDLen)
         846                 : {
         847           15064 :     nsFactoryEntry *entry = GetFactoryEntry(contractID, aContractIDLen);
         848           15064 :     if (!entry)
         849           15064 :         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            2734 : nsComponentManagerImpl::GetClassObject(const nsCID &aClass, const nsIID &aIID,
         862                 :                                        void **aResult)
         863                 : {
         864                 :     nsresult rv;
         865                 :
         866                 : #ifdef PR_LOGGING
         867            2734 :     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            2734 :     PR_ASSERT(aResult != nsnull);
         877                 :
         878            5468 :     nsCOMPtr<nsIFactory> factory = FindFactory(aClass);
         879            2734 :     if (!factory)
         880               0 :         return NS_ERROR_FACTORY_NOT_REGISTERED;
         881                 :
         882            2734 :     rv = factory->QueryInterface(aIID, aResult);
         883                 :
         884            2734 :     PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
         885                 :            ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
         886                 :
         887            2734 :     return rv;
         888                 : }
         889                 :
         890                 :
         891                 : NS_IMETHODIMP
         892           15064 : nsComponentManagerImpl::GetClassObjectByContractID(const char *contractID,
         893                 :                                                    const nsIID &aIID,
         894                 :                                                    void **aResult)
         895                 : {
         896           15064 :     NS_ENSURE_ARG_POINTER(aResult);
         897           15064 :     NS_ENSURE_ARG_POINTER(contractID);
         898                 :
         899                 :     nsresult rv;
         900                 :
         901                 :
         902                 : #ifdef PR_LOGGING
         903           15064 :     if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_DEBUG))
         904                 :     {
         905               0 :         PR_LogPrint("nsComponentManager: GetClassObject(%s)", contractID);
         906                 :     }
         907                 : #endif
         908                 :
         909           30128 :     nsCOMPtr<nsIFactory> factory = FindFactory(contractID, strlen(contractID));
         910           15064 :     if (!factory)
         911           15064 :         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          114643 : 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          114643 :     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          114643 :     if (aResult == nsnull)
         952                 :     {
         953               0 :         return NS_ERROR_NULL_POINTER;
         954                 :     }
         955          114643 :     *aResult = nsnull;
         956                 :
         957          114643 :     nsFactoryEntry *entry = GetFactoryEntry(aClass);
         958                 :
         959          114643 :     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          229286 :     nsCOMPtr<nsIFactory> factory = entry->GetFactory();
         975          114643 :     if (factory)
         976                 :     {
         977          114643 :         rv = factory->CreateInstance(aDelegate, aIID, aResult);
         978          114643 :         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          114643 :     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          114643 :     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          459658 : nsComponentManagerImpl::CreateInstanceByContractID(const char *aContractID,
        1014                 :                                                    nsISupports *aDelegate,
        1015                 :                                                    const nsIID &aIID,
        1016                 :                                                    void **aResult)
        1017                 : {
        1018                 :     COMPMGR_TIME_FUNCTION_CONTRACTID(aContractID);
        1019                 :
        1020          459658 :     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          459658 :     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          459410 :     if (aResult == nsnull)
        1037                 :     {
        1038               0 :         return NS_ERROR_NULL_POINTER;
        1039                 :     }
        1040          459410 :     *aResult = nsnull;
        1041                 :
        1042          459410 :     nsFactoryEntry *entry = GetFactoryEntry(aContractID, strlen(aContractID));
        1043                 :
        1044          459410 :     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          918772 :     nsCOMPtr<nsIFactory> factory = entry->GetFactory();
        1061          459386 :     if (factory)
        1062                 :     {
        1063                 :
        1064          459386 :         rv = factory->CreateInstance(aDelegate, aIID, aResult);
        1065          459386 :         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          459386 :     PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
        1076                 :            ("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID,
        1077                 :             NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
        1078                 :
        1079          459386 :     return rv;
        1080                 : }
        1081                 :
        1082                 : static PLDHashOperator
        1083         1091108 : FreeFactoryEntries(const nsID& aCID,
        1084                 :                    nsFactoryEntry* aEntry,
        1085                 :                    void* arg)
        1086                 : {
        1087         1091108 :     aEntry->mFactory = NULL;
        1088         1091108 :     aEntry->mServiceObject = NULL;
        1089         1091108 :     return PL_DHASH_NEXT;
        1090                 : }
        1091                 :
        1092                 : nsresult
        1093            1365 : nsComponentManagerImpl::FreeServices()
        1094                 : {
        1095            1365 :     NS_ASSERTION(gXPCOMShuttingDown, "Must be shutting down in order to free all services");
        1096                 :
        1097            1365 :     if (!gXPCOMShuttingDown)
        1098               0 :         return NS_ERROR_FAILURE;
        1099                 :
        1100            1365 :     mFactories.EnumerateRead(FreeFactoryEntries, NULL);
        1101            1365 :     return NS_OK;
        1102                 : }
        1103                 :
        1104                 : // This should only ever be called within the monitor!
        1105                 : nsComponentManagerImpl::PendingServiceInfo*
        1106           75762 : nsComponentManagerImpl::AddPendingService(const nsCID& aServiceCID,
        1107                 :                                           PRThread* aThread)
        1108                 : {
        1109           75762 :   PendingServiceInfo* newInfo = mPendingServices.AppendElement();
        1110           75762 :   if (newInfo) {
        1111           75762 :     newInfo->cid = &aServiceCID;
        1112           75762 :     newInfo->thread = aThread;
        1113                 :   }
        1114           75762 :   return newInfo;
        1115                 : }
        1116                 :
        1117                 : // This should only ever be called within the monitor!
        1118                 : void
        1119           75762 : nsComponentManagerImpl::RemovePendingService(const nsCID& aServiceCID)
        1120                 : {
        1121           75762 :   PRUint32 pendingCount = mPendingServices.Length();
        1122          106399 :   for (PRUint32 index = 0; index < pendingCount; ++index) {
        1123          106399 :     const PendingServiceInfo& info = mPendingServices.ElementAt(index);
        1124          106399 :     if (info.cid->Equals(aServiceCID)) {
        1125           75762 :       mPendingServices.RemoveElementAt(index);
        1126           75762 :       return;
        1127                 :     }
        1128                 :   }
        1129                 : }
        1130                 :
        1131                 : // This should only ever be called within the monitor!
        1132                 : PRThread*
        1133          151524 : nsComponentManagerImpl::GetPendingServiceThread(const nsCID& aServiceCID) const
        1134                 : {
        1135          151524 :   PRUint32 pendingCount = mPendingServices.Length();
        1136          212798 :   for (PRUint32 index = 0; index < pendingCount; ++index) {
        1137          137036 :     const PendingServiceInfo& info = mPendingServices.ElementAt(index);
        1138          137036 :     if (info.cid->Equals(aServiceCID)) {
        1139           75762 :       return info.thread;
        1140                 :     }
        1141                 :   }
        1142           75762 :   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          763865 :     AutoReentrantMonitor(ReentrantMonitor& aReentrantMonitor) : mReentrantMonitor(&aReentrantMonitor), mEnterCount(0)
        1159                 :     {
        1160          763865 :         Enter();
        1161          763865 :     }
        1162                 :
        1163          763865 :     ~AutoReentrantMonitor()
        1164                 :     {
        1165          763865 :         if (mEnterCount) {
        1166           98947 :             Exit();
        1167                 :         }
        1168          763865 :     }
        1169                 :
        1170          839627 :     void Enter()
        1171                 :     {
        1172          839627 :         mReentrantMonitor->Enter();
        1173          839627 :         ++mEnterCount;
        1174          839627 :     }
        1175                 :
        1176          839627 :     void Exit()
        1177                 :     {
        1178          839627 :         --mEnterCount;
        1179          839627 :         mReentrantMonitor->Exit();
        1180          839627 :     }
        1181                 :
        1182                 :     ReentrantMonitor* mReentrantMonitor;
        1183                 :     PRInt32 mEnterCount;
        1184                 : };
        1185                 :
        1186                 : NS_IMETHODIMP
        1187          111969 : 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          111969 :     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             278 :         return NS_ERROR_UNEXPECTED;
        1204                 :     }
        1205                 :
        1206          223382 :     AutoReentrantMonitor mon(mMon);
        1207                 :
        1208          111691 :     nsFactoryEntry* entry = mFactories.Get(aClass);
        1209          111691 :     if (!entry)
        1210               0 :         return NS_ERROR_FACTORY_NOT_REGISTERED;
        1211                 :
        1212          111691 :     if (entry->mServiceObject) {
        1213          209444 :         nsCOMPtr<nsISupports> supports = entry->mServiceObject;
        1214          104722 :         mon.Exit();
        1215          104722 :         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            6969 :     PRThread* currentPRThread = PR_GetCurrentThread();
        1222            6969 :     NS_ASSERTION(currentPRThread, "This should never be null!");
        1223                 :
        1224                 :     // Needed to optimize the event loop below.
        1225            6969 :     nsIThread* currentThread = nsnull;
        1226                 :
        1227                 :     PRThread* pendingPRThread;
        1228           13938 :     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            6969 :     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            6969 :     AddPendingService(aClass, currentPRThread);
        1262            6969 :     NS_ASSERTION(newInfo, "Failed to add info to the array!");
        1263                 :
        1264           13938 :     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            6969 :     mon.Exit();
        1269                 :
        1270            6969 :     nsresult rv = CreateInstance(aClass, nsnull, aIID, getter_AddRefs(service));
        1271                 :
        1272            6969 :     mon.Enter();
        1273                 :
        1274                 : #ifdef DEBUG
        1275            6969 :     pendingPRThread = GetPendingServiceThread(aClass);
        1276            6969 :     NS_ASSERTION(pendingPRThread == currentPRThread,
        1277                 :                  "Pending service array has been changed!");
        1278                 : #endif
        1279            6969 :     RemovePendingService(aClass);
        1280                 :
        1281            6969 :     if (NS_FAILED(rv))
        1282               1 :         return rv;
        1283                 :
        1284            6968 :     NS_ASSERTION(!entry->mServiceObject, "Created two instances of a service!");
        1285                 :
        1286            6968 :     entry->mServiceObject = service;
        1287            6968 :     *result = service.get();
        1288            6968 :     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            6968 :     NS_ADDREF(static_cast<nsISupports*>((*result)));
        1293            6968 :     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          671436 : 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          671436 :     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           19262 :         return NS_ERROR_UNEXPECTED;
        1394                 :     }
        1395                 :
        1396         1304348 :     AutoReentrantMonitor mon(mMon);
        1397                 :
        1398          652174 :     nsFactoryEntry *entry = mContractIDs.Get(nsDependentCString(aContractID));
        1399          652174 :     if (!entry)
        1400           23185 :         return NS_ERROR_FACTORY_NOT_REGISTERED;
        1401                 :
        1402          628989 :     if (entry->mServiceObject) {
        1403         1120392 :         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          560196 :         mon.Exit();
        1410          560196 :         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           68793 :     PRThread* currentPRThread = PR_GetCurrentThread();
        1417           68793 :     NS_ASSERTION(currentPRThread, "This should never be null!");
        1418                 :
        1419                 :     // Needed to optimize the event loop below.
        1420           68793 :     nsIThread* currentThread = nsnull;
        1421                 :
        1422                 :     PRThread* pendingPRThread;
        1423          137586 :     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           68793 :     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           68793 :     AddPendingService(*entry->mCIDEntry->cid, currentPRThread);
        1457           68793 :     NS_ASSERTION(newInfo, "Failed to add info to the array!");
        1458                 :
        1459          137586 :     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           68793 :     mon.Exit();
        1464                 :
        1465                 :     nsresult rv = CreateInstanceByContractID(aContractID, nsnull, aIID,
        1466           68793 :                                              getter_AddRefs(service));
        1467                 :
        1468           68793 :     mon.Enter();
        1469                 :
        1470                 : #ifdef DEBUG
        1471           68793 :     pendingPRThread = GetPendingServiceThread(*entry->mCIDEntry->cid);
        1472           68793 :     NS_ASSERTION(pendingPRThread == currentPRThread,
        1473                 :                  "Pending service array has been changed!");
        1474                 : #endif
        1475           68793 :     RemovePendingService(*entry->mCIDEntry->cid);
        1476                 :
        1477           68793 :     if (NS_FAILED(rv))
        1478            8252 :         return rv;
        1479                 :
        1480           60541 :     NS_ASSERTION(!entry->mServiceObject, "Created two instances of a service!");
        1481                 :
        1482           60541 :     entry->mServiceObject = service;
        1483           60541 :     *result = service.get();
        1484           60541 :     NS_ADDREF(static_cast<nsISupports*>(*result));
        1485           60541 :     return rv;
        1486                 : }
        1487                 :
        1488                 : already_AddRefed<mozilla::ModuleLoader>
        1489            2054 : nsComponentManagerImpl::LoaderForExtension(const nsACString& aExt)
        1490                 : {
        1491            4108 :     nsCOMPtr<mozilla::ModuleLoader> loader = mLoaderMap.Get(aExt);
        1492            2054 :     if (!loader) {
        1493                 :         loader = do_GetServiceFromCategory("module-loader",
        1494             754 :                                            PromiseFlatCString(aExt).get());
        1495             754 :         if (!loader)
        1496               0 :             return NULL;
        1497                 :
        1498             754 :         mLoaderMap.Put(aExt, loader);
        1499                 :     }
        1500                 :
        1501            2054 :     return loader.forget();
        1502                 : }
        1503                 :
        1504                 : NS_IMETHODIMP
        1505            3221 : nsComponentManagerImpl::RegisterFactory(const nsCID& aClass,
        1506                 :                                         const char* aName,
        1507                 :                                         const char* aContractID,
        1508                 :                                         nsIFactory* aFactory)
        1509                 : {
        1510            3221 :     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            6440 :     nsAutoPtr<nsFactoryEntry> f(new nsFactoryEntry(aClass, aFactory));
        1526                 :
        1527            6440 :     ReentrantMonitorAutoEnter mon(mMon);
        1528            3220 :     nsFactoryEntry* oldf = mFactories.Get(aClass);
        1529            3220 :     if (oldf)
        1530               0 :         return NS_ERROR_FACTORY_EXISTS;
        1531                 :
        1532            3220 :     if (aContractID)
        1533            3220 :         mContractIDs.Put(nsDependentCString(aContractID), f);
        1534                 :
        1535            3220 :     mFactories.Put(aClass, f.forget());
        1536                 :
        1537            3220 :     return NS_OK;
        1538                 : }
        1539                 :
        1540                 : NS_IMETHODIMP
        1541            2777 : 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            5554 :     nsCOMPtr<nsIFactory> dyingFactory;
        1547            5554 :     nsCOMPtr<nsISupports> dyingServiceObject;
        1548                 :
        1549                 :     {
        1550            5554 :         ReentrantMonitorAutoEnter mon(mMon);
        1551            2777 :         nsFactoryEntry* f = mFactories.Get(aClass);
        1552            2777 :         if (!f || f->mFactory != aFactory)
        1553               0 :             return NS_ERROR_FACTORY_NOT_REGISTERED;
        1554                 :
        1555            2777 :         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            2777 :         f->mFactory.swap(dyingFactory);
        1561            5554 :         f->mServiceObject.swap(dyingServiceObject);
        1562                 :     }
        1563                 :
        1564            2777 :     return NS_OK;
        1565                 : }
        1566                 :
        1567                 : NS_IMETHODIMP
        1568              31 : nsComponentManagerImpl::AutoRegister(nsIFile* aLocation)
        1569                 : {
        1570              62 :     nsCOMPtr<nsILocalFile> lf = do_QueryInterface(aLocation);
        1571              31 :     if (!lf)
        1572               0 :         return NS_ERROR_INVALID_ARG;
        1573                 :
        1574              31 :     XRE_AddManifestLocation(NS_COMPONENT_LOCATION, lf);
        1575              31 :     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               5 : nsComponentManagerImpl::IsCIDRegistered(const nsCID & aClass,
        1607                 :                                         bool *_retval)
        1608                 : {
        1609               5 :     *_retval = (nsnull != GetFactoryEntry(aClass));
        1610               5 :     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           53075 : nsComponentManagerImpl::ContractIDToCID(const char *aContractID,
        1682                 :                                         nsCID * *_retval)
        1683                 : {
        1684                 :     {
        1685          106150 :         ReentrantMonitorAutoEnter mon(mMon);
        1686           53075 :         nsFactoryEntry* entry = mContractIDs.Get(nsDependentCString(aContractID));
        1687           53075 :         if (entry) {
        1688           51511 :             *_retval = (nsCID*) NS_Alloc(sizeof(nsCID));
        1689           51511 :             **_retval = *entry->mCIDEntry->cid;
        1690           51511 :             return NS_OK;
        1691                 :         }
        1692                 :     }
        1693            1564 :     *_retval = NULL;
        1694            1564 :     return NS_ERROR_FACTORY_NOT_REGISTERED;
        1695                 : }
        1696                 :
        1697                 : ////////////////////////////////////////////////////////////////////////////////
        1698                 : // nsFactoryEntry
        1699                 : ////////////////////////////////////////////////////////////////////////////////
        1700                 :
        1701         1090665 : nsFactoryEntry::nsFactoryEntry(const mozilla::Module::CIDEntry* entry,
        1702                 :                                nsComponentManagerImpl::KnownModule* module)
        1703                 :     : mCIDEntry(entry)
        1704         1090665 :     , mModule(module)
        1705                 : {
        1706         1090665 : }
        1707                 :
        1708            3220 : nsFactoryEntry::nsFactoryEntry(const nsCID& aCID, nsIFactory* factory)
        1709                 :     : mCIDEntry(NULL)
        1710                 :     , mModule(NULL)
        1711            3220 :     , mFactory(factory)
        1712                 : {
        1713            3220 :     mozilla::Module::CIDEntry* e = new mozilla::Module::CIDEntry();
        1714            3220 :     nsCID* cid = new nsCID;
        1715            3220 :     *cid = aCID;
        1716            3220 :     e->cid = cid;
        1717            3220 :     mCIDEntry = e;
        1718            3220 : }
        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          576763 : nsFactoryEntry::GetFactory()
        1731                 : {
        1732          576763 :     if (!mFactory) {
        1733                 :         // RegisterFactory then UnregisterFactory can leave an entry in mContractIDs
        1734                 :         // pointing to an unusable nsFactoryEntry.
        1735           99511 :         if (!mModule)
        1736               0 :             return NULL;
        1737                 :
        1738           99511 :         if (!mModule->Load())
        1739               0 :             return NULL;
        1740                 :
        1741           99511 :         if (mModule->Module()->getFactoryProc) {
        1742            4206 :             mFactory = mModule->Module()->getFactoryProc(*mModule->Module(),
        1743            4206 :                                                          *mCIDEntry);
        1744                 :         }
        1745           97408 :         else if (mCIDEntry->getFactoryProc) {
        1746             147 :             mFactory = mCIDEntry->getFactoryProc(*mModule->Module(), *mCIDEntry);
        1747                 :         }
        1748                 :         else {
        1749           97261 :             NS_ASSERTION(mCIDEntry->constructorProc, "no getfactory or constructor");
        1750           97261 :             mFactory = new mozilla::GenericFactory(mCIDEntry->constructorProc);
        1751                 :         }
        1752           99511 :         if (!mFactory)
        1753               0 :             return NULL;
        1754                 :     }
        1755          576763 :     nsIFactory* factory = mFactory.get();
        1756          576763 :     NS_ADDREF(factory);
        1757          576763 :     return factory;
        1758                 : }
        1759                 :
        1760                 : ////////////////////////////////////////////////////////////////////////////////
        1761                 : // Static Access Functions
        1762                 : ////////////////////////////////////////////////////////////////////////////////
        1763                 :
        1764                 : nsresult
        1765          102743 : NS_GetComponentManager(nsIComponentManager* *result)
        1766                 : {
        1767          102743 :     if (!nsComponentManagerImpl::gComponentManager)
        1768               0 :         return NS_ERROR_NOT_INITIALIZED;
        1769                 :
        1770          102743 :     NS_ADDREF(*result = nsComponentManagerImpl::gComponentManager);
        1771          102743 :     return NS_OK;
        1772                 : }
        1773                 :
        1774                 : nsresult
        1775          184143 : NS_GetServiceManager(nsIServiceManager* *result)
        1776                 : {
        1777          184143 :     if (!nsComponentManagerImpl::gComponentManager)
        1778               0 :         return NS_ERROR_NOT_INITIALIZED;
        1779                 :
        1780          184143 :     NS_ADDREF(*result = nsComponentManagerImpl::gComponentManager);
        1781          184143 :     return NS_OK;
        1782                 : }
        1783                 :
        1784                 :
        1785                 : nsresult
        1786           47920 : NS_GetComponentRegistrar(nsIComponentRegistrar* *result)
        1787                 : {
        1788           47920 :     if (!nsComponentManagerImpl::gComponentManager)
        1789               0 :         return NS_ERROR_NOT_INITIALIZED;
        1790                 :
        1791           47920 :     NS_ADDREF(*result = nsComponentManagerImpl::gComponentManager);
        1792           47920 :     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            1495 : XRE_AddManifestLocation(NSLocationType aType, nsILocalFile* aLocation)
        1857                 : {
        1858            1495 :     nsComponentManagerImpl::InitializeModuleLocations();
        1859                 :     nsComponentManagerImpl::ComponentLocation* c =
        1860            1495 :         nsComponentManagerImpl::sModuleLocations->AppendElement();
        1861            1495 :     c->type = aType;
        1862            1495 :     c->location.Init(aLocation);
        1863                 :
        1864            1495 :     if (nsComponentManagerImpl::gComponentManager &&
        1865                 :         nsComponentManagerImpl::NORMAL == nsComponentManagerImpl::gComponentManager->mStatus)
        1866             130 :         nsComponentManagerImpl::gComponentManager->RegisterManifest(aType, c->location, false);
        1867                 :
        1868            1495 :     return NS_OK;
        1869                 : }
        1870                 :
        1871                 : EXPORT_XPCOM_API(nsresult)
        1872              97 : XRE_AddJarManifestLocation(NSLocationType aType, nsILocalFile* aLocation)
        1873                 : {
        1874              97 :     nsComponentManagerImpl::InitializeModuleLocations();
        1875                 :     nsComponentManagerImpl::ComponentLocation* c =
        1876              97 :         nsComponentManagerImpl::sModuleLocations->AppendElement();
        1877                 :
        1878              97 :     c->type = aType;
        1879              97 :     c->location.Init(aLocation, "chrome.manifest");
        1880                 :
        1881              97 :     if (nsComponentManagerImpl::gComponentManager &&
        1882                 :         nsComponentManagerImpl::NORMAL == nsComponentManagerImpl::gComponentManager->mStatus)
        1883              97 :         nsComponentManagerImpl::gComponentManager->RegisterManifest(aType, c->location, false);
        1884                 :
        1885              97 :     return NS_OK;
        1886                 : }
        1887                 :

Generated by: LCOV version 1.7