diff --git a/content/events/public/nsIPrivateDOMEvent.h b/content/events/public/nsIPrivateDOMEvent.h index cf4b4e2504e..1b451c1dafc 100644 --- a/content/events/public/nsIPrivateDOMEvent.h +++ b/content/events/public/nsIPrivateDOMEvent.h @@ -67,6 +67,8 @@ public: NS_IMETHOD IsDispatchStopped(PRBool* aIsDispatchPrevented) = 0; NS_IMETHOD GetInternalNSEvent(nsEvent** aNSEvent) = 0; NS_IMETHOD HasOriginalTarget(PRBool* aResult)=0; + NS_IMETHOD IsTrustedEvent(PRBool* aResult)=0; + NS_IMETHOD SetTrusted(PRBool aTrusted)=0; }; extern nsresult NS_NewDOMEvent(nsIDOMEvent** aInstancePtrResult, nsIPresContext* aPresContext, nsEvent *aEvent); diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index d094061d464..d006c11c717 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -151,11 +151,13 @@ nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, NS_INIT_REFCNT(); mPresContext = aPresContext; + mEventIsTrusted = PR_FALSE; NS_IF_ADDREF(mPresContext); if (aEvent) { mEvent = aEvent; + mEventIsTrusted = PR_TRUE; } else { mEventIsInternal = PR_TRUE; @@ -375,6 +377,20 @@ nsDOMEvent::HasOriginalTarget(PRBool* aResult) return NS_OK; } +NS_IMETHODIMP +nsDOMEvent::IsTrustedEvent(PRBool* aResult) +{ + *aResult = mEventIsTrusted; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMEvent::SetTrusted(PRBool aTrusted) +{ + mEventIsTrusted = aTrusted; + return NS_OK; +} + NS_IMETHODIMP nsDOMEvent::GetEventPhase(PRUint16* aEventPhase) { diff --git a/content/events/src/nsDOMEvent.h b/content/events/src/nsDOMEvent.h index 2f652be01ca..8c61fd7af3b 100644 --- a/content/events/src/nsDOMEvent.h +++ b/content/events/src/nsDOMEvent.h @@ -195,6 +195,8 @@ public: NS_IMETHOD IsDispatchStopped(PRBool* aIsDispatchStopped); NS_IMETHOD GetInternalNSEvent(nsEvent** aNSEvent); NS_IMETHOD HasOriginalTarget(PRBool* aResult); + NS_IMETHOD IsTrustedEvent(PRBool* aResult); + NS_IMETHOD SetTrusted(PRBool aTrusted); NS_IMETHOD IsHandled(PRBool* aHandled); NS_IMETHOD SetHandled(PRBool aHandled); @@ -245,6 +247,7 @@ protected: nsString* mText; nsIPrivateTextRangeList* mTextRange; PRPackedBool mEventIsInternal; + PRPackedBool mEventIsTrusted; //These are use for internal data for user created events PRInt16 mButton; diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index b578d460249..b79ea80531e 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -80,6 +80,7 @@ #include "nsIServiceManager.h" #include "nsIPref.h" +#include "nsIScriptSecurityManager.h" #include "nsIChromeEventHandler.h" #include "nsIFocusController.h" @@ -3766,6 +3767,29 @@ nsEventStateManager::DispatchNewEvent(nsISupports* aTarget, nsIDOMEvent* aEvent, nsCOMPtr eventTarget(do_QueryInterface(aTarget)); privEvt->SetTarget(eventTarget); + //Key and mouse events have additional security to prevent event spoofing + nsEvent * internalEvent; + privEvt->GetInternalNSEvent(&internalEvent); + if (internalEvent && (internalEvent->eventStructType == NS_KEY_EVENT || + internalEvent->eventStructType == NS_MOUSE_EVENT)) { + //Check security state to determine if dispatcher is trusted + nsCOMPtr + securityManager(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID)); + NS_ENSURE_TRUE(securityManager, NS_ERROR_FAILURE); + + PRBool enabled; + nsresult res = securityManager->IsCapabilityEnabled("UniversalBrowserWrite", &enabled); + if (NS_SUCCEEDED(res) && enabled) { + privEvt->SetTrusted(PR_TRUE); + } + else { + privEvt->SetTrusted(PR_FALSE); + } + } + else { + privEvt->SetTrusted(PR_TRUE); + } + nsEvent* innerEvent; privEvt->GetInternalNSEvent(&innerEvent); if (innerEvent) { diff --git a/content/xbl/src/nsXBLPrototypeHandler.cpp b/content/xbl/src/nsXBLPrototypeHandler.cpp index d4f4aefd7f1..098161361f9 100644 --- a/content/xbl/src/nsXBLPrototypeHandler.cpp +++ b/content/xbl/src/nsXBLPrototypeHandler.cpp @@ -213,6 +213,17 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, // See if our event receiver is a content node (and not us). PRBool isXULKey = (mType == NS_HANDLER_TYPE_XUL); + //XUL handlers shouldn't be triggered by non-trusted events. + if (isXULKey) { + nsCOMPtr privateEvent = do_QueryInterface(aEvent); + if (privateEvent) { + PRBool trustedEvent; + privateEvent->IsTrustedEvent(&trustedEvent); + if (!trustedEvent) + return NS_OK; + } + } + PRBool isReceiverCommandElement = PR_FALSE; nsCOMPtr content(do_QueryInterface(aReceiver)); if (isXULKey && content && content.get() != mHandlerElement) diff --git a/content/xbl/src/nsXBLWindowKeyHandler.cpp b/content/xbl/src/nsXBLWindowKeyHandler.cpp index 0fd8b28cb2c..33b3aff8a75 100644 --- a/content/xbl/src/nsXBLWindowKeyHandler.cpp +++ b/content/xbl/src/nsXBLWindowKeyHandler.cpp @@ -46,6 +46,7 @@ #include "nsIDOMNSUIEvent.h" #include "nsIDOMKeyEvent.h" #include "nsIDOMEventReceiver.h" +#include "nsIPrivateDOMEvent.h" #include "nsXBLService.h" #include "nsIServiceManager.h" #include "nsHTMLAtoms.h" @@ -145,6 +146,15 @@ nsXBLWindowKeyHandler::WalkHandlers(nsIDOMEvent* aKeyEvent, nsIAtom* aEventType) if (prevent) return NS_OK; + nsCOMPtr privateEvent = do_QueryInterface(aKeyEvent); + if (privateEvent) { + //Don't process the event if it was not dispatched from a trusted source + PRBool trustedEvent; + privateEvent->IsTrustedEvent(&trustedEvent); + if (!trustedEvent) + return NS_OK; + } + // Make sure our event is really a key event nsCOMPtr keyEvent(do_QueryInterface(aKeyEvent)); if (!keyEvent) diff --git a/layout/xul/base/src/nsMenuListener.cpp b/layout/xul/base/src/nsMenuListener.cpp index d8b4be36bc3..a065a3b174e 100644 --- a/layout/xul/base/src/nsMenuListener.cpp +++ b/layout/xul/base/src/nsMenuListener.cpp @@ -51,6 +51,7 @@ #include "nsWidgetsCID.h" #include "nsCOMPtr.h" #include "nsIDOMKeyEvent.h" +#include "nsIPrivateDOMEvent.h" #include "nsIPresContext.h" #include "nsIContent.h" #include "nsIDOMNode.h" @@ -176,6 +177,17 @@ nsMenuListener::KeyPress(nsIDOMEvent* aKeyEvent) return NS_OK; // don't consume event } + //handlers shouldn't be triggered by non-trusted events. + if (aKeyEvent) { + nsCOMPtr privateEvent = do_QueryInterface(aKeyEvent); + if (privateEvent) { + PRBool trustedEvent; + privateEvent->IsTrustedEvent(&trustedEvent); + if (!trustedEvent) + return NS_OK; + } + } + nsCOMPtr keyEvent = do_QueryInterface(aKeyEvent); PRUint32 theChar; keyEvent->GetKeyCode(&theChar);