LCOV - code coverage report
Current view: directory - dom/base - nsScriptNameSpaceManager.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 331 201 60.7 %
Date: 2012-06-02 Functions: 27 20 74.1 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       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 Communicator client 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                 : #include "nsScriptNameSpaceManager.h"
      39                 : #include "nsCOMPtr.h"
      40                 : #include "nsIComponentManager.h"
      41                 : #include "nsIComponentRegistrar.h"
      42                 : #include "nsICategoryManager.h"
      43                 : #include "nsIServiceManager.h"
      44                 : #include "nsXPCOM.h"
      45                 : #include "nsISupportsPrimitives.h"
      46                 : #include "nsIScriptExternalNameSet.h"
      47                 : #include "nsIScriptNameSpaceManager.h"
      48                 : #include "nsIScriptContext.h"
      49                 : #include "nsIInterfaceInfoManager.h"
      50                 : #include "nsIInterfaceInfo.h"
      51                 : #include "xptinfo.h"
      52                 : #include "nsXPIDLString.h"
      53                 : #include "nsReadableUtils.h"
      54                 : #include "nsHashKeys.h"
      55                 : #include "nsDOMClassInfo.h"
      56                 : #include "nsCRT.h"
      57                 : #include "nsIObserverService.h"
      58                 : #include "mozilla/Services.h"
      59                 : 
      60                 : #define NS_INTERFACE_PREFIX "nsI"
      61                 : #define NS_DOM_INTERFACE_PREFIX "nsIDOM"
      62                 : 
      63                 : using namespace mozilla;
      64                 : 
      65                 : // Our extended PLDHashEntryHdr
      66                 : class GlobalNameMapEntry : public PLDHashEntryHdr
      67                 : {
      68                 : public:
      69                 :   // Our hash table ops don't care about the order of these members
      70                 :   nsString mKey;
      71                 :   nsGlobalNameStruct mGlobalName;
      72                 : };
      73                 : 
      74                 : 
      75                 : static PLDHashNumber
      76          429318 : GlobalNameHashHashKey(PLDHashTable *table, const void *key)
      77                 : {
      78          429318 :   const nsAString *str = static_cast<const nsAString *>(key);
      79          429318 :   return HashString(*str);
      80                 : }
      81                 : 
      82                 : static bool
      83          277542 : GlobalNameHashMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *entry,
      84                 :                          const void *key)
      85                 : {
      86                 :   const GlobalNameMapEntry *e =
      87          277542 :     static_cast<const GlobalNameMapEntry *>(entry);
      88          277542 :   const nsAString *str = static_cast<const nsAString *>(key);
      89                 : 
      90          277542 :   return str->Equals(e->mKey);
      91                 : }
      92                 : 
      93                 : static void
      94          151280 : GlobalNameHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
      95                 : {
      96          151280 :   GlobalNameMapEntry *e = static_cast<GlobalNameMapEntry *>(entry);
      97                 : 
      98                 :   // An entry is being cleared, let the key (nsString) do its own
      99                 :   // cleanup.
     100          151280 :   e->mKey.~nsString();
     101          151280 :   if (e->mGlobalName.mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
     102               0 :     nsIClassInfo* ci = GET_CLEAN_CI_PTR(e->mGlobalName.mData->mCachedClassInfo);
     103                 : 
     104                 :     // If we constructed an internal helper, we'll let the helper delete 
     105                 :     // the nsDOMClassInfoData structure, if not we do it here.
     106               0 :     if (!ci || e->mGlobalName.mData->u.mExternalConstructorFptr) {
     107               0 :       delete e->mGlobalName.mData;
     108                 :     }
     109                 : 
     110                 :     // Release our pointer to the helper.
     111               0 :     NS_IF_RELEASE(ci);
     112                 :   }
     113          151280 :   else if (e->mGlobalName.mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
     114             915 :     delete e->mGlobalName.mAlias;
     115                 :   }
     116                 : 
     117                 :   // This will set e->mGlobalName.mType to
     118                 :   // nsGlobalNameStruct::eTypeNotInitialized
     119          151280 :   memset(&e->mGlobalName, 0, sizeof(nsGlobalNameStruct));
     120          151280 : }
     121                 : 
     122                 : static bool
     123          151776 : GlobalNameHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry,
     124                 :                         const void *key)
     125                 : {
     126          151776 :   GlobalNameMapEntry *e = static_cast<GlobalNameMapEntry *>(entry);
     127          151776 :   const nsAString *keyStr = static_cast<const nsAString *>(key);
     128                 : 
     129                 :   // Initialize the key in the entry with placement new
     130          151776 :   new (&e->mKey) nsString(*keyStr);
     131                 : 
     132                 :   // This will set e->mGlobalName.mType to
     133                 :   // nsGlobalNameStruct::eTypeNotInitialized
     134          151776 :   memset(&e->mGlobalName, 0, sizeof(nsGlobalNameStruct));
     135          151776 :   return true;
     136                 : }
     137                 : 
     138            2833 : NS_IMPL_ISUPPORTS2(nsScriptNameSpaceManager,
     139                 :                    nsIObserver,
     140                 :                    nsISupportsWeakReference)
     141                 : 
     142             306 : nsScriptNameSpaceManager::nsScriptNameSpaceManager()
     143             306 :   : mIsInitialized(false)
     144                 : {
     145             306 :   MOZ_COUNT_CTOR(nsScriptNameSpaceManager);
     146             306 : }
     147                 : 
     148             915 : nsScriptNameSpaceManager::~nsScriptNameSpaceManager()
     149                 : {
     150             305 :   if (mIsInitialized) {
     151                 :     // Destroy the hash
     152             305 :     PL_DHashTableFinish(&mGlobalNames);
     153             305 :     PL_DHashTableFinish(&mNavigatorNames);
     154                 :   }
     155             305 :   MOZ_COUNT_DTOR(nsScriptNameSpaceManager);
     156            1220 : }
     157                 : 
     158                 : nsGlobalNameStruct *
     159          429318 : nsScriptNameSpaceManager::AddToHash(PLDHashTable *aTable, const char *aKey,
     160                 :                                     const PRUnichar **aClassName)
     161                 : {
     162          858636 :   NS_ConvertASCIItoUTF16 key(aKey);
     163                 :   GlobalNameMapEntry *entry =
     164                 :     static_cast<GlobalNameMapEntry *>
     165          429318 :                (PL_DHashTableOperate(aTable, &key, PL_DHASH_ADD));
     166                 : 
     167          429318 :   if (!entry) {
     168               0 :     return nsnull;
     169                 :   }
     170                 : 
     171          429318 :   if (aClassName) {
     172          115362 :     *aClassName = entry->mKey.get();
     173                 :   }
     174                 : 
     175          429318 :   return &entry->mGlobalName;
     176                 : }
     177                 : 
     178                 : nsGlobalNameStruct*
     179               0 : nsScriptNameSpaceManager::GetConstructorProto(const nsGlobalNameStruct* aStruct)
     180                 : {
     181               0 :   NS_ASSERTION(aStruct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias,
     182                 :                "This function only works on constructor aliases!");
     183               0 :   if (!aStruct->mAlias->mProto) {
     184                 :     GlobalNameMapEntry *proto =
     185                 :       static_cast<GlobalNameMapEntry *>
     186                 :                  (PL_DHashTableOperate(&mGlobalNames,
     187                 :                                           &aStruct->mAlias->mProtoName,
     188               0 :                                           PL_DHASH_LOOKUP));
     189                 : 
     190               0 :     if (PL_DHASH_ENTRY_IS_BUSY(proto)) {
     191               0 :       aStruct->mAlias->mProto = &proto->mGlobalName;
     192                 :     }
     193                 :   }
     194               0 :   return aStruct->mAlias->mProto;
     195                 : }
     196                 : 
     197                 : nsresult
     198            1836 : nsScriptNameSpaceManager::FillHash(nsICategoryManager *aCategoryManager,
     199                 :                                    const char *aCategory)
     200                 : {
     201            3672 :   nsCOMPtr<nsISimpleEnumerator> e;
     202                 :   nsresult rv = aCategoryManager->EnumerateCategory(aCategory,
     203            1836 :                                                     getter_AddRefs(e));
     204            1836 :   NS_ENSURE_SUCCESS(rv, rv);
     205                 : 
     206            3672 :   nsCOMPtr<nsISupports> entry;
     207            1836 :   while (NS_SUCCEEDED(e->GetNext(getter_AddRefs(entry)))) {
     208            3672 :     rv = AddCategoryEntryToHash(aCategoryManager, aCategory, entry);
     209            3672 :     if (NS_FAILED(rv)) {
     210               0 :       return rv;
     211                 :     }
     212                 :   }
     213                 : 
     214            1836 :   return NS_OK;
     215                 : }
     216                 : 
     217                 : 
     218                 : // This method enumerates over all installed interfaces (in .xpt
     219                 : // files) and finds ones that start with "nsIDOM" and has constants
     220                 : // defined in the interface itself (inherited constants doesn't
     221                 : // count), once such an interface is found the "nsIDOM" prefix is cut
     222                 : // off the name and the rest of the name is added into the hash for
     223                 : // global names. This makes things like 'Node.ELEMENT_NODE' work in
     224                 : // JS. See nsCommonWindowSH::GlobalResolve() for detais on how this is used.
     225                 : 
     226                 : nsresult
     227             306 : nsScriptNameSpaceManager::FillHashWithDOMInterfaces()
     228                 : {
     229                 :   nsCOMPtr<nsIInterfaceInfoManager>
     230             612 :     iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
     231             306 :   NS_ENSURE_TRUE(iim, NS_ERROR_UNEXPECTED);
     232                 : 
     233                 :   // First look for all interfaces whose name starts with nsIDOM
     234             612 :   nsCOMPtr<nsIEnumerator> domInterfaces;
     235                 :   nsresult rv =
     236             306 :     iim->EnumerateInterfacesWhoseNamesStartWith(NS_DOM_INTERFACE_PREFIX,
     237             306 :                                                 getter_AddRefs(domInterfaces));
     238             306 :   NS_ENSURE_SUCCESS(rv, rv);
     239                 : 
     240             612 :   nsCOMPtr<nsISupports> entry;
     241                 : 
     242             306 :   rv = domInterfaces->First();
     243                 : 
     244             306 :   if (NS_FAILED(rv)) {
     245                 :     // Empty interface list?
     246                 : 
     247               0 :     NS_WARNING("What, no nsIDOM interfaces installed?");
     248                 : 
     249               0 :     return NS_OK;
     250                 :   }
     251                 : 
     252                 :   bool found_old;
     253             612 :   nsCOMPtr<nsIInterfaceInfo> if_info;
     254             306 :   const char *if_name = nsnull;
     255                 :   const nsIID *iid;
     256                 : 
     257          130356 :   for ( ; domInterfaces->IsDone() == NS_ENUMERATOR_FALSE; domInterfaces->Next()) {
     258          130050 :     rv = domInterfaces->CurrentItem(getter_AddRefs(entry));
     259          130050 :     NS_ENSURE_SUCCESS(rv, rv);
     260                 : 
     261          260100 :     nsCOMPtr<nsIInterfaceInfo> if_info(do_QueryInterface(entry));
     262          130050 :     if_info->GetNameShared(&if_name);
     263          130050 :     if_info->GetIIDShared(&iid);
     264                 :     rv = RegisterInterface(if_name + sizeof(NS_DOM_INTERFACE_PREFIX) - 1,
     265          130050 :                            iid, &found_old);
     266                 : 
     267                 : #ifdef DEBUG
     268          130050 :     NS_ASSERTION(!found_old,
     269                 :                  "Whaaa, interface name already in hash!");
     270                 : #endif
     271                 :   }
     272                 : 
     273                 :   // Next, look for externally registered DOM interfaces
     274             306 :   rv = RegisterExternalInterfaces(false);
     275                 : 
     276             306 :   return rv;
     277                 : }
     278                 : 
     279                 : nsresult
     280             612 : nsScriptNameSpaceManager::RegisterExternalInterfaces(bool aAsProto)
     281                 : {
     282                 :   nsresult rv;
     283                 :   nsCOMPtr<nsICategoryManager> cm =
     284            1224 :     do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
     285             612 :   NS_ENSURE_SUCCESS(rv, rv);
     286                 : 
     287                 :   nsCOMPtr<nsIInterfaceInfoManager>
     288            1224 :     iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
     289             612 :   NS_ENSURE_TRUE(iim, NS_ERROR_NOT_AVAILABLE);
     290                 : 
     291            1224 :   nsCOMPtr<nsISimpleEnumerator> enumerator;
     292             612 :   rv = cm->EnumerateCategory(JAVASCRIPT_DOM_INTERFACE,
     293             612 :                              getter_AddRefs(enumerator));
     294             612 :   NS_ENSURE_SUCCESS(rv, rv);
     295                 : 
     296            1224 :   nsXPIDLCString IID_string;
     297            1224 :   nsCAutoString category_entry;
     298                 :   const char* if_name;
     299            1224 :   nsCOMPtr<nsISupports> entry;
     300            1224 :   nsCOMPtr<nsIInterfaceInfo> if_info;
     301                 :   bool found_old, dom_prefix;
     302                 : 
     303            1224 :   while (NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(entry)))) {
     304               0 :     nsCOMPtr<nsISupportsCString> category(do_QueryInterface(entry));
     305                 : 
     306               0 :     if (!category) {
     307               0 :       NS_WARNING("Category entry not an nsISupportsCString!");
     308                 : 
     309               0 :       continue;
     310                 :     }
     311                 : 
     312               0 :     rv = category->GetData(category_entry);
     313               0 :     NS_ENSURE_SUCCESS(rv, rv);
     314                 : 
     315               0 :     rv = cm->GetCategoryEntry(JAVASCRIPT_DOM_INTERFACE, category_entry.get(),
     316               0 :                               getter_Copies(IID_string));
     317               0 :     NS_ENSURE_SUCCESS(rv, rv);
     318                 : 
     319                 :     nsIID primary_IID;
     320               0 :     if (!primary_IID.Parse(IID_string) ||
     321               0 :         primary_IID.Equals(NS_GET_IID(nsISupports))) {
     322               0 :       NS_ERROR("Invalid IID registered with the script namespace manager!");
     323               0 :       continue;
     324                 :     }
     325                 : 
     326               0 :     iim->GetInfoForIID(&primary_IID, getter_AddRefs(if_info));
     327                 : 
     328               0 :     while (if_info) {
     329                 :       const nsIID *iid;
     330               0 :       if_info->GetIIDShared(&iid);
     331               0 :       NS_ENSURE_TRUE(iid, NS_ERROR_UNEXPECTED);
     332                 : 
     333               0 :       if (iid->Equals(NS_GET_IID(nsISupports))) {
     334               0 :         break;
     335                 :       }
     336                 : 
     337               0 :       if_info->GetNameShared(&if_name);
     338                 :       dom_prefix = (strncmp(if_name, NS_DOM_INTERFACE_PREFIX,
     339               0 :                             sizeof(NS_DOM_INTERFACE_PREFIX) - 1) == 0);
     340                 : 
     341                 :       const char* name;
     342               0 :       if (dom_prefix) {
     343               0 :         if (!aAsProto) {
     344                 :           // nsIDOM* interfaces have already been registered.
     345               0 :           break;
     346                 :         }
     347               0 :         name = if_name + sizeof(NS_DOM_INTERFACE_PREFIX) - 1;
     348                 :       } else {
     349               0 :         name = if_name + sizeof(NS_INTERFACE_PREFIX) - 1;
     350                 :       }
     351                 : 
     352               0 :       if (aAsProto) {
     353               0 :         RegisterClassProto(name, iid, &found_old);
     354                 :       } else {
     355               0 :         RegisterInterface(name, iid, &found_old);
     356                 :       }
     357                 : 
     358               0 :       if (found_old) {
     359               0 :         break;
     360                 :       }
     361                 : 
     362               0 :       nsCOMPtr<nsIInterfaceInfo> tmp(if_info);
     363               0 :       tmp->GetParent(getter_AddRefs(if_info));
     364                 :     }
     365                 :   }
     366                 : 
     367             612 :   return NS_OK;
     368                 : }
     369                 : 
     370                 : nsresult
     371          130050 : nsScriptNameSpaceManager::RegisterInterface(const char* aIfName,
     372                 :                                             const nsIID *aIfIID,
     373                 :                                             bool* aFoundOld)
     374                 : {
     375          130050 :   *aFoundOld = false;
     376                 : 
     377          130050 :   nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aIfName);
     378          130050 :   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
     379                 : 
     380          130050 :   if (s->mType != nsGlobalNameStruct::eTypeNotInitialized) {
     381               0 :     *aFoundOld = true;
     382                 : 
     383               0 :     return NS_OK;
     384                 :   }
     385                 : 
     386          130050 :   s->mType = nsGlobalNameStruct::eTypeInterface;
     387          130050 :   s->mIID = *aIfIID;
     388                 : 
     389          130050 :   return NS_OK;
     390                 : }
     391                 : 
     392                 : #define GLOBALNAME_HASHTABLE_INITIAL_SIZE       1024
     393                 : 
     394                 : nsresult
     395             306 : nsScriptNameSpaceManager::Init()
     396                 : {
     397                 :   static PLDHashTableOps hash_table_ops =
     398                 :   {
     399                 :     PL_DHashAllocTable,
     400                 :     PL_DHashFreeTable,
     401                 :     GlobalNameHashHashKey,
     402                 :     GlobalNameHashMatchEntry,
     403                 :     PL_DHashMoveEntryStub,
     404                 :     GlobalNameHashClearEntry,
     405                 :     PL_DHashFinalizeStub,
     406                 :     GlobalNameHashInitEntry
     407                 :   };
     408                 : 
     409                 :   mIsInitialized = PL_DHashTableInit(&mGlobalNames, &hash_table_ops, nsnull,
     410                 :                                      sizeof(GlobalNameMapEntry), 
     411             306 :                                      GLOBALNAME_HASHTABLE_INITIAL_SIZE);
     412             306 :   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_OUT_OF_MEMORY);
     413                 : 
     414                 :   mIsInitialized = PL_DHashTableInit(&mNavigatorNames, &hash_table_ops, nsnull,
     415                 :                                      sizeof(GlobalNameMapEntry), 
     416             306 :                                      GLOBALNAME_HASHTABLE_INITIAL_SIZE);
     417             306 :   if (!mIsInitialized) {
     418               0 :     PL_DHashTableFinish(&mGlobalNames);
     419                 : 
     420               0 :     return NS_ERROR_OUT_OF_MEMORY;
     421                 :   }
     422                 : 
     423             306 :   nsresult rv = NS_OK;
     424                 : 
     425             306 :   rv = FillHashWithDOMInterfaces();
     426             306 :   NS_ENSURE_SUCCESS(rv, rv);
     427                 : 
     428                 :   nsCOMPtr<nsICategoryManager> cm =
     429             612 :     do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
     430             306 :   NS_ENSURE_SUCCESS(rv, rv);
     431                 : 
     432             306 :   rv = FillHash(cm, JAVASCRIPT_GLOBAL_CONSTRUCTOR_CATEGORY);
     433             306 :   NS_ENSURE_SUCCESS(rv, rv);
     434                 : 
     435             306 :   rv = FillHash(cm, JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY);
     436             306 :   NS_ENSURE_SUCCESS(rv, rv);
     437                 : 
     438             306 :   rv = FillHash(cm, JAVASCRIPT_GLOBAL_PRIVILEGED_PROPERTY_CATEGORY);
     439             306 :   NS_ENSURE_SUCCESS(rv, rv);
     440                 : 
     441             306 :   rv = FillHash(cm, JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY);
     442             306 :   NS_ENSURE_SUCCESS(rv, rv);
     443                 : 
     444             306 :   rv = FillHash(cm, JAVASCRIPT_GLOBAL_DYNAMIC_NAMESET_CATEGORY);
     445             306 :   NS_ENSURE_SUCCESS(rv, rv);
     446                 : 
     447             306 :   rv = FillHash(cm, JAVASCRIPT_NAVIGATOR_PROPERTY_CATEGORY);
     448             306 :   NS_ENSURE_SUCCESS(rv, rv);
     449                 : 
     450                 :   // Initial filling of the has table has been done.
     451                 :   // Now, listen for changes.
     452                 :   nsCOMPtr<nsIObserverService> serv = 
     453             612 :     mozilla::services::GetObserverService();
     454                 : 
     455             306 :   if (serv) {
     456             306 :     serv->AddObserver(this, NS_XPCOM_CATEGORY_ENTRY_ADDED_OBSERVER_ID, true);
     457                 :   }
     458                 : 
     459             306 :   return NS_OK;
     460                 : }
     461                 : 
     462                 : struct NameSetClosure {
     463                 :   nsIScriptContext* ctx;
     464                 :   nsresult rv;
     465                 : };
     466                 : 
     467                 : static PLDHashOperator
     468               0 : NameSetInitCallback(PLDHashTable *table, PLDHashEntryHdr *hdr,
     469                 :                     PRUint32 number, void *arg)
     470                 : {
     471               0 :   GlobalNameMapEntry *entry = static_cast<GlobalNameMapEntry *>(hdr);
     472                 : 
     473               0 :   if (entry->mGlobalName.mType == nsGlobalNameStruct::eTypeStaticNameSet) {
     474               0 :     nsresult rv = NS_OK;
     475                 :     nsCOMPtr<nsIScriptExternalNameSet> ns =
     476               0 :       do_CreateInstance(entry->mGlobalName.mCID, &rv);
     477               0 :     NS_ENSURE_SUCCESS(rv, PL_DHASH_NEXT);
     478                 : 
     479               0 :     NameSetClosure *closure = static_cast<NameSetClosure *>(arg);
     480               0 :     closure->rv = ns->InitializeNameSet(closure->ctx);
     481               0 :     if (NS_FAILED(closure->rv)) {
     482               0 :       NS_ERROR("Initing external script classes failed!");
     483               0 :       return PL_DHASH_STOP;
     484                 :     }
     485                 :   }
     486                 : 
     487               0 :   return PL_DHASH_NEXT;
     488                 : }
     489                 : 
     490                 : nsresult
     491               0 : nsScriptNameSpaceManager::InitForContext(nsIScriptContext *aContext)
     492                 : {
     493                 :   NameSetClosure closure;
     494               0 :   closure.ctx = aContext;
     495               0 :   closure.rv = NS_OK;
     496               0 :   PL_DHashTableEnumerate(&mGlobalNames, NameSetInitCallback, &closure);
     497                 : 
     498               0 :   return closure.rv;
     499                 : }
     500                 : 
     501                 : nsresult
     502               0 : nsScriptNameSpaceManager::LookupName(const nsAString& aName,
     503                 :                                      const nsGlobalNameStruct **aNameStruct,
     504                 :                                      const PRUnichar **aClassName)
     505                 : {
     506                 :   GlobalNameMapEntry *entry =
     507                 :     static_cast<GlobalNameMapEntry *>
     508                 :                (PL_DHashTableOperate(&mGlobalNames, &aName,
     509               0 :                                         PL_DHASH_LOOKUP));
     510                 : 
     511               0 :   if (PL_DHASH_ENTRY_IS_BUSY(entry) &&
     512               0 :       !((&entry->mGlobalName)->mDisabled)) {
     513               0 :     *aNameStruct = &entry->mGlobalName;
     514               0 :     if (aClassName) {
     515               0 :       *aClassName = entry->mKey.get();
     516                 :     }
     517                 :   } else {
     518               0 :     *aNameStruct = nsnull;
     519               0 :     if (aClassName) {
     520               0 :       *aClassName = nsnull;
     521                 :     }
     522                 :   }
     523                 : 
     524               0 :   return NS_OK;
     525                 : }
     526                 : 
     527                 : nsresult
     528               0 : nsScriptNameSpaceManager::LookupNavigatorName(const nsAString& aName,
     529                 :                                               const nsGlobalNameStruct **aNameStruct)
     530                 : {
     531                 :   GlobalNameMapEntry *entry =
     532                 :     static_cast<GlobalNameMapEntry *>
     533                 :                (PL_DHashTableOperate(&mNavigatorNames, &aName,
     534               0 :                                      PL_DHASH_LOOKUP));
     535                 : 
     536               0 :   if (PL_DHASH_ENTRY_IS_BUSY(entry) &&
     537               0 :       !((&entry->mGlobalName)->mDisabled)) {
     538               0 :     *aNameStruct = &entry->mGlobalName;
     539                 :   } else {
     540               0 :     *aNameStruct = nsnull;
     541                 :   }
     542                 : 
     543               0 :   return NS_OK;
     544                 : }
     545                 : 
     546                 : nsresult
     547          115362 : nsScriptNameSpaceManager::RegisterClassName(const char *aClassName,
     548                 :                                             PRInt32 aDOMClassInfoID,
     549                 :                                             bool aPrivileged,
     550                 :                                             bool aDisabled,
     551                 :                                             const PRUnichar **aResult)
     552                 : {
     553          115362 :   if (!nsCRT::IsAscii(aClassName)) {
     554               0 :     NS_ERROR("Trying to register a non-ASCII class name");
     555               0 :     return NS_OK;
     556                 :   }
     557          115362 :   nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aClassName, aResult);
     558          115362 :   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
     559                 : 
     560          115362 :   if (s->mType == nsGlobalNameStruct::eTypeClassConstructor) {
     561             612 :     return NS_OK;
     562                 :   }
     563                 : 
     564                 :   // If a external constructor is already defined with aClassName we
     565                 :   // won't overwrite it.
     566                 : 
     567          114750 :   if (s->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
     568               0 :     return NS_OK;
     569                 :   }
     570                 : 
     571          114750 :   NS_ASSERTION(s->mType == nsGlobalNameStruct::eTypeNotInitialized ||
     572                 :                s->mType == nsGlobalNameStruct::eTypeInterface,
     573                 :                "Whaaa, JS environment name clash!");
     574                 : 
     575          114750 :   s->mType = nsGlobalNameStruct::eTypeClassConstructor;
     576          114750 :   s->mDOMClassInfoID = aDOMClassInfoID;
     577          114750 :   s->mChromeOnly = aPrivileged;
     578          114750 :   s->mDisabled = aDisabled;
     579                 : 
     580          114750 :   return NS_OK;
     581                 : }
     582                 : 
     583                 : nsresult
     584          180234 : nsScriptNameSpaceManager::RegisterClassProto(const char *aClassName,
     585                 :                                              const nsIID *aConstructorProtoIID,
     586                 :                                              bool *aFoundOld)
     587                 : {
     588          180234 :   NS_ENSURE_ARG_POINTER(aConstructorProtoIID);
     589                 : 
     590          180234 :   *aFoundOld = false;
     591                 : 
     592          180234 :   nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aClassName);
     593          180234 :   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
     594                 : 
     595          180234 :   if (s->mType != nsGlobalNameStruct::eTypeNotInitialized &&
     596                 :       s->mType != nsGlobalNameStruct::eTypeInterface) {
     597          172584 :     *aFoundOld = true;
     598                 : 
     599          172584 :     return NS_OK;
     600                 :   }
     601                 : 
     602            7650 :   s->mType = nsGlobalNameStruct::eTypeClassProto;
     603            7650 :   s->mIID = *aConstructorProtoIID;
     604                 : 
     605            7650 :   return NS_OK;
     606                 : }
     607                 : 
     608                 : nsresult
     609               0 : nsScriptNameSpaceManager::RegisterExternalClassName(const char *aClassName,
     610                 :                                                     nsCID& aCID)
     611                 : {
     612               0 :   nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aClassName);
     613               0 :   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
     614                 : 
     615                 :   // If an external constructor is already defined with aClassName we
     616                 :   // won't overwrite it.
     617                 : 
     618               0 :   if (s->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
     619               0 :     return NS_OK;
     620                 :   }
     621                 : 
     622               0 :   NS_ASSERTION(s->mType == nsGlobalNameStruct::eTypeNotInitialized ||
     623                 :                s->mType == nsGlobalNameStruct::eTypeInterface,
     624                 :                "Whaaa, JS environment name clash!");
     625                 : 
     626               0 :   s->mType = nsGlobalNameStruct::eTypeExternalClassInfoCreator;
     627               0 :   s->mCID = aCID;
     628                 : 
     629               0 :   return NS_OK;
     630                 : }
     631                 : 
     632                 : nsresult
     633               0 : nsScriptNameSpaceManager::RegisterDOMCIData(const char *aName,
     634                 :                                             nsDOMClassInfoExternalConstructorFnc aConstructorFptr,
     635                 :                                             const nsIID *aProtoChainInterface,
     636                 :                                             const nsIID **aInterfaces,
     637                 :                                             PRUint32 aScriptableFlags,
     638                 :                                             bool aHasClassInterface,
     639                 :                                             const nsCID *aConstructorCID)
     640                 : {
     641                 :   const PRUnichar* className;
     642               0 :   nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aName, &className);
     643               0 :   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
     644                 : 
     645                 :   // If an external constructor is already defined with aClassName we
     646                 :   // won't overwrite it.
     647                 : 
     648               0 :   if (s->mType == nsGlobalNameStruct::eTypeClassConstructor ||
     649                 :       s->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
     650               0 :     return NS_OK;
     651                 :   }
     652                 : 
     653                 :   // XXX Should we bail out here?
     654               0 :   NS_ASSERTION(s->mType == nsGlobalNameStruct::eTypeNotInitialized ||
     655                 :                s->mType == nsGlobalNameStruct::eTypeExternalClassInfoCreator,
     656                 :                "Someone tries to register classinfo data for a class that isn't new or external!");
     657                 : 
     658               0 :   s->mData = new nsExternalDOMClassInfoData;
     659               0 :   NS_ENSURE_TRUE(s->mData, NS_ERROR_OUT_OF_MEMORY);
     660                 : 
     661               0 :   s->mType = nsGlobalNameStruct::eTypeExternalClassInfo;
     662               0 :   s->mData->mName = aName;
     663               0 :   s->mData->mNameUTF16 = className;
     664               0 :   if (aConstructorFptr)
     665               0 :     s->mData->u.mExternalConstructorFptr = aConstructorFptr;
     666                 :   else
     667                 :     // null constructor will cause us to use nsDOMGenericSH::doCreate
     668               0 :     s->mData->u.mExternalConstructorFptr = nsnull;
     669               0 :   s->mData->mCachedClassInfo = nsnull;
     670               0 :   s->mData->mProtoChainInterface = aProtoChainInterface;
     671               0 :   s->mData->mInterfaces = aInterfaces;
     672               0 :   s->mData->mScriptableFlags = aScriptableFlags;
     673               0 :   s->mData->mHasClassInterface = aHasClassInterface;
     674               0 :   s->mData->mConstructorCID = aConstructorCID;
     675                 : 
     676               0 :   return NS_OK;
     677                 : }
     678                 : 
     679                 : nsresult
     680            3835 : nsScriptNameSpaceManager::AddCategoryEntryToHash(nsICategoryManager* aCategoryManager,
     681                 :                                                  const char* aCategory,
     682                 :                                                  nsISupports* aEntry)
     683                 : {
     684                 :   // Get the type from the category name.
     685                 :   // NOTE: we could have passed the type in FillHash() and guessed it in
     686                 :   // Observe() but this way, we have only one place to update and this is
     687                 :   // not performance sensitive.
     688                 :   nsGlobalNameStruct::nametype type;
     689            3835 :   if (strcmp(aCategory, JAVASCRIPT_GLOBAL_CONSTRUCTOR_CATEGORY) == 0) {
     690            1530 :     type = nsGlobalNameStruct::eTypeExternalConstructor;
     691            3692 :   } else if (strcmp(aCategory, JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY) == 0 ||
     692            1387 :              strcmp(aCategory, JAVASCRIPT_GLOBAL_PRIVILEGED_PROPERTY_CATEGORY) == 0) {
     693            1224 :     type = nsGlobalNameStruct::eTypeProperty;
     694            1081 :   } else if (strcmp(aCategory, JAVASCRIPT_NAVIGATOR_PROPERTY_CATEGORY) == 0) {
     695             612 :     type = nsGlobalNameStruct::eTypeNavigatorProperty;
     696             469 :   } else if (strcmp(aCategory, JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY) == 0) {
     697             306 :     type = nsGlobalNameStruct::eTypeStaticNameSet;
     698             163 :   } else if (strcmp(aCategory, JAVASCRIPT_GLOBAL_DYNAMIC_NAMESET_CATEGORY) == 0) {
     699               0 :     type = nsGlobalNameStruct::eTypeDynamicNameSet;
     700                 :   } else {
     701             163 :     return NS_OK;
     702                 :   }
     703                 : 
     704            7344 :   nsCOMPtr<nsISupportsCString> strWrapper = do_QueryInterface(aEntry);
     705                 : 
     706            3672 :   if (!strWrapper) {
     707               0 :     NS_WARNING("Category entry not an nsISupportsCString!");
     708               0 :     return NS_OK;
     709                 :   }
     710                 : 
     711            7344 :   nsCAutoString categoryEntry;
     712            3672 :   nsresult rv = strWrapper->GetData(categoryEntry);
     713            3672 :   NS_ENSURE_SUCCESS(rv, rv);
     714                 : 
     715            7344 :   nsXPIDLCString contractId;
     716                 :   rv = aCategoryManager->GetCategoryEntry(aCategory, categoryEntry.get(),
     717            3672 :                                           getter_Copies(contractId));
     718            3672 :   NS_ENSURE_SUCCESS(rv, rv);
     719                 : 
     720            7344 :   nsCOMPtr<nsIComponentRegistrar> registrar;
     721            3672 :   rv = NS_GetComponentRegistrar(getter_AddRefs(registrar));
     722            3672 :   NS_ENSURE_SUCCESS(rv, rv);
     723                 : 
     724                 :   nsCID *cidPtr;
     725            3672 :   rv = registrar->ContractIDToCID(contractId, &cidPtr);
     726                 : 
     727            3672 :   if (NS_FAILED(rv)) {
     728               0 :     NS_WARNING("Bad contract id registed with the script namespace manager");
     729               0 :     return NS_OK;
     730                 :   }
     731                 : 
     732                 :   // Copy CID onto the stack, so we can free it right away and avoid having
     733                 :   // to add cleanup code at every exit point from this function.
     734            3672 :   nsCID cid = *cidPtr;
     735            3672 :   nsMemory::Free(cidPtr);
     736                 : 
     737            3672 :   if (type == nsGlobalNameStruct::eTypeExternalConstructor) {
     738            3060 :     nsXPIDLCString constructorProto;
     739                 :     rv = aCategoryManager->GetCategoryEntry(JAVASCRIPT_GLOBAL_CONSTRUCTOR_PROTO_ALIAS_CATEGORY,
     740                 :                                             categoryEntry.get(),
     741            1530 :                                             getter_Copies(constructorProto));
     742            1530 :     if (NS_SUCCEEDED(rv)) {
     743             918 :       nsGlobalNameStruct *s = AddToHash(&mGlobalNames, categoryEntry.get());
     744             918 :       NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
     745                 : 
     746             918 :       if (s->mType == nsGlobalNameStruct::eTypeNotInitialized) {
     747             918 :         s->mAlias = new nsGlobalNameStruct::ConstructorAlias;
     748             918 :         s->mType = nsGlobalNameStruct::eTypeExternalConstructorAlias;
     749             918 :         s->mChromeOnly = false;
     750             918 :         s->mAlias->mCID = cid;
     751             918 :         AppendASCIItoUTF16(constructorProto, s->mAlias->mProtoName);
     752             918 :         s->mAlias->mProto = nsnull;
     753                 :       } else {
     754               0 :         NS_WARNING("Global script name not overwritten!");
     755                 :       }
     756                 : 
     757             918 :       return NS_OK;
     758                 :     }
     759                 :   }
     760                 : 
     761                 :   PLDHashTable *table;
     762            2754 :   if (type == nsGlobalNameStruct::eTypeNavigatorProperty) {
     763             612 :     table = &mNavigatorNames;
     764                 :   } else {
     765            2142 :     table = &mGlobalNames;
     766                 :   }
     767                 : 
     768            2754 :   nsGlobalNameStruct *s = AddToHash(table, categoryEntry.get());
     769            2754 :   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
     770                 : 
     771            2754 :   if (s->mType == nsGlobalNameStruct::eTypeNotInitialized) {
     772            2754 :     s->mType = type;
     773            2754 :     s->mCID = cid;
     774                 :     s->mChromeOnly =
     775            2754 :       strcmp(aCategory, JAVASCRIPT_GLOBAL_PRIVILEGED_PROPERTY_CATEGORY) == 0;
     776                 :   } else {
     777               0 :     NS_WARNING("Global script name not overwritten!");
     778                 :   }
     779                 : 
     780            2754 :   return NS_OK;
     781                 : }
     782                 : 
     783                 : NS_IMETHODIMP
     784             163 : nsScriptNameSpaceManager::Observe(nsISupports* aSubject, const char* aTopic,
     785                 :                                   const PRUnichar* aData)
     786                 : {
     787             163 :   if (!aData) {
     788               0 :     return NS_OK;
     789                 :   }
     790                 : 
     791             163 :   if (strcmp(aTopic, NS_XPCOM_CATEGORY_ENTRY_ADDED_OBSERVER_ID) == 0) {
     792                 :     nsCOMPtr<nsICategoryManager> cm =
     793             326 :       do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
     794             163 :     if (!cm) {
     795               0 :       return NS_OK;
     796                 :     }
     797                 : 
     798             163 :     return AddCategoryEntryToHash(cm, NS_ConvertUTF16toUTF8(aData).get(),
     799             163 :                                   aSubject);
     800                 :   }
     801                 : 
     802                 :   // TODO: we could observe NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID
     803                 :   // and NS_XPCOM_CATEGORY_CLEARED_OBSERVER_ID but we are safe without it.
     804                 :   // See bug 600460.
     805                 : 
     806               0 :   return NS_OK;
     807                 : }
     808                 : 

Generated by: LCOV version 1.7