diff --git a/mozilla/js/src/xpconnect/idl/xpccomponents.idl b/mozilla/js/src/xpconnect/idl/xpccomponents.idl index febfa7be7f6..f9a215c3ee1 100644 --- a/mozilla/js/src/xpconnect/idl/xpccomponents.idl +++ b/mozilla/js/src/xpconnect/idl/xpccomponents.idl @@ -29,12 +29,18 @@ interface nsIXPCClasses : nsISupports { }; +[scriptable, uuid(336a9590-4d19-11d3-9893-006008962422)] +interface nsIXPCClassesByID : nsISupports +{ +}; + [scriptable, uuid(42624f80-d26c-11d2-9842-006008962422)] interface nsIXPCComponents : nsISupports { readonly attribute nsIXPCInterfaces interfaces; readonly attribute nsIXPCClasses classes; + readonly attribute nsIXPCClassesByID classesByID; readonly attribute nsIJSStackFrameLocation stack; /* 'lastResult' is accessable via JavaScript only */ diff --git a/mozilla/js/src/xpconnect/idl/xpcjsid.idl b/mozilla/js/src/xpconnect/idl/xpcjsid.idl index 9a23437b1e9..2971e216849 100644 --- a/mozilla/js/src/xpconnect/idl/xpcjsid.idl +++ b/mozilla/js/src/xpconnect/idl/xpcjsid.idl @@ -18,16 +18,12 @@ #include "nsISupports.idl" -// XXX this ought to be builtin! -native nsID(nsID*); - - [scriptable, uuid(C86AE131-D101-11d2-9841-006008962422)] interface nsIJSID : nsISupports { readonly attribute string name; readonly attribute string number; - readonly attribute nsID id; + readonly attribute nsIDPtr id; readonly attribute boolean valid; boolean equals(in nsIJSID other); diff --git a/mozilla/js/src/xpconnect/src/xpccomponents.cpp b/mozilla/js/src/xpconnect/src/xpccomponents.cpp index 3ff5892198b..45b7f86e025 100644 --- a/mozilla/js/src/xpconnect/src/xpccomponents.cpp +++ b/mozilla/js/src/xpconnect/src/xpccomponents.cpp @@ -20,6 +20,8 @@ #include "xpcprivate.h" +static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID); + /***************************************************************************/ class InterfacesScriptable : public nsIXPCScriptable @@ -42,7 +44,6 @@ private: void FillCache(JSContext *cx, JSObject *obj, nsIXPConnectWrappedNative *wrapper, nsIXPCScriptable *arbitrary); - }; /**********************************************/ @@ -151,7 +152,7 @@ InterfacesScriptable::FillCache(JSContext *cx, JSObject *obj, goto done; } - if(NS_FAILED(iim->GetInterfaceEnumerator(&Interfaces))) + if(NS_FAILED(iim->EnumerateInterfaces(&Interfaces))) { NS_ASSERTION(0,"failed to get interface enumeration"); goto done; @@ -233,7 +234,8 @@ InterfacesScriptable::CacheDynaProp(JSContext *cx, JSObject *obj, jsid id, const char* property_name = NULL; if(JS_IdToValue(cx, id, &idval) && JSVAL_IS_STRING(idval) && - (property_name = JS_GetStringBytes(JSVAL_TO_STRING(idval))) != NULL) + (property_name = JS_GetStringBytes(JSVAL_TO_STRING(idval))) != NULL && + property_name[0] != '{') // we only allow interfaces by name here { nsJSIID* nsid = nsJSIID::NewID(property_name); nsIXPConnectWrappedNative* nsid_wrapper; @@ -256,6 +258,10 @@ InterfacesScriptable::CacheDynaProp(JSContext *cx, JSObject *obj, jsid id, } NS_RELEASE(nsid_wrapper); } + else + { + NS_RELEASE(nsid); + } NS_RELEASE(xpc); } } @@ -295,6 +301,7 @@ NS_IMPL_ADDREF(nsXPCInterfaces) NS_IMPL_RELEASE(nsXPCInterfaces) NS_IMPL_QUERY_INTERFACE_SCRIPTABLE(nsXPCInterfaces, mScriptable) +/***************************************************************************/ /***************************************************************************/ /***************************************************************************/ class ClassesScriptable : public nsIXPCScriptable @@ -305,9 +312,18 @@ public: ClassesScriptable(); virtual ~ClassesScriptable(); private: + + void RealizeClass(JSContext *cx, JSObject *obj, const char *class_name, + nsIXPConnectWrappedNative* wrapper, + nsIXPCScriptable* arbitrary); + void CacheDynaProp(JSContext *cx, JSObject *obj, jsid id, nsIXPConnectWrappedNative* wrapper, nsIXPCScriptable* arbitrary); + + void FillCache(JSContext *cx, JSObject *obj, + nsIXPConnectWrappedNative *wrapper, + nsIXPCScriptable *arbitrary); }; /**********************************************/ @@ -324,7 +340,7 @@ static NS_DEFINE_IID(kClassesScriptableIID, NS_IXPCSCRIPTABLE_IID); NS_IMPL_ISUPPORTS(ClassesScriptable, kClassesScriptableIID); XPC_IMPLEMENT_FORWARD_CREATE(ClassesScriptable); -XPC_IMPLEMENT_IGNORE_GETFLAGS(ClassesScriptable); +// XPC_IMPLEMENT_IGNORE_GETFLAGS(ClassesScriptable); // XPC_IMPLEMENT_FORWARD_LOOKUPPROPERTY(ClassesScriptable); XPC_IMPLEMENT_IGNORE_DEFINEPROPERTY(ClassesScriptable); // XPC_IMPLEMENT_FORWARD_GETPROPERTY(ClassesScriptable); @@ -333,12 +349,25 @@ XPC_IMPLEMENT_IGNORE_GETATTRIBUTES(ClassesScriptable); XPC_IMPLEMENT_IGNORE_SETATTRIBUTES(ClassesScriptable); XPC_IMPLEMENT_IGNORE_DELETEPROPERTY(ClassesScriptable); XPC_IMPLEMENT_FORWARD_DEFAULTVALUE(ClassesScriptable); -XPC_IMPLEMENT_FORWARD_ENUMERATE(ClassesScriptable); +// XPC_IMPLEMENT_FORWARD_ENUMERATE(ClassesScriptable); XPC_IMPLEMENT_FORWARD_CHECKACCESS(ClassesScriptable); XPC_IMPLEMENT_IGNORE_CALL(ClassesScriptable); XPC_IMPLEMENT_IGNORE_CONSTRUCT(ClassesScriptable); XPC_IMPLEMENT_FORWARD_FINALIZE(ClassesScriptable); + +NS_IMETHODIMP +ClassesScriptable::GetFlags(JSContext *cx, JSObject *obj, + nsIXPConnectWrappedNative* wrapper, + JSUint32* flagsp, + nsIXPCScriptable* arbitrary) +{ + NS_PRECONDITION(flagsp, "bad param"); + *flagsp = XPCSCRIPTABLE_DONT_ENUM_STATIC_PROPS; + return NS_OK; +} + + NS_IMETHODIMP ClassesScriptable::LookupProperty(JSContext *cx, JSObject *obj, jsid id, @@ -372,6 +401,96 @@ ClassesScriptable::GetProperty(JSContext *cx, JSObject *obj, } + +NS_IMETHODIMP +ClassesScriptable::Enumerate(JSContext *cx, JSObject *obj, + JSIterateOp enum_op, + jsval *statep, jsid *idp, + nsIXPConnectWrappedNative *wrapper, + nsIXPCScriptable *arbitrary, + JSBool *retval) +{ + if(enum_op == JSENUMERATE_INIT) + FillCache(cx, obj, wrapper, arbitrary); + + return arbitrary->Enumerate(cx, obj, enum_op, statep, idp, wrapper, + arbitrary, retval); +} + +/* enumerate the known progids, adding a property for each new one */ +void +ClassesScriptable::FillCache(JSContext *cx, JSObject *obj, + nsIXPConnectWrappedNative *wrapper, + nsIXPCScriptable *arbitrary) +{ + + nsIEnumerator* Classes; + nsISupports* is_Class; + nsISupportsString* ClassNameHolder; + nsresult rv; + + NS_WITH_SERVICE(nsIComponentManager, compMgr, kComponentManagerCID, &rv); + if(NS_FAILED(rv)) + return; + + if(NS_FAILED(rv = compMgr->EnumerateProgIDs(&Classes))) + return; + + if(!NS_FAILED(rv = Classes->First())) + { + do + { + if(NS_FAILED(rv = Classes->CurrentItem(&is_Class))|| !is_Class) + { + Classes->Next(); + continue; + } + + rv = is_Class->QueryInterface(NS_GET_IID(nsISupportsString), + (void **)&ClassNameHolder); + if(!NS_FAILED(rv)) + { + char *class_name; + if(NS_SUCCEEDED(ClassNameHolder->GetData(&class_name))) + { + RealizeClass(cx, obj, class_name, wrapper, arbitrary); + nsAllocator::Free(class_name); + } + NS_RELEASE(ClassNameHolder); + } + else + break; + + NS_RELEASE(is_Class); + Classes->Next(); + + } while(!NS_FAILED(Classes->IsDone())); + } + NS_RELEASE(Classes); +} + +void +ClassesScriptable::RealizeClass(JSContext *cx, JSObject *obj, + const char *class_name, + nsIXPConnectWrappedNative* wrapper, + nsIXPCScriptable* arbitrary) +{ + jsval prop; + + if(!JS_LookupProperty(cx, obj, class_name, &prop) || + JSVAL_IS_PRIMITIVE(prop)) + { + jsid id; + JSString *jstrid; + + if(NULL != (jstrid = JS_InternString(cx, class_name)) && + JS_ValueToId(cx, STRING_TO_JSVAL(jstrid), &id)) + { + CacheDynaProp(cx, obj, id, wrapper, arbitrary); + } + } +} + void ClassesScriptable::CacheDynaProp(JSContext *cx, JSObject *obj, jsid id, nsIXPConnectWrappedNative* wrapper, @@ -381,7 +500,8 @@ ClassesScriptable::CacheDynaProp(JSContext *cx, JSObject *obj, jsid id, const char* property_name = NULL; if(JS_IdToValue(cx, id, &idval) && JSVAL_IS_STRING(idval) && - (property_name = JS_GetStringBytes(JSVAL_TO_STRING(idval))) != NULL) + (property_name = JS_GetStringBytes(JSVAL_TO_STRING(idval))) != NULL && + property_name[0] != '{') // we only allow progids here { nsJSCID* nsid = nsJSCID::NewID(property_name); nsIXPConnectWrappedNative* nsid_wrapper; @@ -404,6 +524,10 @@ ClassesScriptable::CacheDynaProp(JSContext *cx, JSObject *obj, jsid id, } NS_RELEASE(nsid_wrapper); } + else + { + NS_RELEASE(nsid); + } NS_RELEASE(xpc); } } @@ -443,6 +567,310 @@ NS_IMPL_QUERY_INTERFACE_SCRIPTABLE(nsXPCClasses, mScriptable) /***************************************************************************/ /***************************************************************************/ +/***************************************************************************/ +class ClassesByIDScriptable : public nsIXPCScriptable +{ +public: + NS_DECL_ISUPPORTS + XPC_DECLARE_IXPCSCRIPTABLE + ClassesByIDScriptable(); + virtual ~ClassesByIDScriptable(); +private: + + void RealizeClass(JSContext *cx, JSObject *obj, const char *class_name, + nsIXPConnectWrappedNative* wrapper, + nsIXPCScriptable* arbitrary, + JSBool knownToBeRegistered); + + void CacheDynaProp(JSContext *cx, JSObject *obj, jsid id, + nsIXPConnectWrappedNative* wrapper, + nsIXPCScriptable* arbitrary, + JSBool knownToBeRegistered); + + void FillCache(JSContext *cx, JSObject *obj, + nsIXPConnectWrappedNative *wrapper, + nsIXPCScriptable *arbitrary); + }; + +/**********************************************/ + +ClassesByIDScriptable::ClassesByIDScriptable() +{ + NS_INIT_REFCNT(); + NS_ADDREF_THIS(); +} + +ClassesByIDScriptable::~ClassesByIDScriptable() {} + +static NS_DEFINE_IID(kClassesByIDScriptableIID, NS_IXPCSCRIPTABLE_IID); +NS_IMPL_ISUPPORTS(ClassesByIDScriptable, kClassesByIDScriptableIID); + +XPC_IMPLEMENT_FORWARD_CREATE(ClassesByIDScriptable); +// XPC_IMPLEMENT_IGNORE_GETFLAGS(ClassesByIDScriptable); +// XPC_IMPLEMENT_FORWARD_LOOKUPPROPERTY(ClassesByIDScriptable); +XPC_IMPLEMENT_IGNORE_DEFINEPROPERTY(ClassesByIDScriptable); +// XPC_IMPLEMENT_FORWARD_GETPROPERTY(ClassesByIDScriptable); +XPC_IMPLEMENT_IGNORE_SETPROPERTY(ClassesByIDScriptable); +XPC_IMPLEMENT_IGNORE_GETATTRIBUTES(ClassesByIDScriptable); +XPC_IMPLEMENT_IGNORE_SETATTRIBUTES(ClassesByIDScriptable); +XPC_IMPLEMENT_IGNORE_DELETEPROPERTY(ClassesByIDScriptable); +XPC_IMPLEMENT_FORWARD_DEFAULTVALUE(ClassesByIDScriptable); +// XPC_IMPLEMENT_FORWARD_ENUMERATE(ClassesByIDScriptable); +XPC_IMPLEMENT_FORWARD_CHECKACCESS(ClassesByIDScriptable); +XPC_IMPLEMENT_IGNORE_CALL(ClassesByIDScriptable); +XPC_IMPLEMENT_IGNORE_CONSTRUCT(ClassesByIDScriptable); +XPC_IMPLEMENT_FORWARD_FINALIZE(ClassesByIDScriptable); + + +NS_IMETHODIMP +ClassesByIDScriptable::GetFlags(JSContext *cx, JSObject *obj, + nsIXPConnectWrappedNative* wrapper, + JSUint32* flagsp, + nsIXPCScriptable* arbitrary) +{ + NS_PRECONDITION(flagsp, "bad param"); + *flagsp = XPCSCRIPTABLE_DONT_ENUM_STATIC_PROPS; + return NS_OK; +} + +NS_IMETHODIMP +ClassesByIDScriptable::LookupProperty(JSContext *cx, JSObject *obj, + jsid id, + JSObject **objp, JSProperty **propp, + nsIXPConnectWrappedNative* wrapper, + nsIXPCScriptable* arbitrary, + JSBool* retval) +{ + if(NS_SUCCEEDED(arbitrary->LookupProperty(cx, obj, id, objp, propp, wrapper, + NULL, retval)) && *retval) + return NS_OK; + CacheDynaProp(cx, obj, id, wrapper, arbitrary, JS_FALSE); + return arbitrary->LookupProperty(cx, obj, id, objp, propp, wrapper, + NULL, retval); +} + +NS_IMETHODIMP +ClassesByIDScriptable::GetProperty(JSContext *cx, JSObject *obj, + jsid id, jsval *vp, + nsIXPConnectWrappedNative* wrapper, + nsIXPCScriptable* arbitrary, + JSBool* retval) +{ + if(NS_SUCCEEDED(arbitrary->GetProperty(cx, obj, id, vp, wrapper, + NULL, retval)) && *retval && + *vp != JSVAL_VOID) + return NS_OK; + + CacheDynaProp(cx, obj, id, wrapper, arbitrary, JS_FALSE); + return arbitrary->GetProperty(cx, obj, id, vp, wrapper, NULL, retval); +} + + + +NS_IMETHODIMP +ClassesByIDScriptable::Enumerate(JSContext *cx, JSObject *obj, + JSIterateOp enum_op, + jsval *statep, jsid *idp, + nsIXPConnectWrappedNative *wrapper, + nsIXPCScriptable *arbitrary, + JSBool *retval) +{ + if(enum_op == JSENUMERATE_INIT) + FillCache(cx, obj, wrapper, arbitrary); + + return arbitrary->Enumerate(cx, obj, enum_op, statep, idp, wrapper, + arbitrary, retval); +} + +/* enumerate the known progids, adding a property for each new one */ +void +ClassesByIDScriptable::FillCache(JSContext *cx, JSObject *obj, + nsIXPConnectWrappedNative *wrapper, + nsIXPCScriptable *arbitrary) +{ + + nsIEnumerator* Classes; + nsISupports* is_Class; + nsISupportsID* ClassIDHolder; + nsresult rv; + + NS_WITH_SERVICE(nsIComponentManager, compMgr, kComponentManagerCID, &rv); + if(NS_FAILED(rv)) + return; + + if(NS_FAILED(rv = compMgr->EnumerateCLSIDs(&Classes))) + return; + + if(!NS_FAILED(rv = Classes->First())) + { + do + { + if(NS_FAILED(rv = Classes->CurrentItem(&is_Class))|| !is_Class) + { + Classes->Next(); + continue; + } + + rv = is_Class->QueryInterface(NS_GET_IID(nsISupportsID), + (void **)&ClassIDHolder); + if(!NS_FAILED(rv)) + { + nsID* class_id; + if(NS_SUCCEEDED(ClassIDHolder->GetData(&class_id))) + { + char* class_name; + if(nsnull != (class_name = class_id->ToString())) + { + RealizeClass(cx, obj, class_name, wrapper, + arbitrary, JS_TRUE); + delete [] class_name; + } + nsAllocator::Free(class_id); + } + NS_RELEASE(ClassIDHolder); + } + else + break; + + NS_RELEASE(is_Class); + Classes->Next(); + + } while(!NS_FAILED(Classes->IsDone())); + } + NS_RELEASE(Classes); +} + +void +ClassesByIDScriptable::RealizeClass(JSContext *cx, JSObject *obj, + const char *class_name, + nsIXPConnectWrappedNative* wrapper, + nsIXPCScriptable* arbitrary, + JSBool knownToBeRegistered) +{ + jsval prop; + + if(!JS_LookupProperty(cx, obj, class_name, &prop) || + JSVAL_IS_PRIMITIVE(prop)) + { + jsid id; + JSString *jstrid; + + if(NULL != (jstrid = JS_InternString(cx, class_name)) && + JS_ValueToId(cx, STRING_TO_JSVAL(jstrid), &id)) + { + CacheDynaProp(cx, obj, id, wrapper, arbitrary, knownToBeRegistered); + } + } +} + +static PRBool +IsCanonicalFormOfRegisteredCLSID(const char* str) +{ + nsresult rv; + NS_WITH_SERVICE(nsIComponentManager, compMgr, kComponentManagerCID, &rv); + if(NS_FAILED(rv)) + return PR_FALSE; + + char* copy = (char*)nsAllocator::Clone(str, (strlen(str)+1)*sizeof(char)); + if(!copy) + return PR_FALSE; + + nsID id; + PRBool idIsOK = id.Parse(copy); + nsAllocator::Free(copy); + if(!idIsOK) + return PR_FALSE; + + PRBool registered; + if(NS_SUCCEEDED(compMgr->IsRegistered(id, ®istered))) + return registered; + return PR_FALSE; +} + +void +ClassesByIDScriptable::CacheDynaProp(JSContext *cx, JSObject *obj, jsid id, + nsIXPConnectWrappedNative* wrapper, + nsIXPCScriptable* arbitrary, + JSBool knownToBeRegistered) +{ + jsval idval; + const char* property_name = NULL; + + if(JS_IdToValue(cx, id, &idval) && JSVAL_IS_STRING(idval) && + (property_name = JS_GetStringBytes(JSVAL_TO_STRING(idval))) != NULL && + property_name[0] == '{') // we only allow canonical CLSIDs here + { + // in this case we are responsible for verifying that the + // component manager has this CLSID registered. + if(!knownToBeRegistered) + if(!IsCanonicalFormOfRegisteredCLSID(property_name)) + return; + + nsJSCID* nsid = nsJSCID::NewID(property_name); + nsIXPConnectWrappedNative* nsid_wrapper; + if(nsid) + { + nsXPConnect* xpc = nsXPConnect::GetXPConnect(); + if(xpc) + { + if(NS_SUCCEEDED(xpc->WrapNative(cx, nsid, + nsIJSCID::GetIID(), + &nsid_wrapper))) + { + JSObject* idobj; + if(NS_SUCCEEDED(nsid_wrapper->GetJSObject(&idobj))) + { + JSBool retval; + jsval val = OBJECT_TO_JSVAL(idobj); + arbitrary->SetProperty(cx, obj, id, &val, wrapper, + NULL, &retval); + } + NS_RELEASE(nsid_wrapper); + } + else + { + NS_RELEASE(nsid); + } + NS_RELEASE(xpc); + } + } + } +} + +/***************************************************************************/ + +class nsXPCClassesByID : public nsIXPCClassesByID +{ +public: + // all the interface method declarations... + NS_DECL_ISUPPORTS + +public: + nsXPCClassesByID(); + virtual ~nsXPCClassesByID(); +private: + ClassesByIDScriptable* mScriptable; +}; + +nsXPCClassesByID::nsXPCClassesByID() +{ + NS_INIT_ISUPPORTS(); + NS_ADDREF_THIS(); + mScriptable = new ClassesByIDScriptable(); +} + +nsXPCClassesByID::~nsXPCClassesByID() +{ + NS_RELEASE(mScriptable); +} + +NS_IMPL_ADDREF(nsXPCClassesByID) +NS_IMPL_RELEASE(nsXPCClassesByID) +NS_IMPL_QUERY_INTERFACE_SCRIPTABLE(nsXPCClassesByID, mScriptable) + +/***************************************************************************/ +/***************************************************************************/ + class ComponentsScriptable : public nsIXPCScriptable { public: @@ -512,6 +940,7 @@ nsXPCComponents::nsXPCComponents() NS_ADDREF_THIS(); mInterfaces = new nsXPCInterfaces(); mClasses = new nsXPCClasses(); + mClassesByID = new nsXPCClassesByID(); mScriptable = new ComponentsScriptable(); } @@ -521,6 +950,8 @@ nsXPCComponents::~nsXPCComponents() NS_RELEASE(mInterfaces); if(mClasses) NS_RELEASE(mClasses); + if(mClassesByID) + NS_RELEASE(mClassesByID); if(mScriptable) NS_RELEASE(mScriptable); } @@ -550,6 +981,18 @@ nsXPCComponents::GetClasses(nsIXPCClasses * *aClasses) *aClasses = NULL; return NS_ERROR_UNEXPECTED; } +NS_IMETHODIMP +nsXPCComponents::GetClassesByID(nsIXPCClassesByID * *aClassesByID) +{ + if(mClassesByID) + { + NS_ADDREF(mClassesByID); + *aClassesByID = mClassesByID; + return NS_OK; + } + *aClassesByID = NULL; + return NS_ERROR_UNEXPECTED; +} NS_IMETHODIMP nsXPCComponents::GetStack(nsIJSStackFrameLocation * *aStack) diff --git a/mozilla/js/src/xpconnect/src/xpcconvert.cpp b/mozilla/js/src/xpconnect/src/xpcconvert.cpp index ae144d11356..857547adb00 100644 --- a/mozilla/js/src/xpconnect/src/xpcconvert.cpp +++ b/mozilla/js/src/xpconnect/src/xpcconvert.cpp @@ -93,6 +93,41 @@ XPCConvert::IsMethodReflectable(const nsXPTMethodInfo& info) /***************************************************************************/ +static JSBool +ObjectHasPrivate(JSContext* cx, JSObject* obj) +{ + JSClass* jsclass = +#ifdef JS_THREADSAFE + JS_GetClass(cx, obj); +#else + JS_GetClass(obj); +#endif + NS_ASSERTION(jsclass, "obj has no class"); + return jsclass && (jsclass->flags & JSCLASS_HAS_PRIVATE); +} + +static JSBool +GetISupportsFromJSObject(JSContext* cx, JSObject* obj, nsISupports** iface) +{ + JSClass* jsclass = +#ifdef JS_THREADSAFE + JS_GetClass(cx, obj); +#else + JS_GetClass(obj); +#endif + NS_ASSERTION(jsclass, "obj has no class"); + if(jsclass && + (jsclass->flags & JSCLASS_HAS_PRIVATE) && + (jsclass->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS)) + { + *iface = (nsISupports*) JS_GetPrivate(cx, obj); + return JS_TRUE; + } + return JS_FALSE; +} + +/***************************************************************************/ + /* * Support for 64 bit conversions were 'long long' not supported. * (from John Fairhurst ) @@ -269,6 +304,7 @@ XPCConvert::NativeData2JS(JSContext* cx, jsval* d, const void* s, NS_ASSERTION(owner,"QI succeeded but yielded NULL!"); if(NULL != (globalObject = JS_GetGlobalObject(cx)) && + ObjectHasPrivate(cx, globalObject) && NULL != (domObject = (nsISupports*) JS_GetPrivate(cx, globalObject))) { @@ -323,26 +359,6 @@ XPCConvert::NativeData2JS(JSContext* cx, jsval* d, const void* s, return JS_TRUE; } -static JSBool -GetISupportsFromJSObject(JSContext* cx, JSObject* obj, nsISupports** iface) -{ - JSClass* jsclass = -#ifdef JS_THREADSAFE - JS_GetClass(cx, obj); -#else - JS_GetClass(obj); -#endif - NS_ASSERTION(jsclass, "obj has no class"); - if(jsclass && - (jsclass->flags & JSCLASS_HAS_PRIVATE) && - (jsclass->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS)) - { - *iface = (nsISupports*) JS_GetPrivate(cx, obj); - return JS_TRUE; - } - return JS_FALSE; -} - /***************************************************************************/ // static JSBool diff --git a/mozilla/js/src/xpconnect/src/xpcjsid.cpp b/mozilla/js/src/xpconnect/src/xpcjsid.cpp index 9b62c08c109..9325d6cdaf9 100644 --- a/mozilla/js/src/xpconnect/src/xpcjsid.cpp +++ b/mozilla/js/src/xpconnect/src/xpcjsid.cpp @@ -21,56 +21,31 @@ #include "xpcprivate.h" /***************************************************************************/ -// stuff used for both classes... +// stuff used by all static void ThrowException(uintN errNum, JSContext* cx) - {nsXPConnect::GetJSThrower()->ThrowException(errNum, cx);} +{ + nsXPConnect::GetJSThrower()->ThrowException(errNum, cx); +} static void ThrowBadResultException(uintN errNum, JSContext* cx, nsresult rv) - {nsXPConnect::GetJSThrower()->ThrowBadResultException(errNum, cx, nsnull, - nsnull, rv);} - -static const nsID& GetInvalidIID() { - // {BB1F47B0-D137-11d2-9841-006008962422} - static nsID invalid = {0xbb1f47b0, 0xd137, 0x11d2, - {0x98, 0x41, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22}}; - return invalid; + nsXPConnect::GetJSThrower()->ThrowBadResultException(errNum, cx, nsnull, + nsnull, rv); } -static char* gNoString = ""; - /***************************************************************************/ -// nsJSIID +// shared impl... -nsresult -nsJSIID::QueryInterface(REFNSIID aIID, void** aInstancePtr) -{ - if (NULL == aInstancePtr) { - return NS_ERROR_NULL_POINTER; - } - if (aIID.Equals(nsCOMTypeInfo::GetIID()) || - aIID.Equals(nsIJSID::GetIID()) || - aIID.Equals(nsIJSIID::GetIID())) { - *aInstancePtr = (void*) this; - NS_ADDREF_THIS(); - return NS_OK; - } - *aInstancePtr = NULL; - return NS_NOINTERFACE; -} +char nsJSIDDDetails::gNoString[] = ""; -NS_IMPL_ADDREF(nsJSIID) -NS_IMPL_RELEASE(nsJSIID) - -nsJSIID::nsJSIID() +nsJSIDDDetails::nsJSIDDDetails() : mID(GetInvalidIID()), mNumber(gNoString), mName(gNoString) { - NS_INIT_ISUPPORTS(); - NS_ADDREF_THIS(); + // empty }; -nsJSIID::~nsJSIID() +nsJSIDDDetails::~nsJSIDDDetails() { if(mNumber && mNumber != gNoString) delete [] mNumber; @@ -78,7 +53,7 @@ nsJSIID::~nsJSIID() delete [] mName; } -void nsJSIID::reset() +void nsJSIDDDetails::reset() { mID = GetInvalidIID(); @@ -90,59 +65,29 @@ void nsJSIID::reset() mNumber = mName = NULL; } -//static -nsJSIID* -nsJSIID::NewID(const char* str) -{ - PRBool success; - nsJSIID* idObj = new nsJSIID(); - if(!idObj) - return NULL; - - if(NS_FAILED(idObj->init(str, &success)) || !success) - { - delete idObj; - return NULL; - } - - return idObj; -} - -void -nsJSIID::setName(const char* name) +PRBool +nsJSIDDDetails::setName(const char* name) { + NS_ASSERTION(!mName || mName == gNoString ,"name already set"); + NS_ASSERTION(name,"null name"); int len = strlen(name)+1; mName = new char[len]; - if(mName) - memcpy(mName, name, len); + if(!mName) + return PR_FALSE; + memcpy(mName, name, len); + return PR_TRUE; } -NS_IMETHODIMP -nsJSIID::GetName(char * *aName) +nsresult +nsJSIDDDetails::GetName(char * *aName) { - if(!mName) - { - nsIInterfaceInfoManager* iim; - if(NULL != (iim = nsXPConnect::GetInterfaceInfoManager())) - { - char* name; - if(NS_SUCCEEDED(iim->GetNameForIID(&mID, &name)) && name) - { - setName(name); - nsAllocator::Free(name); - } - NS_RELEASE(iim); - } - if(!mName) - mName = gNoString; - } - + NS_ASSERTION(mName, "name not set"); *aName = (char*) nsAllocator::Clone(mName, strlen(mName)+1); return *aName ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } -NS_IMETHODIMP -nsJSIID::GetNumber(char * *aNumber) +nsresult +nsJSIDDDetails::GetNumber(char * *aNumber) { if(!mNumber) { @@ -154,23 +99,22 @@ nsJSIID::GetNumber(char * *aNumber) return *aNumber ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } - -NS_IMETHODIMP -nsJSIID::GetId(nsID* *aId) +nsresult +nsJSIDDDetails::GetId(nsID* *aId) { *aId = (nsID*) nsAllocator::Clone(&mID, sizeof(nsID)); return *aId ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } -NS_IMETHODIMP -nsJSIID::GetValid(PRBool *aValid) +nsresult +nsJSIDDDetails::GetValid(PRBool *aValid) { *aValid = !mID.Equals(GetInvalidIID()); return NS_OK; } -NS_IMETHODIMP -nsJSIID::equals(nsIJSID *other, PRBool *_retval) +nsresult +nsJSIDDDetails::equals(nsIJSID *other, PRBool *_retval) { if(!_retval) return NS_ERROR_NULL_POINTER; @@ -189,8 +133,8 @@ nsJSIID::equals(nsIJSID *other, PRBool *_retval) return NS_OK; } -NS_IMETHODIMP -nsJSIID::init(const char *idString, PRBool *_retval) +nsresult +nsJSIDDDetails::init(const char *idString, PRBool *_retval) { if(!_retval || !idString) return NS_ERROR_NULL_POINTER; @@ -210,34 +154,160 @@ nsJSIID::init(const char *idString, PRBool *_retval) success = PR_TRUE; } } + } + *_retval = success; + return NS_OK; +} + +PRBool +nsJSIDDDetails::initWithName(const nsID& id, const char *nameString) +{ + NS_ASSERTION(nameString, "no name"); + reset(); + mID = id; + return setName(nameString); +} + +// try to use the name, if no name, then use the number +nsresult +nsJSIDDDetails::toString(char **_retval) +{ + if(mName != gNoString) + { + char* str; + if(NS_SUCCEEDED(GetName(&str))) + { + if(mName != gNoString) + { + *_retval = str; + return NS_OK; + } + else + nsAllocator::Free(str); + } + } + return GetNumber(_retval); +} + +const nsID& +nsJSIDDDetails::GetInvalidIID() const +{ + // {BB1F47B0-D137-11d2-9841-006008962422} + static nsID invalid = {0xbb1f47b0, 0xd137, 0x11d2, + {0x98, 0x41, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22}}; + return invalid; +} + +/***************************************************************************/ +/***************************************************************************/ + +NS_IMETHODIMP +nsJSIID::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(NS_GET_IID(nsISupports)) || + aIID.Equals(NS_GET_IID(nsIJSID)) || + aIID.Equals(NS_GET_IID(nsIJSIID))) { + *aInstancePtr = (void*) this; + NS_ADDREF_THIS(); + return NS_OK; + } + *aInstancePtr = NULL; + return NS_NOINTERFACE; +} + +NS_IMPL_ADDREF(nsJSIID) +NS_IMPL_RELEASE(nsJSIID) + +nsJSIID::nsJSIID() {NS_INIT_ISUPPORTS();} +nsJSIID::~nsJSIID() {} + +NS_IMETHODIMP nsJSIID::GetName(char * *aName) + {resolveName(); return mDetails.GetName(aName);} + +NS_IMETHODIMP nsJSIID::GetNumber(char * *aNumber) + {return mDetails.GetNumber(aNumber);} + +NS_IMETHODIMP nsJSIID::GetId(nsID* *aId) + {return mDetails.GetId(aId);} + +NS_IMETHODIMP nsJSIID::GetValid(PRBool *aValid) + {return mDetails.GetValid(aValid);} + +NS_IMETHODIMP nsJSIID::equals(nsIJSID *other, PRBool *_retval) + {return mDetails.equals(other, _retval);} + +NS_IMETHODIMP nsJSIID::init(const char *idString, PRBool *_retval) + {return mDetails.init(idString, _retval);} + +NS_IMETHODIMP nsJSIID::toString(char **_retval) + {resolveName(); return mDetails.toString(_retval);} + +void +nsJSIID::resolveName() +{ + if(!mDetails.nameIsSet()) + { + nsIInterfaceInfoManager* iim; + if(NULL != (iim = nsXPConnect::GetInterfaceInfoManager())) + { + char* name; + if(NS_SUCCEEDED(iim->GetNameForIID(mDetails.getID(), &name)) && name) + { + mDetails.setName(name); + nsAllocator::Free(name); + } + NS_RELEASE(iim); + } + if(!mDetails.nameIsSet()) + mDetails.setNameToNoString(); + } +} + +//static +nsJSIID* +nsJSIID::NewID(const char* str) +{ + if(!str) + { + NS_ASSERTION(0,"no string"); + return nsnull; + } + + nsJSIID* idObj = new nsJSIID(); + if(idObj) + { + PRBool success = PR_FALSE; + NS_ADDREF(idObj); + + if(str[0] == '{') + { + idObj->init(str, &success); + } else { nsIInterfaceInfoManager* iim; if(NULL != (iim = nsXPConnect::GetInterfaceInfoManager())) { nsID* pid; - if(NS_SUCCEEDED(iim->GetIIDForName(idString, &pid)) && pid) + if(NS_SUCCEEDED(iim->GetIIDForName(str, &pid)) && pid) { - mID = *pid; - setName(idString); - success = PR_TRUE; + success = idObj->mDetails.initWithName(*pid, str); nsAllocator::Free(pid); } NS_RELEASE(iim); } } + if(!success) + NS_RELEASE(idObj); } - - *_retval = success; - return NS_OK; -} - -NS_IMETHODIMP -nsJSIID::toString(char **_retval) -{ - return GetName(_retval); + return idObj; } +/***************************************************************************/ +/***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /* @@ -281,7 +351,6 @@ private: CIDCreateInstanceScriptable::CIDCreateInstanceScriptable() { NS_INIT_REFCNT(); - NS_ADDREF_THIS(); } CIDCreateInstanceScriptable::~CIDCreateInstanceScriptable() {} @@ -371,9 +440,10 @@ CIDCreateInstanceScriptable::Call(JSContext *cx, JSObject *obj, nsresult rv; rv = nsComponentManager::CreateInstance(*cid, NULL, *piid, (void**) &inst); + NS_ASSERTION(NS_FAILED(rv) || inst, "component manager returned success, but instance is null!"); nsAllocator::Free(cid); - if(NS_FAILED(rv)) + if(NS_FAILED(rv) || !inst) { ThrowBadResultException(XPCJSError::CI_RETURNED_FAILURE, cx, rv); *retval = JS_FALSE; @@ -417,7 +487,6 @@ CIDCreateInstance::CIDCreateInstance(nsJSCID *aCID) { NS_PRECONDITION(mCID, "bad cid"); NS_INIT_ISUPPORTS(); - NS_ADDREF_THIS(); NS_ADDREF(mCID); } @@ -432,9 +501,13 @@ CIDCreateInstanceScriptable* CIDCreateInstance::GetScriptable() { static CIDCreateInstanceScriptable* scriptable = NULL; - // we leak this singleton if(!scriptable) + { scriptable = new CIDCreateInstanceScriptable(); + // we leak this singleton + if(scriptable) + NS_ADDREF(scriptable); + } return scriptable; } @@ -498,7 +571,6 @@ ServiceReleaser::ServiceReleaser(const nsCID& aCID) : mCID(aCID) { NS_INIT_ISUPPORTS(); - NS_ADDREF_THIS(); } ServiceReleaser::~ServiceReleaser() {} @@ -514,7 +586,6 @@ ServiceReleaser::AboutToRelease(nsISupports* aObj) CIDGetServiceScriptable::CIDGetServiceScriptable() { NS_INIT_REFCNT(); - NS_ADDREF_THIS(); } CIDGetServiceScriptable::~CIDGetServiceScriptable() {} @@ -604,8 +675,9 @@ CIDGetServiceScriptable::Call(JSContext *cx, JSObject *obj, nsresult rv; rv = nsServiceManager::GetService(*cid, *piid, &srvc, NULL); + NS_ASSERTION(NS_FAILED(rv) || srvc, "service manager returned success, but service is null!"); - if(NS_FAILED(rv)) + if(NS_FAILED(rv) || !srvc) { ThrowBadResultException(XPCJSError::GS_RETURNED_FAILURE, cx, rv); *retval = JS_FALSE; @@ -633,14 +705,18 @@ CIDGetServiceScriptable::Call(JSContext *cx, JSObject *obj, // This will eventually release the reference we got from // nsServiceManager::GetService ServiceReleaser* releaser = new ServiceReleaser(*cid); - if(NS_FAILED(srvcWrapper->SetFinalizeListener(releaser))) + if(releaser) { - // Failure means that we are using a preexisting wrapper on - // this service that has already setup a listener. So, we just - // release our extra ref and trust the lister that is already in - // place to do the right thing. - NS_RELEASE(srvc); - NS_RELEASE(releaser); + NS_ADDREF(releaser); + if(NS_FAILED(srvcWrapper->SetFinalizeListener(releaser))) + { + // Failure means that we are using a preexisting wrapper on + // this service that has already setup a listener. So, we just + // release our extra ref and trust the lister that is already in + // place to do the right thing. + NS_RELEASE(srvc); + NS_RELEASE(releaser); + } } nsAllocator::Free(cid); @@ -664,7 +740,6 @@ CIDGetService::CIDGetService(nsJSCID *aCID) { NS_PRECONDITION(mCID, "bad cid"); NS_INIT_ISUPPORTS(); - NS_ADDREF_THIS(); NS_ADDREF(mCID); } @@ -679,25 +754,28 @@ CIDGetServiceScriptable* CIDGetService::GetScriptable() { static CIDGetServiceScriptable* scriptable = NULL; - // we leak this singleton if(!scriptable) + { + // we leak this singleton scriptable = new CIDGetServiceScriptable(); + if(scriptable) + NS_ADDREF(scriptable); + } return scriptable; } - /***************************************************************************/ -// nsJSCID +/***************************************************************************/ -nsresult +NS_IMETHODIMP nsJSCID::QueryInterface(REFNSIID aIID, void** aInstancePtr) { if (NULL == aInstancePtr) { return NS_ERROR_NULL_POINTER; } - if (aIID.Equals(nsCOMTypeInfo::GetIID()) || - aIID.Equals(nsIJSID::GetIID()) || - aIID.Equals(nsIJSCID::GetIID())) { + if (aIID.Equals(NS_GET_IID(nsISupports)) || + aIID.Equals(NS_GET_IID(nsIJSID)) || + aIID.Equals(NS_GET_IID(nsIJSCID))) { *aInstancePtr = (void*) this; NS_ADDREF_THIS(); return NS_OK; @@ -709,160 +787,69 @@ nsJSCID::QueryInterface(REFNSIID aIID, void** aInstancePtr) NS_IMPL_ADDREF(nsJSCID) NS_IMPL_RELEASE(nsJSCID) -nsJSCID::nsJSCID() - : mID(GetInvalidIID()), - mNumber(gNoString), - mName(gNoString) +nsJSCID::nsJSCID() {NS_INIT_ISUPPORTS();} +nsJSCID::~nsJSCID() {} + +NS_IMETHODIMP nsJSCID::GetName(char * *aName) + {resolveName(); return mDetails.GetName(aName);} + +NS_IMETHODIMP nsJSCID::GetNumber(char * *aNumber) + {return mDetails.GetNumber(aNumber);} + +NS_IMETHODIMP nsJSCID::GetId(nsID* *aId) + {return mDetails.GetId(aId);} + +NS_IMETHODIMP nsJSCID::GetValid(PRBool *aValid) + {return mDetails.GetValid(aValid);} + +NS_IMETHODIMP nsJSCID::equals(nsIJSID *other, PRBool *_retval) + {return mDetails.equals(other, _retval);} + +NS_IMETHODIMP nsJSCID::init(const char *idString, PRBool *_retval) + {return mDetails.init(idString, _retval);} + +NS_IMETHODIMP nsJSCID::toString(char **_retval) + {resolveName(); return mDetails.toString(_retval);} + +void +nsJSCID::resolveName() { - NS_INIT_ISUPPORTS(); - NS_ADDREF_THIS(); -}; - -nsJSCID::~nsJSCID() -{ - if(mNumber && mNumber != gNoString) - delete [] mNumber; - if(mName && mName != gNoString) - delete [] mName; -} - -void nsJSCID::reset() -{ - mID = GetInvalidIID(); - - if(mNumber && mNumber != gNoString) - delete [] mNumber; - if(mName && mName != gNoString) - delete [] mName; - - mNumber = mName = NULL; + if(!mDetails.nameIsSet()) + mDetails.setNameToNoString(); } //static nsJSCID* nsJSCID::NewID(const char* str) { - PRBool success; + if(!str) + { + NS_ASSERTION(0,"no string"); + return nsnull; + } + nsJSCID* idObj = new nsJSCID(); - if(!idObj) - return NULL; - - if(NS_FAILED(idObj->init(str, &success)) || !success) + if(idObj) { - delete idObj; - return NULL; - } + PRBool success = PR_FALSE; + NS_ADDREF(idObj); - return idObj; -} - -void -nsJSCID::setName(const char* name) -{ - int len = strlen(name)+1; - mName = new char[len]; - if(mName) - memcpy(mName, name, len); -} - -NS_IMETHODIMP -nsJSCID::GetName(char * *aName) -{ - if(!mName) - mName = gNoString; - *aName = (char*) nsAllocator::Clone(mName, strlen(mName)+1); - return *aName ? NS_OK : NS_ERROR_OUT_OF_MEMORY; -} - -NS_IMETHODIMP -nsJSCID::GetNumber(char * *aNumber) -{ - if(!mNumber) - { - if(!(mNumber = mID.ToString())) - mNumber = gNoString; - } - - *aNumber = (char*) nsAllocator::Clone(mNumber, strlen(mNumber)+1); - return *aNumber ? NS_OK : NS_ERROR_OUT_OF_MEMORY; -} - - -NS_IMETHODIMP -nsJSCID::GetId(nsID* *aId) -{ - *aId = (nsID*) nsAllocator::Clone(&mID, sizeof(nsID)); - return *aId ? NS_OK : NS_ERROR_OUT_OF_MEMORY; -} - -NS_IMETHODIMP -nsJSCID::GetValid(PRBool *aValid) -{ - *aValid = !mID.Equals(GetInvalidIID()); - return NS_OK; -} - -NS_IMETHODIMP -nsJSCID::equals(nsIJSID *other, PRBool *_retval) -{ - if(!_retval) - return NS_ERROR_NULL_POINTER; - - *_retval = PR_FALSE; - - if(mID.Equals(GetInvalidIID())) - return NS_OK; - - nsID* otherID; - if(NS_SUCCEEDED(other->GetId(&otherID))) - { - *_retval = mID.Equals(*otherID); - nsAllocator::Free(otherID); - } - return NS_OK; -} - -NS_IMETHODIMP -nsJSCID::init(const char *idString, PRBool *_retval) -{ - if(!_retval || !idString) - return NS_ERROR_NULL_POINTER; - - PRBool success = PR_FALSE; - - if(strlen(idString) && mID.Equals(GetInvalidIID())) - { - reset(); - - if(idString[0] == '{') + if(str[0] == '{') { - nsID id; - if(id.Parse((char*)idString)) - { - mID = id; - success = PR_TRUE; - } + idObj->init(str, &success); } else { nsCID cid; - if(NS_SUCCEEDED(nsComponentManager::ProgIDToCLSID(idString, &cid))) + if(NS_SUCCEEDED(nsComponentManager::ProgIDToCLSID(str, &cid))) { - mID = cid; - setName(idString); - success = PR_TRUE; + success = idObj->mDetails.initWithName(cid, str); } } + if(!success) + NS_RELEASE(idObj); } - - *_retval = success; - return NS_OK; -} - -NS_IMETHODIMP -nsJSCID::toString(char **_retval) -{ - return GetName(_retval); + return idObj; } /* readonly attribute nsISupports createInstance; */ @@ -873,6 +860,9 @@ nsJSCID::GetCreateInstance(nsISupports * *aCreateInstance) return NS_ERROR_NULL_POINTER; *aCreateInstance = new CIDCreateInstance(this); + if(*aCreateInstance) + NS_ADDREF(*aCreateInstance); + return NS_OK; } @@ -884,6 +874,8 @@ nsJSCID::GetGetService(nsISupports * *aGetService) return NS_ERROR_NULL_POINTER; *aGetService = new CIDGetService(this); + if(*aGetService) + NS_ADDREF(*aGetService); return NS_OK; } @@ -906,9 +898,10 @@ xpc_NewIIDObject(JSContext *cx, const nsID& aID) if(xpc) { nsIXPConnectWrappedNative* nsid_wrapper; - if(NS_SUCCEEDED(xpc->WrapNative(cx, iid, - nsIJSIID::GetIID(), - &nsid_wrapper))) + if(NS_SUCCEEDED(xpc->WrapNative(cx, + NS_STATIC_CAST(nsISupports*,iid), + NS_GET_IID(nsIJSIID), + &nsid_wrapper))) { nsid_wrapper->GetJSObject(&obj); NS_RELEASE(nsid_wrapper); diff --git a/mozilla/js/src/xpconnect/src/xpcprivate.h b/mozilla/js/src/xpconnect/src/xpcprivate.h index 88f300b8d6a..bbb8f9353a8 100644 --- a/mozilla/js/src/xpconnect/src/xpcprivate.h +++ b/mozilla/js/src/xpconnect/src/xpcprivate.h @@ -28,6 +28,7 @@ #include "nsISupports.h" #include "nsIServiceManager.h" #include "nsIComponentManager.h" +#include "nsISupportsPrimitives.h" #include "nsIGenericFactory.h" #include "nsIAllocator.h" #include "nsIXPConnect.h" @@ -697,6 +698,41 @@ XPC_JSArgumentFormatter(JSContext *cx, const char *format, JSBool fromJS, jsval **vpp, va_list *app); /***************************************************************************/ +// This is a hidden shared base to handle most of the shared implementation +// between nsJSIID and nsJSCID + +class nsJSIDDDetails +{ +public: + nsresult GetName(char * *aName); + nsresult GetNumber(char * *aNumber); + nsresult GetId(nsID* *aId); + nsresult GetValid(PRBool *aValid); + nsresult equals(nsIJSID *other, PRBool *_retval); + nsresult init(const char *idString, PRBool *_retval); + nsresult toString(char **_retval); + + PRBool initWithName(const nsID& id, const char *nameString); + PRBool setName(const char* name); + void setNameToNoString() + {NS_ASSERTION(!mName, "name already set"); mName = gNoString;} + PRBool nameIsSet() const {return nsnull != mName;} + const nsID* getID() const {return &mID;} + + nsJSIDDDetails(); + ~nsJSIDDDetails(); +protected: + + void reset(); + const nsID& GetInvalidIID() const; + +protected: + static char gNoString[]; + nsID mID; + char* mNumber; + char* mName; +}; + // nsJSIID class nsJSIID : public nsIJSIID @@ -704,6 +740,8 @@ class nsJSIID : public nsIJSIID public: NS_DECL_ISUPPORTS + // we manually delagate these to nsJSIDDDetails + /* readonly attribute string name; */ NS_IMETHOD GetName(char * *aName); @@ -725,22 +763,20 @@ public: /* string toString (); */ NS_IMETHOD toString(char **_retval); - nsJSIID(); - virtual ~nsJSIID(); + // we implement the rest... static nsJSIID* NewID(const char* str); -private: - void reset(); - void setName(const char* name); + nsJSIID(); + virtual ~nsJSIID(); private: - nsID mID; - char* mNumber; - char* mName; + void resolveName(); + +private: + nsJSIDDDetails mDetails; }; -/***************************************************************************/ // nsJSCID class nsJSCID : public nsIJSCID @@ -748,6 +784,8 @@ class nsJSCID : public nsIJSCID public: NS_DECL_ISUPPORTS + // we manually delagate these to nsJSIDDDetails + /* readonly attribute string name; */ NS_IMETHOD GetName(char * *aName); @@ -766,30 +804,30 @@ public: /* boolean init (in string idString); */ NS_IMETHOD init(const char *idString, PRBool *_retval); + /* string toString (); */ + NS_IMETHOD toString(char **_retval); + + // we implement the rest... + /* readonly attribute nsISupports createInstance; */ NS_IMETHOD GetCreateInstance(nsISupports * *aCreateInstance); /* readonly attribute nsISupports getService; */ NS_IMETHOD GetGetService(nsISupports * *aGetService); - /* string toString (); */ - NS_IMETHOD toString(char **_retval); + static nsJSCID* NewID(const char* str); nsJSCID(); virtual ~nsJSCID(); - static nsJSCID* NewID(const char* str); +private: + void resolveName(); private: - void reset(); - void setName(const char* name); - -private: - nsID mID; - char* mNumber; - char* mName; + nsJSIDDDetails mDetails; }; + JSObject* xpc_NewIIDObject(JSContext *cx, const nsID& aID); @@ -801,6 +839,7 @@ xpc_JSObjectToID(JSContext *cx, JSObject* obj); class nsXPCInterfaces; class nsXPCClasses; +class nsXPCClassesByID; class ComponentsScriptable; class nsXPCComponents : public nsIXPCComponents @@ -814,14 +853,18 @@ public: /* readonly attribute nsIXPCClasses classes; */ NS_IMETHOD GetClasses(nsIXPCClasses * *aClasses); + /* readonly attribute nsIXPCClassesByID classes; */ + NS_IMETHOD GetClassesByID(nsIXPCClassesByID * *aClassesByID); + /* readonly attribute nsIJSStackFrameLocation stack; */ NS_IMETHOD GetStack(nsIJSStackFrameLocation * *aStack); nsXPCComponents(); virtual ~nsXPCComponents(); private: - nsXPCInterfaces* mInterfaces; - nsXPCClasses* mClasses; + nsXPCInterfaces* mInterfaces; + nsXPCClasses* mClasses; + nsXPCClassesByID* mClassesByID; ComponentsScriptable* mScriptable; }; diff --git a/mozilla/js/src/xpconnect/src/xpcwrappednativeclass.cpp b/mozilla/js/src/xpconnect/src/xpcwrappednativeclass.cpp index 87ec70eae05..8db138f1be6 100644 --- a/mozilla/js/src/xpconnect/src/xpcwrappednativeclass.cpp +++ b/mozilla/js/src/xpconnect/src/xpcwrappednativeclass.cpp @@ -697,25 +697,25 @@ nsXPCWrappedNativeClass::DynamicEnumerate(nsXPCWrappedNative* wrapper, return JS_TRUE; } case JSENUMERATE_NEXT: - holder = (EnumStateHolder*) JSVAL_TO_PRIVATE(*statep); - NS_ASSERTION(holder,"bad statep"); - - if(holder->dstate != JSVAL_NULL) + if(NULL != (holder = (EnumStateHolder*) JSVAL_TO_PRIVATE(*statep))) { - JSBool retval; - if(NS_FAILED(ds->Enumerate(cx, obj, JSENUMERATE_NEXT, - &holder->dstate, idp, wrapper, - as, &retval)) || !retval) - *idp = holder->dstate = JSVAL_NULL; + if(holder->dstate != JSVAL_NULL) + { + JSBool retval; + if(NS_FAILED(ds->Enumerate(cx, obj, JSENUMERATE_NEXT, + &holder->dstate, idp, wrapper, + as, &retval)) || !retval) + *idp = holder->dstate = JSVAL_NULL; + } + + if(holder->dstate == JSVAL_NULL && holder->sstate != JSVAL_NULL) + StaticEnumerate(wrapper, JSENUMERATE_NEXT, &holder->sstate, idp); + + // are we done? + if(holder->dstate != JSVAL_NULL || holder->sstate != JSVAL_NULL) + return JS_TRUE; } - if(holder->dstate == JSVAL_NULL && holder->sstate != JSVAL_NULL) - StaticEnumerate(wrapper, JSENUMERATE_NEXT, &holder->sstate, idp); - - // are we done? - if(holder->dstate != JSVAL_NULL || holder->sstate != JSVAL_NULL) - return JS_TRUE; - /* Fall through ... */ case JSENUMERATE_DESTROY: diff --git a/mozilla/js/src/xpconnect/tests/Makefile.in b/mozilla/js/src/xpconnect/tests/Makefile.in index aa0f4ad7c86..fbb26ecae0c 100644 --- a/mozilla/js/src/xpconnect/tests/Makefile.in +++ b/mozilla/js/src/xpconnect/tests/Makefile.in @@ -40,6 +40,8 @@ LIBS = \ TEST_FILES = $(srcdir)/testxpc.js \ $(srcdir)/xpctest_echo.js \ + $(srcdir)/xpctest_ids.js \ + $(srcdir)/xpctest_enum_create.js \ $(srcdir)/xpctest_primitives.js diff --git a/mozilla/js/src/xpconnect/tests/TestXPC.cpp b/mozilla/js/src/xpconnect/tests/TestXPC.cpp index 0e9f8566d47..a1c187d1993 100644 --- a/mozilla/js/src/xpconnect/tests/TestXPC.cpp +++ b/mozilla/js/src/xpconnect/tests/TestXPC.cpp @@ -28,6 +28,8 @@ #include "nsIXPCSecurityManager.h" #include "nsIServiceManager.h" #include "nsIComponentManager.h" +#include "nsIEnumerator.h" +#include "nsISupportsPrimitives.h" #include "jsapi.h" #include "xpclog.h" #include "nscore.h" @@ -40,6 +42,7 @@ #include "nsIJSContextStack.h" +static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID); static NS_DEFINE_CID(kGenericFactoryCID, NS_GENERICFACTORY_CID); static NS_DEFINE_IID(kIAllocatorIID, NS_IALLOCATOR_IID); static NS_DEFINE_IID(kAllocatorCID, NS_ALLOCATOR_CID); @@ -1257,6 +1260,103 @@ sm_test_done: NS_RELEASE(xpc); JS_DestroyRuntime(rt); JS_ShutDown(); + +#if 0 +// a fun test... + { + nsresult rv; + NS_WITH_SERVICE(nsIComponentManager, cm, kComponentManagerCID, &rv); + if(NS_SUCCEEDED(rv)) + { + int count = 0; + nsIEnumerator* cids; + rv = cm->EnumerateCLSIDs(&cids); + if(NS_SUCCEEDED(rv)) + { + nsISupports* raw_holder; + + for(rv = cids->First(); + NS_SUCCEEDED(rv) && !cids->IsDone(); + rv = cids->Next()) + { + rv = cids->CurrentItem(&raw_holder); + if(NS_FAILED(rv)) + continue; + nsISupportsID* holder; + rv = raw_holder->QueryInterface(NS_GET_IID(nsISupportsID), + (void**) &holder); + NS_RELEASE(raw_holder); + if(NS_SUCCEEDED(rv)) + { + nsID* cid; + rv = holder->GetData(&cid); + if(NS_SUCCEEDED(rv)) + { + char* str = cid->ToString(); + if(str) + { + char* progid; + char* classname; + rv = cm->CLSIDToProgID(cid, &classname, &progid); + if(NS_SUCCEEDED(rv)) + { + printf("%s - %s - %s\n", str, progid, classname); + delete [] progid; + delete [] classname; + } + else + printf("%s\n", str); + count++; + delete [] str; + } + nsAllocator::Free(cid); + } + NS_RELEASE(holder); + } + } + NS_RELEASE(cids); + } + printf("%d CIDs found\n", count); + count = 0; + + + nsIEnumerator* progids; + rv = cm->EnumerateProgIDs(&progids); + if(NS_SUCCEEDED(rv)) + { + nsISupports* raw_holder; + + for(rv = progids->First(); + NS_SUCCEEDED(rv) && !progids->IsDone(); + rv = progids->Next()) + { + rv = progids->CurrentItem(&raw_holder); + if(NS_FAILED(rv)) + continue; + nsISupportsString* holder; + rv = raw_holder->QueryInterface(NS_GET_IID(nsISupportsString), + (void**) &holder); + NS_RELEASE(raw_holder); + if(NS_SUCCEEDED(rv)) + { + char* progid; + rv = holder->GetData(&progid); + if(NS_SUCCEEDED(rv)) + { + printf("%s\n", progid); + count++; + nsAllocator::Free(progid); + } + NS_RELEASE(holder); + } + } + NS_RELEASE(progids); + } + printf("%d Progids found\n", count); + } + } +#endif + return 0; } diff --git a/mozilla/js/src/xpconnect/tests/makefile.win b/mozilla/js/src/xpconnect/tests/makefile.win index 5857b70af3f..464bfad8c42 100644 --- a/mozilla/js/src/xpconnect/tests/makefile.win +++ b/mozilla/js/src/xpconnect/tests/makefile.win @@ -28,7 +28,9 @@ TESTCASES = \ testxpc.js \ simpletest.js \ xpctest_echo.js \ - xpctest_primitives.js + xpctest_ids.js \ + xpctest_enum_create.js \ + xpctest_primitives.js LCFLAGS=-DUSE_NSREG -DWIN32_LEAN_AND_MEAN -DJS_THREADSAFE -DJSFILE diff --git a/mozilla/js/src/xpconnect/tests/xpctest_enum_create.js b/mozilla/js/src/xpconnect/tests/xpctest_enum_create.js new file mode 100644 index 00000000000..6ecf4ffd921 --- /dev/null +++ b/mozilla/js/src/xpconnect/tests/xpctest_enum_create.js @@ -0,0 +1,186 @@ +if (typeof document == "undefined") /* in xpcshell */ + dumpln = print; +else + dumpln = function (str) {dump (str + "\n");} + +function dumpObject (o, pfx, sep) +{ + var p; + var s = ""; + + sep = (typeof sep == "undefined") ? " = " : sep; + pfx = (typeof pfx == "undefined") ? "" : pfx; + + + for (p in o) + { + if (typeof (o[p]) != "function") + s += pfx + p + sep + o[p] + "\n"; + else + s += pfx + p + sep + "function\n"; + } + + return s; + +} + +function bruteForceEnumeration(ignore) +{ + var interfaceInfo = new Object(); + +loop: for (var c in Components.classes) + { + var cls = Components.classes[c]; + dumpln ("**"); + dumpln (" * ProgID: '" + cls.name + "'"); + dumpln (" * CLSID: " + cls.number); + + if(ignore) { + for(var i = 0; i < ignore.length; i++) { + if(0 == cls.name.indexOf(ignore[i])) { + dumpln (" * This one might cause a crash - SKIPPING"); + continue loop; + } + } + } + + try + { + var ins = cls.createInstance(); + for (var i in Components.interfaces) + { + try + { + qi = ins.QueryInterface (Components.interfaces[i]); + dumpln (" * Supports Interface: " + i); + if (typeof interfaceInfo[i] == "undefined") + { + interfaceInfo[i] = dumpObject (qi, " ** "); + } + dumpln (interfaceInfo[i]); + } + catch (e) + { + /* nada */ + } + } + } + catch (e) + { + dumpln (" * createInstance FAILED:"); + dumpln (dumpObject (e)); + } + + dumpln (""); + + } + + dumpln ("**"); + dumpln (" * Interface Information :"); + dumpln (""); + // dump of giant string does not always work, split it up. + var bulk = dumpObject (interfaceInfo, (void 0), "::\n") + var lines = bulk.split("\n"); + for(var i = 0; i < lines.length; i++) + dumpln (lines[i]); + +} + +/** tests **/ +var totalClasses = 0, + nonameClasses = 0, + strangeClasses = 0, + totalIfaces = 0, + strangeIfaces = 0; + +dumpln ("**> Enumerating Classes"); +for (var c in Components.classes) +{ + totalClasses++; + if (Components.classes[c].name == "") + { + dumpln ("CLSID " + c + " has no progID."); + nonameClasses++; + } + else + if (c.search(/^component:\/\//) == -1) + { + dumpln ("Strange progID '" + c + "'"); + strangeClasses++; + } +} + +dumpln ("**> Enumerating Interfaces"); +for (var i in Components.interfaces) +{ + if (i != "QueryInterface") + { + totalIfaces++; + + if (i.search(/^nsI/) == -1) + { + dumpln ("Strange interface name '" + i + "'"); + strangeIfaces++; + } + } +} + +dumpln ("** Enumerated " + totalClasses + " classes"); +dumpln (" * " + nonameClasses + " without progIDs"); +dumpln (" * " + strangeClasses + " with strange names"); +dumpln (""); +dumpln ("** Enumerated " + totalIfaces + " interfaces"); +dumpln (" * " + strangeIfaces + " with strange names"); + +var progIDsTo_NOT_Create = [ + "component://netscape/messenger/maildb", // calling a property - nsMsgDatabase::m_newSet used but not set + "component://netscape/rdf/resource-factory", // calling a property - trying to copy a null value in nsRDFResource::GetValue + "component://netscape/addressbook/directoryproperty", // fails to init refcount + "component://netscape/image/decoder&type=image/", // PNGDecoder::QueryInterface and JPGDecoder::QueryInterface, do NS_INIT_REFCNT() in QueryInterface! (npunn) + "component://netscape/messenger/identity", // calling a property - nsMsgIdentity::getCharPref is null + "component://netscape/messenger/account", // calling a property - nsMsgAccount::GetIncomingServer asserts because m_accountKey is null + "component://netscape/messenger/server&type=", // calling a property - nsMsgIncomingServer::getCharPref uses m_prefs which is null + "component://netscape/prefwindow", // nsPrefWindow::~nsPrefWindow() releases null service + "component://netscape/rdf/xul-sort-service", // XULSortServiceImpl releases itself in its own destructor! + "component://netscape/rdf/datasource?name=msgaccounts", // nsMsgAccountDataSource::QueryInterface is COMPLETELY fucked up + "componment://netscape/intl/charsetconvertermanager", // another case where CreateInstance returned NS_OK, but the instance pointer was null! + "component://netscape/wallet", // WalletFactoryImpl::CreateInstance broken : calls "delete inst" then calls "NS_IF_RELEASE(inst)" + "component://netscape/rdf/datasource?name=mail-messageview", // nsMessageViewDataSource::RemoveDataSource uses mDataSource without checking for validity + + "component://netscape/rdf/datasource?name=local-store", //NS_NewLocalStore calls stuff that asserts + "component://netscape/rdf/datasource?name=xpinstall-update-notifier", //RDFXMLDataSourceImpl::Refresh does CreateInstance of parser but fails to check the result (I think I've seen this elsewhere) + "component://netscape/rdf/xul-template-builder", //RDFXMLDataSourceImpl::Refresh does CreateInstance of parser but fails to check the result (I think I've seen this elsewhere) + + "component://netscape/rdf/xul-key-listener", // RDFFactoryImpl::CreateInstance asserts when creating if requested interface is nsISupports! + "component://netscape/rdf/xul-popup-listener", // RDFFactoryImpl::CreateInstance asserts when creating if requested interface is nsISupports! + "component://netscape/rdf/xul-focus-tracker", // RDFFactoryImpl::CreateInstance asserts when creating if requested interface is nsISupports! + + "component://netscape/messengercompose/compose", // ASSERTION in nsMsgAccountManager::prefService() (needs prefs service) + "component://netscape/messenger", // ASSERTION in nsMsgAccountManager::prefService() (needs prefs service) + "component://netscape/rdf/datasource?name=msgaccountmanager", // ASSERTION in nsMsgAccountManager::prefService() (needs prefs service) + "component://netscape/rdf/datasource?name=mailnewsfolders", // ASSERTION in nsMsgAccountManager::prefService() (needs prefs service) + "component://netscape/rdf/datasource?name=msgnotifications", // ASSERTION in nsMsgAccountManager::prefService() (needs prefs service) + "component://netscape/rdf/datasource?name=mailnewsmessages", // ASSERTION in nsMsgAccountManager::prefService() (needs prefs service) + + "component://netscape/rdf/xul-content-sink", // nsXULContentSink.cpp, XULContentSinkImpl::XULContentSinkImpl needs to init mNameSpaceManager + "component://netscape/rdf/datasource?name=find", // FindDataSource::~FindDataSource calls gRDFService->UnregisterDataSource(this) even if it was not actaully registered. + + "component://netscape/rdf/datasource?name=addresscard", // nsAbRDFDataSource::~nsAbRDFDataSource calls mRDFService->UnregisterDataSource(this); even though it was not registered + "component://netscape/rdf/datasource?name=addressdirectory", // nsAbRDFDataSource::~nsAbRDFDataSource calls mRDFService->UnregisterDataSource(this); even though it was not registered + + "component://netscape/rdf/datasource?name=files", // FileSystemDataSource::~FileSystemDataSource calls gRDFService->UnregisterDataSource(this); even though it was not registered + + +]; + + +dumpln ("-------------------------------------------------------"); +dumpln (" Now let's create every component we can find..."); + +if(progIDsTo_NOT_Create.length) { + dumpln ("...except the following 'cuz they've been know to cause CRASHES!...") + for(var i = 0; i < progIDsTo_NOT_Create.length; i++) + dumpln (" "+progIDsTo_NOT_Create[i]); + dumpln (); +} +bruteForceEnumeration(progIDsTo_NOT_Create); diff --git a/mozilla/js/src/xpconnect/tests/xpctest_ids.js b/mozilla/js/src/xpconnect/tests/xpctest_ids.js new file mode 100644 index 00000000000..2269105cf61 --- /dev/null +++ b/mozilla/js/src/xpconnect/tests/xpctest_ids.js @@ -0,0 +1,126 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1999 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* This is a test for nsIIDs and nsCIDs in JavaScript. */ + +// our standard print function +function println(s) +{ + if(typeof(this.document) == "undefined") + print(s); + else + dump(s+"\n"); +} + +// a ctor for Interface IDs +function nsIID(str) +{ + var id = Components.classes.nsIID.createInstance(); + id = id.QueryInterface(Components.interfaces.nsIJSIID); + id.init(str); + return id; +} + +// a ctor for CLSIDs +function nsCID(str) +{ + var id = Components.classes.nsCID.createInstance(); + id = id.QueryInterface(Components.interfaces.nsIJSCID); + id.init(str); + return id; +} + +// some explicit IDs + +var NS_ISUPPORTS_IID = new nsIID("{00000000-0000-0000-c000-000000000046}"); +var NS_ECHO_UPPER = new nsCID("{ED132C20-EED1-11D2-BAA4-00805F8A5DD7}"); +var NS_ECHO = new nsCID("{ed132c20-eed1-11d2-baa4-00805f8a5dd7}"); +var NS_BOGUS_IID = new nsIID("{15898420-4d11-11d3-9893-006008962422}"); + +// our test data array +data = [ + // we expect bare interfacesIDs to resolve to names of interfaces (if they exist) + [NS_ISUPPORTS_IID , "nsISupports"], + [NS_ISUPPORTS_IID.name , "nsISupports"], + [NS_ISUPPORTS_IID.number , "{00000000-0000-0000-c000-000000000046}"], + // this one is made up so it only resolves to the number + [NS_BOGUS_IID , "{15898420-4d11-11d3-9893-006008962422}"], + + // now we check those the 'Components' knows about + [Components.interfaces.nsISupports , "nsISupports"], + [Components.classes.nsEcho , "nsEcho"], + [Components.classes.nsEcho.number , "{ed132c20-eed1-11d2-baa4-00805f8a5dd7}"], + + // now a bogus one + [Components.interfaces.bogus , "undefined"], + + // even though these 'exist', they are not addressable by canonical name + [Components.interfaces["{00000000-0000-0000-c000-000000000046}"] , "undefined"], + [Components.classes.nsEcho["{ed132c20-eed1-11d2-baa4-00805f8a5dd7}"], "undefined"], + + // we *don't* expect bare CLSIDs to resolve to progids + [NS_ECHO_UPPER , "{ed132c20-eed1-11d2-baa4-00805f8a5dd7}"], + [NS_ECHO , "{ed132c20-eed1-11d2-baa4-00805f8a5dd7}"], + [NS_ECHO_UPPER.number , "{ed132c20-eed1-11d2-baa4-00805f8a5dd7}"], + [NS_ECHO.number , "{ed132c20-eed1-11d2-baa4-00805f8a5dd7}"], + + // classesByID requires canonical numbers + [Components.classesByID.nsEcho , "undefined"], + [Components.classesByID["{ed132c20-eed1-11d2-baa4-00805f8a5dd7}"], "{ed132c20-eed1-11d2-baa4-00805f8a5dd7}"], + [Components.classesByID["{ed132c20-eed1-11d2-baa4-00805f8a5dd7}"].number, "{ed132c20-eed1-11d2-baa4-00805f8a5dd7}"], + + // works with valid CID + [Components.classesByID["{ed132c20-eed1-11d2-baa4-00805f8a5dd7}"], "{ed132c20-eed1-11d2-baa4-00805f8a5dd7}"], + + // does not work with bogus CID + [Components.classesByID["{35fb7000-4d23-11d3-9893-006008962422}"], "undefined"], + + // but the same bogus CID works if not claiming that it is a registered CID + [new nsCID("{35fb7000-4d23-11d3-9893-006008962422}"), "{35fb7000-4d23-11d3-9893-006008962422}"], + + // classesByID should not resolve the number to the progid + [Components.classesByID["{ed132c20-eed1-11d2-baa4-00805f8a5dd7}"].name, ""], + // ...though it is clearly the same object... + [Components.classesByID["{ed132c20-eed1-11d2-baa4-00805f8a5dd7}"].equals(Components.classes.nsEcho), true], + + // equals self + [Components.classes.nsEcho.equals(Components.classes.nsEcho), true], + + // we could add tests for more of the ID properties here... + +] + +// do the tests + +println("\nJavaScript nsID tests...\n"); +var failureCount = 0; +for(var i = 0; i < data.length; i++) { + var item = data[i]; + if(""+item[0] != ""+item[1]) { + println("failed for item "+i+" expected \""+item[1]+"\" got \""+item[0]+"\""); + failureCount ++; + } +} + +// show the final results + +println(""); +if(failureCount) + println(failureCount+" FAILURES total"); +else + println("all PASSED"); diff --git a/mozilla/xpcom/components/nsComponentManager.cpp b/mozilla/xpcom/components/nsComponentManager.cpp index 69c547c9143..2eaf667f1ab 100644 --- a/mozilla/xpcom/components/nsComponentManager.cpp +++ b/mozilla/xpcom/components/nsComponentManager.cpp @@ -23,6 +23,8 @@ #include "nsSpecialSystemDirectory.h" #include "nsCRT.h" #include "nsIEnumerator.h" +#include "nsHashtableEnumerator.h" +#include "nsISupportsPrimitives.h" #include "plstr.h" #include "prlink.h" @@ -140,7 +142,8 @@ private: nsComponentManagerImpl::nsComponentManagerImpl() - : mFactories(NULL), mProgIDs(NULL), mMon(NULL), mDllStore(NULL), mRegistry(NULL) + : mFactories(NULL), mProgIDs(NULL), mMon(NULL), mDllStore(NULL), + mRegistry(NULL), mPrePopulationDone(PR_FALSE) { NS_INIT_REFCNT(); } @@ -868,6 +871,7 @@ nsresult nsComponentManagerImpl::PlatformPrePopulateRegistry() // printf("Populating [ %s, %s ]\n", cidString, progidString); } + mPrePopulationDone = PR_TRUE; return NS_OK; } @@ -2208,6 +2212,116 @@ nsComponentManagerImpl::SelfUnregisterDll(nsDll *dll) return res; } +nsresult +nsComponentManagerImpl::IsRegistered(const nsCID &aClass, + PRBool *aRegistered) +{ + if(!aRegistered) + { + NS_ASSERTION(0, "null ptr"); + return NS_ERROR_NULL_POINTER; + } + *aRegistered = (nsnull != GetFactoryEntry(aClass, PR_TRUE)); + return NS_OK; +} + +static NS_IMETHODIMP +ConvertFactoryEntryToCID(nsHashKey *key, void *data, void *convert_data, + nsISupports **retval) +{ + nsComponentManagerImpl *compMgr = (nsComponentManagerImpl*) convert_data; + nsresult rv; + + nsISupportsID* cidHolder; + + if(NS_SUCCEEDED(rv = compMgr->CreateInstance(NS_SUPPORTS_ID_PROGID, nsnull, + NS_GET_IID(nsISupportsID), + (void **)&cidHolder))) + { + nsFactoryEntry *fe = (nsFactoryEntry *) data; + cidHolder->SetData(&fe->cid); + *retval = cidHolder; + } + else + *retval = nsnull; + + return rv; +} + +static NS_IMETHODIMP +ConvertProgIDKeyToString(nsHashKey *key, void *data, void *convert_data, + nsISupports **retval) +{ + nsComponentManagerImpl *compMgr = (nsComponentManagerImpl*) convert_data; + nsresult rv; + + nsISupportsString* strHolder; + + if(NS_SUCCEEDED(rv = compMgr->CreateInstance(NS_SUPPORTS_STRING_PROGID, nsnull, + NS_GET_IID(nsISupportsString), + (void **)&strHolder))) + { + nsStringKey *strKey = (nsStringKey *) key; + const nsString& str = strKey->GetString(); + char* yetAnotherCopyOfTheString = str.ToNewCString(); + if(yetAnotherCopyOfTheString) + { + strHolder->SetData(yetAnotherCopyOfTheString); + delete [] yetAnotherCopyOfTheString; + } + *retval = strHolder; + } + else + *retval = nsnull; + + return rv; +} + +nsresult +nsComponentManagerImpl::EnumerateCLSIDs(nsIEnumerator** aEmumerator) +{ + if(!aEmumerator) + { + NS_ASSERTION(0, "null ptr"); + return NS_ERROR_NULL_POINTER; + } + *aEmumerator = nsnull; + + nsresult rv; + if(!mPrePopulationDone) + { + rv = PlatformPrePopulateRegistry(); + if(NS_FAILED(rv)) + return rv; + } + + return NS_NewHashtableEnumerator(mFactories, ConvertFactoryEntryToCID, + this, aEmumerator); +} + +nsresult +nsComponentManagerImpl::EnumerateProgIDs(nsIEnumerator** aEmumerator) +{ + if(!aEmumerator) + { + NS_ASSERTION(0, "null ptr"); + return NS_ERROR_NULL_POINTER; + } + + *aEmumerator = nsnull; + + nsresult rv; + if(!mPrePopulationDone) + { + rv = PlatformPrePopulateRegistry(); + if(NS_FAILED(rv)) + return rv; + } + + return NS_NewHashtableEnumerator(mProgIDs, ConvertProgIDKeyToString, + this, aEmumerator); +} + //////////////////////////////////////////////////////////////////////////////// NS_COM nsresult diff --git a/mozilla/xpcom/components/nsComponentManager.h b/mozilla/xpcom/components/nsComponentManager.h index 0dcfdbe25bd..8c5d7f6bf9e 100644 --- a/mozilla/xpcom/components/nsComponentManager.h +++ b/mozilla/xpcom/components/nsComponentManager.h @@ -119,6 +119,16 @@ public: // Unload dynamically loaded factories that are not in use NS_IMETHOD FreeLibraries(void); + // Is the given CID currently registered? + NS_IMETHOD IsRegistered(const nsCID &aClass, + PRBool *aRegistered); + + // Get an enumeration of all the CIDs + NS_IMETHOD EnumerateCLSIDs(nsIEnumerator** aEmumerator); + + // Get an enumeration of all the ProgIDs + NS_IMETHOD EnumerateProgIDs(nsIEnumerator** aEmumerator); + ////////////////////////////////////////////////////////////////////////////// // DLL registration support // Autoregistration will try only files with these extensions. @@ -178,6 +188,7 @@ protected: nsIRegistry::Key mXPCOMKey; nsIRegistry::Key mClassesKey; nsIRegistry::Key mCLSIDKey; + PRBool mPrePopulationDone; }; #define NS_MAX_FILENAME_LEN 1024 diff --git a/mozilla/xpcom/components/nsIComponentManager.h b/mozilla/xpcom/components/nsIComponentManager.h index 3a224a228dd..95ed590829f 100644 --- a/mozilla/xpcom/components/nsIComponentManager.h +++ b/mozilla/xpcom/components/nsIComponentManager.h @@ -26,6 +26,7 @@ #include "nsISupports.h" #include "nsIFactory.h" #include "nsIFileSpec.h" +#include "nsIEnumerator.h" /* * Prototypes for dynamic library export functions. Your DLL/DSO needs to export @@ -175,6 +176,17 @@ public: NS_IMETHOD AutoRegister(RegistrationTime when, nsIFileSpec* directory) = 0; NS_IMETHOD AutoRegisterComponent(RegistrationTime when, nsIFileSpec *component) = 0; + + // Is the given CID currently registered? + NS_IMETHOD IsRegistered(const nsCID &aClass, + PRBool *aRegistered) = 0; + + // Get an enumeration of all the CIDs + NS_IMETHOD EnumerateCLSIDs(nsIEnumerator** aEmumerator) = 0; + + // Get an enumeration of all the ProgIDs + NS_IMETHOD EnumerateProgIDs(nsIEnumerator** aEmumerator) = 0; + }; //////////////////////////////////////////////////////////////////////////////// @@ -267,7 +279,6 @@ public: // Unload dynamically loaded factories that are not in use static nsresult FreeLibraries(void); - ////////////////////////////////////////////////////////////////////////////// // DLL registration support @@ -279,6 +290,16 @@ public: static nsresult AutoRegisterComponent(nsIComponentManager::RegistrationTime when, nsIFileSpec *component); + // Is the given CID currently registered? + static nsresult IsRegistered(const nsCID &aClass, + PRBool *aRegistered); + + // Get an enumeration of all the CIDs + static nsresult EnumerateCLSIDs(nsIEnumerator** aEmumerator); + + // Get an enumeration of all the ProgIDs + static nsresult EnumerateProgIDs(nsIEnumerator** aEmumerator); + }; //////////////////////////////////////////////////////////////////////////////// diff --git a/mozilla/xpcom/components/nsRepository.cpp b/mozilla/xpcom/components/nsRepository.cpp index e2324169f8b..f76c3bdab46 100644 --- a/mozilla/xpcom/components/nsRepository.cpp +++ b/mozilla/xpcom/components/nsRepository.cpp @@ -186,3 +186,34 @@ nsComponentManager::AutoRegisterComponent(nsIComponentManager::RegistrationTime if (NS_FAILED(rv)) return rv; return cm->AutoRegisterComponent(when, fullname); } + +nsresult +nsComponentManager::IsRegistered(const nsCID &aClass, + PRBool *aRegistered) +{ + nsIComponentManager* cm; + nsresult rv = NS_GetGlobalComponentManager(&cm); + if (NS_FAILED(rv)) return rv; + return cm->IsRegistered(aClass, aRegistered); +} + +nsresult +nsComponentManager::EnumerateCLSIDs(nsIEnumerator** aEmumerator) +{ + nsIComponentManager* cm; + nsresult rv = NS_GetGlobalComponentManager(&cm); + if (NS_FAILED(rv)) return rv; + return cm->EnumerateCLSIDs(aEmumerator); +} + +nsresult +nsComponentManager::EnumerateProgIDs(nsIEnumerator** aEmumerator) +{ + nsIComponentManager* cm; + nsresult rv = NS_GetGlobalComponentManager(&cm); + if (NS_FAILED(rv)) return rv; + return cm->EnumerateProgIDs(aEmumerator); +} + + + diff --git a/mozilla/xpcom/ds/nsHashtable.cpp b/mozilla/xpcom/ds/nsHashtable.cpp index 1837676f6c1..92cbc204b75 100644 --- a/mozilla/xpcom/ds/nsHashtable.cpp +++ b/mozilla/xpcom/ds/nsHashtable.cpp @@ -300,6 +300,11 @@ nsHashKey* nsStringKey::Clone() const return new nsStringKey(mStr); } +const nsString& nsStringKey::GetString() const +{ + return mStr; +} + //////////////////////////////////////////////////////////////////////////////// // nsObjectHashtable: an nsHashtable where the elements are C++ objects to be // deleted diff --git a/mozilla/xpcom/ds/nsHashtable.h b/mozilla/xpcom/ds/nsHashtable.h index 5e3099850ad..3d7da84aab3 100644 --- a/mozilla/xpcom/ds/nsHashtable.h +++ b/mozilla/xpcom/ds/nsHashtable.h @@ -209,6 +209,9 @@ public: nsHashKey* Clone() const; + // For when the owner of the hashtable wants to peek at the actual + // string in the key. No copy is made, so be careful. + const nsString& GetString() const; }; diff --git a/mozilla/xpcom/reflect/xptinfo/public/nsIInterfaceInfoManager.h b/mozilla/xpcom/reflect/xptinfo/public/nsIInterfaceInfoManager.h index 8729cbef41a..305ad2c7f79 100644 --- a/mozilla/xpcom/reflect/xptinfo/public/nsIInterfaceInfoManager.h +++ b/mozilla/xpcom/reflect/xptinfo/public/nsIInterfaceInfoManager.h @@ -46,7 +46,7 @@ public: NS_IMETHOD GetNameForIID(const nsIID* iid, char** name) = 0; // Get an enumeration of all the interfaces - NS_IMETHOD GetInterfaceEnumerator(nsIEnumerator** emumerator) = 0; + NS_IMETHOD EnumerateInterfaces(nsIEnumerator** emumerator) = 0; // XXX other methods? diff --git a/mozilla/xpcom/reflect/xptinfo/src/nsInterfaceInfoManager.cpp b/mozilla/xpcom/reflect/xptinfo/src/nsInterfaceInfoManager.cpp index 7ef34b6a66b..d7c68078c8a 100644 --- a/mozilla/xpcom/reflect/xptinfo/src/nsInterfaceInfoManager.cpp +++ b/mozilla/xpcom/reflect/xptinfo/src/nsInterfaceInfoManager.cpp @@ -511,9 +511,13 @@ NS_IMETHODIMP convert_interface_record(nsHashKey *key, void *data, } NS_IMETHODIMP -nsInterfaceInfoManager::GetInterfaceEnumerator(nsIEnumerator** emumerator) +nsInterfaceInfoManager::EnumerateInterfaces(nsIEnumerator** emumerator) { - NS_PRECONDITION (emumerator, "null ptr"); + if(!emumerator) + { + NS_ASSERTION(0, "null ptr"); + return NS_ERROR_NULL_POINTER; + } return NS_NewHashtableEnumerator(this->IIDTable, convert_interface_record, nsnull, emumerator); diff --git a/mozilla/xpcom/reflect/xptinfo/src/nsInterfaceInfoManager.h b/mozilla/xpcom/reflect/xptinfo/src/nsInterfaceInfoManager.h index b09bdadc500..15d6857e6d7 100644 --- a/mozilla/xpcom/reflect/xptinfo/src/nsInterfaceInfoManager.h +++ b/mozilla/xpcom/reflect/xptinfo/src/nsInterfaceInfoManager.h @@ -47,7 +47,7 @@ class nsInterfaceInfoManager : public nsIInterfaceInfoManager NS_IMETHOD GetNameForIID(const nsIID* iid, char** name); // Get an enumeration of all the interfaces - NS_IMETHOD GetInterfaceEnumerator(nsIEnumerator** emumerator); + NS_IMETHOD EnumerateInterfaces(nsIEnumerator** emumerator); public: virtual ~nsInterfaceInfoManager();