Bug 316416 - Convert nsIComponentLoader into nsIModuleLoader, xpcom bits r=darin xpconnect bits r=shaver; and bug 318625 - Make a version of nsTArray.AppendElement that doesn't copy-construct, r=darin

This commit is contained in:
bsmedberg%covad.net 2005-12-02 16:34:42 +00:00
Родитель 568b305cac
Коммит 28e3019754
21 изменённых файлов: 1309 добавлений и 3366 удалений

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

@ -48,10 +48,9 @@
#include "prlog.h"
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsICategoryManager.h"
#include "nsIComponentLoader.h"
#include "nsIComponentManager.h"
#include "nsIComponentManagerObsolete.h"
#include "nsIGenericFactory.h"
#include "nsILocalFile.h"
#include "nsIModule.h"
@ -63,7 +62,6 @@
#include "nsIXPConnect.h"
#include "nsCRT.h"
#include "nsMemory.h"
#include "nsXPIDLString.h"
#include "nsIObserverService.h"
#include "nsIXPCScriptable.h"
#include "nsString.h"
@ -72,7 +70,6 @@
#include "nsIURI.h"
#include "nsNetUtil.h"
#endif
#include "nsIComponentLoaderManager.h"
#include "jsxdrapi.h"
#include "nsIFastLoadFileControl.h"
// For reporting errors with the console service
@ -377,97 +374,36 @@ WriteScriptToStream(JSContext *cx, JSScript *script,
mozJSComponentLoader::mozJSComponentLoader()
: mRuntime(nsnull),
mContext(nsnull),
mModules(nsnull),
mGlobals(nsnull),
mInitialized(PR_FALSE)
{
NS_ASSERTION(!sSelf, "mozJSComponentLoader should be a singleton");
#ifdef PR_LOGGING
if (!gJSCLLog) {
gJSCLLog = PR_NewLogModule("JSComponentLoader");
}
#endif
}
static PRIntn PR_CALLBACK
UnrootGlobals(PLHashEntry *he, PRIntn i, void *arg)
{
JSContext *cx = (JSContext *)arg;
JSObject *global = (JSObject *)he->value;
JS_ClearScope(cx, global);
JS_RemoveRoot(cx, &he->value);
nsCRT::free((char *)he->key);
return HT_ENUMERATE_REMOVE;
}
static PRIntn PR_CALLBACK
UnloadAndReleaseModules(PLHashEntry *he, PRIntn i, void *arg)
{
nsIModule *module = NS_STATIC_CAST(nsIModule *, he->value);
nsIComponentManager *mgr = NS_STATIC_CAST(nsIComponentManager *, arg);
PRBool canUnload;
nsresult rv = module->CanUnload(mgr, &canUnload);
NS_ASSERTION(NS_SUCCEEDED(rv), "module CanUnload failed");
if (NS_SUCCEEDED(rv) && canUnload) {
NS_RELEASE(module);
/* XXX need to unroot the global for the module as well */
nsCRT::free((char *)he->key);
return HT_ENUMERATE_REMOVE;
}
return HT_ENUMERATE_NEXT;
sSelf = this;
}
mozJSComponentLoader::~mozJSComponentLoader()
{
if (mInitialized) {
NS_ERROR("'xpcom-shutdown-loaders' was not fired before cleaning up mozJSComponentLoader");
UnloadModules();
}
NS_ASSERTION(!mFastLoadTimer,
"Fastload file should have been closed via xpcom-shutdown");
sSelf = nsnull;
}
NS_IMPL_ISUPPORTS2(mozJSComponentLoader, nsIComponentLoader, nsIObserver)
mozJSComponentLoader*
mozJSComponentLoader::sSelf;
NS_IMETHODIMP
mozJSComponentLoader::GetFactory(const nsIID &aCID,
const char *aLocation,
const char *aType,
nsIFactory **_retval)
{
if (!_retval)
return NS_ERROR_NULL_POINTER;
#ifdef DEBUG_shaver_off
char *cidString = aCID.ToString();
fprintf(stderr, "mJCL::GetFactory(%s,%s,%s)\n", cidString, aLocation, aType);
delete [] cidString;
#endif
nsresult rv;
nsIModule *module = ModuleForLocation(aLocation, 0, &rv);
if (NS_FAILED(rv)) {
#ifdef DEBUG_shaver_off
fprintf(stderr, "ERROR: couldn't get module for %s\n", aLocation);
#endif
return rv;
}
rv = module->GetClassObject(mCompMgr, aCID, NS_GET_IID(nsIFactory),
(void **)_retval);
#ifdef DEBUG_shaver_off
fprintf(stderr, "GetClassObject %s\n", NS_FAILED(rv) ? "FAILED" : "ok");
#endif
return rv;
}
NS_IMETHODIMP
mozJSComponentLoader::Init(nsIComponentManager *aCompMgr, nsISupports *aReg)
{
mCompMgr = aCompMgr;
nsresult rv;
mLoaderManager = do_QueryInterface(mCompMgr, &rv);
if (NS_FAILED(rv))
return rv;
return NS_OK;
}
NS_IMPL_ISUPPORTS2(mozJSComponentLoader, nsIModuleLoader, nsIObserver)
nsresult
mozJSComponentLoader::ReallyInit()
@ -504,14 +440,7 @@ mozJSComponentLoader::ReallyInit()
return NS_ERROR_FAILURE;
#endif
mModules = PL_NewHashTable(16, PL_HashString, PL_CompareStrings,
PL_CompareValues, 0, 0);
if (!mModules)
return NS_ERROR_OUT_OF_MEMORY;
mGlobals = PL_NewHashTable(16, PL_HashString, PL_CompareStrings,
PL_CompareValues, 0, 0);
if (!mGlobals)
if (!mModules.Init(32))
return NS_ERROR_OUT_OF_MEMORY;
// Set up our fastload file
@ -532,6 +461,9 @@ mozJSComponentLoader::ReallyInit()
rv = obsSvc->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
rv = obsSvc->AddObserver(this, "xpcom-shutdown-loaders", PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG_shaver_off
fprintf(stderr, "mJCL: ReallyInit success!\n");
#endif
@ -541,401 +473,62 @@ mozJSComponentLoader::ReallyInit()
}
NS_IMETHODIMP
mozJSComponentLoader::AutoRegisterComponents(PRInt32 when,
nsIFile *aDirectory)
{
return RegisterComponentsInDir(when, aDirectory);
}
nsresult
mozJSComponentLoader::RegisterComponentsInDir(PRInt32 when, nsIFile *dir)
mozJSComponentLoader::LoadModule(nsILocalFile* aComponentFile,
nsIModule* *aResult)
{
nsresult rv;
PRBool isDir;
if (NS_FAILED(rv = dir->IsDirectory(&isDir)))
return rv;
if (!isDir)
nsCAutoString leafName;
aComponentFile->GetNativeLeafName(leafName);
if (!StringTail(leafName, 3).LowerCaseEqualsLiteral(".js"))
return NS_ERROR_INVALID_ARG;
// Create a directory iterator
nsCOMPtr<nsISimpleEnumerator> dirIterator;
rv = dir->GetDirectoryEntries(getter_AddRefs(dirIterator));
if (NS_FAILED(rv)) return rv;
// whip through the directory to register every file
nsIFile *dirEntry = NULL;
PRBool more = PR_FALSE;
rv = dirIterator->HasMoreElements(&more);
if (NS_FAILED(rv)) return rv;
while (more == PR_TRUE)
{
rv = dirIterator->GetNext((nsISupports**)&dirEntry);
if (NS_SUCCEEDED(rv))
{
rv = dirEntry->IsDirectory(&isDir);
if (NS_SUCCEEDED(rv))
{
if (isDir == PR_TRUE)
{
// This is a directory. Grovel for components into the directory.
rv = RegisterComponentsInDir(when, dirEntry);
}
else
{
PRBool registered;
// This is a file. Try to register it.
rv = AutoRegisterComponent(when, dirEntry, &registered);
}
}
NS_RELEASE(dirEntry);
}
rv = dirIterator->HasMoreElements(&more);
if (NS_FAILED(rv)) return rv;
}
return NS_OK;
}
nsresult
mozJSComponentLoader::SetRegistryInfo(const char *registryLocation,
nsIFile *component)
{
nsresult rv;
if (!mLoaderManager)
return NS_ERROR_FAILURE;
PRInt64 modDate;
rv = component->GetLastModifiedTime(&modDate);
if (NS_FAILED(rv))
return rv;
#ifdef DEBUG_shaver_off
fprintf(stderr, "SetRegistryInfo(%s) => (%d,%d)\n", registryLocation,
modDate, fileSize);
#endif
return mLoaderManager->SaveFileInfo(component, registryLocation, modDate);
}
nsresult
mozJSComponentLoader::RemoveRegistryInfo(nsIFile *component, const char *registryLocation)
{
if (!mLoaderManager)
return NS_ERROR_FAILURE;
return mLoaderManager->RemoveFileInfo(component, registryLocation);
}
PRBool
mozJSComponentLoader::HasChanged(const char *registryLocation,
nsIFile *component)
{
if (!mLoaderManager)
return NS_ERROR_FAILURE;
PRInt64 lastTime;
component->GetLastModifiedTime(&lastTime);
PRBool hasChanged = PR_TRUE;
mLoaderManager->HasFileChanged(component, registryLocation, lastTime, &hasChanged);
return hasChanged;
}
NS_IMETHODIMP
mozJSComponentLoader::AutoRegisterComponent(PRInt32 when,
nsIFile *component,
PRBool *registered)
{
nsresult rv;
if (!registered)
return NS_ERROR_NULL_POINTER;
const char jsExtension[] = ".js";
int jsExtensionLen = 3;
nsCAutoString leafName;
*registered = PR_FALSE;
/* we only do files */
PRBool isFile = PR_FALSE;
if (NS_FAILED(rv = component->IsFile(&isFile)) || !isFile)
return rv;
if (NS_FAILED(rv = component->GetNativeLeafName(leafName)))
return rv;
int len = leafName.Length();
/* if it's not *.js, return now */
if (len < jsExtensionLen || // too short
PL_strcasecmp(leafName.get() + len - jsExtensionLen, jsExtension))
return NS_OK;
#ifdef DEBUG_shaver_off
fprintf(stderr, "mJCL: registering JS component %s\n",
leafName.get());
#endif
rv = AttemptRegistration(component, PR_FALSE);
#ifdef DEBUG_shaver_off
if (NS_SUCCEEDED(rv))
fprintf(stderr, "registered module %s\n", leafName.get());
else if (rv == NS_ERROR_FACTORY_REGISTER_AGAIN)
fprintf(stderr, "deferred module %s\n", leafName.get());
else
fprintf(stderr, "failed to register %s\n", leafName.get());
#endif
*registered = (PRBool) NS_SUCCEEDED(rv);
return NS_OK;
}
NS_IMETHODIMP
mozJSComponentLoader::AutoUnregisterComponent(PRInt32 when,
nsIFile *component,
PRBool *unregistered)
{
nsresult rv;
if (!unregistered)
return NS_ERROR_NULL_POINTER;
const char jsExtension[] = ".js";
int jsExtensionLen = 3;
nsCAutoString leafName;
*unregistered = PR_FALSE;
/* we only do files */
PRBool isFile = PR_FALSE;
if (NS_FAILED(rv = component->IsFile(&isFile)) || !isFile)
return rv;
if (NS_FAILED(rv = component->GetNativeLeafName(leafName)))
return rv;
int len = leafName.Length();
/* if it's not *.js, return now */
if (len < jsExtensionLen || // too short
PL_strcasecmp(leafName.get() + len - jsExtensionLen, jsExtension))
return NS_OK;
rv = UnregisterComponent(component);
#ifdef DEBUG_dp
if (NS_SUCCEEDED(rv))
fprintf(stderr, "unregistered module %s\n", leafName.get());
else
fprintf(stderr, "failed to unregister %s\n", leafName.get());
#endif
*unregistered = (PRBool) NS_SUCCEEDED(rv);
return NS_OK;
}
nsresult
mozJSComponentLoader::AttemptRegistration(nsIFile *component,
PRBool deferred)
{
nsXPIDLCString registryLocation;
nsresult rv;
// what I want to do here is QI for a Component Registration Manager. Since this
// has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &rv);
if (obsoleteManager)
rv = obsoleteManager->RegistryLocationForSpec(component,
getter_Copies(registryLocation));
if (NS_FAILED(rv))
return rv;
/* no need to check registry data on deferred reg */
if (!deferred && !HasChanged(registryLocation, component))
return NS_OK;
nsIModule *module = ModuleForLocation(registryLocation, component, &rv);
if (NS_FAILED(rv)) {
SetRegistryInfo(registryLocation, component);
return rv;
}
// Notify observers, if any, of autoregistration work
nsCOMPtr<nsIObserverService> observerService =
do_GetService(kObserverServiceContractID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIServiceManager> mgr;
rv = NS_GetServiceManager(getter_AddRefs(mgr));
NS_ENSURE_SUCCESS(rv, rv);
// this string can't come from a string bundle, because we
// don't have string bundles yet.
NS_ConvertASCIItoUCS2 fileName("(no name)");
// get the file name
if (component) {
component->GetLeafName(fileName);
}
// this string can't come from a string bundle, because we
// don't have string bundles yet.
const nsPromiseFlatString &msg =
PromiseFlatString(NS_LITERAL_STRING("Registering JS component ") +
fileName);
observerService->NotifyObservers(mgr,
NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
msg.get());
rv = module->RegisterSelf(mCompMgr, component, registryLocation,
MOZJSCOMPONENTLOADER_TYPE_NAME);
if (rv == NS_ERROR_FACTORY_REGISTER_AGAIN) {
if (!deferred) {
mDeferredComponents.AppendElement(component);
}
/*
* we don't enter in the registry because we may want to
* try again on a later autoreg, in case a dependency has
* become available.
*/
} else {
SetRegistryInfo(registryLocation, component);
}
return rv;
}
nsresult
mozJSComponentLoader::UnregisterComponent(nsIFile *component)
{
nsXPIDLCString registryLocation;
nsresult rv;
// what I want to do here is QI for a Component Registration Manager. Since this
// has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &rv);
if (obsoleteManager)
rv = obsoleteManager->RegistryLocationForSpec(component,
getter_Copies(registryLocation));
if (NS_FAILED(rv))
return rv;
nsIModule *module = ModuleForLocation(registryLocation, component, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Notify observers, if any, of autoregistration work
nsCOMPtr<nsIObserverService> observerService =
do_GetService(kObserverServiceContractID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIServiceManager> mgr;
rv = NS_GetServiceManager(getter_AddRefs(mgr));
NS_ENSURE_SUCCESS(rv, rv);
const nsAFlatString &msg = NS_LITERAL_STRING("Unregistering JS component");
observerService->NotifyObservers(mgr,
NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
msg.get());
rv = module->UnregisterSelf(mCompMgr, component, registryLocation);
if (NS_SUCCEEDED(rv)) {
// Remove any autoreg specific info. Ignore error.
RemoveRegistryInfo(component, registryLocation);
}
return rv;
}
nsresult
mozJSComponentLoader::RegisterDeferredComponents(PRInt32 aWhen,
PRBool *aRegistered)
{
nsresult rv;
*aRegistered = PR_FALSE;
PRUint32 count;
rv = mDeferredComponents.Count(&count);
#ifdef DEBUG_shaver_off
fprintf(stderr, "mJCL: registering deferred (%d)\n", count);
#endif
if (NS_FAILED(rv) || !count)
return NS_OK;
for (PRUint32 i = 0; i < count; i++) {
nsCOMPtr<nsIFile> component;
rv = mDeferredComponents.QueryElementAt(i, NS_GET_IID(nsIFile), getter_AddRefs(component));
if (NS_FAILED(rv))
continue;
rv = AttemptRegistration(component, PR_TRUE /* deferred */);
if (rv != NS_ERROR_FACTORY_REGISTER_AGAIN) {
if (NS_SUCCEEDED(rv))
*aRegistered = PR_TRUE;
mDeferredComponents.RemoveElementAt(i);
}
}
#ifdef DEBUG_shaver_off
rv = mDeferredComponents.Count(&count);
if (NS_SUCCEEDED(rv)) {
if (*aRegistered)
fprintf(stderr, "mJCL: registered deferred, %d left\n",
count);
else
fprintf(stderr, "mJCL: didn't register any components, %d left\n",
count);
}
#endif
/* are there any fatal errors? */
return NS_OK;
}
nsIModule*
mozJSComponentLoader::ModuleForLocation(const char *registryLocation,
nsIFile *component, nsresult *status)
{
nsresult rv;
if (!mInitialized) {
rv = ReallyInit();
if (NS_FAILED(rv)) {
*status = rv;
return nsnull;
}
if (NS_FAILED(rv))
return rv;
}
PLHashNumber hash = PL_HashString(registryLocation);
PLHashEntry **hep = PL_HashTableRawLookup(mModules, hash,
registryLocation);
PLHashEntry *he = *hep;
if (he) {
*status = NS_OK;
return NS_STATIC_CAST(nsIModule*, he->value);
nsCOMPtr<nsIHashable> lfhash(do_QueryInterface(aComponentFile));
if (!lfhash) {
NS_ERROR("nsLocalFile not implementing nsIHashable");
return NS_NOINTERFACE;
}
JSObject *global;
rv = GlobalForLocation(registryLocation, component, &global);
ModuleEntry* mod;
if (mModules.Get(lfhash, &mod)) {
NS_ASSERTION(mod->module, "Bad hashtable data!");
NS_ADDREF(*aResult = mod->module);
return NS_OK;
}
nsAutoPtr<ModuleEntry> entry(new ModuleEntry);
if (!entry)
return NS_ERROR_OUT_OF_MEMORY;
rv = GlobalForLocation(aComponentFile, &entry->global, &entry->location);
if (NS_FAILED(rv)) {
#ifdef DEBUG_shaver
fprintf(stderr, "GlobalForLocation failed!\n");
#endif
*status = rv;
return nsnull;
return rv;
}
nsCOMPtr<nsIXPConnect> xpc = do_GetService(kXPConnectServiceContractID,
&rv);
if (NS_FAILED(rv)) {
*status = rv;
return nsnull;
}
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIComponentManager> cm;
rv = NS_GetComponentManager(getter_AddRefs(cm));
if (NS_FAILED(rv))
return rv;
JSCLContextHelper cx(mContext);
JSObject* cm_jsobj;
nsCOMPtr<nsIXPConnectJSObjectHolder> cm_holder;
rv = xpc->WrapNative(cx, global, mCompMgr,
rv = xpc->WrapNative(cx, entry->global, cm,
NS_GET_IID(nsIComponentManager),
getter_AddRefs(cm_holder));
@ -944,8 +537,7 @@ mozJSComponentLoader::ModuleForLocation(const char *registryLocation,
fprintf(stderr, "WrapNative(%p,%p,nsIComponentManager) failed: %x\n",
(void *)(JSContext*)cx, (void *)mCompMgr, rv);
#endif
*status = rv;
return nsnull;
return rv;
}
rv = cm_holder->GetJSObject(&cm_jsobj);
@ -953,32 +545,47 @@ mozJSComponentLoader::ModuleForLocation(const char *registryLocation,
#ifdef DEBUG_shaver
fprintf(stderr, "GetJSObject of ComponentManager failed\n");
#endif
*status = rv;
return nsnull;
return rv;
}
JSObject* file_jsobj;
nsCOMPtr<nsIXPConnectJSObjectHolder> file_holder;
rv = xpc->WrapNative(cx, entry->global, aComponentFile,
NS_GET_IID(nsIFile),
getter_AddRefs(file_holder));
if (NS_FAILED(rv)) {
return rv;
}
rv = cm_holder->GetJSObject(&file_jsobj);
if (NS_FAILED(rv)) {
return rv;
}
JSCLAutoErrorReporterSetter aers(cx, Reporter);
jsval argv[2], retval, NSGetModule_val;
if (!JS_GetProperty(cx, global, "NSGetModule", &NSGetModule_val) ||
if (!JS_GetProperty(cx, entry->global, "NSGetModule", &NSGetModule_val) ||
JSVAL_IS_VOID(NSGetModule_val)) {
*status = NS_ERROR_FAILURE;
return nsnull;
return NS_ERROR_FAILURE;
}
if (JS_TypeOfValue(cx, NSGetModule_val) != JSTYPE_FUNCTION) {
nsCAutoString path;
aComponentFile->GetNativePath(path);
JS_ReportError(cx, "%s has NSGetModule property that is not a function",
registryLocation);
*status = NS_ERROR_FAILURE;
return nsnull;
path.get());
return NS_ERROR_FAILURE;
}
argv[0] = OBJECT_TO_JSVAL(cm_jsobj);
argv[1] = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, registryLocation));
if (!JS_CallFunctionValue(cx, global, NSGetModule_val, 2, argv, &retval)) {
*status = NS_ERROR_FAILURE;
return nsnull;
argv[1] = OBJECT_TO_JSVAL(file_jsobj);
if (!JS_CallFunctionValue(cx, entry->global, NSGetModule_val,
2, argv, &retval)) {
return NS_ERROR_FAILURE;
}
#ifdef DEBUG_shaver_off
@ -990,31 +597,29 @@ mozJSComponentLoader::ModuleForLocation(const char *registryLocation,
JSObject *jsModuleObj;
if (!JS_ValueToObject(cx, retval, &jsModuleObj)) {
/* XXX report error properly */
#ifdef DEBUG
fprintf(stderr, "mJCL: couldn't convert %s's nsIModule to obj\n",
registryLocation);
#endif
*status = NS_ERROR_FAILURE;
return nsnull;
return NS_ERROR_FAILURE;
}
nsIModule *module;
rv = xpc->WrapJS(cx, jsModuleObj, NS_GET_IID(nsIModule), (void**)&module);
rv = xpc->WrapJS(cx, jsModuleObj,
NS_GET_IID(nsIModule), getter_AddRefs(entry->module));
if (NS_FAILED(rv)) {
/* XXX report error properly */
#ifdef DEBUG
fprintf(stderr, "mJCL: couldn't get nsIModule from jsval\n");
#endif
*status = rv;
return nsnull;
return rv;
}
/* we hand our reference to the hash table, it'll be released much later */
he = PL_HashTableRawAdd(mModules, hep, hash,
nsCRT::strdup(registryLocation), module);
// Cache this module for later
if (!mModules.Put(lfhash, entry))
return NS_ERROR_OUT_OF_MEMORY;
*status = NS_OK;
return module;
NS_ADDREF(*aResult = entry->module);
// The hash owns the ModuleEntry now, forget about it
entry.forget();
return NS_OK;
}
// Some stack based classes for cleaning up on early return
@ -1308,25 +913,11 @@ mozJSComponentLoader::WriteScript(nsIFastLoadService *flSvc, JSScript *script,
}
nsresult
mozJSComponentLoader::GlobalForLocation(const char *aLocation,
nsIFile *aComponent,
JSObject **aGlobal)
mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponent,
JSObject **aGlobal,
char **aLocation)
{
nsresult rv;
if (!mInitialized) {
rv = ReallyInit();
NS_ENSURE_SUCCESS(rv, rv);
}
PLHashNumber hash = PL_HashString(aLocation);
PLHashEntry **hep = PL_HashTableRawLookup(mGlobals, hash, aLocation);
PLHashEntry *he = *hep;
if (he) {
*aGlobal = NS_STATIC_CAST(JSObject*, he->value);
return NS_OK;
}
*aGlobal = nsnull;
JSPrincipals* jsPrincipals = nsnull;
JSCLContextHelper cx(mContext);
@ -1368,24 +959,8 @@ mozJSComponentLoader::GlobalForLocation(const char *aLocation,
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIFile> component = aComponent;
if (!component) {
// what I want to do here is QI for a Component Registration Manager. Since this
// has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
nsCOMPtr<nsIComponentManagerObsolete> mgr = do_QueryInterface(mCompMgr,
&rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = mgr->SpecForRegistryLocation(aLocation,
getter_AddRefs(component));
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(component, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXPConnectJSObjectHolder> locationHolder;
rv = xpc->WrapNative(cx, global, localFile,
rv = xpc->WrapNative(cx, global, aComponent,
NS_GET_IID(nsILocalFile),
getter_AddRefs(locationHolder));
NS_ENSURE_SUCCESS(rv, rv);
@ -1407,7 +982,7 @@ mozJSComponentLoader::GlobalForLocation(const char *aLocation,
#ifdef XPCONNECT_STANDALONE
localFile->GetNativePath(nativePath);
#else
NS_GetURLSpecFromFile(localFile, nativePath);
NS_GetURLSpecFromFile(aComponent, nativePath);
#endif
// Before compiling the script, first check to see if we have it in
@ -1472,7 +1047,7 @@ mozJSComponentLoader::GlobalForLocation(const char *aLocation,
#ifdef HAVE_PR_MEMMAP
PRInt64 fileSize;
localFile->GetFileSize(&fileSize);
aComponent->GetFileSize(&fileSize);
PRInt64 maxSize;
LL_UI2L(maxSize, PR_UINT32_MAX);
@ -1482,7 +1057,7 @@ mozJSComponentLoader::GlobalForLocation(const char *aLocation,
}
PRFileDesc *fileHandle;
rv = localFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fileHandle);
rv = aComponent->OpenNSPRFileDesc(PR_RDONLY, 0, &fileHandle);
NS_ENSURE_SUCCESS(rv, rv);
// Make sure the file is closed, no matter how we return.
@ -1521,7 +1096,7 @@ mozJSComponentLoader::GlobalForLocation(const char *aLocation,
*/
FILE *fileHandle;
rv = localFile->OpenANSIFileDesc("r", &fileHandle);
rv = aComponent->OpenANSIFileDesc("r", &fileHandle);
NS_ENSURE_SUCCESS(rv, rv);
script = JS_CompileFileHandleForPrincipals(cx, global,
@ -1551,7 +1126,7 @@ mozJSComponentLoader::GlobalForLocation(const char *aLocation,
if (fastLoading) {
// We successfully compiled the script, so cache it in fastload.
rv = WriteScript(flSvc, script, component, nativePath.get(), uri, cx);
rv = WriteScript(flSvc, script, aComponent, nativePath.get(), uri, cx);
// Don't treat failure to write as fatal, since we might be working
// with a read-only fastload file.
@ -1573,76 +1148,56 @@ mozJSComponentLoader::GlobalForLocation(const char *aLocation,
return NS_ERROR_FAILURE;
}
*aGlobal = global;
/* Freed when we remove from the table. */
char *location = nsCRT::strdup(aLocation);
NS_ENSURE_TRUE(location, NS_ERROR_OUT_OF_MEMORY);
nsCAutoString path;
aComponent->GetNativePath(path);
*aLocation = ToNewCString(path);
if (!*aLocation)
return NS_ERROR_OUT_OF_MEMORY;
he = PL_HashTableRawAdd(mGlobals, hep, hash, location, global);
JS_AddNamedRoot(cx, &he->value, location);
*aGlobal = global;
JS_AddNamedRoot(cx, aGlobal, *aLocation);
return NS_OK;
}
NS_IMETHODIMP
mozJSComponentLoader::OnRegister(const nsIID &aCID, const char *aType,
const char *aClassName, const char *aContractID,
const char *aLocation,
PRBool aReplace, PRBool aPersist)
void
mozJSComponentLoader::UnloadModules()
{
#ifdef DEBUG_shaver_off
fprintf(stderr, "mJCL: registered %s/%s in %s\n", aClassName, aContractID,
aLocation);
#endif
return NS_OK;
}
mInitialized = PR_FALSE;
NS_IMETHODIMP
mozJSComponentLoader::UnloadAll(PRInt32 aWhen)
{
if (mInitialized) {
mInitialized = PR_FALSE;
mModules.Clear();
// stabilize the component manager, etc.
nsCOMPtr<nsIComponentManager> kungFuDeathGrip = mCompMgr;
// Destroying our context will force a GC.
JS_DestroyContext(mContext);
mContext = nsnull;
PL_HashTableEnumerateEntries(mModules,
UnloadAndReleaseModules,
mCompMgr);
PL_HashTableDestroy(mModules);
mModules = nsnull;
PL_HashTableEnumerateEntries(mGlobals, UnrootGlobals, mContext);
PL_HashTableDestroy(mGlobals);
mGlobals = nsnull;
// Destroying our context will force a GC.
JS_DestroyContext(mContext);
mContext = nsnull;
mRuntimeService = nsnull;
}
mRuntimeService = nsnull;
#ifdef DEBUG_shaver_off
fprintf(stderr, "mJCL: UnloadAll(%d)\n", aWhen);
#endif
return NS_OK;
}
NS_IMETHODIMP
mozJSComponentLoader::Observe(nsISupports *subject, const char *topic,
const PRUnichar *data)
{
NS_ASSERTION(!strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID),
"Unexpected observer topic");
if (!strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
if (mFastLoadTimer) {
mFastLoadTimer->Cancel();
}
if (mFastLoadTimer) {
mFastLoadTimer->Cancel();
JS_GC(mContext);
CloseFastLoad();
}
else if (!strcmp(topic, "xpcom-shutdown-loaders")) {
UnloadModules();
}
else {
NS_ERROR("Unexpected observer topic.");
}
CloseFastLoad();
return NS_OK;
}
@ -1663,7 +1218,3 @@ JSCLContextHelper::~JSCLContextHelper()
if (mContextThread)
JS_EndRequest(mContext);
}
//----------------------------------------------------------------------
/* XXX this should all be data-driven, via NS_IMPL_GETMODULE_WITH_CATEGORIES */

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

@ -1,4 +1,4 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -39,14 +39,12 @@
#include "plhash.h"
#include "jsapi.h"
#include "nsIComponentLoader.h"
#include "nsIComponentLoaderManager.h"
#include "nsIModuleLoader.h"
#include "nsIJSRuntimeService.h"
#include "nsIJSContextStack.h"
#include "nsISupports.h"
#include "nsIXPConnect.h"
#include "nsIModule.h"
#include "nsSupportsArray.h"
#include "nsIFile.h"
#include "nsAutoPtr.h"
#include "nsIFastLoadService.h"
@ -54,6 +52,7 @@
#include "nsIObjectOutputStream.h"
#include "nsITimer.h"
#include "nsIObserver.h"
#include "nsClassHashtable.h"
#ifndef XPCONNECT_STANDALONE
#include "nsIPrincipal.h"
#endif
@ -89,29 +88,26 @@ class nsXPCFastLoadIO : public nsIFastLoadFileIO
};
class mozJSComponentLoader : public nsIComponentLoader,
class mozJSComponentLoader : public nsIModuleLoader,
public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICOMPONENTLOADER
NS_DECL_NSIMODULELOADER
NS_DECL_NSIOBSERVER
mozJSComponentLoader();
virtual ~mozJSComponentLoader();
protected:
static mozJSComponentLoader* sSelf;
nsresult ReallyInit();
nsresult AttemptRegistration(nsIFile *component, PRBool deferred);
nsresult UnregisterComponent(nsIFile *component);
nsresult RegisterComponentsInDir(PRInt32 when, nsIFile *dir);
nsresult GlobalForLocation(const char *aLocation, nsIFile *aComponent,
JSObject **aGlobal);
nsIModule* ModuleForLocation(const char *aLocation, nsIFile *component,
nsresult *status);
PRBool HasChanged(const char *registryLocation, nsIFile *component);
nsresult SetRegistryInfo(const char *registryLocation, nsIFile *component);
nsresult RemoveRegistryInfo(nsIFile *component, const char *registryLocation);
void UnloadModules();
nsresult GlobalForLocation(nsILocalFile *aComponent,
JSObject **aGlobal,
char **location);
nsresult StartFastLoad(nsIFastLoadService *flSvc);
nsresult ReadScript(nsIFastLoadService *flSvc, const char *nativePath,
@ -123,7 +119,6 @@ class mozJSComponentLoader : public nsIComponentLoader,
void CloseFastLoad();
nsCOMPtr<nsIComponentManager> mCompMgr;
nsCOMPtr<nsIComponentLoaderManager> mLoaderManager;
nsCOMPtr<nsIJSRuntimeService> mRuntimeService;
nsCOMPtr<nsIFile> mFastLoadFile;
nsRefPtr<nsXPCFastLoadIO> mFastLoadIO;
@ -135,9 +130,33 @@ class mozJSComponentLoader : public nsIComponentLoader,
#endif
JSRuntime *mRuntime;
JSContext *mContext;
PLHashTable *mModules;
PLHashTable *mGlobals;
class ModuleEntry
{
public:
ModuleEntry() {
global = nsnull;
location = nsnull;
}
~ModuleEntry() {
module = nsnull;
if (global) {
JS_ClearScope(sSelf->mContext, global);
JS_RemoveRoot(sSelf->mContext, &global);
}
if (location)
NS_Free(location);
}
nsCOMPtr<nsIModule> module;
JSObject *global;
char *location;
};
nsClassHashtable<nsHashableHashKey, ModuleEntry> mModules;
PRBool mInitialized;
nsSupportsArray mDeferredComponents;
};

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

@ -64,7 +64,7 @@ RegisterJSLoader(nsIComponentManager *aCompMgr, nsIFile *aPath,
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
nsXPIDLCString previous;
return catman->AddCategoryEntry("component-loader",
return catman->AddCategoryEntry("module-loader",
MOZJSCOMPONENTLOADER_TYPE_NAME,
MOZJSCOMPONENTLOADER_CONTRACTID,
PR_TRUE, PR_TRUE, getter_Copies(previous));
@ -80,14 +80,14 @@ UnregisterJSLoader(nsIComponentManager *aCompMgr, nsIFile *aPath,
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
nsXPIDLCString jsLoader;
rv = catman->GetCategoryEntry("component-loader",
rv = catman->GetCategoryEntry("module-loader",
MOZJSCOMPONENTLOADER_TYPE_NAME,
getter_Copies(jsLoader));
if (NS_FAILED(rv)) return rv;
// only unregister if we're the current JS component loader
if (!strcmp(jsLoader, MOZJSCOMPONENTLOADER_CONTRACTID)) {
return catman->DeleteCategoryEntry("component-loader",
return catman->DeleteCategoryEntry("module-loader",
MOZJSCOMPONENTLOADER_TYPE_NAME,
PR_TRUE);
}

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

@ -63,7 +63,7 @@
#include "nsISupportsUtils.h"
#include "nsTraceRefcntImpl.h"
#if defined(__GNUC__) && defined(__i386)
#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64__))
# define DebugBreak() { asm("int $3"); }
#elif defined(__APPLE__) && defined(TARGET_CARBON)
# include "MacTypes.h"

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

@ -268,9 +268,4 @@ NS_GetFrozenFunctions(XPCOMFunctions *entryPoints, const char* libraryPath);
#endif
#endif
nsresult
NewStaticComponentLoader(nsStaticModuleInfo const *aStaticModules,
PRUint32 aStaticModuleCount,
nsIComponentLoader **retval);
#endif

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

@ -284,8 +284,8 @@ static PRBool CheckUpdateFile()
return PR_FALSE;
}
// Don't need to check whether compreg exists; if it doesn't
// we won't even be here.
if (NS_FAILED(compregFile->Exists(&exists)) || !exists)
return PR_TRUE;
PRInt64 compregModTime, autoregModTime;
compregFile->GetLastModifiedTime(&compregModTime);
@ -619,98 +619,18 @@ NS_InitXPCOM3(nsIServiceManager* *result,
NS_INIPARSERFACTORY_CONTRACTID,
iniParserFactory);
}
rv = nsComponentManagerImpl::gComponentManager->ReadPersistentRegistry();
#ifdef DEBUG
if (NS_FAILED(rv)) {
printf("No Persistent Registry Found.\n");
}
#endif
if ( NS_FAILED(rv) || CheckUpdateFile()) {
// if we find no persistent registry, we will try to autoregister
// the default components directory.
nsComponentManagerImpl::gComponentManager->AutoRegister(nsnull);
// If the application is using a GRE, then,
// auto register components in the GRE directory as well.
//
// The application indicates that it's using an GRE by
// returning a valid nsIFile when queried (via appFileLocProvider)
// for the NS_GRE_DIR atom as shown below
//
if ( appFileLocationProvider ) {
nsCOMPtr<nsIFile> greDir;
PRBool persistent = PR_TRUE;
appFileLocationProvider->GetFile(NS_GRE_DIR, &persistent, getter_AddRefs(greDir));
if (greDir) {
#ifdef DEBUG_dougt
printf("start - Registering GRE components\n");
#endif
rv = nsDirectoryService::gService->Get(NS_GRE_COMPONENT_DIR,
NS_GET_IID(nsIFile),
getter_AddRefs(greDir));
if (NS_FAILED(rv)) {
NS_ERROR("Could not get GRE components directory!");
return rv;
}
// If the GRE contains any loaders, we want to know about it so that we can cause another
// autoregistration of the applications component directory.
int loaderCount = nsComponentManagerImpl::gComponentManager->GetLoaderCount();
rv = nsComponentManagerImpl::gComponentManager->AutoRegister(greDir);
if (loaderCount != nsComponentManagerImpl::gComponentManager->GetLoaderCount())
nsComponentManagerImpl::gComponentManager->AutoRegisterNonNativeComponents(nsnull);
#ifdef DEBUG_dougt
printf("end - Registering GRE components\n");
#endif
if (NS_FAILED(rv)) {
NS_ERROR("Could not AutoRegister GRE components");
return rv;
}
}
}
//
// If additional component directories have been specified, then
// register them as well.
//
nsCOMPtr<nsISimpleEnumerator> dirList;
nsDirectoryService::gService->Get(NS_XPCOM_COMPONENT_DIR_LIST,
NS_GET_IID(nsISimpleEnumerator),
getter_AddRefs(dirList));
if (dirList) {
PRBool hasMore;
while (NS_SUCCEEDED(dirList->HasMoreElements(&hasMore)) && hasMore) {
nsCOMPtr<nsISupports> elem;
dirList->GetNext(getter_AddRefs(elem));
if (elem) {
nsCOMPtr<nsIFile> dir = do_QueryInterface(elem);
if (dir)
nsComponentManagerImpl::gComponentManager->AutoRegister(dir);
// XXX should we worry about new component loaders being
// XXX defined by this process?
}
}
}
// Make sure the compreg file's mod time is current.
nsCOMPtr<nsIFile> compregFile;
rv = nsDirectoryService::gService->Get(NS_XPCOM_COMPONENT_REGISTRY_FILE,
NS_GET_IID(nsIFile),
getter_AddRefs(compregFile));
compregFile->SetLastModifiedTime(PR_Now() / 1000);
}
// Pay the cost at startup time of starting this singleton.
(void) xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef();
nsIInterfaceInfoManager* iim =
xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef();
if (CheckUpdateFile() || NS_FAILED(
nsComponentManagerImpl::gComponentManager->ReadPersistentRegistry())) {
// If the component registry is out of date, malformed, or incomplete,
// autoregister the default component directories.
(void) iim->AutoRegisterInterfaces();
nsComponentManagerImpl::gComponentManager->AutoRegister(nsnull);
}
// After autoreg, but before we actually instantiate any components,
// add any services listed in the "xpcom-directory-providers" category
@ -852,16 +772,16 @@ NS_ShutdownXPCOM(nsIServiceManager* servMgr)
// here again:
NS_IF_RELEASE(servMgr);
// Shutdown global servicemanager
if (nsComponentManagerImpl::gComponentManager) {
nsComponentManagerImpl::gComponentManager->FreeServices();
}
if (currentQ) {
currentQ->ProcessPendingEvents();
currentQ = 0;
}
// Shutdown global servicemanager
if (nsComponentManagerImpl::gComponentManager) {
nsComponentManagerImpl::gComponentManager->FreeServices();
}
nsProxyObjectManager::Shutdown();
// Release the directory service

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

@ -57,21 +57,17 @@ CPPSRCS = \
nsNativeComponentLoader.cpp \
nsStaticComponentLoader.cpp \
nsServiceManagerObsolete.cpp \
xcDll.cpp \
$(NULL)
EXPORTS = \
nsCategoryManagerUtils.h \
nsIServiceManagerObsolete.h \
nsModule.h \
nsNativeComponentLoader.h \
nsObsoleteModuleLoading.h \
xcDll.h \
$(NULL)
XPIDLSRCS = \
nsIComponentLoader.idl \
nsIComponentLoaderManager.idl \
nsIModuleLoader.idl \
nsIComponentManagerObsolete.idl \
$(NULL)

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -40,15 +40,17 @@
#include "nsXPCOM.h"
#include "nsIComponentLoader.h"
#include "xpcom-private.h"
#include "nsNativeComponentLoader.h"
#include "nsIComponentManager.h"
#include "nsIComponentRegistrar.h"
#include "nsIComponentManagerObsolete.h"
#include "nsIComponentLoaderManager.h"
#include "nsCategoryManager.h"
#include "nsIServiceManager.h"
#include "nsILocalFile.h"
#include "nsIModule.h"
#include "nsIModuleLoader.h"
#include "nsStaticComponentLoader.h"
#include "nsNativeComponentLoader.h"
#include "nsIFactory.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
@ -57,12 +59,13 @@
#include "prmon.h"
#include "nsCOMPtr.h"
#include "nsWeakReference.h"
#include "nsXPIDLString.h"
#include "nsIFile.h"
#include "plarena.h"
#include "nsCOMArray.h"
#include "nsDataHashtable.h"
#include "nsTArray.h"
class nsFactoryEntry;
class nsDll;
struct nsFactoryEntry;
class nsIServiceManager;
#define NS_COMPONENTMANAGER_CID \
@ -81,14 +84,12 @@ extern const char fileSizeValueName[];
extern const char nativeComponentType[];
extern const char staticComponentType[];
// Predefined loader types. Do not change the numbers.
// NATIVE should be 0 as it is being used as the first array index.
#define NS_COMPONENT_TYPE_NATIVE 0
#define NS_COMPONENT_TYPE_FACTORY_ONLY -1
// this define means that the factory entry only has a ContractID
// to service mapping and has no cid mapping.
#define NS_COMPONENT_TYPE_SERVICE_ONLY -2
typedef int LoaderType;
// Predefined loader types.
#define NS_LOADER_TYPE_NATIVE -1
#define NS_LOADER_TYPE_STATIC -2
#define NS_LOADER_TYPE_INVALID -3
#ifdef DEBUG
#define XPCOM_CHECK_PENDING_CIDS
@ -97,8 +98,22 @@ extern const char staticComponentType[];
// Array of Loaders and their type strings
struct nsLoaderdata {
nsIComponentLoader *loader;
const char *type;
nsCOMPtr<nsIModuleLoader> loader;
nsCString type;
};
// Deferred modules are kept as a nsTArray of this type. This is not a nested
// class so that nsStaticComponentLoader.h can forward-declare it.
struct DeferredModule
{
DeferredModule() :
type(nsnull), modTime(0) { }
const char *type;
nsCOMPtr<nsILocalFile> file;
nsCString location;
nsCOMPtr<nsIModule> module;
PRInt64 modTime;
};
class nsComponentManagerImpl
@ -107,7 +122,6 @@ class nsComponentManagerImpl
public nsIComponentRegistrar,
public nsSupportsWeakReference,
public nsIInterfaceRequestor,
public nsIComponentLoaderManager,
public nsIServiceManagerObsolete,
public nsIComponentManagerObsolete
{
@ -143,9 +157,13 @@ public:
NS_IMETHOD CIDToContractID(const nsCID & aClass, char **_retval);
NS_IMETHOD ContractIDToCID(const char *aContractID, nsCID * *_retval);
nsresult RegistryLocationForFile(nsIFile* aFile,
nsCString& aResult);
nsresult FileForRegistryLocation(const nsCString &aLocation,
nsILocalFile **aSpec);
NS_DECL_NSISERVICEMANAGER
NS_DECL_NSISERVICEMANAGEROBSOLETE
NS_DECL_NSICOMPONENTLOADERMANAGER
// nsComponentManagerImpl methods:
nsComponentManagerImpl();
@ -153,6 +171,8 @@ public:
static nsComponentManagerImpl* gComponentManager;
nsresult Init(nsStaticModuleInfo const *aStaticModules,
PRUint32 aStaticModuleCount);
// NOTE: XPCOM initialization must call either ReadPersistentRegistry or
// AutoRegister to fully initialize the nsComponentManagerImpl.
nsresult WritePersistentRegistry();
nsresult ReadPersistentRegistry();
@ -172,8 +192,18 @@ public:
PRUint32 aRegistryNameLen,
PRBool aReplace, PRBool aPersist,
const char *aType);
nsresult GetLoaderForType(int aType,
nsIComponentLoader **aLoader);
// Convert a loader type string into an index into the loader data
// array. Empty loader types are converted to NATIVE. Returns
// NS_LOADER_TYPE_INVALID if loader type cannot be determined.
LoaderType GetLoaderType(const char *typeStr);
LoaderType AddLoaderType(const char *typeStr);
const char* StringForLoaderType(LoaderType aType) {
return mLoaderData[aType].type.get();
}
nsIModuleLoader* LoaderForType(LoaderType aType);
int GetLoaderCount() { return mLoaderData.Length(); }
void GetAllLoaders();
nsresult FindFactory(const char *contractID, PRUint32 aContractIDLen, nsIFactory **aFactory) ;
nsresult LoadFactory(nsFactoryEntry *aEntry, nsIFactory **aFactory);
@ -182,40 +212,31 @@ public:
nsFactoryEntry *GetFactoryEntry(const nsCID &aClass);
nsresult SyncComponentsInDir(PRInt32 when, nsIFile *dirSpec);
nsresult SelfRegisterDll(nsDll *dll);
nsresult SelfUnregisterDll(nsDll *dll);
nsresult HashContractID(const char *acontractID, PRUint32 aContractIDLen,
nsFactoryEntry *fe_ptr);
void DeleteContractIDEntriesByCID(const nsCID* aClass, nsIFactory* factory);
nsresult AutoRegisterImpl(nsIFile* inDirSpec,
nsCOMArray<nsILocalFile> &aLeftovers,
nsTArray<DeferredModule> &aDeferred);
nsresult AutoRegisterDirectory(nsIFile* aComponentFile,
nsCOMArray<nsILocalFile> &aLeftovers,
nsTArray<DeferredModule> &aDeferred);
nsresult AutoRegisterComponent(nsILocalFile* aComponentFile,
nsTArray<DeferredModule> &aDeferred,
LoaderType minLoader = NS_LOADER_TYPE_NATIVE);
void LoadLeftoverComponents(nsCOMArray<nsILocalFile> &aLeftovers,
nsTArray<DeferredModule> &aDeferred,
LoaderType minLoader);
nsresult UnloadLibraries(nsIServiceManager *servmgr, PRInt32 when);
// Convert a loader type string into an index into the loader data
// array. Empty loader types are converted to NATIVE. Returns -1 if
// loader type cannot be determined.
int GetLoaderType(const char *typeStr);
// Add a loader type if not already known. Out the typeIndex
// if the loader type is either added or already there;
// returns NS_OK or an error on failure.
nsresult AddLoaderType(const char *typeStr, int *typeIndex);
int GetLoaderCount() { return mNLoaderData + 1; }
// registers only the files in spec's location by loaders other than the
// native loader. This is an optimization method only.
nsresult AutoRegisterNonNativeComponents(nsIFile* spec);
nsresult AutoRegisterImpl(PRInt32 when, nsIFile *inDirSpec, PRBool fileIsCompDir=PR_TRUE);
nsresult RemoveEntries(nsIFile* file);
void LoadDeferredModules(nsTArray<DeferredModule> &aDeferred);
PLDHashTable mFactories;
PLDHashTable mContractIDs;
PRMonitor* mMon;
nsNativeComponentLoader *mNativeComponentLoader;
nsIComponentLoader *mStaticComponentLoader;
nsNativeModuleLoader mNativeModuleLoader;
nsStaticModuleLoader mStaticModuleLoader;
nsCOMPtr<nsIFile> mComponentsDir;
PRInt32 mComponentsOffset;
@ -230,12 +251,11 @@ public:
#define NS_SHUTDOWN_COMPLETE 2
PRUint32 mShuttingDown;
nsLoaderdata *mLoaderData;
int mNLoaderData;
int mMaxNLoaderData;
nsTArray<nsLoaderdata> mLoaderData;
nsDataHashtable<nsHashableHashKey, PRInt64> mAutoRegEntries;
PRBool mRegistryDirty;
nsHashtable mAutoRegEntries;
nsCOMPtr<nsCategoryManager> mCategoryManager;
PLArenaPool mArena;
@ -271,51 +291,35 @@ private:
* These are strictly session specific and in memory only.
*/
class nsFactoryEntry {
public:
nsFactoryEntry(const nsCID &aClass,
const char *location, PRUint32 locationlen, int aType, class nsFactoryEntry* parent = nsnull);
nsFactoryEntry(const nsCID &aClass, nsIFactory *aFactory, class nsFactoryEntry* parent = nsnull);
~nsFactoryEntry();
struct nsFactoryEntry {
nsFactoryEntry(const nsCID &aClass,
LoaderType aLoaderType,
const char *aLocationKey,
nsFactoryEntry *aParent = nsnull);
nsresult ReInit(const nsCID &aClass, const char *location, int aType);
nsresult GetFactory(nsIFactory **aFactory,
nsComponentManagerImpl * mgr) {
if (mFactory) {
*aFactory = mFactory.get();
NS_ADDREF(*aFactory);
return NS_OK;
}
if (mTypeIndex < 0)
return NS_ERROR_FAILURE;
nsresult rv;
nsCOMPtr<nsIComponentLoader> loader;
rv = mgr->GetLoaderForType(mTypeIndex, getter_AddRefs(loader));
if(NS_FAILED(rv))
return rv;
rv = loader->GetFactory(mCid, mLocation, mgr->mLoaderData[mTypeIndex].type, aFactory);
if (NS_FAILED(rv))
return rv;
NS_ASSERTION(*aFactory, "Loader says it succeeded; got null factory!");
mFactory = do_QueryInterface(*aFactory);
if (!mFactory)
return NS_ERROR_NO_INTERFACE;
return NS_OK;
nsFactoryEntry(const nsCID &aClass,
nsIFactory *aFactory,
nsFactoryEntry *aParent = nsnull) :
mCid(aClass),
mLoaderType(NS_LOADER_TYPE_INVALID),
mFactory(aFactory),
mParent(aParent) {
mLocationKey = nsnull;
}
nsCID mCid;
nsCOMPtr<nsIFactory> mFactory;
// This is an index into the mLoaderData array that holds the type string and the loader
int mTypeIndex;
nsCOMPtr<nsISupports> mServiceObject;
char* mLocation;
class nsFactoryEntry* mParent;
~nsFactoryEntry();
void ReInit(LoaderType aLoaderType,
const char *aLocationKey);
nsresult GetFactory(nsIFactory **aFactory);
nsCID mCid;
LoaderType mLoaderType;
const char *mLocationKey;
nsCOMPtr<nsIFactory> mFactory;
nsCOMPtr<nsISupports> mServiceObject;
nsFactoryEntry *mParent;
};
////////////////////////////////////////////////////////////////////////////////
@ -330,29 +334,5 @@ struct nsContractIDTableEntry : public PLDHashEntryHdr {
nsFactoryEntry *mFactoryEntry;
};
class AutoRegEntry
{
public:
AutoRegEntry(const nsACString& name, PRInt64* modDate);
~AutoRegEntry();
const nsDependentCString GetName()
{ return nsDependentCString(mName, mNameLen); }
PRInt64 GetDate() {return mModDate;}
void SetDate(PRInt64 *date) { mModDate = *date;}
PRBool Modified(PRInt64 *date);
// this is the optional field line in the compreg.dat.
// it must not contain any comma's and it must be null terminated.
char* GetOptionalData() {return mData;};
void SetOptionalData(const char* data);
private:
char* mName;
PRUint32 mNameLen;
char* mData;
PRInt64 mModDate;
};
#endif // nsComponentManager_h__

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

@ -1,109 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org Code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "nsIFactory.idl"
#include "nsIFile.idl"
#include "nsIComponentManager.idl"
[object, uuid(c073cfc0-567c-11d3-aec1-0000f8e25c06)]
interface nsIComponentLoader : nsISupports {
/**
* Get the factory for a given component.
*/
nsIFactory getFactory(in nsIIDRef aCID, in string aLocation,
in string aType);
/**
* Initialize the loader.
*
* We use nsISupports here because nsIRegistry isn't IDLized yet.
*/
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,
in string aClassName, in string aContractID,
in string aLocation, in boolean aReplace,
in boolean aPersist);
/**
* When is AutoRegistration occuring?
*/
const long Startup = 0;
const long Component = 1;
const long Timer = 2;
/**
* AutoRegister components in the given directory.
*/
void autoRegisterComponents(in long aWhen, in nsIFile aDirectory);
/**
* AutoRegister the given component.
*
* Returns true if the component was registered, false if it couldn't
* 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 nsIFile aComponent);
/**
* AutoUnregister the given component.
* Returns true if the component was unregistered, false if it coudln't
* attempt to unregister the component (not found, wrong type).
*/
boolean autoUnregisterComponent(in long aWhen, in nsIFile 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);
};

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

@ -61,13 +61,12 @@ interface nsIComponentRegistrar : nsISupports
*
* @param aSpec : Filename spec for component file's location. If aSpec
* is a directory, then every component file in the
* directory will be registered.
* If the aSpec is null, then the application component's
* directory as defined by NS_XPCOM_COMPONENT_DIR will be
* registered (see nsIDirectoryService.idl)
*
* @return NS_OK : Registration was successful.
* NS_ERROR: Method failure.
* directory will be registered.
* If aSpec is null, static components, GRE components,
* and the application's component directories will be
* registered. See NS_GRE_DIR, NS_XPCOM_COMPONENT_DIR,
* and NS_XPCOM_COMPONENT_DIR_LIST in
* nsDirectoryServiceDefs.h.
*/
void autoRegister(in nsIFile aSpec);

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

@ -11,11 +11,13 @@
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is XPCOM.
* The Original Code is Mozilla XPCOM.
*
* The Initial Developer of the Original Code is Netscape Communications.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
* The Initial Developer of the Original Code is
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* Portions created by the Initial Developer are Copyright (C) 2005
* the Mozilla Foundation <http://www.mozilla.org/>. All Rights Reserved.
*
* Contributor(s):
*
@ -33,40 +35,30 @@
*
* ***** END LICENSE BLOCK ***** */
/**
* The nsIComponentRegistrar interface.
* @status EXPERIMENTAL
*
* USE AT YOUR OWN RISK
* USE AT YOUR OWN RISK
* USE AT YOUR OWN RISK
* USE AT YOUR OWN RISK
* USE AT YOUR OWN RISK
* USE AT YOUR OWN RISK
*/
#include "nsISupports.idl"
interface nsIFile;
interface nsILocalFile;
interface nsIModule;
[uuid(fce83d37-a3c0-4e09-ad9f-6842a984dbdf)]
interface nsIComponentLoaderManager : nsISupports
/**
* Module loaders are responsible for loading a component file. The static
* component loader is special and does not use this interface.
*
* @note Implementations of this interface should be threadsafe,
* methods may be called from any thread.
*/
[scriptable, uuid(9b328e24-4d85-4a9c-9cb7-f25e66f430c3)]
interface nsIModuleLoader : nsISupports
{
boolean hasFileChanged(in nsIFile file, in string loaderString, in PRInt64 modDate);
void saveFileInfo(in nsIFile file, in string loaderString, in PRInt64 modDate);
void removeFileInfo(in nsIFile file, in string loaderString);
void flushPersistentStore(in boolean now);
string getOptionalData(in nsIFile file, in string loaderString);
void setOptionalData(in nsIFile file, in string loaderString, in string value);
/**
* Return the module for a specified file. The module loader should
* cache the module and return the same module for subsequent
* requests for the same physical file. The module loader is
* responsible for unloading the module during shutdown.
*
* @throws NS_ERROR_INVALID_ARG If the filename is not recognized.
* @throws NS_ERROR_FACTORY_NOT_LOADED If the filename is recognized but
* the module fails to load, e.g.: missing symbols, syntax errors
*/
nsIModule loadModule(in nsILocalFile aFile);
};

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -35,48 +35,43 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsNativeModuleLoader_h__
#define nsNativeModuleLoader_h__
#include "nsISupports.h"
#include "nsIComponentLoader.h"
#include "nsIComponentManager.h"
#include "nsDirectoryService.h"
#include "nsCOMPtr.h"
#include "nsHashtable.h"
#include "nsIModuleLoader.h"
#include "nsVoidArray.h"
#include "xcDll.h"
#include "nsDataHashtable.h"
#include "nsHashKeys.h"
#include "prlink.h"
#ifndef nsNativeComponentLoader_h__
#define nsNativeComponentLoader_h__
class nsNativeComponentLoader : public nsIComponentLoader
class nsNativeModuleLoader : public nsIModuleLoader
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICOMPONENTLOADER
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIMODULELOADER
nsNativeComponentLoader();
nsIComponentManager* mCompMgr; // weak reference -- backpointer
nsNativeModuleLoader() {}
~nsNativeModuleLoader() {}
nsresult Init();
void UnloadLibraries();
private:
nsObjectHashtable mDllStore;
nsVoidArray mDeferredComponents;
struct NativeLoadData
{
nsCOMPtr<nsIModule> module;
PRLibrary *library;
};
~nsNativeComponentLoader() {}
static PLDHashOperator
ReleaserFunc(nsIHashable* aHashedFile, NativeLoadData &aLoadData, void*);
NS_IMETHOD RegisterComponentsInDir(PRInt32 when, nsIFile *dir);
static PLDHashOperator
UnloaderFunc(nsIHashable* aHashedFile, NativeLoadData &aLoadData, void*);
nsresult CreateDll(nsIFile *aSpec, const char *aLocation, nsDll **aDll);
nsresult SelfRegisterDll(nsDll *dll, const char *registryLocation,
PRBool deferred);
nsresult SelfUnregisterDll(nsDll *dll);
nsresult GetFactoryFromModule(nsDll *aDll, const nsCID &aCID,
nsIFactory **aFactory);
nsresult DumpLoadError(nsDll *dll,
const char *aCallerName,
const char *aNsprErrorMsg);
nsDataHashtable<nsHashableHashKey, NativeLoadData> mLibraries;
};
#endif /* nsNativeComponentLoader_h__ */
#endif /* nsNativeModuleLoader_h__ */

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

@ -38,6 +38,7 @@
#include "nsIServiceManager.h"
#include "nsIServiceManagerObsolete.h"
#include "nsComponentManager.h"
#include "nsIModule.h"
extern PRBool gXPCOMShuttingDown;

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

@ -36,13 +36,14 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsXPCOMPrivate.h"
#include "nsStaticComponentLoader.h"
#include "nsComponentManager.h"
#include "nsCOMPtr.h"
#include "pldhash.h"
#include "nsIComponentLoader.h"
#include "nsIModule.h"
#include "nsVoidArray.h"
#include "pldhash.h"
#include NEW_H
#include "prlog.h"
@ -62,37 +63,6 @@ struct StaticModuleInfo : public PLDHashEntryHdr {
StaticModuleInfo *next;
};
class nsStaticComponentLoader : public nsIComponentLoader
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICOMPONENTLOADER
nsStaticComponentLoader() :
mAutoRegistered(PR_FALSE),
mFirst(nsnull)
{ }
nsresult Init(nsStaticModuleInfo const *aStaticModules,
PRUint32 aModuleCount);
private:
~nsStaticComponentLoader() {
if (mInfoHash.ops)
PL_DHashTableFinish(&mInfoHash);
}
protected:
nsresult GetInfoFor(const char *aLocation, StaticModuleInfo **retval);
PRBool mAutoRegistered;
nsCOMPtr<nsIComponentManager> mComponentMgr;
PLDHashTable mInfoHash;
static PLDHashTableOps sInfoHashOps;
nsVoidArray mDeferredComponents;
StaticModuleInfo *mFirst;
};
PR_STATIC_CALLBACK(void)
info_ClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
{
@ -109,18 +79,16 @@ info_InitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, const void *key)
return PR_TRUE;
}
/* static */ PLDHashTableOps nsStaticComponentLoader::sInfoHashOps = {
/* static */ PLDHashTableOps nsStaticModuleLoader::sInfoHashOps = {
PL_DHashAllocTable, PL_DHashFreeTable,
PL_DHashGetKeyStub, PL_DHashStringKey, PL_DHashMatchStringKey,
PL_DHashMoveEntryStub, info_ClearEntry,
PL_DHashFinalizeStub, info_InitEntry
};
NS_IMPL_THREADSAFE_ISUPPORTS1(nsStaticComponentLoader, nsIComponentLoader)
nsresult
nsStaticComponentLoader::Init(nsStaticModuleInfo const *aStaticModules,
PRUint32 aModuleCount)
nsStaticModuleLoader::Init(nsStaticModuleInfo const *aStaticModules,
PRUint32 aModuleCount)
{
if (!PL_DHashTableInit(&mInfoHash, &sInfoHashOps, nsnull,
sizeof(StaticModuleInfo), 1024)) {
@ -153,9 +121,26 @@ nsStaticComponentLoader::Init(nsStaticModuleInfo const *aStaticModules,
return NS_OK;
}
void
nsStaticModuleLoader::EnumerateModules(StaticLoaderCallback cb,
nsTArray<DeferredModule> &deferred)
{
for (StaticModuleInfo *c = mFirst; c; c = c->next) {
if (!c->module) {
nsresult rv = c->info.
getModule(nsComponentManagerImpl::gComponentManager, nsnull,
getter_AddRefs(c->module));
LOG(("nSCL: EnumerateModules(): %lx\n", rv));
if (NS_FAILED(rv))
continue;
}
cb(c->info.name, c->module, deferred);
}
}
nsresult
nsStaticComponentLoader::GetInfoFor(const char *aLocation,
StaticModuleInfo **retval)
nsStaticModuleLoader::GetModuleFor(const char *aLocation,
nsIModule* *aResult)
{
nsresult rv;
StaticModuleInfo *info =
@ -167,146 +152,14 @@ nsStaticComponentLoader::GetInfoFor(const char *aLocation,
return NS_ERROR_FACTORY_NOT_REGISTERED;
if (!info->module) {
rv = info->info.getModule(mComponentMgr, nsnull,
getter_AddRefs(info->module));
LOG(("nSCL: GetInfoFor(\"%s\"): %lx\n", aLocation, rv));
rv = info->info.
getModule(nsComponentManagerImpl::gComponentManager, nsnull,
getter_AddRefs(info->module));
LOG(("nSCL: GetModuleForFor(\"%s\"): %lx\n", aLocation, rv));
if (NS_FAILED(rv))
return rv;
}
*retval = info;
return NS_OK;
}
NS_IMETHODIMP
nsStaticComponentLoader::Init(nsIComponentManager *mgr, nsISupports *aReg)
{
mComponentMgr = mgr;
return NS_OK;
}
NS_IMETHODIMP
nsStaticComponentLoader::AutoRegisterComponents(PRInt32 when, nsIFile *dir)
{
if (mAutoRegistered)
return NS_OK;
// if a directory has been explicitly specified, then return early. we
// don't load static components from disk ;)
if (dir)
return NS_OK;
nsresult rv;
StaticModuleInfo *info = mFirst;
while (info) {
if (!info->module) {
rv = info->info.getModule(mComponentMgr, nsnull, getter_AddRefs(info->module));
LOG(("nSCL: getModule(\"%s\"): %lx\n", info->info.name, rv));
if (NS_FAILED(rv) || !info->module)
continue; // oh well
}
rv = info->module->RegisterSelf(mComponentMgr, nsnull, info->info.name,
staticComponentType);
LOG(("nSCL: autoreg of \"%s\": %lx\n", info->info.name, rv));
if (rv == NS_ERROR_FACTORY_REGISTER_AGAIN)
mDeferredComponents.AppendElement(info);
info = info->next;
}
mAutoRegistered = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsStaticComponentLoader::AutoUnregisterComponent(PRInt32 when,
nsIFile *component,
PRBool *retval)
{
*retval = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsStaticComponentLoader::AutoRegisterComponent(PRInt32 when, nsIFile *component,
PRBool *retval)
{
*retval = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsStaticComponentLoader::RegisterDeferredComponents(PRInt32 when,
PRBool *aRegistered)
{
*aRegistered = PR_FALSE;
if (!mDeferredComponents.Count())
return NS_OK;
for (int i = mDeferredComponents.Count() - 1; i >= 0; i--) {
StaticModuleInfo *info = NS_STATIC_CAST(StaticModuleInfo *,
mDeferredComponents[i]);
nsresult rv = info->module->RegisterSelf(mComponentMgr, nsnull,
info->info.name,
staticComponentType);
if (rv != NS_ERROR_FACTORY_REGISTER_AGAIN) {
if (NS_SUCCEEDED(rv))
*aRegistered = PR_TRUE;
mDeferredComponents.RemoveElementAt(i);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsStaticComponentLoader::OnRegister(const nsCID &aCID, const char *aType,
const char *aClassName,
const char *aContractID,
const char *aLocation,
PRBool aReplace, PRBool aPersist)
{
return NS_OK;
}
NS_IMETHODIMP
nsStaticComponentLoader::UnloadAll(PRInt32 aWhen)
{
return NS_OK;
}
NS_IMETHODIMP
nsStaticComponentLoader::GetFactory(const nsCID &aCID, const char *aLocation,
const char *aType, nsIFactory **_retval)
{
StaticModuleInfo *info;
nsresult rv;
if (NS_FAILED(rv = GetInfoFor(aLocation, &info)))
return rv;
return info->module->GetClassObject(mComponentMgr, aCID,
NS_GET_IID(nsIFactory),
(void **)_retval);
}
nsresult
NewStaticComponentLoader(nsStaticModuleInfo const *aStaticModules,
PRUint32 aStaticModuleCount,
nsIComponentLoader **retval)
{
nsCOMPtr<nsStaticComponentLoader> lthis = new nsStaticComponentLoader();
if (!lthis)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = ((nsStaticComponentLoader*) lthis)->
Init(aStaticModules, aStaticModuleCount);
if (NS_FAILED(rv))
return rv;
NS_ADDREF(*retval = lthis);
NS_ADDREF(*aResult = info->module);
return NS_OK;
}

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

@ -0,0 +1,81 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org Code. This file was copied
* from nsStaticComponentLoader.cpp
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsStaticModuleLoader_h__
#define nsStaticModuleLoader_h__
#include "nsXPCOM.h"
#include "pldhash.h"
#include "nsTArray.h"
class nsIModule;
struct StaticModuleInfo;
class nsComponentManagerImpl;
struct DeferredModule;
typedef void (*StaticLoaderCallback)(const char *key,
nsIModule* module,
nsTArray<DeferredModule> &deferred);
class nsStaticModuleLoader
{
public:
nsStaticModuleLoader() :
mFirst(nsnull)
{ }
nsresult Init(nsStaticModuleInfo const *aStaticModules,
PRUint32 aModuleCount);
~nsStaticModuleLoader() {
if (mInfoHash.ops)
PL_DHashTableFinish(&mInfoHash);
}
void EnumerateModules(StaticLoaderCallback cb,
nsTArray<DeferredModule> &deferred);
nsresult GetModuleFor(const char *key, nsIModule* *aResult);
private:
PLDHashTable mInfoHash;
static PLDHashTableOps sInfoHashOps;
StaticModuleInfo *mFirst;
};
#endif

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

@ -1,336 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* nsDll
*
* Abstraction of a Dll. Stores modifiedTime and size for easy detection of
* change in dll.
*
* dp Suresh <dp@netscape.com>
*/
#include "xcDll.h"
#include "nsDebug.h"
#include "nsIComponentManager.h"
#include "nsIComponentLoaderManager.h"
#include "nsIModule.h"
#include "nsILocalFile.h"
#include "nsDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include "nsCOMPtr.h"
#include "nsCRT.h"
#include "nsString.h"
#include "nsITimelineService.h"
#include "nsModule.h"
#ifdef DEBUG
#if defined(VMS)
#include <lib$routines.h>
#include <ssdef.h>
#elif defined(XP_MACOSX)
#include <signal.h>
#endif
#endif /* defined(DEBUG) */
#include "nsTraceRefcntImpl.h"
#define UNLOAD_DEPENDENT_LIBS
#ifdef HPUX
#undef UNLOAD_DEPENDENT_LIBS
#endif
#include "nsNativeComponentLoader.h"
nsDll::nsDll(nsIFile *dllSpec, nsNativeComponentLoader *loader)
: m_dllSpec(do_QueryInterface(dllSpec)),
m_instance(NULL),
m_moduleObject(NULL),
m_loader(loader),
m_markForUnload(PR_FALSE)
{
NS_ASSERTION(loader, "Null loader when creating a nsDLL");
}
nsDll::~nsDll(void)
{
//#if DEBUG_dougt
// The dll gets deleted when the dllStore is destroyed. This happens on
// app shutdown. At that point, unloading dlls can cause crashes if we have
// - dll dependencies
// - callbacks
// - static dtors
// Hence turn it back on after all the above have been removed.
//Unload();
//#endif
}
void
nsDll::GetDisplayPath(nsACString& aLeafName)
{
m_dllSpec->GetNativeLeafName(aLeafName);
if (aLeafName.IsEmpty())
aLeafName.AssignLiteral("unknown!");
}
PRBool
nsDll::HasChanged()
{
nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(m_loader->mCompMgr);
if (!manager)
return PR_TRUE;
// If mod date has changed, then dll has changed
PRInt64 currentDate;
nsresult rv = m_dllSpec->GetLastModifiedTime(&currentDate);
if (NS_FAILED(rv))
return PR_TRUE;
PRBool changed = PR_TRUE;
manager->HasFileChanged(m_dllSpec, nsnull, currentDate, &changed);
return changed;
}
PRBool nsDll::Load(void)
{
if (m_instance != NULL)
{
// Already loaded
return (PR_TRUE);
}
if (m_dllSpec)
{
#ifdef NS_BUILD_REFCNT_LOGGING
nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
#endif
// load the component
nsCOMPtr<nsILocalFile> lf(do_QueryInterface(m_dllSpec));
NS_ASSERTION(lf, "nsIFile here must implement a nsILocalFile");
lf->Load(&m_instance);
#ifdef NS_BUILD_REFCNT_LOGGING
nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
if (m_instance) {
// Inform refcnt tracer of new library so that calls through the
// new library can be traced.
nsXPIDLCString displayPath;
GetDisplayPath(displayPath);
nsTraceRefcntImpl::LoadLibrarySymbols(displayPath.get(), m_instance);
}
#endif
}
#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
// Debugging help for components. Component dlls need to have their
// symbols loaded before we can put a breakpoint in the debugger.
// This will help figureing out the point when the dll was loaded.
nsXPIDLCString displayPath;
GetDisplayPath(displayPath);
BreakAfterLoad(displayPath.get());
#endif
return ((m_instance == NULL) ? PR_FALSE : PR_TRUE);
}
PRBool nsDll::Unload(void)
{
if (m_instance == NULL)
return (PR_FALSE);
// Shutdown the dll
Shutdown();
#ifdef NS_BUILD_REFCNT_LOGGING
nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
#endif
PRStatus ret = PR_UnloadLibrary(m_instance);
#ifdef NS_BUILD_REFCNT_LOGGING
nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
#endif
if (ret == PR_SUCCESS)
{
m_instance = NULL;
return (PR_TRUE);
}
else
return (PR_FALSE);
}
void * nsDll::FindSymbol(const char *symbol)
{
if (symbol == NULL)
return (NULL);
// If not already loaded, load it now.
if (Load() != PR_TRUE)
return (NULL);
return(PR_FindSymbol(m_instance, symbol));
}
// Component dll specific functions
nsresult nsDll::GetDllSpec(nsIFile **fsobj)
{
NS_ASSERTION(m_dllSpec, "m_dllSpec NULL");
NS_ASSERTION(fsobj, "xcDll::GetModule : Null argument" );
*fsobj = m_dllSpec;
NS_ADDREF(*fsobj);
return NS_OK;
}
nsresult nsDll::GetModule(nsISupports *servMgr, nsIModule **cobj)
{
// using the backpointer of the loader.
nsIComponentManager* compMgr = m_loader->mCompMgr;
NS_ASSERTION(compMgr, "Global Component Manager is null" );
if (!compMgr) return NS_ERROR_UNEXPECTED;
NS_ASSERTION(cobj, "xcDll::GetModule : Null argument" );
if (m_moduleObject)
{
NS_ADDREF(m_moduleObject);
*cobj = m_moduleObject;
return NS_OK;
}
// If not already loaded, load it now.
if (Load() != PR_TRUE) return NS_ERROR_FAILURE;
// We need a nsIFile for location
if (!m_dllSpec)
{
return NS_ERROR_FAILURE;
}
nsGetModuleProc proc =
(nsGetModuleProc) FindSymbol(NS_GET_MODULE_SYMBOL);
if (proc == NULL)
return NS_ERROR_FACTORY_NOT_LOADED;
nsresult rv = (*proc) (compMgr, m_dllSpec, &m_moduleObject);
if (NS_SUCCEEDED(rv))
{
NS_ADDREF(m_moduleObject);
*cobj = m_moduleObject;
}
return rv;
}
// These are used by BreakAfterLoad, below.
#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
static nsCString *sBreakList[16];
static int sBreakListCount = 0;
#endif
nsresult nsDll::Shutdown(void)
{
// Release the module object if we got one
nsrefcnt refcnt;
if (m_moduleObject)
{
NS_RELEASE2(m_moduleObject, refcnt);
NS_ASSERTION(refcnt == 0, "Dll moduleObject refcount non zero");
}
#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
for (int i = 0; i < sBreakListCount; i++)
{
delete sBreakList[i];
sBreakList[i] = nsnull;
}
sBreakListCount = 0;
#endif
return NS_OK;
}
#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
void nsDll::BreakAfterLoad(const char *nsprPath)
{
static PRBool firstTime = PR_TRUE;
// return if invalid input
if (!nsprPath || !*nsprPath) return;
// return if nothing to break on
if (!firstTime && sBreakListCount == 0) return;
if (firstTime)
{
firstTime = PR_FALSE;
// Form the list of dlls to break on load
nsCAutoString envList(getenv("XPCOM_BREAK_ON_LOAD"));
if (envList.IsEmpty()) return;
PRInt32 ofset = 0;
PRInt32 start = 0;
do
{
ofset = envList.FindChar(':', start);
sBreakList[sBreakListCount] = new nsCString();
envList.Mid(*(sBreakList[sBreakListCount]), start, ofset);
sBreakListCount++;
start = ofset + 1;
}
while (ofset != -1 && 16 > sBreakListCount); // avoiding vc6.0 compiler issue. count < thinks it is starting a template
}
// Find the dllname part of the string
nsCString currentPath(nsprPath);
PRInt32 lastSep = currentPath.RFindCharInSet(":\\/");
for (int i=0; i<sBreakListCount; i++)
if (currentPath.Find(*(sBreakList[i]), PR_TRUE, lastSep) > 0)
{
// Loading a dll that we want to break on
// Put your breakpoint here
fprintf(stderr, "...Loading module %s\n", nsprPath);
// Break in the debugger here.
#if defined(__i386) && defined(__GNUC__)
asm("int $3");
#elif defined(VMS)
lib$signal(SS$_DEBUG);
#elif defined(XP_MACOSX)
raise(SIGTRAP);
#endif
}
return;
}
#endif /* SHOULD_IMPLEMENT_BREAKAFTERLOAD */

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

@ -1,121 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* Dll
*
* Programmatic representation of a dll. Stores modifiedTime and size for
* easy detection of change in dll.
*
* dp Suresh <dp@netscape.com>
*/
#ifndef xcDll_h__
#define xcDll_h__
#include "prio.h"
#include "prlink.h"
#include "nsISupports.h"
#include "nsILocalFile.h"
#include "nsCOMPtr.h"
#include "nsString.h"
class nsNativeComponentLoader;
#if defined(DEBUG) && !defined(XP_BEOS)
#define SHOULD_IMPLEMENT_BREAKAFTERLOAD
#endif
class nsIModule;
class nsIServiceManager;
typedef enum nsDllStatus
{
DLL_OK = 0,
DLL_NO_MEM = 1,
DLL_STAT_ERROR = 2,
DLL_NOT_FILE = 3,
DLL_INVALID_PARAM = 4
} nsDllStatus;
class nsDll
{
private:
nsCOMPtr<nsIFile> m_dllSpec;
PRLibrary *m_instance;
nsIModule *m_moduleObject;
nsNativeComponentLoader *m_loader;
PRBool m_markForUnload;
void Init(nsIFile *dllSpec);
#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
void BreakAfterLoad(const char *nsprPath);
#endif
public:
nsDll(nsIFile *dllSpec, nsNativeComponentLoader* loader);
~nsDll(void);
// Dll Loading
PRBool Load(void);
PRBool Unload(void);
PRBool IsLoaded(void)
{
return ((m_instance != 0) ? PR_TRUE : PR_FALSE);
}
void MarkForUnload(PRBool mark) { m_markForUnload = mark; }
PRBool IsMarkedForUnload(void) { return m_markForUnload; }
// Shutdown the dll. This will call any on unload hook for the dll.
// This won't unload the dll. Unload() implicitly calls Shutdown().
nsresult Shutdown(void);
void *FindSymbol(const char *symbol);
PRBool HasChanged(void);
void GetDisplayPath(nsACString& string);
PRLibrary *GetInstance(void) { return (m_instance); }
// NS_RELEASE() is required to be done on objects returned
nsresult GetDllSpec(nsIFile **dllSpec);
nsresult GetModule(nsISupports *servMgr, nsIModule **mobj);
};
#endif /* xcDll_h__ */

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

@ -54,7 +54,7 @@ NS_strspnp(const char *delims, const char *str);
/**
* Tokenize a string. This function is similar to the strtok function in the
* C standard library, but it does use static variables to maintain state
* C standard library, but it does not use static variables to maintain state
* and is therefore thread and reentrancy-safe.
*
* Any leading delimiters in str are skipped. Then the string is scanned

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

@ -380,6 +380,18 @@ class nsTArray : public nsTArray_base {
return ReplaceElementsAt(index, 0, &elem, 1);
}
// Insert a new element without copy-constructing. This is useful to avoid
// temporaries.
// @return A pointer to the newly inserted element, or null on OOM.
elem_type* InsertElementAt(index_type index) {
if (!EnsureCapacity(Length() + 1, sizeof(elem_type)))
return nsnull;
ShiftData(index, 0, 1, sizeof(elem_type));
elem_type *elem = Elements() + index;
elem_traits::Construct(elem);
return elem;
}
// This method appends elements to the end of this array.
// @param array The elements to append to this array.
// @param arrayLen The number of elements to append to this array.
@ -402,6 +414,18 @@ class nsTArray : public nsTArray_base {
return AppendElements(&elem, 1);
}
// Append a new element without copy-constructing. This is useful to avoid
// temporaries.
// @return A pointer to the newly appended element, or null on OOM.
elem_type* AppendElement() {
if (!EnsureCapacity(Length() + 1, sizeof(elem_type)))
return nsnull;
elem_type *elem = Elements() + Length();
elem_traits::Construct(elem);
++mLength;
return elem;
}
// This method removes a range of elements from this array.
// @param start The starting index of the elements to remove.
// @param count The number of elements to remove.