зеркало из https://github.com/mozilla/pjs.git
Share pref settings between com connect and plugin. b=179573 r=dbradley@netscape.com sr=brendan@mozilla.org a=asa@mozilla.org
This commit is contained in:
Родитель
c7d9f92951
Коммит
1657fa34f3
|
@ -45,13 +45,136 @@
|
|||
|
||||
std::list<CControlSite *> CControlSite::m_cControlList;
|
||||
|
||||
class CDefaultControlSiteSecurityPolicy : public CControlSiteSecurityPolicy
|
||||
{
|
||||
// Test if the specified class id implements the specified category
|
||||
BOOL ClassImplementsCategory(const CLSID & clsid, const CATID &catid, BOOL &bClassExists);
|
||||
public:
|
||||
// Test if the class is safe to host
|
||||
virtual BOOL IsClassSafeToHost(const CLSID & clsid);
|
||||
// Test if the specified class is marked safe for scripting
|
||||
virtual BOOL IsClassMarkedSafeForScripting(const CLSID & clsid, BOOL &bClassExists);
|
||||
// Test if the instantiated object is safe for scripting on the specified interface
|
||||
virtual BOOL IsObjectSafeForScripting(IUnknown *pObject, const IID &iid);
|
||||
};
|
||||
|
||||
BOOL
|
||||
CDefaultControlSiteSecurityPolicy::ClassImplementsCategory(const CLSID &clsid, const CATID &catid, BOOL &bClassExists)
|
||||
{
|
||||
bClassExists = FALSE;
|
||||
|
||||
// Test if there is a CLSID entry. If there isn't then obviously
|
||||
// the object doesn't exist and therefore doesn't implement any category.
|
||||
// In this situation, the function returns REGDB_E_CLASSNOTREG.
|
||||
|
||||
CRegKey key;
|
||||
if (key.Open(HKEY_CLASSES_ROOT, _T("CLSID"), KEY_READ) != ERROR_SUCCESS)
|
||||
{
|
||||
// Must fail if we can't even open this!
|
||||
return FALSE;
|
||||
}
|
||||
LPOLESTR szCLSID = NULL;
|
||||
if (FAILED(StringFromCLSID(clsid, &szCLSID)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
USES_CONVERSION;
|
||||
CRegKey keyCLSID;
|
||||
LONG lResult = keyCLSID.Open(key, W2CT(szCLSID), KEY_READ);
|
||||
CoTaskMemFree(szCLSID);
|
||||
if (lResult != ERROR_SUCCESS)
|
||||
{
|
||||
// Class doesn't exist
|
||||
return FALSE;
|
||||
}
|
||||
keyCLSID.Close();
|
||||
|
||||
// CLSID exists, so try checking what categories it implements
|
||||
bClassExists = TRUE;
|
||||
CIPtr(ICatInformation) spCatInfo;
|
||||
HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatInformation, (LPVOID*) &spCatInfo);
|
||||
if (spCatInfo == NULL)
|
||||
{
|
||||
// Must fail if we can't open the category manager
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// See what categories the class implements
|
||||
CIPtr(IEnumCATID) spEnumCATID;
|
||||
if (FAILED(spCatInfo->EnumImplCategoriesOfClass(clsid, &spEnumCATID)))
|
||||
{
|
||||
// Can't enumerate classes in category so fail
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Search for matching categories
|
||||
BOOL bFound = FALSE;
|
||||
CATID catidNext = GUID_NULL;
|
||||
while (spEnumCATID->Next(1, &catidNext, NULL) == S_OK)
|
||||
{
|
||||
if (::IsEqualCATID(catid, catidNext))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Test if the class is safe to host
|
||||
BOOL CDefaultControlSiteSecurityPolicy::IsClassSafeToHost(const CLSID & clsid)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Test if the specified class is marked safe for scripting
|
||||
BOOL CDefaultControlSiteSecurityPolicy::IsClassMarkedSafeForScripting(const CLSID & clsid, BOOL &bClassExists)
|
||||
{
|
||||
// Test the category the object belongs to
|
||||
return ClassImplementsCategory(clsid, CATID_SafeForScripting, bClassExists);
|
||||
}
|
||||
|
||||
// Test if the instantiated object is safe for scripting on the specified interface
|
||||
BOOL CDefaultControlSiteSecurityPolicy::IsObjectSafeForScripting(IUnknown *pObject, const IID &iid)
|
||||
{
|
||||
if (!pObject) {
|
||||
return FALSE;
|
||||
}
|
||||
// Ask the control if its safe for scripting
|
||||
CComQIPtr<IObjectSafety> spObjectSafety = pObject;
|
||||
if (!spObjectSafety)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD dwSupported = 0; // Supported options (mask)
|
||||
DWORD dwEnabled = 0; // Enabled options
|
||||
|
||||
// Assume scripting via IDispatch
|
||||
if (FAILED(spObjectSafety->GetInterfaceSafetyOptions(
|
||||
iid, &dwSupported, &dwEnabled)))
|
||||
{
|
||||
// Interface is not safe or failure.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Test if safe for scripting
|
||||
if (!(dwEnabled & dwSupported) & INTERFACESAFE_FOR_UNTRUSTED_CALLER)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Constructor
|
||||
CControlSite::CControlSite()
|
||||
{
|
||||
NG_TRACE_METHOD(CControlSite::CControlSite);
|
||||
|
||||
m_hWndParent = NULL;
|
||||
m_clsid = CLSID_NULL;
|
||||
m_CLSID = CLSID_NULL;
|
||||
m_bSetClientSiteFirst = FALSE;
|
||||
m_bVisibleAtRuntime = TRUE;
|
||||
memset(&m_rcObjectPos, 0, sizeof(m_rcObjectPos));
|
||||
|
@ -62,6 +185,8 @@ CControlSite::CControlSite()
|
|||
m_bWindowless = FALSE;
|
||||
m_bSupportWindowlessActivation = TRUE;
|
||||
m_bSafeForScriptingObjectsOnly = FALSE;
|
||||
m_pDefaultSecurityPolicy = new CDefaultControlSiteSecurityPolicy;
|
||||
m_pSecurityPolicy = m_pDefaultSecurityPolicy;
|
||||
|
||||
// Initialise ambient properties
|
||||
m_nAmbientLocale = 0;
|
||||
|
@ -89,80 +214,11 @@ CControlSite::~CControlSite()
|
|||
NG_TRACE_METHOD(CControlSite::~CControlSite);
|
||||
Detach();
|
||||
m_cControlList.remove(this);
|
||||
|
||||
if (m_pDefaultSecurityPolicy)
|
||||
delete m_pDefaultSecurityPolicy;
|
||||
}
|
||||
|
||||
// Helper method checks whether a class implements a particular category
|
||||
HRESULT CControlSite::ClassImplementsCategory(const CLSID &clsid, const CATID &catid)
|
||||
{
|
||||
// Test if there is a CLSID entry. If there isn't then obviously
|
||||
// the object doesn't exist and therefore doesn't implement any category.
|
||||
// In this situation, the function returns REGDB_E_CLASSNOTREG.
|
||||
|
||||
CRegKey key;
|
||||
if (key.Open(HKEY_CLASSES_ROOT, _T("CLSID"), KEY_READ) != ERROR_SUCCESS)
|
||||
{
|
||||
// Must fail if we can't even open this!
|
||||
return E_FAIL;
|
||||
}
|
||||
LPOLESTR szCLSID = NULL;
|
||||
if (FAILED(StringFromCLSID(clsid, &szCLSID)))
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
USES_CONVERSION;
|
||||
CRegKey keyCLSID;
|
||||
LONG lResult = keyCLSID.Open(key, W2CT(szCLSID), KEY_READ);
|
||||
CoTaskMemFree(szCLSID);
|
||||
if (lResult != ERROR_SUCCESS)
|
||||
{
|
||||
// Class doesn't exist
|
||||
return REGDB_E_CLASSNOTREG;
|
||||
}
|
||||
keyCLSID.Close();
|
||||
|
||||
// CLSID exists, so try checking what categories it implements
|
||||
|
||||
CIPtr(ICatInformation) spCatInfo;
|
||||
HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatInformation, (LPVOID*) &spCatInfo);
|
||||
if (spCatInfo == NULL)
|
||||
{
|
||||
// Must fail if we can't open the category manager
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// See what categories the class implements
|
||||
CIPtr(IEnumCATID) spEnumCATID;
|
||||
if (FAILED(spCatInfo->EnumImplCategoriesOfClass(clsid, &spEnumCATID)))
|
||||
{
|
||||
// Can't enumerate classes in category so fail
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Search for matching categories
|
||||
BOOL bFound = FALSE;
|
||||
CATID catidNext = GUID_NULL;
|
||||
while (spEnumCATID->Next(1, &catidNext, NULL) == S_OK)
|
||||
{
|
||||
if (::IsEqualCATID(catid, catidNext))
|
||||
{
|
||||
bFound = TRUE;
|
||||
}
|
||||
}
|
||||
if (!bFound)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
// For use when the SDK does not define it (which isn't the case these days)
|
||||
static const CATID CATID_SafeForScripting =
|
||||
{ 0x7DD95801, 0x9882, 0x11CF, { 0x9F, 0xA9, 0x00, 0xAA, 0x00, 0x6C, 0x42, 0xC4 } };
|
||||
#endif
|
||||
|
||||
// Create the specified control, optionally providing properties to initialise
|
||||
// it with and a name.
|
||||
HRESULT CControlSite::Create(REFCLSID clsid, PropertyList &pl,
|
||||
|
@ -170,19 +226,26 @@ HRESULT CControlSite::Create(REFCLSID clsid, PropertyList &pl,
|
|||
{
|
||||
NG_TRACE_METHOD(CControlSite::Create);
|
||||
|
||||
m_clsid = clsid;
|
||||
m_CLSID = clsid;
|
||||
m_ParameterList = pl;
|
||||
|
||||
// See if security policy will allow the control to be hosted
|
||||
if (m_pSecurityPolicy && !m_pSecurityPolicy->IsClassSafeToHost(clsid))
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// See if object is script safe
|
||||
BOOL checkForObjectSafety = FALSE;
|
||||
if (m_bSafeForScriptingObjectsOnly)
|
||||
if (m_pSecurityPolicy && m_bSafeForScriptingObjectsOnly)
|
||||
{
|
||||
HRESULT hrClass = ClassImplementsCategory(clsid, CATID_SafeForScripting);
|
||||
if (hrClass == REGDB_E_CLASSNOTREG && szCodebase)
|
||||
BOOL bClassExists = FALSE;
|
||||
BOOL bIsSafe = m_pSecurityPolicy->IsClassMarkedSafeForScripting(clsid, bClassExists);
|
||||
if (!bClassExists && szCodebase)
|
||||
{
|
||||
// Class doesn't exist, so allow code below to fetch it
|
||||
}
|
||||
else if (FAILED(hrClass))
|
||||
else if (!bIsSafe)
|
||||
{
|
||||
// The class is not flagged as safe for scripting, so
|
||||
// we'll have to create it to ask it if its safe.
|
||||
|
@ -195,26 +258,8 @@ HRESULT CControlSite::Create(REFCLSID clsid, PropertyList &pl,
|
|||
HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_IUnknown, (void **) &spObject);
|
||||
if (SUCCEEDED(hr) && checkForObjectSafety)
|
||||
{
|
||||
// The control was created but it didn't check out as safe so
|
||||
// it must be asked if its safe for scripting.
|
||||
CComQIPtr<IObjectSafety> spObjectSafety = spObject;
|
||||
if (!spObjectSafety)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
DWORD dwSupported = 0; // Supported options (mask)
|
||||
DWORD dwEnabled = 0; // Enabled options
|
||||
|
||||
// Assume scripting via IDispatch
|
||||
if (FAILED(spObjectSafety->GetInterfaceSafetyOptions(
|
||||
__uuidof(IDispatch), &dwSupported, &dwEnabled)))
|
||||
{
|
||||
// Interface is not safe or failure.
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Test if safe for scripting
|
||||
if (!(dwEnabled & dwSupported) & INTERFACESAFE_FOR_UNTRUSTED_CALLER)
|
||||
if (!m_pSecurityPolicy->IsObjectSafeForScripting(spObject, __uuidof(IDispatch)))
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
@ -596,6 +641,37 @@ void CControlSite::SetAmbientUserMode(BOOL bUserMode)
|
|||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CControlSiteSecurityPolicy implementation
|
||||
|
||||
// Test if the class is safe to host
|
||||
BOOL CControlSite::IsClassSafeToHost(const CLSID & clsid)
|
||||
{
|
||||
if (m_pSecurityPolicy)
|
||||
return m_pSecurityPolicy->IsClassSafeToHost(clsid);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Test if the specified class is marked safe for scripting
|
||||
BOOL CControlSite::IsClassMarkedSafeForScripting(const CLSID & clsid, BOOL &bClassExists)
|
||||
{
|
||||
if (m_pSecurityPolicy)
|
||||
return m_pSecurityPolicy->IsClassMarkedSafeForScripting(clsid, bClassExists);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Test if the instantiated object is safe for scripting on the specified interface
|
||||
BOOL CControlSite::IsObjectSafeForScripting(IUnknown *pObject, const IID &iid)
|
||||
{
|
||||
if (m_pSecurityPolicy)
|
||||
return m_pSecurityPolicy->IsObjectSafeForScripting(pObject, iid);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CControlSite::IsObjectSafeForScripting(const IID &iid)
|
||||
{
|
||||
return IsObjectSafeForScripting(m_spObject, iid);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IServiceProvider implementation
|
||||
|
|
|
@ -61,6 +61,21 @@
|
|||
COM_INTERFACE_ENTRY(IBindStatusCallback) \
|
||||
COM_INTERFACE_ENTRY(IWindowForBindingUI)
|
||||
|
||||
|
||||
// Class that defines the control's security policy with regards to
|
||||
// what controls it hosts etc.
|
||||
|
||||
class CControlSiteSecurityPolicy
|
||||
{
|
||||
public:
|
||||
// Test if the class is safe to host
|
||||
virtual BOOL IsClassSafeToHost(const CLSID & clsid) = 0;
|
||||
// Test if the specified class is marked safe for scripting
|
||||
virtual BOOL IsClassMarkedSafeForScripting(const CLSID & clsid, BOOL &bClassExists) = 0;
|
||||
// Test if the instantiated object is safe for scripting on the specified interface
|
||||
virtual BOOL IsObjectSafeForScripting(IUnknown *pObject, const IID &iid) = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// Class for hosting an ActiveX control
|
||||
//
|
||||
|
@ -85,6 +100,7 @@
|
|||
// pSite = NULL;
|
||||
|
||||
class CControlSite : public CComObjectRootEx<CComSingleThreadModel>,
|
||||
public CControlSiteSecurityPolicy,
|
||||
public IOleClientSite,
|
||||
public IOleInPlaceSiteWindowless,
|
||||
public IOleControlSite,
|
||||
|
@ -135,9 +151,13 @@ protected:
|
|||
// Pointer to object's IOleInPlaceObjectWindowless interface
|
||||
CComQIPtr<IOleInPlaceObjectWindowless, &IID_IOleInPlaceObjectWindowless> m_spIOleInPlaceObjectWindowless;
|
||||
// CLSID of the control
|
||||
CLSID m_clsid;
|
||||
CLSID m_CLSID;
|
||||
// Parameter list
|
||||
PropertyList m_ParameterList;
|
||||
// Default security policy
|
||||
CControlSiteSecurityPolicy *m_pDefaultSecurityPolicy;
|
||||
// Pointer to the security policy
|
||||
CControlSiteSecurityPolicy *m_pSecurityPolicy;
|
||||
|
||||
// Binding variables
|
||||
// Flag indicating whether binding is in progress
|
||||
|
@ -196,9 +216,6 @@ END_OLECOMMAND_TABLE()
|
|||
// List of controls
|
||||
static std::list<CControlSite *> m_cControlList;
|
||||
|
||||
// Helper method
|
||||
static HRESULT ClassImplementsCategory(const CLSID &clsid, const CATID &catid);
|
||||
|
||||
// Returns the window used when processing ole commands
|
||||
HWND GetCommandTargetWindow()
|
||||
{
|
||||
|
@ -234,6 +251,16 @@ END_OLECOMMAND_TABLE()
|
|||
{
|
||||
m_spContainer = pContainer;
|
||||
}
|
||||
// Set the security policy object. Ownership of this object remains with the caller and the security
|
||||
// policy object is meant to exist for as long as it is set here.
|
||||
virtual void SetSecurityPolicy(CControlSiteSecurityPolicy *pSecurityPolicy)
|
||||
{
|
||||
m_pSecurityPolicy = pSecurityPolicy;
|
||||
}
|
||||
virtual CControlSiteSecurityPolicy *GetSecurityPolicy() const
|
||||
{
|
||||
return m_pSecurityPolicy;
|
||||
}
|
||||
|
||||
// Methods to set ambient properties
|
||||
virtual void SetAmbientUserMode(BOOL bUser);
|
||||
|
@ -242,7 +269,7 @@ END_OLECOMMAND_TABLE()
|
|||
// Returns the object's CLSID
|
||||
virtual const CLSID &GetObjectCLSID() const
|
||||
{
|
||||
return m_clsid;
|
||||
return m_CLSID;
|
||||
}
|
||||
// Tests if the object is valid or not
|
||||
virtual BOOL IsObjectValid() const
|
||||
|
@ -260,6 +287,16 @@ END_OLECOMMAND_TABLE()
|
|||
return m_bInPlaceActive;
|
||||
}
|
||||
|
||||
// CControlSiteSecurityPolicy
|
||||
// Test if the class is safe to host
|
||||
virtual BOOL IsClassSafeToHost(const CLSID & clsid);
|
||||
// Test if the specified class is marked safe for scripting
|
||||
virtual BOOL IsClassMarkedSafeForScripting(const CLSID & clsid, BOOL &bClassExists);
|
||||
// Test if the instantiated object is safe for scripting on the specified interface
|
||||
virtual BOOL IsObjectSafeForScripting(IUnknown *pObject, const IID &iid);
|
||||
// Test if the instantiated object is safe for scripting on the specified interface
|
||||
virtual BOOL IsObjectSafeForScripting(const IID &iid);
|
||||
|
||||
// IServiceProvider
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void** ppv);
|
||||
|
||||
|
|
|
@ -56,21 +56,20 @@
|
|||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// These are constants to control certain behaviours
|
||||
// These are constants to control certain default behaviours
|
||||
|
||||
// Flag determines if only controls marked safe for scripting will be instantiated
|
||||
const BOOL kSafeForScriptingControlsOnly = FALSE;
|
||||
#ifndef MOZ_ACTIVEX_PLUGIN_XPCONNECT
|
||||
// Flag determines if controls should be created if they are not marked
|
||||
// safe for scripting.
|
||||
const BOOL kHostSafeControlsOnly = FALSE;
|
||||
// Flag determines if controls should be downloaded and installed if there is a
|
||||
// codebase specified
|
||||
const BOOL kDownloadControlsIfMissing = TRUE;
|
||||
const BOOL kDownloadControlsIfMissing = FALSE;
|
||||
#endif
|
||||
|
||||
// Flag determines whether the plugin will complain to the user if a page
|
||||
// contains a control it cannot load
|
||||
const BOOL kDisplayErrorMessages = FALSE;
|
||||
// Registry keys containing lists of controls that the plugin explicitly does
|
||||
// or does not support.
|
||||
const TCHAR *kControlsToAllowKey = _T("Software\\Mozilla\\ActiveX\\Whitelist\\CLSID");
|
||||
const TCHAR *kControlsToDenyKey = _T("Software\\Mozilla\\ActiveX\\Blacklist\\CLSID");
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CInstallControlProgress
|
||||
|
@ -256,24 +255,90 @@ jref NPP_GetJavaClass(void)
|
|||
#define MIME_OLEOBJECT2 "application/oleobject"
|
||||
#define MIME_ACTIVESCRIPT "text/x-activescript"
|
||||
|
||||
NPError NewScript(const char *pluginType,
|
||||
PluginInstanceData *pData,
|
||||
uint16 mode,
|
||||
int16 argc,
|
||||
char *argn[],
|
||||
char *argv[])
|
||||
enum MozAxPluginErrors
|
||||
{
|
||||
MozAxErrorActiveScriptNotSupported,
|
||||
MozAxErrorControlIsNotSafeForScripting,
|
||||
MozAxErrorCouldNotCreateControl,
|
||||
};
|
||||
|
||||
static void
|
||||
ShowError(MozAxPluginErrors errorCode, const CLSID &clsid)
|
||||
{
|
||||
if (!kDisplayErrorMessages)
|
||||
return;
|
||||
|
||||
const TCHAR *szMsg = NULL;
|
||||
const unsigned long kBufSize = 256;
|
||||
TCHAR szBuffer[kBufSize];
|
||||
|
||||
// TODO errors are hardcoded for now
|
||||
switch (errorCode)
|
||||
{
|
||||
case MozAxErrorActiveScriptNotSupported:
|
||||
szMsg = _T("ActiveScript not supported yet!");
|
||||
break;
|
||||
case MozAxErrorControlIsNotSafeForScripting:
|
||||
{
|
||||
USES_CONVERSION;
|
||||
LPOLESTR szClsid;
|
||||
StringFromCLSID(clsid, &szClsid);
|
||||
_sntprintf(szBuffer, kBufSize - 1,
|
||||
_T("Could not create the control %s because it is not marked safe for scripting."), OLE2T(szClsid));
|
||||
CoTaskMemFree(szClsid);
|
||||
szMsg = szBuffer;
|
||||
}
|
||||
break;
|
||||
case MozAxErrorCouldNotCreateControl:
|
||||
{
|
||||
USES_CONVERSION;
|
||||
LPOLESTR szClsid;
|
||||
StringFromCLSID(clsid, &szClsid);
|
||||
_sntprintf(szBuffer, kBufSize - 1,
|
||||
_T("Could not create the control %s. Check that it has been installed on your computer "
|
||||
"and that this page correctly references it."), OLE2T(szClsid));
|
||||
CoTaskMemFree(szClsid);
|
||||
szMsg = szBuffer;
|
||||
}
|
||||
break;
|
||||
}
|
||||
szBuffer[kBufSize - 1] = TCHAR('\0');
|
||||
if (szMsg)
|
||||
MessageBox(NULL, szMsg, _T("ActiveX Error"), MB_OK | MB_ICONWARNING);
|
||||
}
|
||||
|
||||
static NPError
|
||||
NewScript(const char *pluginType,
|
||||
PluginInstanceData *pData,
|
||||
uint16 mode,
|
||||
int16 argc,
|
||||
char *argn[],
|
||||
char *argv[])
|
||||
{
|
||||
CActiveScriptSiteInstance *pScriptSite = NULL;
|
||||
CActiveScriptSiteInstance::CreateInstance(&pScriptSite);
|
||||
|
||||
// TODO support ActiveScript
|
||||
if (kDisplayErrorMessages)
|
||||
MessageBox(NULL, _T("ActiveScript not supported yet!"), NULL, MB_OK);
|
||||
ShowError(MozAxErrorActiveScriptNotSupported, CLSID_NULL);
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
static BOOL WillHandleCLSID(const CLSID &clsid)
|
||||
static BOOL
|
||||
WillHandleCLSID(const CLSID &clsid)
|
||||
{
|
||||
#if defined(MOZ_ACTIVEX_PLUGIN_XPCONNECT) && defined(XPC_IDISPATCH_SUPPORT)
|
||||
// Ensure the control is safe for scripting
|
||||
nsCOMPtr<nsIDispatchSupport> dispSupport = do_GetService(NS_IDISPATCH_SUPPORT_CONTRACTID);
|
||||
if (!dispSupport)
|
||||
return FALSE;
|
||||
nsCID cid;
|
||||
memcpy(&cid, &clsid, sizeof(nsCID));
|
||||
PRBool isSafe = PR_FALSE;
|
||||
PRBool classExists = PR_FALSE;
|
||||
dispSupport->IsClassSafeToHost(cid, &isSafe, &classExists);
|
||||
if (classExists && !isSafe)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
#else
|
||||
if (::IsEqualCLSID(clsid, CLSID_NULL))
|
||||
{
|
||||
return FALSE;
|
||||
|
@ -363,14 +428,225 @@ static BOOL WillHandleCLSID(const CLSID &clsid)
|
|||
}
|
||||
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
NPError NewControl(const char *pluginType,
|
||||
PluginInstanceData *pData,
|
||||
uint16 mode,
|
||||
int16 argc,
|
||||
char *argn[],
|
||||
char *argv[])
|
||||
static NPError
|
||||
CreateControl(const CLSID &clsid, PluginInstanceData *pData, PropertyList &pl, LPCOLESTR szCodebase)
|
||||
{
|
||||
// Make sure we got a CLSID we can handle
|
||||
if (!WillHandleCLSID(clsid))
|
||||
{
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
pData->clsid = clsid;
|
||||
|
||||
// Set flags to specify if it is allowed to host safe or unsafe controls
|
||||
// and download them.
|
||||
PRBool hostSafeControlsOnly;
|
||||
PRBool downloadControlsIfMissing;
|
||||
#if defined(MOZ_ACTIVEX_PLUGIN_XPCONNECT) && defined(XPC_IDISPATCH_SUPPORT)
|
||||
PRUint32 hostingFlags = MozAxPlugin::PrefGetHostingFlags();
|
||||
if (hostingFlags & nsIActiveXSecurityPolicy::HOSTING_FLAGS_HOST_SAFE_OBJECTS &&
|
||||
!(hostingFlags & nsIActiveXSecurityPolicy::HOSTING_FLAGS_HOST_ALL_OBJECTS))
|
||||
{
|
||||
hostSafeControlsOnly = TRUE;
|
||||
}
|
||||
else if (hostingFlags & nsIActiveXSecurityPolicy::HOSTING_FLAGS_HOST_ALL_OBJECTS)
|
||||
{
|
||||
hostSafeControlsOnly = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Plugin can host neither safe nor unsafe controls, so just return
|
||||
// without creating anything.
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
if (hostingFlags & nsIActiveXSecurityPolicy::HOSTING_FLAGS_DOWNLOAD_CONTROLS)
|
||||
{
|
||||
downloadControlsIfMissing = PR_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
downloadControlsIfMissing = PR_FALSE;
|
||||
}
|
||||
// Ensure we can obtain the nsIDispatchSupport service
|
||||
nsCOMPtr<nsIDispatchSupport> dispSupport = do_GetService(NS_IDISPATCH_SUPPORT_CONTRACTID);
|
||||
if (!dispSupport)
|
||||
{
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
// Now test if the CLSID is safe for scripting
|
||||
PRBool classIsMarkedSafeForScripting = PR_FALSE;
|
||||
if (hostSafeControlsOnly)
|
||||
{
|
||||
PRBool classExists = PR_FALSE;
|
||||
PRBool isClassSafeForScripting = PR_FALSE;
|
||||
nsCID cid;
|
||||
memcpy(&cid, &clsid, sizeof(cid));
|
||||
if (NS_SUCCEEDED(dispSupport->IsClassMarkedSafeForScripting(cid, &classExists, &isClassSafeForScripting)) &&
|
||||
classExists && isClassSafeForScripting)
|
||||
{
|
||||
classIsMarkedSafeForScripting = PR_TRUE;
|
||||
}
|
||||
}
|
||||
#else
|
||||
hostSafeControlsOnly = kHostSafeControlsOnly;
|
||||
downloadControlsIfMissing = kDownloadControlsIfMissing;
|
||||
#endif
|
||||
|
||||
// Create the control site
|
||||
CControlSiteInstance *pSite = NULL;
|
||||
CControlSiteInstance::CreateInstance(&pSite);
|
||||
if (pSite == NULL)
|
||||
{
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
pSite->m_bSupportWindowlessActivation = FALSE;
|
||||
#if defined(MOZ_ACTIVEX_PLUGIN_XPCONNECT) && defined(XPC_IDISPATCH_SUPPORT)
|
||||
// We handle our own security further down
|
||||
pSite->SetSecurityPolicy(NULL);
|
||||
pSite->m_bSafeForScriptingObjectsOnly = FALSE;
|
||||
#else
|
||||
pSite->m_bSafeForScriptingObjectsOnly = hostSafeControlsOnly;
|
||||
#endif
|
||||
|
||||
pSite->AddRef();
|
||||
|
||||
#ifdef MOZ_ACTIVEX_PLUGIN_XPCONNECT
|
||||
// Set up the service provider and container so the control can get hold
|
||||
// of the IE DOM and other interfaces
|
||||
CComPtr<IServiceProvider> sp;
|
||||
MozAxPlugin::GetServiceProvider(pData, &sp);
|
||||
if (sp)
|
||||
pSite->SetServiceProvider(sp);
|
||||
CComQIPtr<IOleContainer> container = sp;
|
||||
if (container)
|
||||
pSite->SetContainer(container);
|
||||
#endif
|
||||
|
||||
// TODO check the object is installed and at least as recent as
|
||||
// that specified in szCodebase
|
||||
|
||||
// Create the object
|
||||
HRESULT hr;
|
||||
if (!downloadControlsIfMissing || !szCodebase)
|
||||
{
|
||||
hr = pSite->Create(clsid, pl);
|
||||
}
|
||||
else if (szCodebase)
|
||||
{
|
||||
CComObject<CInstallControlProgress> *pProgress = NULL;
|
||||
CComPtr<IBindCtx> spBindCtx;
|
||||
CComPtr<IBindStatusCallback> spOldBSC;
|
||||
CComObject<CInstallControlProgress>::CreateInstance(&pProgress);
|
||||
pProgress->AddRef();
|
||||
CreateBindCtx(0, &spBindCtx);
|
||||
RegisterBindStatusCallback(spBindCtx, dynamic_cast<IBindStatusCallback *>(pProgress), &spOldBSC, 0);
|
||||
|
||||
hr = pSite->Create(clsid, pl, szCodebase, spBindCtx);
|
||||
if (hr == MK_S_ASYNCHRONOUS)
|
||||
{
|
||||
pProgress->mNPP = pData->pPluginInstance;
|
||||
pProgress->mBindingInProgress = TRUE;
|
||||
pProgress->mResult = E_FAIL;
|
||||
|
||||
// Spin around waiting for binding to complete
|
||||
HANDLE hFakeEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
while (pProgress->mBindingInProgress)
|
||||
{
|
||||
MSG msg;
|
||||
// Process pending messages
|
||||
while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
|
||||
{
|
||||
if (!::GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
pProgress->mBindingInProgress = FALSE;
|
||||
break;
|
||||
}
|
||||
::TranslateMessage(&msg);
|
||||
::DispatchMessage(&msg);
|
||||
}
|
||||
if (!pProgress->mBindingInProgress)
|
||||
break;
|
||||
// Sleep for a bit or the next msg to appear
|
||||
::MsgWaitForMultipleObjects(1, &hFakeEvent, FALSE, 500, QS_ALLEVENTS);
|
||||
}
|
||||
::CloseHandle(hFakeEvent);
|
||||
|
||||
hr = pProgress->mResult;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pSite->Create(clsid, pl);
|
||||
}
|
||||
}
|
||||
if (pProgress)
|
||||
{
|
||||
RevokeBindStatusCallback(spBindCtx, dynamic_cast<IBindStatusCallback *>(pProgress));
|
||||
pProgress->Release();
|
||||
}
|
||||
}
|
||||
if (FAILED(hr))
|
||||
{
|
||||
ShowError(MozAxErrorCouldNotCreateControl, clsid);
|
||||
}
|
||||
#if defined(MOZ_ACTIVEX_PLUGIN_XPCONNECT) && defined(XPC_IDISPATCH_SUPPORT)
|
||||
if (SUCCEEDED(hr) && hostSafeControlsOnly && !classIsMarkedSafeForScripting)
|
||||
{
|
||||
CComPtr<IUnknown> cpUnk;
|
||||
pSite->GetControlUnknown(&cpUnk);
|
||||
nsIID iidDispatch;
|
||||
memcpy(&iidDispatch, &__uuidof(IDispatch), sizeof(nsIID));
|
||||
PRBool isObjectSafe = PR_FALSE;
|
||||
if (!cpUnk ||
|
||||
NS_FAILED(dispSupport->IsObjectSafeForScripting(
|
||||
reinterpret_cast<void *>(cpUnk.p), iidDispatch, &isObjectSafe)) ||
|
||||
!isObjectSafe)
|
||||
{
|
||||
pSite->Detach();
|
||||
hr = E_FAIL;
|
||||
ShowError(MozAxErrorControlIsNotSafeForScripting, clsid);
|
||||
// DROP THROUGH
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Clean up if the control could not be created
|
||||
if (FAILED(hr))
|
||||
{
|
||||
pSite->Release();
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
#if defined(MOZ_ACTIVEX_PLUGIN_XPCONNECT) && defined(XPC_IDISPATCH_SUPPORT)
|
||||
// Hook up the event sink
|
||||
nsEventSinkInstance *pSink = NULL;
|
||||
nsEventSinkInstance::CreateInstance(&pSink);
|
||||
if (pSink)
|
||||
{
|
||||
pSink->AddRef();
|
||||
pSink->mPlugin = pData;
|
||||
CComPtr<IUnknown> control;
|
||||
pSite->GetControlUnknown(&control);
|
||||
pSink->SubscribeToEvents(control);
|
||||
}
|
||||
pData->pControlEventSink = pSink;
|
||||
#endif
|
||||
pData->nType = itControl;
|
||||
pData->pControlSite = pSite;
|
||||
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
static NPError
|
||||
NewControl(const char *pluginType,
|
||||
PluginInstanceData *pData,
|
||||
uint16 mode,
|
||||
int16 argc,
|
||||
char *argn[],
|
||||
char *argv[])
|
||||
{
|
||||
// Read the parameters
|
||||
CLSID clsid = CLSID_NULL;
|
||||
|
@ -380,7 +656,7 @@ NPError NewControl(const char *pluginType,
|
|||
if (strcmp(pluginType, MIME_OLEOBJECT1) != 0 &&
|
||||
strcmp(pluginType, MIME_OLEOBJECT2) != 0)
|
||||
{
|
||||
clsid = xpc_GetCLSIDForType(pluginType);
|
||||
clsid = MozAxPlugin::GetCLSIDForType(pluginType);
|
||||
}
|
||||
|
||||
for (int16 i = 0; i < argc; i++)
|
||||
|
@ -490,129 +766,7 @@ NPError NewControl(const char *pluginType,
|
|||
}
|
||||
}
|
||||
|
||||
// Make sure we got a CLSID we can handle
|
||||
if (!WillHandleCLSID(clsid))
|
||||
{
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
pData->clsid = clsid;
|
||||
|
||||
// Create the control site
|
||||
CControlSiteInstance *pSite = NULL;
|
||||
CControlSiteInstance::CreateInstance(&pSite);
|
||||
if (pSite == NULL)
|
||||
{
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
pSite->m_bSafeForScriptingObjectsOnly = kSafeForScriptingControlsOnly;
|
||||
pSite->m_bSupportWindowlessActivation = FALSE;
|
||||
pSite->AddRef();
|
||||
|
||||
#ifdef MOZ_ACTIVEX_PLUGIN_XPCONNECT
|
||||
CComPtr<IServiceProvider> sp;
|
||||
xpc_GetServiceProvider(pData, &sp);
|
||||
if (sp)
|
||||
pSite->SetServiceProvider(sp);
|
||||
CComQIPtr<IOleContainer> container = sp;
|
||||
if (container)
|
||||
pSite->SetContainer(container);
|
||||
#endif
|
||||
|
||||
// TODO check the object is installed and at least as recent as
|
||||
// that specified in szCodebase
|
||||
|
||||
// Create the object
|
||||
HRESULT hr;
|
||||
if (!kDownloadControlsIfMissing || !codebase.m_str)
|
||||
{
|
||||
hr = pSite->Create(clsid, pl);
|
||||
}
|
||||
else if (codebase.m_str)
|
||||
{
|
||||
CComObject<CInstallControlProgress> *pProgress = NULL;
|
||||
CComPtr<IBindCtx> spBindCtx;
|
||||
CComPtr<IBindStatusCallback> spOldBSC;
|
||||
CComObject<CInstallControlProgress>::CreateInstance(&pProgress);
|
||||
pProgress->AddRef();
|
||||
CreateBindCtx(0, &spBindCtx);
|
||||
RegisterBindStatusCallback(spBindCtx, dynamic_cast<IBindStatusCallback *>(pProgress), &spOldBSC, 0);
|
||||
|
||||
hr = pSite->Create(clsid, pl, codebase, spBindCtx);
|
||||
if (hr == MK_S_ASYNCHRONOUS)
|
||||
{
|
||||
pProgress->mNPP = pData->pPluginInstance;
|
||||
pProgress->mBindingInProgress = TRUE;
|
||||
pProgress->mResult = E_FAIL;
|
||||
|
||||
// Spin around waiting for binding to complete
|
||||
HANDLE hFakeEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
while (pProgress->mBindingInProgress)
|
||||
{
|
||||
MSG msg;
|
||||
// Process pending messages
|
||||
while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
|
||||
{
|
||||
if (!::GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
pProgress->mBindingInProgress = FALSE;
|
||||
break;
|
||||
}
|
||||
::TranslateMessage(&msg);
|
||||
::DispatchMessage(&msg);
|
||||
}
|
||||
if (!pProgress->mBindingInProgress)
|
||||
break;
|
||||
// Sleep for a bit or the next msg to appear
|
||||
::MsgWaitForMultipleObjects(1, &hFakeEvent, FALSE, 500, QS_ALLEVENTS);
|
||||
}
|
||||
::CloseHandle(hFakeEvent);
|
||||
|
||||
hr = pProgress->mResult;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pSite->Create(clsid, pl);
|
||||
}
|
||||
}
|
||||
if (pProgress)
|
||||
{
|
||||
RevokeBindStatusCallback(spBindCtx, dynamic_cast<IBindStatusCallback *>(pProgress));
|
||||
pProgress->Release();
|
||||
}
|
||||
}
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (kDisplayErrorMessages)
|
||||
{
|
||||
USES_CONVERSION;
|
||||
LPOLESTR szClsid;
|
||||
StringFromCLSID(clsid, &szClsid);
|
||||
TCHAR szBuffer[256];
|
||||
_stprintf(szBuffer, _T("Could not create the control %s. Check that it has been installed on your computer and that this page correctly references it."), OLE2T(szClsid));
|
||||
MessageBox(NULL, szBuffer, _T("ActiveX Error"), MB_OK | MB_ICONWARNING);
|
||||
CoTaskMemFree(szClsid);
|
||||
}
|
||||
pSite->Release();
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
nsEventSinkInstance *pSink = NULL;
|
||||
nsEventSinkInstance::CreateInstance(&pSink);
|
||||
if (pSink)
|
||||
{
|
||||
pSink->AddRef();
|
||||
pSink->mPlugin = pData;
|
||||
CComPtr<IUnknown> control;
|
||||
pSite->GetControlUnknown(&control);
|
||||
pSink->SubscribeToEvents(control);
|
||||
}
|
||||
pData->pControlEventSink = pSink;
|
||||
#endif
|
||||
pData->nType = itControl;
|
||||
pData->pControlSite = pSite;
|
||||
|
||||
return NPERR_NO_ERROR;
|
||||
return CreateControl(clsid, pData, pl, codebase.m_str);
|
||||
}
|
||||
|
||||
|
||||
|
@ -651,7 +805,7 @@ NPError NP_LOADDS NPP_New(NPMIMEType pluginType,
|
|||
|
||||
// Create a plugin according to the mime type
|
||||
#ifdef MOZ_ACTIVEX_PLUGIN_XPCONNECT
|
||||
xpc_AddRef();
|
||||
MozAxPlugin::AddRef();
|
||||
#endif
|
||||
|
||||
NPError rv = NPERR_GENERIC_ERROR;
|
||||
|
@ -674,7 +828,7 @@ NPError NP_LOADDS NPP_New(NPMIMEType pluginType,
|
|||
free(pData->szUrl);
|
||||
delete pData;
|
||||
#ifdef MOZ_ACTIVEX_PLUGIN_XPCONNECT
|
||||
xpc_Release();
|
||||
MozAxPlugin::Release();
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
@ -709,7 +863,7 @@ NPP_Destroy(NPP instance, NPSavedData** save)
|
|||
pSite->Detach();
|
||||
pSite->Release();
|
||||
}
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
#if defined(MOZ_ACTIVEX_PLUGIN_XPCONNECT) && defined(XPC_IDISPATCH_SUPPORT)
|
||||
if (pData->pControlEventSink)
|
||||
{
|
||||
pData->pControlEventSink->UnsubscribeFromEvents();
|
||||
|
@ -734,7 +888,7 @@ NPP_Destroy(NPP instance, NPSavedData** save)
|
|||
free(pData->szContentType);
|
||||
delete pData;
|
||||
#ifdef MOZ_ACTIVEX_PLUGIN_XPCONNECT
|
||||
xpc_Release();
|
||||
MozAxPlugin::Release();
|
||||
#endif
|
||||
|
||||
instance->pdata = 0;
|
||||
|
@ -971,7 +1125,7 @@ NPP_GetValue(NPP instance, NPPVariable variable, void *value)
|
|||
{
|
||||
NPError rv = NPERR_GENERIC_ERROR;
|
||||
#ifdef MOZ_ACTIVEX_PLUGIN_XPCONNECT
|
||||
rv = xpc_GetValue(instance, variable, value);
|
||||
rv = MozAxPlugin::GetValue(instance, variable, value);
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -119,7 +119,6 @@ CPPSRCS = \
|
|||
StdAfx.cpp \
|
||||
LegacyPlugin.cpp \
|
||||
MozActiveX.cpp \
|
||||
PrefObserver.cpp \
|
||||
npwin.cpp \
|
||||
$(_CONTROL_CPPSRCS) \
|
||||
$(NULL)
|
||||
|
@ -133,6 +132,10 @@ CPPSRCS += LiveConnect.cpp
|
|||
CSRCS += javastubs.c
|
||||
endif
|
||||
|
||||
ifdef XPC_IDISPATCH_SUPPORT
|
||||
CPPSRCS += PrefObserver.cpp
|
||||
endif
|
||||
|
||||
LOCAL_INCLUDES = -I$(MOZCTLSRC)
|
||||
|
||||
ifdef MOZ_ACTIVEX_PLUGIN_LIVECONNECT
|
||||
|
@ -198,6 +201,9 @@ install-class: MozAxPlugin.class
|
|||
install-typelib: $(XPIDL_GEN_DIR)/nsIMozAxPlugin.xpt
|
||||
$(INSTALL) $< $(DIST)/bin/plugins
|
||||
|
||||
install-securitypolicy: nsAxSecurityPolicy.js
|
||||
$(INSTALL) $< $(DIST)/bin/components
|
||||
|
||||
libs:: install-plugin
|
||||
|
||||
ifdef MOZ_ACTIVEX_PLUGIN_LIVECONNECT
|
||||
|
@ -208,6 +214,10 @@ ifdef MOZ_ACTIVEX_PLUGIN_XPCONNECT
|
|||
libs:: install-typelib
|
||||
endif
|
||||
|
||||
ifdef XPC_IDISPATCH_SUPPORT
|
||||
libs:: install-securitypolicy
|
||||
endif
|
||||
|
||||
## Note: Ensure you create the redist dir containing the correct runtime dlls
|
||||
|
||||
xpi:: install.js $(SHARED_LIBRARY)
|
||||
|
|
|
@ -44,10 +44,25 @@
|
|||
#include "npapi.h"
|
||||
#include "nsIServiceManagerUtils.h"
|
||||
#include "nsISupportsUtils.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranchInternal.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "XPConnect.h"
|
||||
|
||||
// These are the default hosting flags in the absence of a pref.
|
||||
|
||||
const PRUint32 kDefaultHostingFlags =
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
nsIActiveXSecurityPolicy::HOSTING_FLAGS_HOST_NOTHING;
|
||||
#else
|
||||
nsIActiveXSecurityPolicy::HOSTING_FLAGS_HOST_SAFE_OBJECTS |
|
||||
nsIActiveXSecurityPolicy::HOSTING_FLAGS_DOWNLOAD_CONTROLS |
|
||||
nsIActiveXSecurityPolicy::HOSTING_FLAGS_SCRIPT_SAFE_OBJECTS;
|
||||
#endif
|
||||
|
||||
class PrefObserver :
|
||||
public nsSupportsWeakReference,
|
||||
|
@ -55,23 +70,38 @@ class PrefObserver :
|
|||
{
|
||||
public:
|
||||
PrefObserver();
|
||||
|
||||
protected:
|
||||
virtual ~PrefObserver();
|
||||
|
||||
static PrefObserver *sPrefObserver;
|
||||
void Sync(nsIPrefBranch *aPrefBranch);
|
||||
|
||||
PRUint32 mHostingFlags;
|
||||
nsCOMPtr<nsIPrefService> mPrefService;
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
static nsresult Subscribe();
|
||||
static nsresult Unsubscribe();
|
||||
static PrefObserver *sPrefObserver;
|
||||
|
||||
nsresult Subscribe();
|
||||
nsresult Unsubscribe();
|
||||
PRUint32 GetHostingFlags() const;
|
||||
};
|
||||
|
||||
const char *kActiveXHostingFlags = "security.xpconnect.activex.";
|
||||
const char *kUserAgentPref = "general.useragent.";
|
||||
const char *kProxyPref = "network.http.";
|
||||
|
||||
PrefObserver *PrefObserver::sPrefObserver = nsnull;
|
||||
|
||||
PrefObserver::PrefObserver()
|
||||
PrefObserver::PrefObserver() :
|
||||
mHostingFlags(kDefaultHostingFlags)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
nsresult rv = NS_OK;
|
||||
mPrefService = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
|
||||
NS_ASSERTION(mPrefService, "where is the pref service?");
|
||||
}
|
||||
|
||||
PrefObserver::~PrefObserver()
|
||||
|
@ -89,38 +119,65 @@ NS_INTERFACE_MAP_END
|
|||
/* void observe (in nsISupports aSubject, in string aTopic, in wstring aData); */
|
||||
NS_IMETHODIMP PrefObserver::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
|
||||
{
|
||||
if (nsCRT::strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic) != 0)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(aSubject, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCAutoString pref = NS_ConvertUCS2toUTF8(aData);
|
||||
if (nsCRT::strcmp(kActiveXHostingFlags, pref.get()) == 0 ||
|
||||
nsCRT::strcmp(kUserAgentPref, pref.get()) == 0 ||
|
||||
nsCRT::strcmp(kProxyPref, pref.get()) == 0)
|
||||
{
|
||||
Sync(prefBranch);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void PrefObserver::Sync(nsIPrefBranch *aPrefBranch)
|
||||
{
|
||||
NS_ASSERTION(aPrefBranch, "no pref branch");
|
||||
if (!aPrefBranch)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO
|
||||
// const char *userAgent = NPN_UserAgent(mData->pPluginInstance);
|
||||
// ::UrlMkSetSessionOption(URLMON_OPTION_USERAGENT, userAgent, strlen(userAgent), 0);
|
||||
|
||||
// TODO
|
||||
// INTERNET_PROXY_INFO ipi;
|
||||
// UrlMkSetSessionOption(INTERNET_OPTION_PROXY, ....);
|
||||
return NS_OK;
|
||||
// ::UrlMkSetSessionOption(INTERNET_OPTION_PROXY, ....);
|
||||
|
||||
nsCOMPtr<nsIDispatchSupport> dispSupport = do_GetService(NS_IDISPATCH_SUPPORT_CONTRACTID);
|
||||
if (!dispSupport)
|
||||
mHostingFlags = kDefaultHostingFlags;
|
||||
else
|
||||
dispSupport->GetHostingFlags(nsnull, &mHostingFlags);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PrefObserver::Subscribe()
|
||||
{
|
||||
if (sPrefObserver)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
NS_ENSURE_TRUE(mPrefService, NS_ERROR_FAILURE);
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(mPrefService, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
sPrefObserver = new PrefObserver();
|
||||
NS_ENSURE_TRUE(sPrefObserver, NS_ERROR_OUT_OF_MEMORY);
|
||||
sPrefObserver->AddRef();
|
||||
nsCOMPtr<nsIPrefBranchInternal> prefInternal = do_QueryInterface(prefBranch, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIPrefService> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
prefInternal->AddObserver(kProxyPref, this, PR_TRUE);
|
||||
prefInternal->AddObserver(kUserAgentPref, this, PR_TRUE);
|
||||
prefInternal->AddObserver(kActiveXHostingFlags, this, PR_TRUE);
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch;
|
||||
prefService->GetBranch(nsnull, getter_AddRefs(prefBranch));
|
||||
NS_ENSURE_TRUE(prefBranch, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIPrefBranchInternal> pbi = do_QueryInterface(prefBranch);
|
||||
NS_ENSURE_TRUE(pbi, NS_ERROR_FAILURE);
|
||||
|
||||
pbi->AddObserver("network.http.proxy.", sPrefObserver, PR_TRUE);
|
||||
pbi->AddObserver("general.useragent.", sPrefObserver, PR_TRUE);
|
||||
Sync(prefBranch);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -128,10 +185,50 @@ PrefObserver::Subscribe()
|
|||
nsresult
|
||||
PrefObserver::Unsubscribe()
|
||||
{
|
||||
if (sPrefObserver)
|
||||
{
|
||||
sPrefObserver->Release();
|
||||
sPrefObserver = nsnull;
|
||||
}
|
||||
NS_ENSURE_TRUE(mPrefService, NS_ERROR_FAILURE);
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(mPrefService, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIPrefBranchInternal> prefInternal = do_QueryInterface(prefBranch, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
prefInternal->RemoveObserver(kProxyPref, this);
|
||||
prefInternal->RemoveObserver(kUserAgentPref, this);
|
||||
prefInternal->RemoveObserver(kActiveXHostingFlags, this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint32 PrefObserver::GetHostingFlags() const
|
||||
{
|
||||
return mHostingFlags;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PRUint32 MozAxPlugin::PrefGetHostingFlags()
|
||||
{
|
||||
if (!PrefObserver::sPrefObserver)
|
||||
{
|
||||
PrefObserver::sPrefObserver = new PrefObserver();
|
||||
if (!PrefObserver::sPrefObserver)
|
||||
{
|
||||
return nsIActiveXSecurityPolicy::HOSTING_FLAGS_HOST_NOTHING;
|
||||
}
|
||||
PrefObserver::sPrefObserver->AddRef();
|
||||
PrefObserver::sPrefObserver->Subscribe();
|
||||
}
|
||||
return PrefObserver::sPrefObserver->GetHostingFlags();
|
||||
}
|
||||
|
||||
void MozAxPlugin::ReleasePrefObserver()
|
||||
{
|
||||
if (PrefObserver::sPrefObserver)
|
||||
{
|
||||
PrefObserver::sPrefObserver->Unsubscribe();
|
||||
PrefObserver::sPrefObserver->Release();
|
||||
PrefObserver::sPrefObserver = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -734,7 +734,7 @@ public:
|
|||
mBrowser(NULL),
|
||||
mData(NULL)
|
||||
{
|
||||
xpc_AddRef();
|
||||
MozAxPlugin::AddRef();
|
||||
}
|
||||
|
||||
HRESULT Init(PluginInstanceData *pData)
|
||||
|
@ -799,7 +799,7 @@ public:
|
|||
{
|
||||
mWindow->Release();
|
||||
}
|
||||
xpc_Release();
|
||||
MozAxPlugin::Release();
|
||||
}
|
||||
|
||||
BEGIN_COM_MAP(IEDocument)
|
||||
|
@ -1703,7 +1703,7 @@ END_COM_MAP()
|
|||
|
||||
};
|
||||
|
||||
HRESULT xpc_GetServiceProvider(PluginInstanceData *pData, IServiceProvider **pSP)
|
||||
HRESULT MozAxPlugin::GetServiceProvider(PluginInstanceData *pData, IServiceProvider **pSP)
|
||||
{
|
||||
// Note this should be called on the main NPAPI thread
|
||||
CComObject<IEDocument> *pDoc = NULL;
|
||||
|
|
|
@ -64,9 +64,6 @@
|
|||
|
||||
#include "nsIScriptEventManager.h"
|
||||
#include "jsapi.h"
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
#include "nsIDispatchSupport.h"
|
||||
#endif
|
||||
|
||||
#include "LegacyPlugin.h"
|
||||
#include "XPConnect.h"
|
||||
|
@ -82,13 +79,13 @@ nsScriptablePeer::nsScriptablePeer() :
|
|||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
NS_ASSERTION(mTearOff, "can't create tearoff");
|
||||
xpc_AddRef();
|
||||
MozAxPlugin::AddRef();
|
||||
}
|
||||
|
||||
nsScriptablePeer::~nsScriptablePeer()
|
||||
{
|
||||
delete mTearOff;
|
||||
xpc_Release();
|
||||
MozAxPlugin::Release();
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsScriptablePeer)
|
||||
|
@ -760,10 +757,6 @@ nsEventSink::InternalInvoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wF
|
|||
|
||||
nsDependentString eventName(bstrName.m_str);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMDocument> domdoc;
|
||||
nsCOMPtr<nsIDOMNodeList> scriptElements;
|
||||
|
||||
// Fire the script event handler...
|
||||
nsCOMPtr<nsIDOMWindow> window;
|
||||
NPN_GetValue(mPlugin->pPluginInstance, NPNVDOMWindow, (void *)&window);
|
||||
|
@ -920,20 +913,28 @@ HRESULT STDMETHODCALLTYPE nsScriptablePeerTearOff::Invoke(DISPID dispIdMember, R
|
|||
|
||||
static PRUint32 gInstances = 0;
|
||||
|
||||
void xpc_AddRef()
|
||||
void MozAxPlugin::AddRef()
|
||||
{
|
||||
if (gInstances == 0)
|
||||
XPCOMGlueStartup(nsnull);
|
||||
{
|
||||
XPCOMGlueStartup(nsnull);
|
||||
MozAxPlugin::PrefGetHostingFlags(); // Initial call to set it up
|
||||
}
|
||||
gInstances++;
|
||||
}
|
||||
|
||||
void xpc_Release()
|
||||
void MozAxPlugin::Release()
|
||||
{
|
||||
if (--gInstances == 0)
|
||||
XPCOMGlueShutdown();
|
||||
{
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
MozAxPlugin::ReleasePrefObserver();
|
||||
#endif
|
||||
XPCOMGlueShutdown();
|
||||
}
|
||||
}
|
||||
|
||||
CLSID xpc_GetCLSIDForType(const char *mimeType)
|
||||
CLSID MozAxPlugin::GetCLSIDForType(const char *mimeType)
|
||||
{
|
||||
if (mimeType == NULL)
|
||||
{
|
||||
|
@ -954,7 +955,7 @@ CLSID xpc_GetCLSIDForType(const char *mimeType)
|
|||
ULONG nCount = (sizeof(szGUID) / sizeof(szGUID[0])) - 1;
|
||||
|
||||
GUID guidValue = GUID_NULL;
|
||||
if (keyMimeType.QueryValue(_T("CLSID"), szGUID, &nCount) == ERROR_SUCCESS &&
|
||||
if (keyMimeType.QueryValue(szGUID, _T("CLSID"), &nCount) == ERROR_SUCCESS &&
|
||||
SUCCEEDED(::CLSIDFromString(T2OLE(szGUID), &guidValue)))
|
||||
{
|
||||
return guidValue;
|
||||
|
@ -966,20 +967,16 @@ CLSID xpc_GetCLSIDForType(const char *mimeType)
|
|||
|
||||
|
||||
nsScriptablePeer *
|
||||
xpc_GetPeerForCLSID(const CLSID &clsid)
|
||||
MozAxPlugin::GetPeerForCLSID(const CLSID &clsid)
|
||||
{
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
return new nsScriptablePeer();
|
||||
#else
|
||||
return new nsScriptablePeer();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
xpc_GetIIDForCLSID(const CLSID &clsid, nsIID &iid)
|
||||
MozAxPlugin::GetIIDForCLSID(const CLSID &clsid, nsIID &iid)
|
||||
{
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
memcpy(&iid, &_uuidof(IDispatch), sizeof(iid));
|
||||
memcpy(&iid, &__uuidof(IDispatch), sizeof(iid));
|
||||
#else
|
||||
iid = NS_GET_IID(nsIMozAxPlugin);
|
||||
#endif
|
||||
|
@ -987,7 +984,7 @@ xpc_GetIIDForCLSID(const CLSID &clsid, nsIID &iid)
|
|||
|
||||
// Called by NPP_GetValue to provide the scripting values
|
||||
NPError
|
||||
xpc_GetValue(NPP instance, NPPVariable variable, void *value)
|
||||
MozAxPlugin::GetValue(NPP instance, NPPVariable variable, void *value)
|
||||
{
|
||||
if (instance == NULL)
|
||||
{
|
||||
|
@ -1002,6 +999,55 @@ xpc_GetValue(NPP instance, NPPVariable variable, void *value)
|
|||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
// Test if the object is allowed to be scripted
|
||||
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
PRUint32 hostingFlags = MozAxPlugin::PrefGetHostingFlags();
|
||||
if (hostingFlags & nsIActiveXSecurityPolicy::HOSTING_FLAGS_SCRIPT_SAFE_OBJECTS &&
|
||||
!(hostingFlags & nsIActiveXSecurityPolicy::HOSTING_FLAGS_SCRIPT_ALL_OBJECTS))
|
||||
{
|
||||
// Ensure the object is safe for scripting on the specified interface
|
||||
nsCOMPtr<nsIDispatchSupport> dispSupport = do_GetService(NS_IDISPATCH_SUPPORT_CONTRACTID);
|
||||
if (!dispSupport) return NPERR_GENERIC_ERROR;
|
||||
|
||||
PRBool isScriptable = PR_FALSE;
|
||||
|
||||
// Test if the object says its safe for scripting on IDispatch
|
||||
nsIID iid;
|
||||
memcpy(&iid, &__uuidof(IDispatch), sizeof(iid));
|
||||
CComPtr<IUnknown> controlUnk;
|
||||
pData->pControlSite->GetControlUnknown(&controlUnk);
|
||||
dispSupport->IsObjectSafeForScripting(reinterpret_cast<void *>(controlUnk.p), iid, &isScriptable);
|
||||
|
||||
// Test if the class id says safe for scripting
|
||||
if (!isScriptable)
|
||||
{
|
||||
PRBool classExists = PR_FALSE;
|
||||
nsCID cid;
|
||||
memcpy(&iid, &pData->clsid, sizeof(cid));
|
||||
dispSupport->IsClassMarkedSafeForScripting(cid, &classExists, &isScriptable);
|
||||
}
|
||||
if (!isScriptable)
|
||||
{
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
}
|
||||
else if (hostingFlags & nsIActiveXSecurityPolicy::HOSTING_FLAGS_SCRIPT_ALL_OBJECTS)
|
||||
{
|
||||
// Drop through since all objects are scriptable
|
||||
}
|
||||
else
|
||||
{
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
#else
|
||||
// Object *must* be safe
|
||||
if (!pData->pControlSite->IsObjectSafeForScripting(__uuidof(IDispatch)))
|
||||
{
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Happy happy fun fun - redefine some NPPVariable values that we might
|
||||
// be asked for but not defined by every PluginSDK
|
||||
|
||||
|
@ -1012,7 +1058,7 @@ xpc_GetValue(NPP instance, NPPVariable variable, void *value)
|
|||
{
|
||||
if (!pData->pScriptingPeer)
|
||||
{
|
||||
nsScriptablePeer *peer = xpc_GetPeerForCLSID(pData->clsid);
|
||||
nsScriptablePeer *peer = MozAxPlugin::GetPeerForCLSID(pData->clsid);
|
||||
if (peer)
|
||||
{
|
||||
peer->AddRef();
|
||||
|
@ -1030,7 +1076,7 @@ xpc_GetValue(NPP instance, NPPVariable variable, void *value)
|
|||
else if (variable == kVarScriptableIID)
|
||||
{
|
||||
nsIID *piid = (nsIID *) NPN_MemAlloc(sizeof(nsIID));
|
||||
xpc_GetIIDForCLSID(pData->clsid, *piid);
|
||||
GetIIDForCLSID(pData->clsid, *piid);
|
||||
*((nsIID **) value) = piid;
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
|
|
@ -41,8 +41,16 @@
|
|||
|
||||
#include <servprov.h>
|
||||
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
#include "nsIDispatchSupport.h"
|
||||
#include "nsIActiveXSecurityPolicy.h"
|
||||
#endif
|
||||
|
||||
#include "nsID.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIMozAxPlugin.h"
|
||||
#include "nsIServiceManagerUtils.h"
|
||||
|
||||
#include "ControlEventSink.h"
|
||||
|
||||
|
@ -133,12 +141,18 @@ public:
|
|||
typedef CComObject<nsEventSink> nsEventSinkInstance;
|
||||
#endif
|
||||
|
||||
extern void xpc_AddRef();
|
||||
extern void xpc_Release();
|
||||
extern CLSID xpc_GetCLSIDForType(const char *mimeType);
|
||||
extern NPError xpc_GetValue(NPP instance, NPPVariable variable, void *value);
|
||||
extern nsScriptablePeer *xpc_GetPeerForCLSID(const CLSID &clsid);
|
||||
extern nsIID xpc_GetIIDForCLSID(const CLSID &clsid);
|
||||
extern HRESULT xpc_GetServiceProvider(PluginInstanceData *pData, IServiceProvider **pSP);
|
||||
namespace MozAxPlugin {
|
||||
extern void AddRef();
|
||||
extern void Release();
|
||||
extern CLSID GetCLSIDForType(const char *mimeType);
|
||||
extern NPError GetValue(NPP instance, NPPVariable variable, void *value);
|
||||
extern nsScriptablePeer *GetPeerForCLSID(const CLSID &clsid);
|
||||
extern void GetIIDForCLSID(const CLSID &clsid, nsIID &iid);
|
||||
extern HRESULT GetServiceProvider(PluginInstanceData *pData, IServiceProvider **pSP);
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
extern PRUint32 PrefGetHostingFlags();
|
||||
extern void ReleasePrefObserver();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,201 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Adam Lock <adamlock@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const NS_IACTIVEXSECURITYPOLICY_CONTRACTID =
|
||||
"@mozilla.org/nsactivexsecuritypolicy;1";
|
||||
const NS_IACTIVEXSECURITYPOLICY_CID =
|
||||
Components.ID("{B9BDB43B-109E-44b8-858C-B68C6C3DF86F}");
|
||||
|
||||
const nsISupports = Components.interfaces.nsISupports;
|
||||
const nsIObserver = Components.interfaces.nsIObserver;
|
||||
const nsIActiveXSecurityPolicy = Components.interfaces.nsIActiveXSecurityPolicy;
|
||||
|
||||
// TODO lockdown this value
|
||||
const kDefaultGlobalHostingFlags =
|
||||
nsIActiveXSecurityPolicy.HOSTING_FLAGS_HOST_SAFE_OBJECTS |
|
||||
nsIActiveXSecurityPolicy.HOSTING_FLAGS_DOWNLOAD_CONTROLS |
|
||||
nsIActiveXSecurityPolicy.HOSTING_FLAGS_SCRIPT_SAFE_OBJECTS;
|
||||
|
||||
const kDefaultOtherHostingFlags =
|
||||
nsIActiveXSecurityPolicy.HOSTING_FLAGS_HOST_NOTHING;
|
||||
|
||||
var gPref = null;
|
||||
|
||||
function addPrefListener(observer, domain)
|
||||
{
|
||||
try {
|
||||
if (gPref == null)
|
||||
{
|
||||
var prefService = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefService);
|
||||
gPref = prefService.getBranch(null);
|
||||
}
|
||||
var pbi = gPref.QueryInterface(Components.interfaces.nsIPrefBranchInternal);
|
||||
pbi.addObserver(domain, observer, false);
|
||||
} catch(ex) {
|
||||
dump("Failed to observe prefs: " + ex + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
function AxSecurityPolicy()
|
||||
{
|
||||
this.prefPart1 = "security.xpconnect.activex.";
|
||||
this.prefPart2 = ".hosting_flags";
|
||||
this.globalPrefName = this.prefPart1 + "global" + this.prefPart2;
|
||||
// TODO read from prefs
|
||||
// addPrefListener(this, this.globalPrefName);
|
||||
this.syncPrefs();
|
||||
}
|
||||
|
||||
AxSecurityPolicy.prototype = {
|
||||
syncPrefs: function()
|
||||
{
|
||||
this.globalHostingFlags = kDefaultGlobalHostingFlags;
|
||||
// TODO read from prefs
|
||||
/*
|
||||
try {
|
||||
if (gPref == null) {
|
||||
var prefService = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefService);
|
||||
gPref = prefService.getBranch(null);
|
||||
}
|
||||
this.globalHostingFlags = gPref.getIntPref(this.globalPrefName);
|
||||
}
|
||||
catch (ex) {
|
||||
dump("Failed to read prefs from " + this.globalPrefName + " : " + ex + "\n");
|
||||
this.globalHostingFlags = kDefaultGlobalHostingFlags;
|
||||
}
|
||||
*/
|
||||
},
|
||||
|
||||
// nsIActiveXSecurityPolicy
|
||||
getHostingFlags: function(context)
|
||||
{
|
||||
var hostingFlags;
|
||||
if (context == null || context == "global") {
|
||||
hostingFlags = this.globalHostingFlags;
|
||||
}
|
||||
else {
|
||||
// TODO read from prefs
|
||||
/*
|
||||
try {
|
||||
var prefName = prefPart1 + context + prefPart2;
|
||||
hostingFlags = gPref.getIntPref(prefName);
|
||||
}
|
||||
catch (ex) {
|
||||
dump("Failed to read prefs from " + prefName + " : " + ex + "\n");
|
||||
hostingFlags = kDefaultOtherHostingFlags;
|
||||
}
|
||||
*/
|
||||
hostingFlags = kDefaultOtherHostingFlags;
|
||||
}
|
||||
return hostingFlags;
|
||||
},
|
||||
// nsIObserver
|
||||
observe: function(subject, topic, prefName)
|
||||
{
|
||||
if (topic != "nsPref:changed")
|
||||
return;
|
||||
this.syncPrefs();
|
||||
|
||||
},
|
||||
// nsISupports
|
||||
QueryInterface: function(iid) {
|
||||
if (!iid.equals(nsISupports) &&
|
||||
!iid.equals(nsIActiveXSecurityPolicy) &&
|
||||
!iid.equals(nsIObserver))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
/* factory for AxSecurityPolicy */
|
||||
var AxSecurityPolicyFactory = {
|
||||
createInstance: function (outer, iid)
|
||||
{
|
||||
if (outer != null)
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
if (!iid.equals(nsISupports) &&
|
||||
!iid.equals(nsIActiveXSecurityPolicy) &&
|
||||
!iid.equals(nsIObserver))
|
||||
throw Components.results.NS_ERROR_INVALID_ARG;
|
||||
return new AxSecurityPolicy();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var AxSecurityPolicyModule = {
|
||||
registerSelf: function (compMgr, fileSpec, location, type)
|
||||
{
|
||||
debug("*** Registering axsecurity policy.\n");
|
||||
compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
|
||||
compMgr.registerFactoryLocation(
|
||||
NS_IACTIVEXSECURITYPOLICY_CID ,
|
||||
"ActiveX Security Policy Service",
|
||||
NS_IACTIVEXSECURITYPOLICY_CONTRACTID,
|
||||
fileSpec,
|
||||
location,
|
||||
type);
|
||||
},
|
||||
unregisterSelf: function(compMgr, fileSpec, location)
|
||||
{
|
||||
compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
|
||||
compMgr.unregisterFactoryLocation(NS_IACTIVEXSECURITYPOLICY_CID, fileSpec);
|
||||
},
|
||||
getClassObject: function(compMgr, cid, iid)
|
||||
{
|
||||
if (cid.equals(NS_IACTIVEXSECURITYPOLICY_CID))
|
||||
return AxSecurityPolicyFactory;
|
||||
|
||||
if (!iid.equals(Components.interfaces.nsIFactory))
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
canUnload: function(compMgr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/* entrypoint */
|
||||
function NSGetModule(compMgr, fileSpec) {
|
||||
return AxSecurityPolicyModule;
|
||||
}
|
||||
|
||||
|
|
@ -39,6 +39,9 @@
|
|||
#include "nsIVariant.idl"
|
||||
|
||||
%{ C++
|
||||
// Pull in jsval definition
|
||||
#include "jspubtd.h"
|
||||
|
||||
// {40c4883d-079f-43db-82a9-df0a59d37998}
|
||||
#define NS_IDISPATCH_SUPPORT_CID \
|
||||
{ 0x40c4883d, 0x079f, 0x43db, \
|
||||
|
@ -62,24 +65,58 @@ interface IDispatch;
|
|||
interface nsIDispatchSupport : nsISupports
|
||||
{
|
||||
/**
|
||||
* Converts a COM Variant to a jsval
|
||||
* @param comvar The COM Variant to be converted
|
||||
* @param val The jsval to receive the converted value
|
||||
* Converts a COM Variant to a jsval.
|
||||
* @param comvar The COM Variant to be converted.
|
||||
* @param val The jsval to receive the converted value.
|
||||
*/
|
||||
void COMVariant2JSVal(in COMVARIANTPtr comvar, out JSVal val);
|
||||
|
||||
/**
|
||||
* Converts a jsval to a COM Variant
|
||||
* @param var The jsval to be converted
|
||||
* @param var The jsval to be converted.
|
||||
* @param comvar The COM Variant to receive the converted value
|
||||
*/
|
||||
void JSVal2COMVariant(in JSVal var, out COMVARIANT comvar);
|
||||
|
||||
/**
|
||||
* Instantiate a COM component
|
||||
* This checks to see if the component is scriptable. If it is, it instantiates it
|
||||
* @param className contract ID or class ID of the desired component to instantiate
|
||||
* Instantiate a COM component.
|
||||
* @param className ProgID or Class ID of the desired object to instantiate
|
||||
* @return The IDispatch interface pointer if instantiated
|
||||
*/
|
||||
IDispatch CreateInstance(in astring className, in PRBool testScriptability);
|
||||
IDispatch createInstance(in astring className);
|
||||
|
||||
/**
|
||||
* Test if the class is safe to host.
|
||||
* @param clsid The nsID representation of the CLSID to test.
|
||||
* @param classExists Returns containing PR_FALSE if the class is
|
||||
* not registered.
|
||||
*/
|
||||
boolean isClassSafeToHost(in nsCIDRef cid, out boolean classExists);
|
||||
|
||||
/**
|
||||
* Test if the specified class is marked safe for scripting.
|
||||
* @param cid The nsID representation of the CLSID to test.
|
||||
* @param classExists Returns containing PR_FALSE if the class is not
|
||||
* registered.
|
||||
*/
|
||||
boolean isClassMarkedSafeForScripting(in nsCIDRef cid, out boolean classExists);
|
||||
|
||||
/**
|
||||
* Test if the instantiated object is safe for scripting on the specified
|
||||
* interface.
|
||||
* @param theObject The object to test (an IUnknown cast into a void *).
|
||||
* @param iid The interface to test if it is safe for scripting on.
|
||||
*/
|
||||
boolean isObjectSafeForScripting(in voidPtr theObject, in nsIIDRef id);
|
||||
|
||||
/**
|
||||
* Return the ActiveX security and hosting flags. See nsIActiveXSecurityPolicy
|
||||
* for list of flags.
|
||||
* @param context The context for which flags are requested. At present the
|
||||
* only valid value is nsnull.
|
||||
*/
|
||||
unsigned long getHostingFlags(in string aContext);
|
||||
|
||||
};
|
||||
|
||||
%{ C++
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
* XPC_IDispatch_GetterSetter, and XPC_IDispatch_CallMethod
|
||||
*/
|
||||
#include "xpcprivate.h"
|
||||
#include "nsIActiveXSecurityPolicy.h"
|
||||
|
||||
/**
|
||||
* This is COM's IDispatch IID, but in XPCOM's nsID type
|
||||
|
@ -72,88 +73,68 @@ XPCDispObject::WrapIDispatch(IDispatch *pDispatch, XPCCallContext &ccx,
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to determine whether an object has the safe scripting
|
||||
* category
|
||||
* @param the class ID of the COM object to be created
|
||||
* @return true if it has the category
|
||||
*/
|
||||
static PRBool HasSafeScriptingCategory(const CLSID & classID)
|
||||
HRESULT XPCDispObject::COMCreateInstance(BSTR className, PRBool enforceSecurity, IDispatch ** result)
|
||||
{
|
||||
// TODO: probably should look into caching this if this becomes
|
||||
// a performance issue
|
||||
CComPtr<ICatInformation> catInfo;
|
||||
HRESULT hr = catInfo.CoCreateInstance(CLSID_StdComponentCategoriesMgr);
|
||||
// Must fail if we can't open the category manager
|
||||
if(!catInfo)
|
||||
return PR_FALSE;
|
||||
|
||||
// See what categories the class implements
|
||||
CComPtr<IEnumCATID> enumCATID;
|
||||
if(FAILED(catInfo->EnumImplCategoriesOfClass(classID, &enumCATID)))
|
||||
return PR_FALSE; // Can't enumerate classes in category so fail
|
||||
|
||||
// Search for matching categories
|
||||
CATID catidNext = GUID_NULL;
|
||||
// Get the next category, and no, I don't know what the 1 is
|
||||
while(enumCATID->Next(1, &catidNext, NULL) == S_OK)
|
||||
{
|
||||
if(::IsEqualCATID(CATID_SafeForScripting, catidNext))
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* Returns true if the desired scriptable flags are set
|
||||
* @return true if the desired scriptable flags are set
|
||||
*/
|
||||
inline
|
||||
PRBool ScriptOK(DWORD value)
|
||||
{
|
||||
return value & (INTERFACESAFE_FOR_UNTRUSTED_CALLER |
|
||||
INTERFACESAFE_FOR_UNTRUSTED_DATA);
|
||||
}
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDispatchSupport> dispSupport = do_GetService(NS_IDISPATCH_SUPPORT_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return E_UNEXPECTED;
|
||||
|
||||
HRESULT XPCDispObject::COMCreateInstance(BSTR className, PRBool testScriptability, IDispatch ** result)
|
||||
{
|
||||
CLSID classID;
|
||||
HRESULT hr;
|
||||
// If this looks like a class ID
|
||||
if(FAILED(CLSIDFromString(className, &classID)))
|
||||
PRUint32 hostingFlags = nsIActiveXSecurityPolicy::HOSTING_FLAGS_HOST_NOTHING;
|
||||
dispSupport->GetHostingFlags(nsnull, &hostingFlags);
|
||||
|
||||
PRBool allowSafeObjects;
|
||||
if (hostingFlags & (nsIActiveXSecurityPolicy::HOSTING_FLAGS_SCRIPT_SAFE_OBJECTS))
|
||||
allowSafeObjects = PR_TRUE;
|
||||
else
|
||||
allowSafeObjects = PR_FALSE;
|
||||
PRBool allowAnyObjects;
|
||||
if (hostingFlags & (nsIActiveXSecurityPolicy::HOSTING_FLAGS_SCRIPT_ALL_OBJECTS))
|
||||
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)
|
||||
{
|
||||
hr = CLSIDFromProgID(className, &classID);
|
||||
if(FAILED(hr))
|
||||
return hr;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Test if the object is scriptable
|
||||
PRBool isScriptable = PR_FALSE;
|
||||
if(enforceSecurity && !allowAnyObjects)
|
||||
{
|
||||
nsCID cid;
|
||||
memcpy(&cid, &classID, sizeof(nsCID));
|
||||
PRBool classExists = PR_FALSE;
|
||||
dispSupport->IsClassMarkedSafeForScripting(cid, &classExists, &isScriptable);
|
||||
if(!classExists)
|
||||
return REGDB_E_CLASSNOTREG;
|
||||
}
|
||||
PRBool scriptableOK = PR_TRUE;
|
||||
if(testScriptability)
|
||||
scriptableOK = HasSafeScriptingCategory(classID);
|
||||
|
||||
// Didn't have the safe for scripting category so lets look at IObjectSafety
|
||||
// Create the object
|
||||
CComPtr<IDispatch> disp;
|
||||
HRESULT hResult = disp.CoCreateInstance(classID);
|
||||
if(FAILED(hResult))
|
||||
return hResult;
|
||||
hr = disp.CoCreateInstance(classID);
|
||||
if(FAILED(hr))
|
||||
return hr;
|
||||
|
||||
// If we're testing scriptability and it didn't have a scripting category
|
||||
// If we're enforcing security and it didn't have a scripting category
|
||||
// we'll check via the IObjectSafety interface
|
||||
if(testScriptability && !scriptableOK)
|
||||
if(enforceSecurity && !allowAnyObjects && !isScriptable)
|
||||
{
|
||||
CComQIPtr<IObjectSafety> objSafety(disp);
|
||||
// Didn't have IObjectSafety so we'll bail
|
||||
if(!objSafety)
|
||||
return E_FAIL;
|
||||
DWORD supported;
|
||||
DWORD state;
|
||||
hr = objSafety->GetInterfaceSafetyOptions(IID_IDispatch, &supported, &state);
|
||||
if(FAILED(hr))
|
||||
return hr;
|
||||
if(!ScriptOK(supported) || !ScriptOK(state))
|
||||
dispSupport->IsObjectSafeForScripting(disp, NSID_IDISPATCH, &isScriptable);
|
||||
if (!isScriptable)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Copy and addref
|
||||
disp.CopyTo(result);
|
||||
return S_OK;
|
||||
|
|
|
@ -1005,13 +1005,14 @@ public:
|
|||
* Instantiates a COM object given a class ID or a prog ID
|
||||
* @param className a prog ID or a class ID in the form of
|
||||
* {00000000-0000-0000-0000-000000000000}
|
||||
* @param testScriptability if true, this tests the objects for scripting
|
||||
* this tests the category and the IObjectSafety interface
|
||||
* @param enforceSecurity if true, will apply checks to ensure
|
||||
* the object can be created giving the current
|
||||
* security settings.
|
||||
* @param result pointer to the pointer to receive the interface pointer
|
||||
*/
|
||||
static
|
||||
HRESULT COMCreateInstance(BSTR className,
|
||||
PRBool testScriptability, IDispatch ** result);
|
||||
PRBool enforceSecurity, IDispatch ** result);
|
||||
/**
|
||||
* Wraps an IDispatch interface, returning the object as a jsval
|
||||
* @param pDispatch IDispatch pointer
|
||||
|
|
|
@ -42,7 +42,7 @@ PRBool XPCIDispatchExtension::mIsEnabled = PR_TRUE;
|
|||
|
||||
static JSBool
|
||||
CommonConstructor(XPCCallContext &ccx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval, PRBool testScriptability)
|
||||
jsval *rval, PRBool enforceSecurity)
|
||||
{
|
||||
// Check if IDispatch is enabled, fail if not
|
||||
if (!nsXPConnect::IsIDispatchEnabled())
|
||||
|
@ -66,7 +66,7 @@ CommonConstructor(XPCCallContext &ccx, JSObject *obj, uintN argc, jsval *argv,
|
|||
}
|
||||
// Instantiate the desired COM object
|
||||
CComPtr<IDispatch> pDispatch;
|
||||
HRESULT rv = XPCDispObject::COMCreateInstance(bstrClassName, testScriptability, &pDispatch);
|
||||
HRESULT rv = XPCDispObject::COMCreateInstance(bstrClassName, enforceSecurity, &pDispatch);
|
||||
if(FAILED(rv))
|
||||
{
|
||||
XPCThrower::ThrowCOMError(ccx, rv, NS_ERROR_XPC_COM_CREATE_FAILED);
|
||||
|
|
|
@ -43,19 +43,115 @@
|
|||
|
||||
#include "XPCPrivate.h"
|
||||
|
||||
#include "nsIActiveXSecurityPolicy.h"
|
||||
|
||||
static nsresult
|
||||
ClassIsListed(HKEY hkeyRoot, const TCHAR *szKey, const CLSID &clsid, PRBool &listIsEmpty)
|
||||
{
|
||||
// Test if the specified CLSID is found in the specified registry key
|
||||
|
||||
listIsEmpty = PR_FALSE;
|
||||
|
||||
CRegKey keyList;
|
||||
if(keyList.Open(hkeyRoot, szKey, KEY_READ) != ERROR_SUCCESS)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Enumerate CLSIDs looking for this one
|
||||
int i = 0;
|
||||
do {
|
||||
USES_CONVERSION;
|
||||
TCHAR szCLSID[64];
|
||||
const DWORD kBufLength = sizeof(szCLSID) / sizeof(szCLSID[0]);
|
||||
if(::RegEnumKey(keyList, i, szCLSID, kBufLength) != ERROR_SUCCESS)
|
||||
{
|
||||
// An empty list
|
||||
if(i == 0)
|
||||
listIsEmpty = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
szCLSID[kBufLength - 1] = TCHAR('\0');
|
||||
CLSID clsidToCompare = GUID_NULL;
|
||||
if(SUCCEEDED(::CLSIDFromString(T2OLE(szCLSID), &clsidToCompare)) &&
|
||||
::IsEqualCLSID(clsid, clsidToCompare))
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
ClassExists(const CLSID &clsid)
|
||||
{
|
||||
// Test if there is a CLSID entry. If there isn't then obviously
|
||||
// the object doesn't exist.
|
||||
CRegKey key;
|
||||
if(key.Open(HKEY_CLASSES_ROOT, _T("CLSID"), KEY_READ) != ERROR_SUCCESS)
|
||||
return PR_FALSE; // Must fail if we can't even open this!
|
||||
|
||||
LPOLESTR szCLSID = NULL;
|
||||
if(FAILED(StringFromCLSID(clsid, &szCLSID)))
|
||||
return PR_FALSE; // Can't allocate string from CLSID
|
||||
|
||||
USES_CONVERSION;
|
||||
CRegKey keyCLSID;
|
||||
LONG lResult = keyCLSID.Open(key, W2CT(szCLSID), KEY_READ);
|
||||
CoTaskMemFree(szCLSID);
|
||||
if(lResult != ERROR_SUCCESS)
|
||||
return PR_FALSE; // Class doesn't exist
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
ClassImplementsCategory(const CLSID &clsid, const CATID &catid, PRBool &bClassExists)
|
||||
{
|
||||
bClassExists = ClassExists(clsid);
|
||||
// Non existent classes won't implement any category...
|
||||
if(!bClassExists)
|
||||
return PR_FALSE;
|
||||
|
||||
// CLSID exists, so try checking what categories it implements
|
||||
bClassExists = TRUE;
|
||||
CComPtr<ICatInformation> catInfo;
|
||||
HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL,
|
||||
CLSCTX_INPROC_SERVER, __uuidof(ICatInformation), (LPVOID*) &catInfo);
|
||||
if(catInfo == NULL)
|
||||
return PR_FALSE; // Must fail if we can't open the category manager
|
||||
|
||||
// See what categories the class implements
|
||||
CComPtr<IEnumCATID> enumCATID;
|
||||
if(FAILED(catInfo->EnumImplCategoriesOfClass(clsid, &enumCATID)))
|
||||
return PR_FALSE; // Can't enumerate classes in category so fail
|
||||
|
||||
// Search for matching categories
|
||||
BOOL bFound = FALSE;
|
||||
CATID catidNext = GUID_NULL;
|
||||
while (enumCATID->Next(1, &catidNext, NULL) == S_OK)
|
||||
{
|
||||
if(::IsEqualCATID(catid, catidNext))
|
||||
return PR_TRUE; // Match
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsDispatchSupport* nsDispatchSupport::mInstance = nsnull;
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDispatchSupport, nsIDispatchSupport)
|
||||
|
||||
nsDispatchSupport::nsDispatchSupport()
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
/* member initializers and constructor code */
|
||||
NS_INIT_ISUPPORTS();
|
||||
/* member initializers and constructor code */
|
||||
}
|
||||
|
||||
nsDispatchSupport::~nsDispatchSupport()
|
||||
{
|
||||
/* destructor code */
|
||||
/* destructor code */
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -86,6 +182,154 @@ NS_IMETHODIMP nsDispatchSupport::JSVal2COMVariant(jsval val, VARIANT * comvar)
|
|||
return retval;
|
||||
}
|
||||
|
||||
/* boolean isClassSafeToHost (in nsCIDRef clsid, out boolean classExists); */
|
||||
NS_IMETHODIMP nsDispatchSupport::IsClassSafeToHost(const nsCID & cid, PRBool *classExists, PRBool *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
NS_ENSURE_ARG_POINTER(classExists);
|
||||
|
||||
*_retval = PR_FALSE;
|
||||
|
||||
CLSID clsid = XPCDispnsCID2CLSID(cid);
|
||||
|
||||
*classExists = ClassExists(clsid);
|
||||
|
||||
// Test the Internet Explorer black list
|
||||
const TCHAR kIEControlsBlacklist[] = _T("SOFTWARE\\Microsoft\\Internet Explorer\\ActiveX Compatibility");
|
||||
CRegKey keyExplorer;
|
||||
if(keyExplorer.Open(HKEY_LOCAL_MACHINE,
|
||||
kIEControlsBlacklist, KEY_READ) == ERROR_SUCCESS)
|
||||
{
|
||||
LPOLESTR szCLSID = NULL;
|
||||
::StringFromCLSID(clsid, &szCLSID);
|
||||
if(szCLSID)
|
||||
{
|
||||
CRegKey keyCLSID;
|
||||
USES_CONVERSION;
|
||||
if(keyCLSID.Open(keyExplorer, W2T(szCLSID), KEY_READ) == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD dwType = REG_DWORD;
|
||||
DWORD dwFlags = 0;
|
||||
DWORD dwBufSize = sizeof(dwFlags);
|
||||
if(::RegQueryValueEx(keyCLSID, _T("Compatibility Flags"),
|
||||
NULL, &dwType, (LPBYTE) &dwFlags, &dwBufSize) == ERROR_SUCCESS)
|
||||
{
|
||||
// Documented flags for this reg key
|
||||
const DWORD kKillBit = 0x00000400; // MS Knowledge Base 240797
|
||||
if(dwFlags & kKillBit)
|
||||
{
|
||||
::CoTaskMemFree(szCLSID);
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
::CoTaskMemFree(szCLSID);
|
||||
}
|
||||
}
|
||||
|
||||
// Registry keys containing lists of controls that the Gecko explicitly does
|
||||
// or does not support.
|
||||
|
||||
const TCHAR kControlsToDenyKey[] = _T("Software\\Mozilla\\ActiveX\\Blacklist\\CLSID");
|
||||
const TCHAR kControlsToAllowKey[] = _T("Software\\Mozilla\\ActiveX\\Whitelist\\CLSID");
|
||||
|
||||
// Check if the CLSID belongs to a list that the Gecko does not support
|
||||
|
||||
PRBool listIsEmpty = PR_FALSE;
|
||||
if(NS_SUCCEEDED(ClassIsListed(HKEY_LOCAL_MACHINE, kControlsToDenyKey, clsid, listIsEmpty)))
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check if the CLSID is in the whitelist. This test only cares when the whitelist is
|
||||
// non-empty, to indicates that it is being used.
|
||||
|
||||
listIsEmpty = PR_FALSE;
|
||||
if(NS_FAILED(ClassIsListed(HKEY_LOCAL_MACHINE, kControlsToAllowKey, clsid, listIsEmpty)) &&
|
||||
!listIsEmpty)
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*_retval = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* boolean isClassMarkedSafeForScripting (in nsCIDRef clsid, out boolean classExists); */
|
||||
NS_IMETHODIMP nsDispatchSupport::IsClassMarkedSafeForScripting(const nsCID & cid, PRBool *classExists, PRBool *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
NS_ENSURE_ARG_POINTER(classExists);
|
||||
// Test the category the object belongs to
|
||||
CLSID clsid = XPCDispnsCID2CLSID(cid);
|
||||
*_retval = ClassImplementsCategory(clsid, CATID_SafeForScripting, *classExists);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* boolean isObjectSafeForScripting (in voidPtr theObject, in nsIIDRef iid); */
|
||||
NS_IMETHODIMP nsDispatchSupport::IsObjectSafeForScripting(void * theObject, const nsIID & id, PRBool *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(theObject);
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
// Test if the object implements IObjectSafety and is marked safe for scripting
|
||||
IUnknown *pObject = (IUnknown *) theObject;
|
||||
IID iid = XPCDispIID2IID(id);
|
||||
|
||||
// Ask the control if its safe for scripting
|
||||
CComQIPtr<IObjectSafety> objectSafety = pObject;
|
||||
if(!objectSafety)
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DWORD dwSupported = 0; // Supported options (mask)
|
||||
DWORD dwEnabled = 0; // Enabled options
|
||||
|
||||
// Assume scripting via IDispatch
|
||||
if(FAILED(objectSafety->GetInterfaceSafetyOptions(
|
||||
iid, &dwSupported, &dwEnabled)))
|
||||
{
|
||||
// Interface is not safe or failure.
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Test if safe for scripting
|
||||
if(!(dwEnabled & dwSupported) & INTERFACESAFE_FOR_UNTRUSTED_CALLER)
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*_retval = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static const PRUint32 kDefaultHostingFlags =
|
||||
nsIActiveXSecurityPolicy::HOSTING_FLAGS_HOST_NOTHING;
|
||||
|
||||
/* unsigned long getHostingFlags (in string aContext); */
|
||||
NS_IMETHODIMP nsDispatchSupport::GetHostingFlags(const char *aContext, PRUint32 *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
// Ask the activex security policy what the hosting flags are
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIActiveXSecurityPolicy> securityPolicy =
|
||||
do_GetService(NS_IACTIVEXSECURITYPOLICY_CONTRACTID, &rv);
|
||||
if(NS_SUCCEEDED(rv) && securityPolicy)
|
||||
return securityPolicy->GetHostingFlags(aContext, _retval);
|
||||
|
||||
// No policy so use the defaults
|
||||
*_retval = kDefaultHostingFlags;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of an COM object, returning it as an IDispatch interface.
|
||||
* This also allows testing of scriptability.
|
||||
|
@ -97,14 +341,13 @@ NS_IMETHODIMP nsDispatchSupport::JSVal2COMVariant(jsval val, VARIANT * comvar)
|
|||
* @return nsresult
|
||||
*/
|
||||
NS_IMETHODIMP nsDispatchSupport::CreateInstance(const nsAString & className,
|
||||
PRBool testScriptability,
|
||||
IDispatch ** result)
|
||||
{
|
||||
if (!nsXPConnect::IsIDispatchEnabled())
|
||||
return NS_ERROR_XPC_IDISPATCH_NOT_ENABLED;
|
||||
const nsPromiseFlatString & flat = PromiseFlatString(className);
|
||||
CComBSTR name(flat.Length(), flat.get());
|
||||
return XPCDispObject::COMCreateInstance(name, testScriptability, result);
|
||||
return XPCDispObject::COMCreateInstance(name, PR_TRUE, result);
|
||||
}
|
||||
|
||||
nsDispatchSupport* nsDispatchSupport::GetSingleton()
|
||||
|
|
Загрузка…
Ссылка в новой задаче