mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-13 01:55:44 +00:00
Bug 204894 - Implement GeckoActiveXObject.supports(clsid). r=dbradley, sr=alecf
This commit is contained in:
parent
0c73334798
commit
1e7ae8efa5
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -55,6 +55,7 @@ const char* XPCJSRuntime::mStrings[] = {
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
, "GeckoActiveXObject" // IDX_ACTIVEX_OBJECT
|
||||
, "COMObject" // IDX_COMOBJECT
|
||||
, "supports" // IDX_ACTIVEX_SUPPORTS
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user