Bug 204894 - Implement GeckoActiveXObject.supports(clsid). r=dbradley, sr=alecf

This commit is contained in:
dbradley%netscape.com 2003-06-20 04:08:17 +00:00
parent 0c73334798
commit 1e7ae8efa5
5 changed files with 158 additions and 48 deletions

View File

@ -73,26 +73,15 @@ XPCDispObject::WrapIDispatch(IDispatch *pDispatch, XPCCallContext &ccx,
return PR_TRUE;
}
HRESULT XPCDispObject::COMCreateInstance(XPCCallContext & ccx, BSTR className,
PRBool enforceSecurity,
IDispatch ** result)
HRESULT XPCDispObject::SecurityCheck(XPCCallContext & ccx, const CLSID & aCID,
IDispatch ** createdObject)
{
// Turn the string into a CLSID
_bstr_t bstrName(className);
CLSID classID = CLSID_NULL;
HRESULT hr = CLSIDFromString(bstrName, &classID);
if(FAILED(hr))
hr = CLSIDFromProgID(bstrName, &classID);
if(FAILED(hr) || ::IsEqualCLSID(classID, CLSID_NULL))
return hr;
nsresult rv;
nsCOMPtr<nsIDispatchSupport> dispSupport = do_GetService(NS_IDISPATCH_SUPPORT_CONTRACTID, &rv);
if(NS_FAILED(rv)) return E_UNEXPECTED;
PRUint32 hostingFlags = nsIActiveXSecurityPolicy::HOSTING_FLAGS_HOST_NOTHING;
dispSupport->GetHostingFlags(nsnull, &hostingFlags);
PRBool allowSafeObjects;
if(hostingFlags & (nsIActiveXSecurityPolicy::HOSTING_FLAGS_SCRIPT_SAFE_OBJECTS))
allowSafeObjects = PR_TRUE;
@ -103,46 +92,75 @@ HRESULT XPCDispObject::COMCreateInstance(XPCCallContext & ccx, BSTR className,
allowAnyObjects = PR_TRUE;
else
allowAnyObjects = PR_FALSE;
// There is no point proceeding if flags say we can't script safe or unsafe objects
if(enforceSecurity && !allowSafeObjects && !allowAnyObjects)
{
if(!allowSafeObjects && !allowAnyObjects)
return E_FAIL;
}
PRBool classExists = PR_FALSE;
PRBool ok = PR_FALSE;
const nsCID & ourCID = XPCDispCLSID2nsCID(classID);
const nsCID & ourCID = XPCDispCLSID2nsCID(aCID);
dispSupport->IsClassSafeToHost(ccx, ourCID, PR_FALSE, &classExists, &ok);
if(classExists && !ok)
return E_FAIL;
// Test if the object is scriptable
PRBool isScriptable = PR_FALSE;
if(enforceSecurity && !allowAnyObjects)
if(!allowAnyObjects)
{
PRBool classExists = PR_FALSE;
dispSupport->IsClassMarkedSafeForScripting(ourCID, &classExists, &isScriptable);
if(!classExists)
return REGDB_E_CLASSNOTREG;
}
// Create the object
CComPtr<IDispatch> disp;
// If createdObject isn't null we need to create the object
if (createdObject)
{
HRESULT hr = disp.CoCreateInstance(aCID);
if(FAILED(hr))
return hr;
// if we don't allow just any object, and it wasn't marked
// safe for scripting then ask the object (MS idea of security)
if (!allowAnyObjects && !isScriptable)
{
dispSupport->IsObjectSafeForScripting(disp, NSID_IDISPATCH, &isScriptable);
if(!isScriptable)
return E_FAIL;
}
disp.CopyTo(createdObject);
}
return S_OK;
}
HRESULT XPCDispObject::COMCreateInstance(XPCCallContext & ccx, BSTR className,
PRBool enforceSecurity,
IDispatch ** result)
{
NS_ENSURE_ARG_POINTER(result);
// Turn the string into a CLSID
_bstr_t bstrName(className);
CLSID classID = CLSID_NULL;
HRESULT hr = CLSIDFromString(bstrName, &classID);
if(FAILED(hr))
hr = CLSIDFromProgID(bstrName, &classID);
if(FAILED(hr) || ::IsEqualCLSID(classID, CLSID_NULL))
return hr;
// If the caller cares about security do the necessary checks
// This results in the object being instantiated, so we'll use
// it
if(enforceSecurity)
return SecurityCheck(ccx, classID, result);
CComPtr<IDispatch> disp;
hr = disp.CoCreateInstance(classID);
if(FAILED(hr))
return hr;
// If we're enforcing security and it didn't have a scripting category
// we'll check via the IObjectSafety interface
if(enforceSecurity && !allowAnyObjects && !isScriptable)
{
dispSupport->IsObjectSafeForScripting(disp, NSID_IDISPATCH, &isScriptable);
if(!isScriptable)
return E_FAIL;
}
// Copy and addref
disp.CopyTo(result);
return S_OK;
}

View File

@ -1088,6 +1088,17 @@ public:
*/
static
JSBool Invoke(XPCCallContext & ccx, CallMode mode);
/**
* Performs the various security checks, caps, hosting flags, etc.
* Instantiates the object and will return that object if createdObject
* result is not null
* @param ccx an XPConnect call context
* @param aCID the class ID to be tested
* @param createdObject is the optional object to be returned
*/
static
HRESULT SecurityCheck(XPCCallContext & ccx, const CLSID & aCID,
IDispatch ** createdObject = nsnull);
/**
* Instantiates a COM object given a class ID or a prog ID
* @param ccx an XPConnect call context

View File

@ -45,8 +45,14 @@ CommonConstructor(JSContext *cx, int name, JSObject *obj, uintN argc,
jsval *argv, jsval *rval, PRBool enforceSecurity)
{
XPCCallContext ccx(JS_CALLER, cx, JS_GetGlobalObject(cx));
// Check if IDispatch is enabled, fail if not
if(!nsXPConnect::IsIDispatchEnabled())
{
XPCThrower::Throw(NS_ERROR_XPC_IDISPATCH_NOT_ENABLED, ccx);
return JS_FALSE;
}
XPCJSRuntime *rt = ccx.GetRuntime();
if (!rt)
if(!rt)
{
XPCThrower::Throw(NS_ERROR_UNEXPECTED, ccx);
return JS_FALSE;
@ -64,12 +70,6 @@ CommonConstructor(JSContext *cx, int name, JSObject *obj, uintN argc,
// Security manager will have set an exception
return JS_FALSE;
}
// Check if IDispatch is enabled, fail if not
if(!nsXPConnect::IsIDispatchEnabled())
{
XPCThrower::Throw(NS_ERROR_XPC_IDISPATCH_NOT_ENABLED, ccx);
return JS_FALSE;
}
// Make sure we were called with one string parameter
if(argc != 1 || (argc == 1 && !JSVAL_IS_STRING(argv[0])))
{
@ -131,21 +131,100 @@ ActiveXConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
rval, PR_TRUE);
}
JS_STATIC_DLL_CALLBACK(JSBool)
ActiveXSupports(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
XPCCallContext ccx(JS_CALLER, cx, JS_GetGlobalObject(cx));
// Check if IDispatch is enabled, fail if not
if(!nsXPConnect::IsIDispatchEnabled())
{
XPCThrower::Throw(NS_ERROR_XPC_IDISPATCH_NOT_ENABLED, ccx);
return JS_FALSE;
}
XPCJSRuntime *rt = ccx.GetRuntime();
if(!rt)
{
XPCThrower::Throw(NS_ERROR_UNEXPECTED, ccx);
return JS_FALSE;
}
// Make sure we were called with one string parameter
if(argc != 1 || (argc == 1 && !JSVAL_IS_STRING(argv[0])))
{
XPCThrower::Throw(NS_ERROR_XPC_COM_INVALID_CLASS_ID, ccx);
return JS_FALSE;
}
PRUint32 len;
jschar * className = xpc_JSString2String(ccx, argv[0], &len);
CComBSTR bstrClassName(len, className);
if(!className)
{
XPCThrower::Throw(NS_ERROR_XPC_COM_INVALID_CLASS_ID, ccx);
return JS_FALSE;
}
CLSID classID = CLSID_NULL;
HRESULT hr = CLSIDFromString(bstrClassName, &classID);
if(FAILED(hr) || ::IsEqualCLSID(classID, CLSID_NULL))
{
XPCThrower::Throw(NS_ERROR_XPC_COM_INVALID_CLASS_ID, ccx);
return JS_FALSE;
}
// Instantiate the desired COM object
HRESULT rv = XPCDispObject::SecurityCheck(ccx, classID);
*rval = BOOLEAN_TO_JSVAL(SUCCEEDED(rv));
return JS_TRUE;
}
class xpcFunctionDefiner
{
public:
xpcFunctionDefiner(JSContext * aJSContext);
JSFunction * Define(JSObject * globalObject, uintN aNameIndex,
JSNative aCall);
private:
XPCJSRuntime * m_Runtime;
JSContext * m_JSContext;
};
inline
xpcFunctionDefiner::xpcFunctionDefiner(JSContext * aJSContext) :
m_Runtime(nsXPConnect::GetRuntime()), m_JSContext(aJSContext)
{
NS_ASSERTION(m_Runtime, "nsXPConnect::GetRuntime() returned null");
NS_ASSERTION(aJSContext, "xpcFunctionDefiner constructor passed a null context");
}
inline
JSFunction * xpcFunctionDefiner::Define(JSObject * globalObject,
uintN aNameIndex, JSNative aCall)
{
return JS_DefineFunction(m_JSContext, globalObject,
m_Runtime->GetStringName(aNameIndex),
aCall, 1, JSPROP_PERMANENT | JSPROP_READONLY);
}
JSBool XPCIDispatchExtension::Initialize(JSContext * aJSContext,
JSObject * aGlobalJSObj)
{
JSBool result = JS_DefineFunction(aJSContext, aGlobalJSObj,
nsXPConnect::GetRuntime()->GetStringName(
XPCJSRuntime::IDX_ACTIVEX_OBJECT),
ActiveXConstructor, 1, 0) != nsnull;
xpcFunctionDefiner fd(aJSContext);
JSFunction * func = fd.Define(aGlobalJSObj,
XPCJSRuntime::IDX_ACTIVEX_OBJECT,
ActiveXConstructor);
if(!func)
return JS_FALSE;
JSObject * funcObject = JS_GetFunctionObject(func);
if(!funcObject)
return JS_FALSE;
if(!fd.Define(funcObject, XPCJSRuntime::IDX_ACTIVEX_SUPPORTS, ActiveXSupports))
return JS_FALSE;
#ifdef XPC_COMOBJECT
if(result)
result = JS_DefineFunction(aJSContext, aGlobalJSObj,
nsXPConnect::GetRuntime()->GetStringName(
XPCJSRuntime::IDX_COM_OBJECT),
COMObjectConstructor, 1, 0) != nsnull;
if(!fd.Define(aGlobalJSObj, XPCJSRuntime::IDX_COM_OBJECT, COMObjectConstructor))
return JS_FALSE;
#endif
return result;
return JS_TRUE;
}
nsresult XPCIDispatchExtension::IDispatchQIWrappedJS(nsXPCWrappedJS * self,

View File

@ -55,6 +55,7 @@ const char* XPCJSRuntime::mStrings[] = {
#ifdef XPC_IDISPATCH_SUPPORT
, "GeckoActiveXObject" // IDX_ACTIVEX_OBJECT
, "COMObject" // IDX_COMOBJECT
, "supports" // IDX_ACTIVEX_SUPPORTS
#endif
};

View File

@ -554,6 +554,7 @@ public:
#ifdef XPC_IDISPATCH_SUPPORT
IDX_ACTIVEX_OBJECT ,
IDX_COM_OBJECT ,
IDX_ACTIVEX_SUPPORTS ,
#endif
IDX_TOTAL_COUNT // just a count of the above
};