- NS_ERROR_FACTORY_REGISTER_AGAIN for deferring registration of a module until

later in the autoreg cycle.
- teach native component loader about deferred components
- add nsIComponentLoader::registerDeferredComponents
- teach component manager about deferred components
- made nsID::Parse take a |const char *| instead of a simple |char *|.
- move release of XPTI singletons until _after_ shutting down the component
  manager to prevent re-initialization during JS component shutdown.
- category manager work: really delete from reg, start on enumeration
- use nsXPIDLCString instead of autoStringFree.
- fix nsRegistry to use allocator properly.
- cleaner memory management in nsFactoryEntry.
- capitalization fixed in nsIComponentLoader.idl
- clean up loader creation logic
- remove/disable lots of DEBUG_shaver noise
- added (disabled) warning about NSGetFactory usage
- move .so and .shlb higher up in the ValidDllExtensions list to marginally
  speed up registration.
- added nsDll::GetRegistryLocation API
- properly export nsSupportsArray.h
- capitalization fixes in nsIEnumerator.idl
- added deferral to nsSample.js
This commit is contained in:
shaver%netscape.com 1999-11-10 00:28:34 +00:00
Родитель d42626379d
Коммит c73533acb7
21 изменённых файлов: 266 добавлений и 255 удалений

Просмотреть файл

@ -27,6 +27,8 @@
#include "prmem.h"
#include "prlock.h"
#include "prlog.h"
#include "nsCRT.h"
#include "nsAllocator.h"
/* extra locking for the paranoid */
/* #define EXTRA_THREADSAFE */
@ -306,18 +308,6 @@ static void reginfo2Length( const REGINFO &in, PRUint32 &out ) {
}
}
/*-------------------------------- PR_strdup -----------------------------------
| Utility function that does PR_Malloc and copies argument string. Caller |
| must do PR_Free. |
------------------------------------------------------------------------------*/
static char *PR_strdup( const char *in ) {
char *result = (char*)PR_Malloc( strlen( in ) + 1 );
if ( result ) {
strcpy( result, in );
}
return result;
}
/*------------------------ nsISupports Implementation --------------------------
| This code generates the implementation of the nsISupports member functions |
| for each class implemented in this file. |
@ -525,12 +515,8 @@ NS_IMETHODIMP nsRegistry::GetString( nsRegistryKey baseKey, const char *path, ch
if ( err == REGERR_OK )
{
// Allocate buffer for return value
PRUint32 vallen = PL_strlen(regStr);
*result = (char*)PR_Malloc( vallen + 1 );
if (*result)
PL_strcpy(*result, regStr);
else
*result = nsCRT::strdup(regStr);
if (!*result)
rv = NS_ERROR_OUT_OF_MEMORY;
}
else if ( err == REGERR_BUFTOOSMALL )
@ -541,7 +527,7 @@ NS_IMETHODIMP nsRegistry::GetString( nsRegistryKey baseKey, const char *path, ch
// See if that worked.
if( rv == NS_OK )
{
*result =(char*)PR_Malloc( length + 1 );
*result =(char*)nsAllocator::Alloc( length + 1 );
if( *result )
{
// Get string from registry into result buffer.
@ -554,7 +540,7 @@ NS_IMETHODIMP nsRegistry::GetString( nsRegistryKey baseKey, const char *path, ch
if ( rv != NS_OK )
{
// Didn't get result, free buffer
PR_Free( *result );
nsCRT::free( *result );
*result = 0;
}
}
@ -1173,7 +1159,7 @@ nsRegistryNode::~nsRegistryNode()
NS_IMETHODIMP nsRegistryNode::GetName( char **result ) {
if (result == NULL) return NS_ERROR_NULL_POINTER;
// Make sure there is a place to put the result.
*result = PR_strdup( mName );
*result = nsCRT::strdup( mName );
if ( !*result ) return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
@ -1223,7 +1209,7 @@ NS_IMETHODIMP nsRegistryValue::GetName( char **result ) {
rv = getInfo();
if( rv == NS_OK || rv == NS_ERROR_REG_NO_MORE ) {
// worked, return actual result.
*result = PR_strdup( mName );
*result = nsCRT::strdup( mName );
if ( *result ) {
rv = NS_OK;
} else {

Просмотреть файл

@ -172,6 +172,9 @@ typedef PRUint32 nsresult;
/* Returned when a class is not registered */
#define NS_ERROR_FACTORY_NOT_REGISTERED ((nsresult) 0x80040154L)
/* Returned when a class cannot be registered, but may be tried again later */
#define NS_ERROR_FACTORY_REGISTER_AGAIN ((nsresult) 0x80040155L)
/* Returned when a dynamically loaded factory couldn't be found */
#define NS_ERROR_FACTORY_NOT_LOADED ((nsresult) 0x800401f8L)

Просмотреть файл

@ -34,7 +34,7 @@ static const char gIDFormat2[] =
* an nsID
*/
NS_COM PRBool nsID::Parse(char *aIDStr)
NS_COM PRBool nsID::Parse(const char *aIDStr)
{
PRInt32 count = 0;
PRInt32 n1, n2, n3[8];

Просмотреть файл

@ -71,7 +71,7 @@ struct nsID {
* nsID Parsing method. Turns a {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
* string into an nsID
*/
NS_COM PRBool Parse(char *aIDStr);
NS_COM PRBool Parse(const char *aIDStr);
/**
* nsID string encoder. Returns an allocated string in

Просмотреть файл

@ -543,6 +543,12 @@ nsresult NS_COM NS_ShutdownXPCOM(nsIServiceManager* servMgr)
NS_ASSERTION(NS_SUCCEEDED(rv), "Component Manager shutdown failed.");
#endif
// Release our own singletons
// Do this _after_ shutting down the component manager, because the
// JS component loader will use XPConnect to call nsIModule::canUnload,
// and that will spin up the InterfaceInfoManager again -- bad mojo
XPTI_FreeInterfaceInfoManager();
// Finally, release the component manager last because it unloads the
// libraries:
NS_RELEASE2(nsComponentManagerImpl::gComponentManager, cnt);

Просмотреть файл

@ -87,10 +87,9 @@ proto.addCategoryEntry = function (category, entry, value, persist, replace) {
function deleteEntryFromRegistry(category, entry)
{
dump("(not) deleting " + category + "[" + entry + "] from reg\n");
try {
var categorySubtree = registry.getSubtreeRaw(categoriesKey, category);
/* registry.deleteValue(categorySubtree, entry); */
registry.deleteValue(categorySubtree, entry);
} catch (e :
e instanceof Components.interfaces.nsIXPCException &&
e.result === 0x80510003 /* XXX NS_ERROR_REG_NOT_FOUND */) {
@ -124,18 +123,14 @@ function deleteCategoryFromRegistry(category) {
proto.deleteCategory = function (category, persist) {
delete this.categories[category];
/*
* Don't check for delete success, because persist means to remove from
* registry, even if someone has already done a non-persistent removal
* before.
* Don't check for delete success above, because persist means to
* remove from registry, even if someone has already done a
* non-persistent removal before.
*/
if (persist)
deleteCategoryFromRegistry(category);
};
function CategoryEnumerator(category) {
this.category = category;
};
proto.enumerateCategory = function (category) {
return new CategoryEnumerator(this.categories[category] || { });
}
@ -235,6 +230,29 @@ proto.loadRegistryData = function() {
}
}
function CategoryEnumerator(category) {
this.contents = contents = [];
for (var i in category.table)
contents.push(i);
};
CategoryEnumerator.prototype = {
hasMoreElements: function() {
return this.index !== this.contents.length;
},
getNext: function() {
if (!this.hasMoreElements())
return null; // XXX?
var str = Components.classes["component://netscape/supports-string"]
.createInterface(Components.interfaces.nsISupportsString);
str.data = this.contents[this.index++];
return str;
},
index: 0
};
var module = {
registerSelf: function (compMgr, fileSpec, location, type) {
compMgr.registerComponentWithType(this.myCID,

Просмотреть файл

@ -32,6 +32,7 @@
#include "nsISupportsPrimitives.h"
#include "nsIComponentLoader.h"
#include "nsNativeComponentLoader.h"
#include "nsXPIDLString.h"
#include "plstr.h"
#include "prlink.h"
@ -130,8 +131,8 @@ nsCID_Destroy(nsHashKey *aKey, void *aData, void* closure);
////////////////////////////////////////////////////////////////////////////////
nsFactoryEntry::nsFactoryEntry(const nsCID &aClass,
char *aLocation,
char *aType,
const char *aLocation,
const char *aType,
nsIComponentLoader *aLoader)
: cid(aClass), factory(nsnull), loader(aLoader)
{
@ -141,7 +142,7 @@ nsFactoryEntry::nsFactoryEntry(const nsCID &aClass,
}
nsFactoryEntry::nsFactoryEntry(const nsCID &aClass, nsIFactory *aFactory)
: cid(aClass), location(nsnull), type(nsnull), loader(nsnull)
: cid(aClass), loader(nsnull)
{
factory = aFactory;
@ -151,43 +152,8 @@ nsFactoryEntry::~nsFactoryEntry(void)
{
factory = 0;
loader = 0;
if (location)
nsAllocator::Free(location);
if (type)
nsAllocator::Free(type);
}
////////////////////////////////////////////////////////////////////////////////
// autoStringFree
////////////////////////////////////////////////////////////////////////////////
//
// To prevent leaks, we are using this class. Typical use would be
// for each ptr to be deleted, create an object of these types with that ptr.
// Once that object goes out of scope, deletion and hence memory free will
// automatically happen.
//
class autoStringFree
{
public:
enum DeleteModel {
NSPR_Delete = 1,
nsCRT_String_Delete = 2
};
autoStringFree(char *Ptr, DeleteModel whichDelete): mPtr(Ptr), mWhichDelete(whichDelete) {}
~autoStringFree() {
if (mPtr)
if (mWhichDelete == NSPR_Delete) { PR_FREEIF(mPtr); }
else if (mWhichDelete == nsCRT_String_Delete) nsCRT::free(mPtr);
else PR_ASSERT(0);
}
private:
char *mPtr;
DeleteModel mWhichDelete;
};
////////////////////////////////////////////////////////////////////////////////
// nsComponentManagerImpl
////////////////////////////////////////////////////////////////////////////////
@ -474,17 +440,18 @@ nsComponentManagerImpl::PlatformVersionCheck()
if (NS_FAILED(rv)) return rv;
char *buf;
nsresult err = mRegistry->GetString(xpcomKey, versionValueName, &buf);
autoStringFree delete_buf(buf, autoStringFree::NSPR_Delete);
nsXPIDLCString buf;
nsresult err = mRegistry->GetString(xpcomKey, versionValueName,
getter_Copies(buf));
// If there is a version mismatch or no version string, we got an old registry.
// Delete the old repository hierarchies and recreate version string
if (NS_FAILED(err) || PL_strcmp(buf, NS_XPCOM_COMPONENT_MANAGER_VERSION_STRING))
{
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
("nsComponentManager: Registry version mismatch (%s vs %s). Nuking xpcom "
"registry hierarchy.", buf, NS_XPCOM_COMPONENT_MANAGER_VERSION_STRING));
("nsComponentManager: Registry version mismatch (%s vs %s)."
"Nuking xpcom registry hierarchy.", (const char *)buf,
NS_XPCOM_COMPONENT_MANAGER_VERSION_STRING));
// Delete the XPCOM and CLSID hierarchy
nsRegistryKey mozillaKey;
@ -708,28 +675,25 @@ nsComponentManagerImpl::PlatformFind(const nsCID &aCID, nsFactoryEntry* *result)
if (NS_FAILED(rv)) return rv;
char *library = NULL;
rv = mRegistry->GetString(cidKey, inprocServerValueName, &library);
nsXPIDLCString library;
rv = mRegistry->GetString(cidKey, inprocServerValueName,
getter_Copies(library));
if (NS_FAILED(rv))
{
// Registry inconsistent. No File name for CLSID.
return rv;
}
autoStringFree delete_library(library, autoStringFree::NSPR_Delete);
nsXPIDLCString componentType;
rv = mRegistry->GetString(cidKey, componentTypeValueName,
getter_Copies(componentType));
char *componentType = NULL;
rv = mRegistry->GetString(cidKey, componentTypeValueName, &componentType);
if (rv == NS_ERROR_REG_NOT_FOUND) {
if (NS_FAILED(rv))
if (rv == NS_ERROR_REG_NOT_FOUND)
/* missing componentType, we assume application/x-moz-native */
componentType = PL_strdup(nativeComponentType);
if (!componentType)
return NS_ERROR_OUT_OF_MEMORY;
} else if (NS_FAILED(rv)) {
componentType = nativeComponentType;
else
return rv; // XXX translate error code?
}
autoStringFree delete_type(componentType, autoStringFree::NSPR_Delete);
nsCOMPtr<nsIComponentLoader> loader;
@ -824,10 +788,9 @@ nsresult nsComponentManagerImpl::PlatformPrePopulateRegistry()
if (!node) continue;
// Get library name
char *cidString = NULL;
rv = node->GetName(&cidString);
nsXPIDLCString cidString;
rv = node->GetName(getter_Copies(cidString));
if (NS_FAILED(rv)) continue;
autoStringFree delete_cidString(cidString, autoStringFree::nsCRT_String_Delete);
// Get key associated with library
nsRegistryKey cidKey;
@ -835,19 +798,20 @@ nsresult nsComponentManagerImpl::PlatformPrePopulateRegistry()
if (NS_FAILED(rv)) continue;
// Create the CID entry
char *library = NULL;
rv = mRegistry->GetString(cidKey, inprocServerValueName, &library);
nsXPIDLCString library;
rv = mRegistry->GetString(cidKey, inprocServerValueName,
getter_Copies(library));
if (NS_FAILED(rv)) continue;
nsCID aClass;
if (!(aClass.Parse(cidString))) continue;
char *componentType;
nsXPIDLCString componentType;
if (NS_FAILED(mRegistry->GetString(cidKey, componentTypeValueName,
&componentType)))
getter_Copies(componentType))))
continue;
nsFactoryEntry* entry =
/* hand off componentType and library to factory */
new nsFactoryEntry(aClass, library, componentType,
nsCRT::strcmp(componentType,
nativeComponentType) ?
@ -878,19 +842,20 @@ nsresult nsComponentManagerImpl::PlatformPrePopulateRegistry()
if (NS_FAILED(rv)) continue;
// Get the progid string
char *progidString = NULL;
rv = node->GetName(&progidString);
nsXPIDLCString progidString;
rv = node->GetName(getter_Copies(progidString));
if (NS_FAILED(rv)) continue;
autoStringFree delete_progidString(progidString, autoStringFree::nsCRT_String_Delete);
// Get cid string
nsRegistryKey progidKey;
rv = node->GetKey(&progidKey);
if (NS_FAILED(rv)) continue;
char *cidString = NULL;
rv = mRegistry->GetString(progidKey, classIDValueName, &cidString);
nsXPIDLCString cidString;
rv = mRegistry->GetString(progidKey, classIDValueName,
getter_Copies(cidString));
if (NS_FAILED(rv)) continue;
autoStringFree delete_cidString(cidString, autoStringFree::NSPR_Delete);
nsCID *aClass = new nsCID();
if (!aClass) continue; // Protect against out of memory.
if (!(aClass->Parse(cidString)))
@ -1038,7 +1003,7 @@ nsComponentManagerImpl::LoadFactory(nsFactoryEntry *aEntry,
if (NS_FAILED(rv)) {
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
("nsComponentManager: failed to load factory from %s (%s)\n",
aEntry->location, aEntry->type));
(const char *)aEntry->location, (const char *)aEntry->type));
return rv;
}
@ -1054,8 +1019,8 @@ nsComponentManagerImpl::GetFactoryEntry(const nsCID &aClass, PRBool checkRegistr
if (entry) {
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
("\t\tfound %s as %p in factory cache.", entry->location,
entry));
("\t\tfound %s as %p in factory cache.",
(const char *)entry->location, entry));
} else {
#ifdef USE_REGISTRY
if (checkRegistry)
@ -1619,17 +1584,12 @@ nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
goto out;
}
/* hand off aRegistryName to entry */
newEntry = new nsFactoryEntry(aClass, aRegistryName,
nsCRT::strdup(aType),
loader);
newEntry = new nsFactoryEntry(aClass, aRegistryName, aType, loader);
if (!newEntry) {
rv = NS_ERROR_OUT_OF_MEMORY;
goto out;
}
aRegistryName = nsnull; // handed to nsFactoryEntry, so don't free
if (entry) { // aReplace implicit from test above
delete entry;
}
@ -1637,6 +1597,7 @@ nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
/* unless the fabric of the universe bends, we'll get entry back */
sanity = (entry == mFactories->Put(&key, newEntry));
PR_ASSERT(sanity);
/* don't try to clean up, just drop everything and run */
if (!sanity)
return NS_ERROR_FACTORY_NOT_REGISTERED;
@ -1670,7 +1631,8 @@ nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
goto out;
}
PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
PR_LOG(nsComponentManagerLog,
NS_SUCCEEDED(rv) ? PR_LOG_DEBUG : PR_LOG_ERROR,
("\t\tFactory register %s progID=%s.",
NS_SUCCEEDED(rv) ? "succeeded" : "failed",
aProgID ? aProgID : "<none>"));
@ -1710,7 +1672,7 @@ nsComponentManagerImpl::GetLoaderForType(const char *aType,
if (NS_FAILED(rv))
return rv;
#ifdef DEBUG_shaver
#ifdef DEBUG_shaver_off
fprintf(stderr, "nCMI: constructing loader for type %s = %s\n", aType, progID);
#endif
@ -1741,7 +1703,7 @@ nsComponentManagerImpl::RegisterComponentLoader(const char *aType, const char *a
rv = mRegistry->SetString(loaderKey, progIDValueName, aProgID);
#ifdef DEBUG_shaver
#ifdef DEBUG_shaver_off
fprintf(stderr, "nNCI: registered %s as component loader for %s\n",
aProgID, aType);
#endif
@ -2014,28 +1976,39 @@ struct AutoReg_closure {
nsIFileSpec *spec;
nsresult status; // this is a hack around Enumerate's void return
nsIComponentLoader *native;
PRBool registered;
};
static PRBool
AutoRegister_enumerate(nsHashKey *key, void *aData, void *aClosure)
{
nsIComponentLoader *loader = (nsIComponentLoader *)aData;
nsIComponentLoader *loader = NS_STATIC_CAST(nsIComponentLoader *, aData);
struct AutoReg_closure *closure =
(struct AutoReg_closure *)aClosure;
if (loader == closure->native) {
#ifdef DEBUG_shaver
fprintf(stderr, "AutoRegister_enumerate: skipping native\n");
#endif
if (loader == closure->native)
return PR_TRUE;
}
PR_ASSERT(NS_SUCCEEDED(closure->status));
closure->status = loader->AutoRegisterComponents(closure->when, closure->spec);
if (NS_FAILED(closure->status))
return PR_FALSE;
return PR_TRUE;
closure->status = loader->AutoRegisterComponents(closure->when,
closure->spec);
return NS_SUCCEEDED(closure->status) ? PR_TRUE : PR_FALSE;
}
static PRBool
RegisterDeferred_enumerate(nsHashKey *key, void *aData, void *aClosure)
{
nsIComponentLoader *loader = NS_STATIC_CAST(nsIComponentLoader *, aData);
struct AutoReg_closure *closure =
(struct AutoReg_closure *)aClosure;
PR_ASSERT(NS_SUCCEEDED(closure->status));
PRBool registered;
closure->status = loader->RegisterDeferredComponents(closure->when,
&registered);
closure->registered |= registered;
return NS_SUCCEEDED(closure->status) ? PR_TRUE : PR_FALSE;
}
nsresult
@ -2082,24 +2055,16 @@ nsComponentManagerImpl::AutoRegister(PRInt32 when, nsIFileSpec *inDirSpec)
if (NS_FAILED(rv))
continue;
char *type;
rv = node->GetName(&type);
nsXPIDLCString type;
rv = node->GetName(getter_Copies(type));
if (NS_FAILED(rv))
continue;
autoStringFree del_type(type, autoStringFree::nsCRT_String_Delete);
nsStringKey typeKey(type);
nsCOMPtr<nsIComponentLoader> loader =
(nsIComponentLoader *)mLoaders->Get(&typeKey);
if (loader.get())
continue;
#ifdef DEBUG_shaver
fprintf(stderr, "nCMI: creating %s loader for enumeration\n",
type);
#endif
/* this will get it added to the hashtable and stuff */
nsCOMPtr<nsIComponentLoader> loader;
/* this will create it if we haven't already */
GetLoaderForType(type, getter_AddRefs(loader));
continue;
}
@ -2112,6 +2077,14 @@ nsComponentManagerImpl::AutoRegister(PRInt32 when, nsIFileSpec *inDirSpec)
closure.native = mNativeComponentLoader; // prevent duplicate autoreg
mLoaders->Enumerate(AutoRegister_enumerate, &closure);
if (NS_FAILED(closure.status))
return closure.status;
do {
closure.registered = PR_FALSE;
mLoaders->Enumerate(RegisterDeferred_enumerate, &closure);
} while (NS_SUCCEEDED(closure.status) && closure.registered);
return closure.status;
}

Просмотреть файл

@ -33,6 +33,7 @@
#include "prmon.h"
#include "nsCOMPtr.h"
#include "nsWeakReference.h"
#include "nsXPIDLString.h"
class nsFactoryEntry;
class nsDll;
@ -182,8 +183,8 @@ protected:
class nsFactoryEntry {
public:
nsFactoryEntry(const nsCID &aClass, char *location, char *aType,
nsIComponentLoader *aLoader);
nsFactoryEntry(const nsCID &aClass, const char *location,
const char *aType, nsIComponentLoader *aLoader);
nsFactoryEntry(const nsCID &aClass, nsIFactory *aFactory);
~nsFactoryEntry();
@ -209,9 +210,9 @@ public:
}
nsCID cid;
char *location;
nsXPIDLCString location;
nsCOMPtr<nsIFactory> factory;
char *type;
nsXPIDLCString type;
nsCOMPtr<nsIComponentLoader> loader;
};

Просмотреть файл

@ -27,23 +27,22 @@ interface nsIComponentLoader : nsISupports {
/**
* Get the factory for a given component.
*/
nsIFactory GetFactory(in nsIIDRef aCID, in string aLocation,
nsIFactory getFactory(in nsIIDRef aCID, in string aLocation,
in string aType);
/**
* Initialize the loader.
*
* We use nsISupports here because nsIRegistry isn't IDLized yet.
* Should we pass in a service manager reference too/instead?
*/
void Init(in nsIComponentManager aCompMgr, in nsISupports aRegistry);
void init(in nsIComponentManager aCompMgr, in nsISupports aRegistry);
/**
* Called when a component of the appropriate type is registered,
* to give the component loader an opportunity to do things like
* annotate the registry and such.
*/
void OnRegister(in nsIIDRef aCID, in string aType,
void onRegister(in nsIIDRef aCID, in string aType,
in string aClassName, in string aProgID,
in string aLocation, in boolean aReplace,
in boolean aPersist);
@ -58,7 +57,7 @@ interface nsIComponentLoader : nsISupports {
/**
* AutoRegister components in the given directory.
*/
void AutoRegisterComponents(in long aWhen, in nsIFileSpec aDirectory);
void autoRegisterComponents(in long aWhen, in nsIFileSpec aDirectory);
/**
* AutoRegister the given component.
@ -67,11 +66,17 @@ interface nsIComponentLoader : nsISupports {
* attempt to register the component (wrong type) and ``throws'' an
* NS_FAILED code if there was an error during registration.
*/
boolean AutoRegisterComponent(in long aWhen, in nsIFileSpec aComponent);
boolean autoRegisterComponent(in long aWhen, in nsIFileSpec aComponent);
/**
* Register any deferred (NS_ERROR_FACTORY_REGISTER_AGAIN) components.
* Return registered-any-components?
*/
boolean registerDeferredComponents(in long aWhen);
/**
* Unload all components that are willing.
*/
void UnloadAll(in long aWhen);
void unloadAll(in long aWhen);
};

Просмотреть файл

@ -28,6 +28,7 @@
#include "xcDll.h"
#include "nsHashtable.h"
#include "nsHashtableEnumerator.h"
#include "nsXPIDLString.h"
#define PRINT_CRITICAL_ERROR_TO_SCREEN 1
#define USE_REGISTRY 1
@ -35,33 +36,6 @@
extern PRLogModuleInfo *nsComponentManagerLog;
/* XXX consolidate with one in nsComponentManager.cpp */
//
// To prevent leaks, we are using this class. Typical use would be
// for each ptr to be deleted, create an object of these types with that ptr.
// Once that object goes out of scope, deletion and hence memory free will
// automatically happen.
//
class autoStringFree
{
public:
enum DeleteModel {
NSPR_Delete = 1,
nsCRT_String_Delete = 2
};
autoStringFree(char *Ptr, DeleteModel whichDelete): mPtr(Ptr), mWhichDelete(whichDelete) {}
~autoStringFree() {
if (mPtr)
if (mWhichDelete == NSPR_Delete) { PR_FREEIF(mPtr); }
else if (mWhichDelete == nsCRT_String_Delete) nsCRT::free(mPtr);
else PR_ASSERT(0);
}
private:
char *mPtr;
DeleteModel mWhichDelete;
};
nsNativeComponentLoader::nsNativeComponentLoader() :
mRegistry(nsnull), mCompMgr(nsnull), mDllStore(nsnull)
{
@ -140,6 +114,14 @@ nsNativeComponentLoader::GetFactory(const nsIID & aCID,
if (NS_FAILED(rv)) {
if (rv == NS_ERROR_FACTORY_NOT_LOADED) {
rv = GetFactoryFromNSGetFactory(dll, aCID, serviceMgr, _retval);
#ifdef WARN_ABOUT_NSGETFACTORY
if (NS_SUCCEEDED(rv)) {
fprintf(stderr,
"XPCOM: Component %s uses DEPRECATED\n"
" NSGetFactory interface. This could break "
"AT ANY TIME.\n", dll->GetNativePath());
}
#endif
}
}
#endif
@ -166,10 +148,6 @@ nsNativeComponentLoader::Init(nsIComponentManager *aCompMgr, nsISupports *aReg)
{
nsresult rv;
#ifdef DEBUG_shaver
fprintf(stderr, "nNCL: Init()\n");
#endif
mCompMgr = aCompMgr;
mRegistry = do_QueryInterface(aReg);
if (!mCompMgr || !mRegistry)
@ -177,23 +155,15 @@ nsNativeComponentLoader::Init(nsIComponentManager *aCompMgr, nsISupports *aReg)
rv = mRegistry->GetSubtree(nsIRegistry::Common, xpcomKeyName,
&mXPCOMKey);
if (NS_FAILED(rv)) {
#ifdef DEBUG_shaver
fprintf(stderr, "nsNCL::Init: registry is hosed\n");
#endif
if (NS_FAILED(rv))
return rv;
}
if (!mDllStore) {
mDllStore = new nsObjectHashtable(nsnull, nsnull, // never copy
nsDll_Destroy, nsnull,
256, /* Thead Safe */ PR_TRUE);
if (!mDllStore) {
#ifdef DEBUG_shaver
fprintf(stderr, "nNCL::Init: couldn't build hash table\n");
#endif
if (!mDllStore)
return NS_ERROR_OUT_OF_MEMORY;
}
}
@ -216,10 +186,9 @@ nsNativeComponentLoader::Init(nsIComponentManager *aCompMgr, nsISupports *aReg)
if (NS_FAILED(rv)) continue;
// Get library name
char *library = NULL;
rv = node->GetName(&library);
nsXPIDLCString library;
rv = node->GetName(getter_Copies(library));
if (NS_FAILED(rv)) continue;
autoStringFree delete_library(library, autoStringFree::nsCRT_String_Delete);
// Get key associated with library
nsRegistryKey libKey;
@ -441,10 +410,12 @@ nsFreeLibraryEnum(nsHashKey *aKey, void *aData, void* closure)
*
*/
nsresult
nsNativeComponentLoader::SelfRegisterDll(nsDll *dll, const char *registryLocation)
nsNativeComponentLoader::SelfRegisterDll(nsDll *dll,
const char *registryLocation,
PRBool deferred)
{
// Precondition: dll is not loaded already
PR_ASSERT(dll->IsLoaded() == PR_FALSE);
// Precondition: dll is not loaded already, unless we're deferred
PR_ASSERT(deferred || dll->IsLoaded() == PR_FALSE);
nsIServiceManager* serviceMgr = NULL;
nsresult res = nsServiceManager::GetGlobalServiceManager(&serviceMgr);
@ -505,8 +476,14 @@ nsNativeComponentLoader::SelfRegisterDll(nsDll *dll, const char *registryLocatio
#endif /* OBSOLETE_MODULE_LOADING */
// Update the timestamp and size of the dll in registry
dll->Sync();
SetRegistryDllInfo(registryLocation, dll->GetLastModifiedTime(), dll->GetSize());
// Don't enter deferred modules in the registry, because it might only be
// able to register on some later autoreg, after another component has been
// installed.
if (res != NS_ERROR_FACTORY_REGISTER_AGAIN) {
dll->Sync();
SetRegistryDllInfo(registryLocation, dll->GetLastModifiedTime(),
dll->GetSize());
}
return res;
}
@ -573,7 +550,7 @@ nsNativeComponentLoader::DumpLoadError(nsDll *dll,
#endif // MOZ_DEMANGLE_SYMBOLS
// Do NSPR log
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
("nsNativeComponentLoader: %s(%s) Load FAILED with error:%s",
aCallerName,
dll->GetNativePath(),
@ -656,12 +633,12 @@ nsNativeComponentLoader::AutoRegisterComponent(PRInt32 when,
/* this should be a pref or registry entry, or something */
const char *ValidDllExtensions[] = {
".dll", /* Windows */
".so", /* Unix */
".shlb", /* Mac ? */
".dso", /* Unix ? */
".dylib", /* Unix: Rhapsody */
".so", /* Unix */
".so.1.0", /* Unix: BSD */
".sl", /* Unix: HP-UX */
".shlb", /* Mac ? */
#if defined(VMS)
".exe", /* Open VMS */
#endif
@ -731,21 +708,12 @@ nsNativeComponentLoader::AutoRegisterComponent(PRInt32 when,
// Skip invalid extensions
return NS_OK;
/*
* Get the name of the dll
* I think I get to go through every type of string here.
* Pink would be so proud.
*/
char *persistentDescriptor;
rv = mCompMgr->RegistryLocationForSpec(component, &persistentDescriptor);
nsXPIDLCString persistentDescriptor;
rv = mCompMgr->RegistryLocationForSpec(component,
getter_Copies(persistentDescriptor));
if (NS_FAILED(rv))
return rv;
autoStringFree
delete_persistentDescriptor(persistentDescriptor,
autoStringFree::nsCRT_String_Delete);
nsStringKey key(persistentDescriptor);
// Get the registry representation of the dll, if any
@ -834,19 +802,19 @@ nsNativeComponentLoader::AutoRegisterComponent(PRInt32 when,
// changed since we last saw it and it is unloaded successfully.
//
// Now we can try register the dll for sure.
nsresult res = SelfRegisterDll(dll, persistentDescriptor);
nsresult ret = NS_OK;
nsresult res = SelfRegisterDll(dll, persistentDescriptor, PR_FALSE);
if (NS_FAILED(res))
{
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
("nsNativeComponentLoader: Autoregistration FAILED for "
"\"%s\". Skipping...", dll->GetNativePath()));
// Mark dll as not xpcom dll along with modified time and size in
// the registry so that we wont need to load the dll again every
// session until the dll changes.
#ifdef USE_REGISTRY
#endif /* USE_REGISTRY */
ret = NS_ERROR_FAILURE;
if (res == NS_ERROR_FACTORY_REGISTER_AGAIN) {
/* defer for later loading */
mDeferredComponents.AppendElement(dll);
return NS_OK;
} else {
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
("nsNativeComponentLoader: Autoregistration FAILED for "
"\"%s\". Skipping...", dll->GetNativePath()));
return NS_ERROR_FACTORY_NOT_REGISTERED;
}
}
else
{
@ -857,7 +825,39 @@ nsNativeComponentLoader::AutoRegisterComponent(PRInt32 when,
// registry happens at PlatformRegister(). No need to do it
// here again.
}
return ret;
return NS_OK;
}
nsresult
nsNativeComponentLoader::RegisterDeferredComponents(PRInt32 aWhen,
PRBool *aRegistered)
{
fprintf(stderr, "nNCL: registering deferred (%d)\n",
mDeferredComponents.Count());
*aRegistered = PR_FALSE;
if (!mDeferredComponents.Count())
return NS_OK;
for (int i = mDeferredComponents.Count() - 1; i >= 0; i--) {
nsDll *dll = NS_STATIC_CAST(nsDll *, mDeferredComponents[i]);
nsresult rv = SelfRegisterDll(dll,
dll->GetRegistryLocation(),
PR_TRUE);
if (rv != NS_ERROR_FACTORY_REGISTER_AGAIN) {
if (NS_SUCCEEDED(rv))
*aRegistered = PR_TRUE;
mDeferredComponents.RemoveElementAt(i);
}
}
if (*aRegistered)
fprintf(stderr, "nNCL: registered deferred, %d left\n",
mDeferredComponents.Count());
else
fprintf(stderr, "nNCL: didn't register any components, %d left\n",
mDeferredComponents.Count());
/* are there any fatal errors? */
return NS_OK;
}
nsresult

Просмотреть файл

@ -25,6 +25,7 @@
#include "nsSpecialSystemDirectory.h"
#include "nsCOMPtr.h"
#include "nsHashtable.h"
#include "nsVoidArray.h"
#include "xcDll.h"
#ifndef nsNativeComponentLoader_h__
@ -49,11 +50,13 @@ class nsNativeComponentLoader : public nsIComponentLoader {
nsObjectHashtable* mDllStore;
NS_IMETHOD RegisterComponentsInDir(PRInt32 when, nsIFileSpec *dir);
nsRegistryKey mXPCOMKey;
nsVoidArray mDeferredComponents;
private:
nsresult CreateDll(nsIFileSpec *aSpec, const char *aLocation,
PRUint32 modifiedTime, PRUint32 fileSize, nsDll **aDll);
nsresult SelfRegisterDll(nsDll *dll, const char *registryLocation);
nsresult SelfRegisterDll(nsDll *dll, const char *registryLocation,
PRBool deferred);
nsresult SelfUnregisterDll(nsDll *dll);
nsresult GetRegistryDllInfo(const char *aLocation, PRUint32 *lastModifiedTime,
PRUint32 *fileSize);

Просмотреть файл

@ -27,6 +27,8 @@
#include "prmem.h"
#include "prlock.h"
#include "prlog.h"
#include "nsCRT.h"
#include "nsAllocator.h"
/* extra locking for the paranoid */
/* #define EXTRA_THREADSAFE */
@ -306,18 +308,6 @@ static void reginfo2Length( const REGINFO &in, PRUint32 &out ) {
}
}
/*-------------------------------- PR_strdup -----------------------------------
| Utility function that does PR_Malloc and copies argument string. Caller |
| must do PR_Free. |
------------------------------------------------------------------------------*/
static char *PR_strdup( const char *in ) {
char *result = (char*)PR_Malloc( strlen( in ) + 1 );
if ( result ) {
strcpy( result, in );
}
return result;
}
/*------------------------ nsISupports Implementation --------------------------
| This code generates the implementation of the nsISupports member functions |
| for each class implemented in this file. |
@ -525,12 +515,8 @@ NS_IMETHODIMP nsRegistry::GetString( nsRegistryKey baseKey, const char *path, ch
if ( err == REGERR_OK )
{
// Allocate buffer for return value
PRUint32 vallen = PL_strlen(regStr);
*result = (char*)PR_Malloc( vallen + 1 );
if (*result)
PL_strcpy(*result, regStr);
else
*result = nsCRT::strdup(regStr);
if (!*result)
rv = NS_ERROR_OUT_OF_MEMORY;
}
else if ( err == REGERR_BUFTOOSMALL )
@ -541,7 +527,7 @@ NS_IMETHODIMP nsRegistry::GetString( nsRegistryKey baseKey, const char *path, ch
// See if that worked.
if( rv == NS_OK )
{
*result =(char*)PR_Malloc( length + 1 );
*result =(char*)nsAllocator::Alloc( length + 1 );
if( *result )
{
// Get string from registry into result buffer.
@ -554,7 +540,7 @@ NS_IMETHODIMP nsRegistry::GetString( nsRegistryKey baseKey, const char *path, ch
if ( rv != NS_OK )
{
// Didn't get result, free buffer
PR_Free( *result );
nsCRT::free( *result );
*result = 0;
}
}
@ -1173,7 +1159,7 @@ nsRegistryNode::~nsRegistryNode()
NS_IMETHODIMP nsRegistryNode::GetName( char **result ) {
if (result == NULL) return NS_ERROR_NULL_POINTER;
// Make sure there is a place to put the result.
*result = PR_strdup( mName );
*result = nsCRT::strdup( mName );
if ( !*result ) return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
@ -1223,7 +1209,7 @@ NS_IMETHODIMP nsRegistryValue::GetName( char **result ) {
rv = getInfo();
if( rv == NS_OK || rv == NS_ERROR_REG_NO_MORE ) {
// worked, return actual result.
*result = PR_strdup( mName );
*result = nsCRT::strdup( mName );
if ( *result ) {
rv = NS_OK;
} else {

Просмотреть файл

@ -109,6 +109,8 @@ public:
const char *GetNativePath(void);
// WARNING: DONT FREE string returned.
const char *GetPersistentDescriptorString(void);
// WARNING: DONT FREE string returned.
const char *GetRegistryLocation(void) { return m_registryLocation; }
PRUint32 GetLastModifiedTime(void) { return(m_modDate); }
PRUint32 GetSize(void) { return(m_size); }
PRLibrary *GetInstance(void) { return (m_instance); }

Просмотреть файл

@ -17,6 +17,7 @@ nsQuickSort.h
nsStr.h
nsString.h
nsString2.h
nsSupportsArray.h
nsSupportsPrimitives.h
nsTime.h
nsUnitConversion.h

Просмотреть файл

@ -83,6 +83,7 @@ EXPORTS = \
nsStr.h \
nsString.h \
nsString2.h \
nsSupportsArray.h \
nsSupportsPrimitives.h \
nsTime.h \
nsUnitConversion.h \

Просмотреть файл

@ -48,6 +48,7 @@ EXPORTS = \
nsStr.h \
nsString.h \
nsString2.h \
nsSupportsArray.h \
nsSupportsPrimitives.h \
nsTime.h \
nsUnitConversion.h \

Просмотреть файл

@ -28,8 +28,8 @@
[scriptable, uuid(D1899240-F9D2-11D2-BDD6-000064657374)]
interface nsISimpleEnumerator : nsISupports {
boolean HasMoreElements();
nsISupports GetNext();
boolean hasMoreElements();
nsISupports getNext();
};
/*
@ -67,11 +67,11 @@ interface nsIBidirectionalEnumerator : nsIEnumerator {
/** Last will reset the list to the end. will return NS_FAILED if no items
*/
void Last();
void last();
/** Prev will decrement the list. will return failed if already at beginning
*/
void Prev();
void prev();
};
%{C++

Просмотреть файл

@ -34,7 +34,7 @@ static const char gIDFormat2[] =
* an nsID
*/
NS_COM PRBool nsID::Parse(char *aIDStr)
NS_COM PRBool nsID::Parse(const char *aIDStr)
{
PRInt32 count = 0;
PRInt32 n1, n2, n3[8];

Просмотреть файл

@ -71,7 +71,7 @@ struct nsID {
* nsID Parsing method. Turns a {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
* string into an nsID
*/
NS_COM PRBool Parse(char *aIDStr);
NS_COM PRBool Parse(const char *aIDStr);
/**
* nsID string encoder. Returns an allocated string in

Просмотреть файл

@ -44,6 +44,8 @@ mySample.prototype = {
}
var myModule = {
firstTime: true,
/*
* RegisterSelf is called at registration time (component installation
* or the only-until-release startup autoregistration) and is responsible
@ -53,6 +55,12 @@ var myModule = {
* unmolested.
*/
registerSelf: function (compMgr, fileSpec, location, type) {
if (this.firstTime) {
dump("*** Deferring registration of sample JS components\n");
this.firstTime = false;
throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
}
dump("*** Registering sample JS components\n");
compMgr.registerComponentWithType(this.myCID,
"Sample JS Component",
"mozilla.jssample.1", fileSpec,
@ -104,6 +112,22 @@ var myModule = {
return new mySample();
}
},
/*
* canUnload is used to signal that the component is about to be unloaded.
* C++ components can return false to indicate that they don't wish to
* be unloaded, but the return value from JS components' canUnload is
* ignored: mark-and-sweep will keep everything around until it's no
* longer in use, making unconditional ``unload'' safe.
*
* You still need to provide a (likely useless) canUnload method, though:
* it's part of the nsIModule interface contract, and the JS loader _will_
* call it.
*/
canUnload: function(compMgr) {
dump("*** Unloading sample JS components\n");
return true;
}
};

Просмотреть файл

@ -244,7 +244,7 @@ static void displayValues( nsIRegistry *reg, nsRegistryKey root ) {
rv = reg->GetString( root, name, &strValue );
if ( rv == NS_OK ) {
printString( strValue, strlen(name) );
PR_Free( strValue );
nsAllocator::Free( strValue );
} else {
printf( "\t Error getting string value, rv=0x%08X", (int)rv );
}
@ -280,6 +280,7 @@ static void displayValues( nsIRegistry *reg, nsRegistryKey root ) {
printf( "\t= ? (error getting value, rv=0x%08X)", (int)rv );
}
printf("\n");
nsAllocator::Free( name );
} else {
printf( "Error getting value name, rv=0x%08X\n", (int)rv );
}