mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-13 18:27:35 +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;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT XPCDispObject::COMCreateInstance(XPCCallContext & ccx, BSTR className,
|
HRESULT XPCDispObject::SecurityCheck(XPCCallContext & ccx, const CLSID & aCID,
|
||||||
PRBool enforceSecurity,
|
IDispatch ** createdObject)
|
||||||
IDispatch ** 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;
|
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
nsCOMPtr<nsIDispatchSupport> dispSupport = do_GetService(NS_IDISPATCH_SUPPORT_CONTRACTID, &rv);
|
nsCOMPtr<nsIDispatchSupport> dispSupport = do_GetService(NS_IDISPATCH_SUPPORT_CONTRACTID, &rv);
|
||||||
if(NS_FAILED(rv)) return E_UNEXPECTED;
|
if(NS_FAILED(rv)) return E_UNEXPECTED;
|
||||||
|
|
||||||
PRUint32 hostingFlags = nsIActiveXSecurityPolicy::HOSTING_FLAGS_HOST_NOTHING;
|
PRUint32 hostingFlags = nsIActiveXSecurityPolicy::HOSTING_FLAGS_HOST_NOTHING;
|
||||||
dispSupport->GetHostingFlags(nsnull, &hostingFlags);
|
dispSupport->GetHostingFlags(nsnull, &hostingFlags);
|
||||||
|
|
||||||
PRBool allowSafeObjects;
|
PRBool allowSafeObjects;
|
||||||
if(hostingFlags & (nsIActiveXSecurityPolicy::HOSTING_FLAGS_SCRIPT_SAFE_OBJECTS))
|
if(hostingFlags & (nsIActiveXSecurityPolicy::HOSTING_FLAGS_SCRIPT_SAFE_OBJECTS))
|
||||||
allowSafeObjects = PR_TRUE;
|
allowSafeObjects = PR_TRUE;
|
||||||
@ -103,46 +92,75 @@ HRESULT XPCDispObject::COMCreateInstance(XPCCallContext & ccx, BSTR className,
|
|||||||
allowAnyObjects = PR_TRUE;
|
allowAnyObjects = PR_TRUE;
|
||||||
else
|
else
|
||||||
allowAnyObjects = PR_FALSE;
|
allowAnyObjects = PR_FALSE;
|
||||||
|
if(!allowSafeObjects && !allowAnyObjects)
|
||||||
// There is no point proceeding if flags say we can't script safe or unsafe objects
|
|
||||||
if(enforceSecurity && !allowSafeObjects && !allowAnyObjects)
|
|
||||||
{
|
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
|
||||||
PRBool classExists = PR_FALSE;
|
PRBool classExists = PR_FALSE;
|
||||||
PRBool ok = PR_FALSE;
|
PRBool ok = PR_FALSE;
|
||||||
const nsCID & ourCID = XPCDispCLSID2nsCID(classID);
|
const nsCID & ourCID = XPCDispCLSID2nsCID(aCID);
|
||||||
dispSupport->IsClassSafeToHost(ccx, ourCID, PR_FALSE, &classExists, &ok);
|
dispSupport->IsClassSafeToHost(ccx, ourCID, PR_FALSE, &classExists, &ok);
|
||||||
if(classExists && !ok)
|
if(classExists && !ok)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
// Test if the object is scriptable
|
// Test if the object is scriptable
|
||||||
PRBool isScriptable = PR_FALSE;
|
PRBool isScriptable = PR_FALSE;
|
||||||
if(enforceSecurity && !allowAnyObjects)
|
if(!allowAnyObjects)
|
||||||
{
|
{
|
||||||
PRBool classExists = PR_FALSE;
|
PRBool classExists = PR_FALSE;
|
||||||
dispSupport->IsClassMarkedSafeForScripting(ourCID, &classExists, &isScriptable);
|
dispSupport->IsClassMarkedSafeForScripting(ourCID, &classExists, &isScriptable);
|
||||||
if(!classExists)
|
if(!classExists)
|
||||||
return REGDB_E_CLASSNOTREG;
|
return REGDB_E_CLASSNOTREG;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the object
|
// 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;
|
CComPtr<IDispatch> disp;
|
||||||
hr = disp.CoCreateInstance(classID);
|
hr = disp.CoCreateInstance(classID);
|
||||||
if(FAILED(hr))
|
if(FAILED(hr))
|
||||||
return 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);
|
disp.CopyTo(result);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1088,6 +1088,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
JSBool Invoke(XPCCallContext & ccx, CallMode mode);
|
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
|
* Instantiates a COM object given a class ID or a prog ID
|
||||||
* @param ccx an XPConnect call context
|
* @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)
|
jsval *argv, jsval *rval, PRBool enforceSecurity)
|
||||||
{
|
{
|
||||||
XPCCallContext ccx(JS_CALLER, cx, JS_GetGlobalObject(cx));
|
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();
|
XPCJSRuntime *rt = ccx.GetRuntime();
|
||||||
if (!rt)
|
if(!rt)
|
||||||
{
|
{
|
||||||
XPCThrower::Throw(NS_ERROR_UNEXPECTED, ccx);
|
XPCThrower::Throw(NS_ERROR_UNEXPECTED, ccx);
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
@ -64,12 +70,6 @@ CommonConstructor(JSContext *cx, int name, JSObject *obj, uintN argc,
|
|||||||
// Security manager will have set an exception
|
// Security manager will have set an exception
|
||||||
return JS_FALSE;
|
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
|
// Make sure we were called with one string parameter
|
||||||
if(argc != 1 || (argc == 1 && !JSVAL_IS_STRING(argv[0])))
|
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);
|
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,
|
JSBool XPCIDispatchExtension::Initialize(JSContext * aJSContext,
|
||||||
JSObject * aGlobalJSObj)
|
JSObject * aGlobalJSObj)
|
||||||
{
|
{
|
||||||
JSBool result = JS_DefineFunction(aJSContext, aGlobalJSObj,
|
xpcFunctionDefiner fd(aJSContext);
|
||||||
nsXPConnect::GetRuntime()->GetStringName(
|
JSFunction * func = fd.Define(aGlobalJSObj,
|
||||||
XPCJSRuntime::IDX_ACTIVEX_OBJECT),
|
XPCJSRuntime::IDX_ACTIVEX_OBJECT,
|
||||||
ActiveXConstructor, 1, 0) != nsnull;
|
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
|
#ifdef XPC_COMOBJECT
|
||||||
if(result)
|
if(!fd.Define(aGlobalJSObj, XPCJSRuntime::IDX_COM_OBJECT, COMObjectConstructor))
|
||||||
result = JS_DefineFunction(aJSContext, aGlobalJSObj,
|
return JS_FALSE;
|
||||||
nsXPConnect::GetRuntime()->GetStringName(
|
|
||||||
XPCJSRuntime::IDX_COM_OBJECT),
|
|
||||||
COMObjectConstructor, 1, 0) != nsnull;
|
|
||||||
#endif
|
#endif
|
||||||
return result;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult XPCIDispatchExtension::IDispatchQIWrappedJS(nsXPCWrappedJS * self,
|
nsresult XPCIDispatchExtension::IDispatchQIWrappedJS(nsXPCWrappedJS * self,
|
||||||
|
@ -55,6 +55,7 @@ const char* XPCJSRuntime::mStrings[] = {
|
|||||||
#ifdef XPC_IDISPATCH_SUPPORT
|
#ifdef XPC_IDISPATCH_SUPPORT
|
||||||
, "GeckoActiveXObject" // IDX_ACTIVEX_OBJECT
|
, "GeckoActiveXObject" // IDX_ACTIVEX_OBJECT
|
||||||
, "COMObject" // IDX_COMOBJECT
|
, "COMObject" // IDX_COMOBJECT
|
||||||
|
, "supports" // IDX_ACTIVEX_SUPPORTS
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -554,6 +554,7 @@ public:
|
|||||||
#ifdef XPC_IDISPATCH_SUPPORT
|
#ifdef XPC_IDISPATCH_SUPPORT
|
||||||
IDX_ACTIVEX_OBJECT ,
|
IDX_ACTIVEX_OBJECT ,
|
||||||
IDX_COM_OBJECT ,
|
IDX_COM_OBJECT ,
|
||||||
|
IDX_ACTIVEX_SUPPORTS ,
|
||||||
#endif
|
#endif
|
||||||
IDX_TOTAL_COUNT // just a count of the above
|
IDX_TOTAL_COUNT // just a count of the above
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user