зеркало из https://github.com/mozilla/gecko-dev.git
Fix 18553 [DOGFOOD] addEventListener allows sniffing keystrokes
Add checks to nsScriptSecurityManager::CheckCanListenTo that take a principal and ensure that the currently executing script code either is from the same origin as that principal or has the UniversalBrowserRead privilege enabled. (chrome code has all privileges enabled by default.) It's okay for the principal passed in to be null. That just signifies a privileged window/document that only can be listened to with privileges. I added GetPrincipal/SetPrincipal methods to nsIEventListenerManager. nsDocument::GetNewListenerManager sets a principal on the listener manager when it creates one. Obviously there are other places that create listener managers, but scripts seem to go through this one. Another change is to save some memory usage. Currently I allocate an array of PolicyType that is NS_DOM_PROP_MAX elements long. Unfortunately, compilers appear to allocate four bytes for each PolicyType, so the array takes around 2400 bytes. I've added changes to use two bit vectors that should consume about 1/16 that space. r=joki There are also changes that push nsnull onto the JSContext stack when entering a nested event loop. r=jband
This commit is contained in:
Родитель
a20778e024
Коммит
51842ef45e
|
@ -58,6 +58,8 @@ interface nsIScriptSecurityManager : nsISupports
|
||||||
*/
|
*/
|
||||||
void CheckLoadURI(in nsIURI from, in nsIURI uri);
|
void CheckLoadURI(in nsIURI from, in nsIURI uri);
|
||||||
|
|
||||||
|
void CheckCanListenTo(in nsIPrincipal principal);
|
||||||
|
|
||||||
boolean HasSubjectPrincipal();
|
boolean HasSubjectPrincipal();
|
||||||
|
|
||||||
nsIPrincipal GetSubjectPrincipal();
|
nsIPrincipal GetSubjectPrincipal();
|
||||||
|
|
|
@ -49,12 +49,6 @@ public:
|
||||||
static nsScriptSecurityManager *
|
static nsScriptSecurityManager *
|
||||||
GetScriptSecurityManager();
|
GetScriptSecurityManager();
|
||||||
|
|
||||||
enum PolicyType {
|
|
||||||
POLICY_TYPE_NONE = 0,
|
|
||||||
POLICY_TYPE_DEFAULT = 1,
|
|
||||||
POLICY_TYPE_PERDOMAIN = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
nsObjectHashtable *mOriginToPolicyMap;
|
nsObjectHashtable *mOriginToPolicyMap;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -68,12 +62,11 @@ private:
|
||||||
CheckPermissions(JSContext *aCx, JSObject *aObj, const char *aCapability,
|
CheckPermissions(JSContext *aCx, JSObject *aObj, const char *aCapability,
|
||||||
PRBool* result);
|
PRBool* result);
|
||||||
PRInt32
|
PRInt32
|
||||||
GetSecurityLevel(JSContext *cx, nsDOMProp domProp, PolicyType type,
|
GetSecurityLevel(JSContext *cx, nsDOMProp domProp, PRBool isWrite,
|
||||||
PRBool isWrite, char **capability);
|
char **capability);
|
||||||
|
|
||||||
NS_IMETHOD
|
NS_IMETHOD
|
||||||
GetPrefName(JSContext *cx, nsDOMProp domProp, PolicyType type,
|
GetPrefName(JSContext *cx, nsDOMProp domProp, char **result);
|
||||||
char **result);
|
|
||||||
|
|
||||||
NS_IMETHOD
|
NS_IMETHOD
|
||||||
CheckXPCPermissions(JSContext *cx);
|
CheckXPCPermissions(JSContext *cx);
|
||||||
|
@ -81,9 +74,13 @@ private:
|
||||||
NS_IMETHOD
|
NS_IMETHOD
|
||||||
InitFromPrefs();
|
InitFromPrefs();
|
||||||
|
|
||||||
|
static void
|
||||||
|
enumeratePolicyCallback(const char *prefName, void *data);
|
||||||
|
|
||||||
nsIPrincipal *mSystemPrincipal;
|
nsIPrincipal *mSystemPrincipal;
|
||||||
nsSupportsHashtable *mPrincipals;
|
nsSupportsHashtable *mPrincipals;
|
||||||
PolicyType domPropertyPolicyTypes[NS_DOM_PROP_MAX];
|
unsigned char hasPolicyVector[(NS_DOM_PROP_MAX >> 3) + 1];
|
||||||
|
unsigned char hasDomainPolicyVector[(NS_DOM_PROP_MAX >> 3) + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*_NS_SCRIPT_SECURITY_MANAGER_H_*/
|
#endif /*_NS_SCRIPT_SECURITY_MANAGER_H_*/
|
||||||
|
|
|
@ -147,6 +147,10 @@ nsCodebasePrincipal::SameOrigin(nsIPrincipal *other, PRBool *result)
|
||||||
*result = PR_TRUE;
|
*result = PR_TRUE;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
if (other == nsnull) {
|
||||||
|
*result = PR_FALSE;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
nsCOMPtr<nsICodebasePrincipal> otherCodebase;
|
nsCOMPtr<nsICodebasePrincipal> otherCodebase;
|
||||||
if (NS_FAILED(other->QueryInterface(
|
if (NS_FAILED(other->QueryInterface(
|
||||||
NS_GET_IID(nsICodebasePrincipal),
|
NS_GET_IID(nsICodebasePrincipal),
|
||||||
|
|
|
@ -325,6 +325,20 @@ nsScriptSecurityManager::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||||
NS_IMPL_ADDREF(nsScriptSecurityManager);
|
NS_IMPL_ADDREF(nsScriptSecurityManager);
|
||||||
NS_IMPL_RELEASE(nsScriptSecurityManager);
|
NS_IMPL_RELEASE(nsScriptSecurityManager);
|
||||||
|
|
||||||
|
inline PRBool
|
||||||
|
GetBit(unsigned char *bitVector, PRInt32 index)
|
||||||
|
{
|
||||||
|
unsigned char c = bitVector[index >> 3];
|
||||||
|
c &= (1 << (index & 7));
|
||||||
|
return c != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
SetBit(unsigned char *bitVector, PRInt32 index)
|
||||||
|
{
|
||||||
|
bitVector[index >> 3] |= (1 << (index & 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////
|
///////////////////////////////////////////////////
|
||||||
// Methods implementing nsIScriptSecurityManager //
|
// Methods implementing nsIScriptSecurityManager //
|
||||||
|
@ -337,14 +351,14 @@ nsScriptSecurityManager::CheckScriptAccess(nsIScriptContext *aContext,
|
||||||
{
|
{
|
||||||
nsDOMProp domProp = (nsDOMProp) domPropInt;
|
nsDOMProp domProp = (nsDOMProp) domPropInt;
|
||||||
*aResult = PR_FALSE;
|
*aResult = PR_FALSE;
|
||||||
PolicyType type = domPropertyPolicyTypes[domProp];
|
if (!GetBit(hasPolicyVector, domPropInt)) {
|
||||||
if (type == POLICY_TYPE_NONE) {
|
// No policy for this DOM property, so just allow access.
|
||||||
*aResult = PR_TRUE;
|
*aResult = PR_TRUE;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
JSContext *cx = (JSContext *)aContext->GetNativeContext();
|
JSContext *cx = (JSContext *)aContext->GetNativeContext();
|
||||||
nsXPIDLCString capability;
|
nsXPIDLCString capability;
|
||||||
PRInt32 secLevel = GetSecurityLevel(cx, domProp, type, isWrite,
|
PRInt32 secLevel = GetSecurityLevel(cx, domProp, isWrite,
|
||||||
getter_Copies(capability));
|
getter_Copies(capability));
|
||||||
switch (secLevel) {
|
switch (secLevel) {
|
||||||
case SCRIPT_SECURITY_ALL_ACCESS:
|
case SCRIPT_SECURITY_ALL_ACCESS:
|
||||||
|
@ -463,6 +477,37 @@ nsScriptSecurityManager::CheckLoadURI(nsIURI *aFromURI,
|
||||||
return NS_ERROR_DOM_BAD_URI;
|
return NS_ERROR_DOM_BAD_URI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsScriptSecurityManager::CheckCanListenTo(nsIPrincipal *principal)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIPrincipal> subject;
|
||||||
|
nsresult rv;
|
||||||
|
PRBool hasSubject;
|
||||||
|
if (NS_FAILED(rv = HasSubjectPrincipal(&hasSubject)))
|
||||||
|
return rv;
|
||||||
|
if (!hasSubject)
|
||||||
|
return NS_OK; // No script code, so native code has access.
|
||||||
|
if (NS_FAILED(rv = GetSubjectPrincipal(getter_AddRefs(subject))))
|
||||||
|
return rv;
|
||||||
|
nsCOMPtr<nsICodebasePrincipal> codebase = do_QueryInterface(subject);
|
||||||
|
PRBool equals;
|
||||||
|
if (codebase && NS_SUCCEEDED(codebase->SameOrigin(principal, &equals))) {
|
||||||
|
if (equals)
|
||||||
|
return NS_OK; // Listener and Listened-to have same origin
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool enabled;
|
||||||
|
if (NS_SUCCEEDED(IsCapabilityEnabled("UniversalBrowserRead", &enabled))) {
|
||||||
|
if (enabled)
|
||||||
|
return NS_OK; // Capability allows access
|
||||||
|
}
|
||||||
|
|
||||||
|
// Report error
|
||||||
|
JSContext *cx = GetCurrentContext();
|
||||||
|
JS_ReportError(cx, "Access denied to listen to events across origins");
|
||||||
|
return NS_ERROR_DOM_PROP_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsScriptSecurityManager::HasSubjectPrincipal(PRBool *result)
|
nsScriptSecurityManager::HasSubjectPrincipal(PRBool *result)
|
||||||
{
|
{
|
||||||
|
@ -810,7 +855,8 @@ nsScriptSecurityManager::nsScriptSecurityManager(void)
|
||||||
mPrincipals(nsnull)
|
mPrincipals(nsnull)
|
||||||
{
|
{
|
||||||
NS_INIT_REFCNT();
|
NS_INIT_REFCNT();
|
||||||
memset(domPropertyPolicyTypes, 0, sizeof(domPropertyPolicyTypes));
|
memset(hasPolicyVector, 0, sizeof(hasPolicyVector));
|
||||||
|
memset(hasDomainPolicyVector, 0, sizeof(hasDomainPolicyVector));
|
||||||
InitFromPrefs();
|
InitFromPrefs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -948,11 +994,10 @@ nsScriptSecurityManager::CheckPermissions(JSContext *aCx, JSObject *aObj,
|
||||||
|
|
||||||
PRInt32
|
PRInt32
|
||||||
nsScriptSecurityManager::GetSecurityLevel(JSContext *cx, nsDOMProp domProp,
|
nsScriptSecurityManager::GetSecurityLevel(JSContext *cx, nsDOMProp domProp,
|
||||||
PolicyType type, PRBool isWrite,
|
PRBool isWrite, char **capability)
|
||||||
char **capability)
|
|
||||||
{
|
{
|
||||||
nsXPIDLCString prefName;
|
nsXPIDLCString prefName;
|
||||||
if (NS_FAILED(GetPrefName(cx, domProp, type, getter_Copies(prefName))))
|
if (NS_FAILED(GetPrefName(cx, domProp, getter_Copies(prefName))))
|
||||||
return SCRIPT_SECURITY_NO_ACCESS;
|
return SCRIPT_SECURITY_NO_ACCESS;
|
||||||
PRInt32 secLevel;
|
PRInt32 secLevel;
|
||||||
char *secLevelString;
|
char *secLevelString;
|
||||||
|
@ -1893,14 +1938,14 @@ static char *domPropNames[NS_DOM_PROP_MAX] = {
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsScriptSecurityManager::GetPrefName(JSContext *cx, nsDOMProp domProp,
|
nsScriptSecurityManager::GetPrefName(JSContext *cx, nsDOMProp domProp,
|
||||||
PolicyType type, char **result)
|
char **result)
|
||||||
{
|
{
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
static const char *defaultStr = "default";
|
static const char *defaultStr = "default";
|
||||||
nsAutoString s = "security.policy.";
|
nsAutoString s = "security.policy.";
|
||||||
if (type == POLICY_TYPE_DEFAULT) {
|
if (!GetBit(hasDomainPolicyVector, domProp)) {
|
||||||
s += defaultStr;
|
s += defaultStr;
|
||||||
} else if (type == POLICY_TYPE_PERDOMAIN) {
|
} else {
|
||||||
nsCOMPtr<nsIPrincipal> principal;
|
nsCOMPtr<nsIPrincipal> principal;
|
||||||
if (NS_FAILED(GetSubjectPrincipal(cx, getter_AddRefs(principal)))) {
|
if (NS_FAILED(GetSubjectPrincipal(cx, getter_AddRefs(principal)))) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
@ -1963,13 +2008,14 @@ DeleteEntry(nsHashKey *aKey, void *aData, void* closure)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PolicyEnumeratorInfo {
|
struct PolicyEnumeratorInfo {
|
||||||
nsScriptSecurityManager::PolicyType *policies;
|
|
||||||
nsIPref *prefs;
|
nsIPref *prefs;
|
||||||
nsScriptSecurityManager *secMan;
|
nsScriptSecurityManager *secMan;
|
||||||
};
|
};
|
||||||
|
|
||||||
PR_STATIC_CALLBACK(void)
|
void
|
||||||
enumeratePolicy(const char *prefName, void *data) {
|
nsScriptSecurityManager::enumeratePolicyCallback(const char *prefName,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
if (!prefName || !*prefName)
|
if (!prefName || !*prefName)
|
||||||
return;
|
return;
|
||||||
PolicyEnumeratorInfo *info = (PolicyEnumeratorInfo *) data;
|
PolicyEnumeratorInfo *info = (PolicyEnumeratorInfo *) data;
|
||||||
|
@ -2029,12 +2075,9 @@ enumeratePolicy(const char *prefName, void *data) {
|
||||||
int domPropLength = dots[4] - domPropName;
|
int domPropLength = dots[4] - domPropName;
|
||||||
nsDOMProp domProp = findDomProp(domPropName, domPropLength);
|
nsDOMProp domProp = findDomProp(domPropName, domPropLength);
|
||||||
if (domProp < NS_DOM_PROP_MAX) {
|
if (domProp < NS_DOM_PROP_MAX) {
|
||||||
nsScriptSecurityManager::PolicyType *policyType =
|
SetBit(info->secMan->hasPolicyVector, domProp);
|
||||||
info->policies + domProp;
|
|
||||||
if (!isDefault)
|
if (!isDefault)
|
||||||
*policyType = nsScriptSecurityManager::POLICY_TYPE_PERDOMAIN;
|
SetBit(info->secMan->hasDomainPolicyVector, domProp);
|
||||||
else if (*policyType == nsScriptSecurityManager::POLICY_TYPE_NONE)
|
|
||||||
*policyType = nsScriptSecurityManager::POLICY_TYPE_DEFAULT;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2049,10 +2092,10 @@ nsScriptSecurityManager::InitFromPrefs()
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
PolicyEnumeratorInfo info;
|
PolicyEnumeratorInfo info;
|
||||||
info.policies = domPropertyPolicyTypes;
|
|
||||||
info.prefs = prefs;
|
info.prefs = prefs;
|
||||||
info.secMan = this;
|
info.secMan = this;
|
||||||
prefs->EnumerateChildren("security.policy", enumeratePolicy,
|
prefs->EnumerateChildren("security.policy",
|
||||||
|
nsScriptSecurityManager::enumeratePolicyCallback,
|
||||||
(void *) &info);
|
(void *) &info);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2334,9 +2334,9 @@ nsDocument::GetOwnerDocument(nsIDOMDocument** aOwnerDocument)
|
||||||
nsresult nsDocument::GetListenerManager(nsIEventListenerManager **aInstancePtrResult)
|
nsresult nsDocument::GetListenerManager(nsIEventListenerManager **aInstancePtrResult)
|
||||||
{
|
{
|
||||||
if (nsnull != mListenerManager) {
|
if (nsnull != mListenerManager) {
|
||||||
return mListenerManager->QueryInterface(kIEventListenerManagerIID, (void**) aInstancePtrResult);;
|
return mListenerManager->QueryInterface(kIEventListenerManagerIID, (void**) aInstancePtrResult);
|
||||||
}
|
}
|
||||||
if (NS_OK == NS_NewEventListenerManager(aInstancePtrResult)) {
|
if (NS_OK == GetNewListenerManager(aInstancePtrResult)) {
|
||||||
mListenerManager = *aInstancePtrResult;
|
mListenerManager = *aInstancePtrResult;
|
||||||
NS_ADDREF(mListenerManager);
|
NS_ADDREF(mListenerManager);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -2346,7 +2346,15 @@ nsresult nsDocument::GetListenerManager(nsIEventListenerManager **aInstancePtrRe
|
||||||
|
|
||||||
nsresult nsDocument::GetNewListenerManager(nsIEventListenerManager **aInstancePtrResult)
|
nsresult nsDocument::GetNewListenerManager(nsIEventListenerManager **aInstancePtrResult)
|
||||||
{
|
{
|
||||||
return NS_NewEventListenerManager(aInstancePtrResult);
|
nsresult rv = NS_NewEventListenerManager(aInstancePtrResult);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
nsIPrincipal *principal = GetDocumentPrincipal();
|
||||||
|
if (principal) {
|
||||||
|
(*aInstancePtrResult)->SetPrincipal(principal);
|
||||||
|
NS_RELEASE(principal);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsDocument::HandleDOMEvent(nsIPresContext* aPresContext,
|
nsresult nsDocument::HandleDOMEvent(nsIPresContext* aPresContext,
|
||||||
|
|
|
@ -138,11 +138,26 @@ public:
|
||||||
virtual nsresult ReleaseEvent(nsIDOMEventListener *aListener) = 0;
|
virtual nsresult ReleaseEvent(nsIDOMEventListener *aListener) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all events listeners registered by this instance of the listener
|
* Removes all event listeners registered by this instance of the listener
|
||||||
* manager.
|
* manager.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
virtual nsresult RemoveAllListeners(PRBool aScriptOnly) = 0;
|
virtual nsresult RemoveAllListeners(PRBool aScriptOnly) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the principal of the entity being listened to.
|
||||||
|
*
|
||||||
|
* Used for security checks that ensure that events can't propagate past
|
||||||
|
* trust boundaries.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual nsresult SetPrincipal(nsIPrincipal *aListenedToPrincipal) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the principal of the entity being listened to.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual nsresult GetPrincipal(nsIPrincipal **aListenedToPrincipal) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern NS_HTML nsresult NS_NewEventListenerManager(nsIEventListenerManager** aInstancePtrResult);
|
extern NS_HTML nsresult NS_NewEventListenerManager(nsIEventListenerManager** aInstancePtrResult);
|
||||||
|
|
|
@ -50,6 +50,8 @@
|
||||||
#include "nsINameSpaceManager.h"
|
#include "nsINameSpaceManager.h"
|
||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsIServiceManager.h"
|
||||||
|
#include "nsIScriptSecurityManager.h"
|
||||||
|
|
||||||
static NS_DEFINE_IID(kIEventListenerManagerIID, NS_IEVENTLISTENERMANAGER_IID);
|
static NS_DEFINE_IID(kIEventListenerManagerIID, NS_IEVENTLISTENERMANAGER_IID);
|
||||||
static NS_DEFINE_IID(kIDOMEventListenerIID, NS_IDOMEVENTLISTENER_IID);
|
static NS_DEFINE_IID(kIDOMEventListenerIID, NS_IDOMEVENTLISTENER_IID);
|
||||||
|
@ -235,6 +237,15 @@ nsresult nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener
|
||||||
NS_IF_RELEASE(sel);
|
NS_IF_RELEASE(sel);
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
|
// Check to see if we can add a new listener.
|
||||||
|
nsresult rv;
|
||||||
|
NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager,
|
||||||
|
NS_SCRIPTSECURITYMANAGER_PROGID, &rv);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
rv = securityManager->CheckCanListenTo(mPrincipal);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
ls = PR_NEW(nsListenerStruct);
|
ls = PR_NEW(nsListenerStruct);
|
||||||
if (ls) {
|
if (ls) {
|
||||||
ls->mListener = aListener;
|
ls->mListener = aListener;
|
||||||
|
@ -1416,6 +1427,20 @@ nsresult nsEventListenerManager::RemoveAllListeners(PRBool aScriptOnly)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult nsEventListenerManager::GetPrincipal(nsIPrincipal **aListenedToPrincipal)
|
||||||
|
{
|
||||||
|
*aListenedToPrincipal = mPrincipal;
|
||||||
|
if (*aListenedToPrincipal)
|
||||||
|
NS_ADDREF(*aListenedToPrincipal);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult nsEventListenerManager::SetPrincipal(nsIPrincipal *aListenedToPrincipal)
|
||||||
|
{
|
||||||
|
mPrincipal = aListenedToPrincipal;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
NS_HTML nsresult NS_NewEventListenerManager(nsIEventListenerManager** aInstancePtrResult)
|
NS_HTML nsresult NS_NewEventListenerManager(nsIEventListenerManager** aInstancePtrResult)
|
||||||
{
|
{
|
||||||
nsIEventListenerManager* l = new nsEventListenerManager();
|
nsIEventListenerManager* l = new nsEventListenerManager();
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
#include "nsIEventListenerManager.h"
|
#include "nsIEventListenerManager.h"
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsIPrincipal.h"
|
||||||
|
|
||||||
class nsIDOMEvent;
|
class nsIDOMEvent;
|
||||||
class nsIAtom;
|
class nsIAtom;
|
||||||
|
@ -97,6 +99,9 @@ public:
|
||||||
|
|
||||||
virtual nsresult RemoveAllListeners(PRBool aScriptOnly);
|
virtual nsresult RemoveAllListeners(PRBool aScriptOnly);
|
||||||
|
|
||||||
|
virtual nsresult SetPrincipal(nsIPrincipal *aListenedToPrincipal);
|
||||||
|
virtual nsresult GetPrincipal(nsIPrincipal **aListenedToPrincipal);
|
||||||
|
|
||||||
static nsresult GetIdentifiersForType(nsIAtom* aType, nsIID& aIID, PRInt32* aSubType);
|
static nsresult GetIdentifiersForType(nsIAtom* aType, nsIID& aIID, PRInt32* aSubType);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -121,10 +126,11 @@ protected:
|
||||||
nsVoidArray* mTextListeners;
|
nsVoidArray* mTextListeners;
|
||||||
nsVoidArray* mCompositionListeners;
|
nsVoidArray* mCompositionListeners;
|
||||||
nsVoidArray* mMenuListeners;
|
nsVoidArray* mMenuListeners;
|
||||||
|
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//Set of defines for distinguishing event hanlders within listener groupings
|
//Set of defines for distinguishing event handlers within listener groupings
|
||||||
//XXX Current usage allows no more than 7 types per listener grouping
|
//XXX Current usage allows no more than 7 types per listener grouping
|
||||||
|
|
||||||
#define NS_EVENT_BITS_NONE 0x00
|
#define NS_EVENT_BITS_NONE 0x00
|
||||||
|
|
|
@ -1009,7 +1009,7 @@ static const char kMethodBodyBeginStr[] = "\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" PRBool ok;\n"
|
" PRBool ok;\n"
|
||||||
" secMan->CheckScriptAccess(scriptCX, obj, NS_DOM_PROP_%s_%s,PR_FALSE , &ok);\n"
|
" secMan->CheckScriptAccess(scriptCX, obj, NS_DOM_PROP_%s_%s, PR_FALSE, &ok);\n"
|
||||||
" if (!ok) {\n"
|
" if (!ok) {\n"
|
||||||
" return nsJSUtils::nsReportError(cx, NS_ERROR_DOM_SECURITY_ERR);\n"
|
" return nsJSUtils::nsReportError(cx, NS_ERROR_DOM_SECURITY_ERR);\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
|
|
|
@ -2334,9 +2334,9 @@ nsDocument::GetOwnerDocument(nsIDOMDocument** aOwnerDocument)
|
||||||
nsresult nsDocument::GetListenerManager(nsIEventListenerManager **aInstancePtrResult)
|
nsresult nsDocument::GetListenerManager(nsIEventListenerManager **aInstancePtrResult)
|
||||||
{
|
{
|
||||||
if (nsnull != mListenerManager) {
|
if (nsnull != mListenerManager) {
|
||||||
return mListenerManager->QueryInterface(kIEventListenerManagerIID, (void**) aInstancePtrResult);;
|
return mListenerManager->QueryInterface(kIEventListenerManagerIID, (void**) aInstancePtrResult);
|
||||||
}
|
}
|
||||||
if (NS_OK == NS_NewEventListenerManager(aInstancePtrResult)) {
|
if (NS_OK == GetNewListenerManager(aInstancePtrResult)) {
|
||||||
mListenerManager = *aInstancePtrResult;
|
mListenerManager = *aInstancePtrResult;
|
||||||
NS_ADDREF(mListenerManager);
|
NS_ADDREF(mListenerManager);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -2346,7 +2346,15 @@ nsresult nsDocument::GetListenerManager(nsIEventListenerManager **aInstancePtrRe
|
||||||
|
|
||||||
nsresult nsDocument::GetNewListenerManager(nsIEventListenerManager **aInstancePtrResult)
|
nsresult nsDocument::GetNewListenerManager(nsIEventListenerManager **aInstancePtrResult)
|
||||||
{
|
{
|
||||||
return NS_NewEventListenerManager(aInstancePtrResult);
|
nsresult rv = NS_NewEventListenerManager(aInstancePtrResult);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
nsIPrincipal *principal = GetDocumentPrincipal();
|
||||||
|
if (principal) {
|
||||||
|
(*aInstancePtrResult)->SetPrincipal(principal);
|
||||||
|
NS_RELEASE(principal);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsDocument::HandleDOMEvent(nsIPresContext* aPresContext,
|
nsresult nsDocument::HandleDOMEvent(nsIPresContext* aPresContext,
|
||||||
|
|
|
@ -138,11 +138,26 @@ public:
|
||||||
virtual nsresult ReleaseEvent(nsIDOMEventListener *aListener) = 0;
|
virtual nsresult ReleaseEvent(nsIDOMEventListener *aListener) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all events listeners registered by this instance of the listener
|
* Removes all event listeners registered by this instance of the listener
|
||||||
* manager.
|
* manager.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
virtual nsresult RemoveAllListeners(PRBool aScriptOnly) = 0;
|
virtual nsresult RemoveAllListeners(PRBool aScriptOnly) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the principal of the entity being listened to.
|
||||||
|
*
|
||||||
|
* Used for security checks that ensure that events can't propagate past
|
||||||
|
* trust boundaries.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual nsresult SetPrincipal(nsIPrincipal *aListenedToPrincipal) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the principal of the entity being listened to.
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual nsresult GetPrincipal(nsIPrincipal **aListenedToPrincipal) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern NS_HTML nsresult NS_NewEventListenerManager(nsIEventListenerManager** aInstancePtrResult);
|
extern NS_HTML nsresult NS_NewEventListenerManager(nsIEventListenerManager** aInstancePtrResult);
|
||||||
|
|
|
@ -50,6 +50,8 @@
|
||||||
#include "nsINameSpaceManager.h"
|
#include "nsINameSpaceManager.h"
|
||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsIServiceManager.h"
|
||||||
|
#include "nsIScriptSecurityManager.h"
|
||||||
|
|
||||||
static NS_DEFINE_IID(kIEventListenerManagerIID, NS_IEVENTLISTENERMANAGER_IID);
|
static NS_DEFINE_IID(kIEventListenerManagerIID, NS_IEVENTLISTENERMANAGER_IID);
|
||||||
static NS_DEFINE_IID(kIDOMEventListenerIID, NS_IDOMEVENTLISTENER_IID);
|
static NS_DEFINE_IID(kIDOMEventListenerIID, NS_IDOMEVENTLISTENER_IID);
|
||||||
|
@ -235,6 +237,15 @@ nsresult nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener
|
||||||
NS_IF_RELEASE(sel);
|
NS_IF_RELEASE(sel);
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
|
// Check to see if we can add a new listener.
|
||||||
|
nsresult rv;
|
||||||
|
NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager,
|
||||||
|
NS_SCRIPTSECURITYMANAGER_PROGID, &rv);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
rv = securityManager->CheckCanListenTo(mPrincipal);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
ls = PR_NEW(nsListenerStruct);
|
ls = PR_NEW(nsListenerStruct);
|
||||||
if (ls) {
|
if (ls) {
|
||||||
ls->mListener = aListener;
|
ls->mListener = aListener;
|
||||||
|
@ -1416,6 +1427,20 @@ nsresult nsEventListenerManager::RemoveAllListeners(PRBool aScriptOnly)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult nsEventListenerManager::GetPrincipal(nsIPrincipal **aListenedToPrincipal)
|
||||||
|
{
|
||||||
|
*aListenedToPrincipal = mPrincipal;
|
||||||
|
if (*aListenedToPrincipal)
|
||||||
|
NS_ADDREF(*aListenedToPrincipal);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult nsEventListenerManager::SetPrincipal(nsIPrincipal *aListenedToPrincipal)
|
||||||
|
{
|
||||||
|
mPrincipal = aListenedToPrincipal;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
NS_HTML nsresult NS_NewEventListenerManager(nsIEventListenerManager** aInstancePtrResult)
|
NS_HTML nsresult NS_NewEventListenerManager(nsIEventListenerManager** aInstancePtrResult)
|
||||||
{
|
{
|
||||||
nsIEventListenerManager* l = new nsEventListenerManager();
|
nsIEventListenerManager* l = new nsEventListenerManager();
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
#include "nsIEventListenerManager.h"
|
#include "nsIEventListenerManager.h"
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsIPrincipal.h"
|
||||||
|
|
||||||
class nsIDOMEvent;
|
class nsIDOMEvent;
|
||||||
class nsIAtom;
|
class nsIAtom;
|
||||||
|
@ -97,6 +99,9 @@ public:
|
||||||
|
|
||||||
virtual nsresult RemoveAllListeners(PRBool aScriptOnly);
|
virtual nsresult RemoveAllListeners(PRBool aScriptOnly);
|
||||||
|
|
||||||
|
virtual nsresult SetPrincipal(nsIPrincipal *aListenedToPrincipal);
|
||||||
|
virtual nsresult GetPrincipal(nsIPrincipal **aListenedToPrincipal);
|
||||||
|
|
||||||
static nsresult GetIdentifiersForType(nsIAtom* aType, nsIID& aIID, PRInt32* aSubType);
|
static nsresult GetIdentifiersForType(nsIAtom* aType, nsIID& aIID, PRInt32* aSubType);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -121,10 +126,11 @@ protected:
|
||||||
nsVoidArray* mTextListeners;
|
nsVoidArray* mTextListeners;
|
||||||
nsVoidArray* mCompositionListeners;
|
nsVoidArray* mCompositionListeners;
|
||||||
nsVoidArray* mMenuListeners;
|
nsVoidArray* mMenuListeners;
|
||||||
|
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//Set of defines for distinguishing event hanlders within listener groupings
|
//Set of defines for distinguishing event handlers within listener groupings
|
||||||
//XXX Current usage allows no more than 7 types per listener grouping
|
//XXX Current usage allows no more than 7 types per listener grouping
|
||||||
|
|
||||||
#define NS_EVENT_BITS_NONE 0x00
|
#define NS_EVENT_BITS_NONE 0x00
|
||||||
|
|
|
@ -35,6 +35,7 @@ DEPTH=..\..\..
|
||||||
IDLSRCS= \
|
IDLSRCS= \
|
||||||
AppCoresManager.idl \
|
AppCoresManager.idl \
|
||||||
BaseAppCore.idl \
|
BaseAppCore.idl \
|
||||||
|
BrowserAppCore.idl \
|
||||||
ToolkitCore.idl
|
ToolkitCore.idl
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,7 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||||
|
|
||||||
// For JS Execution
|
// For JS Execution
|
||||||
#include "nsIScriptContextOwner.h"
|
#include "nsIScriptContextOwner.h"
|
||||||
|
#include "nsIJSContextStack.h"
|
||||||
|
|
||||||
#include "nsIEventQueueService.h"
|
#include "nsIEventQueueService.h"
|
||||||
#include "plevent.h"
|
#include "plevent.h"
|
||||||
|
@ -1554,14 +1555,25 @@ nsWebShellWindow::NewWebShell(PRUint32 aChromeMask, PRBool aVisible,
|
||||||
PRBool locked = PR_FALSE;
|
PRBool locked = PR_FALSE;
|
||||||
nsresult looprv = NS_OK;
|
nsresult looprv = NS_OK;
|
||||||
newWindow->GetLockedState(locked);
|
newWindow->GetLockedState(locked);
|
||||||
while (NS_SUCCEEDED(looprv) && locked) {
|
|
||||||
void *data;
|
|
||||||
PRBool isRealEvent;
|
|
||||||
|
|
||||||
looprv = subshell->GetNativeEvent(isRealEvent, data);
|
|
||||||
subshell->DispatchNativeEvent(isRealEvent, data);
|
|
||||||
|
|
||||||
newWindow->GetLockedState(locked);
|
// Push nsnull onto the JSContext stack before we dispatch a native event.
|
||||||
|
NS_WITH_SERVICE(nsIJSContextStack, stack, "nsThreadJSContextStack",
|
||||||
|
&rv);
|
||||||
|
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(stack->Push(nsnull))) {
|
||||||
|
|
||||||
|
while (NS_SUCCEEDED(looprv) && locked) {
|
||||||
|
void *data;
|
||||||
|
PRBool isRealEvent;
|
||||||
|
|
||||||
|
looprv = subshell->GetNativeEvent(isRealEvent, data);
|
||||||
|
subshell->DispatchNativeEvent(isRealEvent, data);
|
||||||
|
|
||||||
|
newWindow->GetLockedState(locked);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSContext *cx;
|
||||||
|
stack->Pop(&cx);
|
||||||
|
NS_ASSERTION(cx == nsnull, "JSContextStack mismatch");
|
||||||
}
|
}
|
||||||
|
|
||||||
subshell->Spindown();
|
subshell->Spindown();
|
||||||
|
@ -1737,17 +1749,28 @@ nsWebShellWindow::ShowModalInternal()
|
||||||
window->SetModal(PR_TRUE);
|
window->SetModal(PR_TRUE);
|
||||||
NS_ADDREF(window);
|
NS_ADDREF(window);
|
||||||
mContinueModalLoop = PR_TRUE;
|
mContinueModalLoop = PR_TRUE;
|
||||||
while (NS_SUCCEEDED(rv) && mContinueModalLoop) {
|
|
||||||
void *data;
|
|
||||||
PRBool isRealEvent,
|
|
||||||
processEvent;
|
|
||||||
|
|
||||||
rv = subshell->GetNativeEvent(isRealEvent, data);
|
// Push nsnull onto the JSContext stack before we dispatch a native event.
|
||||||
if (NS_SUCCEEDED(rv)) {
|
NS_WITH_SERVICE(nsIJSContextStack, stack, "nsThreadJSContextStack",
|
||||||
window->ModalEventFilter(isRealEvent, data, &processEvent);
|
&rv);
|
||||||
if (processEvent)
|
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(stack->Push(nsnull))) {
|
||||||
subshell->DispatchNativeEvent(isRealEvent, data);
|
|
||||||
|
while (NS_SUCCEEDED(rv) && mContinueModalLoop) {
|
||||||
|
void *data;
|
||||||
|
PRBool isRealEvent,
|
||||||
|
processEvent;
|
||||||
|
|
||||||
|
rv = subshell->GetNativeEvent(isRealEvent, data);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
window->ModalEventFilter(isRealEvent, data, &processEvent);
|
||||||
|
if (processEvent)
|
||||||
|
subshell->DispatchNativeEvent(isRealEvent, data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSContext *cx;
|
||||||
|
stack->Pop(&cx);
|
||||||
|
NS_ASSERTION(cx == nsnull, "JSContextStack mismatch");
|
||||||
}
|
}
|
||||||
|
|
||||||
window->SetModal(PR_FALSE);
|
window->SetModal(PR_FALSE);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче