diff --git a/extensions/xforms/nsXFormsActionElement.cpp b/extensions/xforms/nsXFormsActionElement.cpp index 5f21d5f147b..8dce449b48c 100644 --- a/extensions/xforms/nsXFormsActionElement.cpp +++ b/extensions/xforms/nsXFormsActionElement.cpp @@ -109,9 +109,8 @@ nsXFormsActionElement::OnDestroyed() { NS_IMETHODIMP nsXFormsActionElement::HandleEvent(nsIDOMEvent* aEvent) { - if (!aEvent) - return NS_ERROR_INVALID_ARG; - return HandleAction(aEvent, nsnull); + return nsXFormsUtils::EventHandlingAllowed(aEvent, mElement) ? + HandleAction(aEvent, nsnull) : NS_OK; } PR_STATIC_CALLBACK(PLDHashOperator) DoDeferredActions(nsISupports * aModel, diff --git a/extensions/xforms/nsXFormsActionModuleBase.cpp b/extensions/xforms/nsXFormsActionModuleBase.cpp index 5ba78797993..f9cd8e236f9 100644 --- a/extensions/xforms/nsXFormsActionModuleBase.cpp +++ b/extensions/xforms/nsXFormsActionModuleBase.cpp @@ -78,8 +78,7 @@ NS_IMETHODIMP nsXFormsActionModuleBase::OnDestroyed() NS_IMETHODIMP nsXFormsActionModuleBase::HandleEvent(nsIDOMEvent* aEvent) { - if (!aEvent) - return NS_ERROR_INVALID_ARG; - return HandleAction(aEvent, nsnull); + return nsXFormsUtils::EventHandlingAllowed(aEvent, mElement) ? + HandleAction(aEvent, nsnull) : NS_OK; } diff --git a/extensions/xforms/nsXFormsContextContainer.cpp b/extensions/xforms/nsXFormsContextContainer.cpp index 6e54e92982a..420cb943f9c 100644 --- a/extensions/xforms/nsXFormsContextContainer.cpp +++ b/extensions/xforms/nsXFormsContextContainer.cpp @@ -174,6 +174,8 @@ nsXFormsContextContainer::HandleDefault(nsIDOMEvent *aEvent, if (!type.EqualsLiteral("focus")) return nsXFormsControlStub::HandleDefault(aEvent, aHandled); + if (!nsXFormsUtils::EventHandlingAllowed(aEvent, mElement)) + return NS_OK; /* * Either we, or an element we contain, has gotten focus, so we need to set * the repeat index. This is done through the \ the diff --git a/extensions/xforms/nsXFormsControlStub.cpp b/extensions/xforms/nsXFormsControlStub.cpp index 10a4a84a4fa..c21154a5aba 100644 --- a/extensions/xforms/nsXFormsControlStub.cpp +++ b/extensions/xforms/nsXFormsControlStub.cpp @@ -66,15 +66,16 @@ nsXFormsHintHelpListener::HandleEvent(nsIDOMEvent* aEvent) nsCOMPtr target; aEvent->GetCurrentTarget(getter_AddRefs(target)); nsCOMPtr targetNode(do_QueryInterface(target)); - - nsCOMPtr keyEvent(do_QueryInterface(aEvent)); - if (keyEvent) { - PRUint32 code = 0; - keyEvent->GetKeyCode(&code); - if (code == nsIDOMKeyEvent::DOM_VK_F1) - nsXFormsUtils::DispatchEvent(targetNode, eEvent_Help); - } else { - nsXFormsUtils::DispatchEvent(targetNode, eEvent_Hint); + if (nsXFormsUtils::EventHandlingAllowed(aEvent, targetNode)) { + nsCOMPtr keyEvent(do_QueryInterface(aEvent)); + if (keyEvent) { + PRUint32 code = 0; + keyEvent->GetKeyCode(&code); + if (code == nsIDOMKeyEvent::DOM_VK_F1) + nsXFormsUtils::DispatchEvent(targetNode, eEvent_Help); + } else { + nsXFormsUtils::DispatchEvent(targetNode, eEvent_Hint); + } } return NS_OK; @@ -284,7 +285,8 @@ nsXFormsControlStub::HandleDefault(nsIDOMEvent *aEvent, { NS_ENSURE_ARG(aHandled); - if (aEvent) { + if (nsXFormsUtils::EventHandlingAllowed(aEvent, mElement)) { + // Check that we are the target of the event nsCOMPtr target; aEvent->GetTarget(getter_AddRefs(target)); diff --git a/extensions/xforms/nsXFormsDispatchElement.cpp b/extensions/xforms/nsXFormsDispatchElement.cpp index 4be44f0598c..97265631c3b 100644 --- a/extensions/xforms/nsXFormsDispatchElement.cpp +++ b/extensions/xforms/nsXFormsDispatchElement.cpp @@ -108,11 +108,9 @@ nsXFormsDispatchElement::HandleAction(nsIDOMEvent* aEvent, docEvent->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event)); event->InitEvent(name, bubbles, cancelable); - // XXX: What about uiEvent->SetTrusted(?), should these events be - // trusted or not? - nsCOMPtr targetEl = do_QueryInterface(el); if (targetEl) { + nsXFormsUtils::SetEventTrusted(event, el); PRBool defaultActionEnabled; targetEl->DispatchEvent(event, &defaultActionEnabled); } diff --git a/extensions/xforms/nsXFormsInputElement.cpp b/extensions/xforms/nsXFormsInputElement.cpp index c00b29f4235..d16b63c2502 100644 --- a/extensions/xforms/nsXFormsInputElement.cpp +++ b/extensions/xforms/nsXFormsInputElement.cpp @@ -259,7 +259,10 @@ nsXFormsInputElement::HandleDefault(nsIDOMEvent *aEvent, if (*aHandled || !mIncremental) { return NS_OK; } - + + if (!nsXFormsUtils::EventHandlingAllowed(aEvent, mElement)) + return NS_OK; + nsAutoString type; aEvent->GetType(type); @@ -290,7 +293,8 @@ nsXFormsInputElement::Focus(nsIDOMEvent *aEvent) NS_IMETHODIMP nsXFormsInputElement::Blur(nsIDOMEvent *aEvent) { - return UpdateInstanceData(); + return nsXFormsUtils::EventHandlingAllowed(aEvent, mElement) ? + UpdateInstanceData() : NS_OK; } nsresult diff --git a/extensions/xforms/nsXFormsMessageElement.cpp b/extensions/xforms/nsXFormsMessageElement.cpp index f139dd3190f..4f2449cbbf6 100644 --- a/extensions/xforms/nsXFormsMessageElement.cpp +++ b/extensions/xforms/nsXFormsMessageElement.cpp @@ -270,9 +270,8 @@ nsXFormsMessageElement::OnDestroyed() NS_IMETHODIMP nsXFormsMessageElement::HandleEvent(nsIDOMEvent* aEvent) { - if (!aEvent) - return NS_ERROR_INVALID_ARG; - return HandleAction(aEvent, nsnull); + return nsXFormsUtils::EventHandlingAllowed(aEvent, mElement) ? + HandleAction(aEvent, nsnull) : NS_OK; } void diff --git a/extensions/xforms/nsXFormsModelElement.cpp b/extensions/xforms/nsXFormsModelElement.cpp index 36586d13625..b98bd47335c 100644 --- a/extensions/xforms/nsXFormsModelElement.cpp +++ b/extensions/xforms/nsXFormsModelElement.cpp @@ -358,6 +358,9 @@ nsXFormsModelElement::DoneAddingChildren() NS_IMETHODIMP nsXFormsModelElement::HandleDefault(nsIDOMEvent *aEvent, PRBool *aHandled) { + if (!nsXFormsUtils::EventHandlingAllowed(aEvent, mElement)) + return NS_OK; + *aHandled = PR_TRUE; nsAutoString type; @@ -734,6 +737,9 @@ nsXFormsModelElement::OnError(nsresult aStatus, NS_IMETHODIMP nsXFormsModelElement::HandleEvent(nsIDOMEvent* aEvent) { + if (!nsXFormsUtils::EventHandlingAllowed(aEvent, mElement)) + return NS_OK; + nsAutoString type; aEvent->GetType(type); if (!type.EqualsLiteral("DOMContentLoaded")) diff --git a/extensions/xforms/nsXFormsSelectElement.cpp b/extensions/xforms/nsXFormsSelectElement.cpp index 25ca04f170c..db330519f5d 100644 --- a/extensions/xforms/nsXFormsSelectElement.cpp +++ b/extensions/xforms/nsXFormsSelectElement.cpp @@ -349,6 +349,9 @@ nsXFormsSelectElement::TryFocus(PRBool* aOK) NS_IMETHODIMP nsXFormsSelectElement::HandleEvent(nsIDOMEvent *aEvent) { + if (!nsXFormsUtils::EventHandlingAllowed(aEvent, mElement)) + return NS_OK; + nsAutoString type; aEvent->GetType(type); diff --git a/extensions/xforms/nsXFormsSubmissionElement.cpp b/extensions/xforms/nsXFormsSubmissionElement.cpp index ef1a81679a1..bedd29ebff9 100644 --- a/extensions/xforms/nsXFormsSubmissionElement.cpp +++ b/extensions/xforms/nsXFormsSubmissionElement.cpp @@ -283,6 +283,9 @@ nsXFormsSubmissionElement::OnDestroyed() NS_IMETHODIMP nsXFormsSubmissionElement::HandleDefault(nsIDOMEvent *aEvent, PRBool *aHandled) { + if (!nsXFormsUtils::EventHandlingAllowed(aEvent, mElement)) + return NS_OK; + nsAutoString type; aEvent->GetType(type); if (type.EqualsLiteral("xforms-submit")) { diff --git a/extensions/xforms/nsXFormsTriggerElement.cpp b/extensions/xforms/nsXFormsTriggerElement.cpp index c43022969fa..112b3b4fa01 100644 --- a/extensions/xforms/nsXFormsTriggerElement.cpp +++ b/extensions/xforms/nsXFormsTriggerElement.cpp @@ -242,6 +242,9 @@ nsXFormsTriggerElement::HandleDefault(nsIDOMEvent *aEvent, PRBool *aHandled) return NS_OK; } + if (!nsXFormsUtils::EventHandlingAllowed(aEvent, mElement)) + return NS_OK; + nsAutoString type; aEvent->GetType(type); @@ -276,8 +279,7 @@ nsXFormsTriggerElement::HandleDefault(nsIDOMEvent *aEvent, PRBool *aHandled) aView, 1); // Simple click - // XXX: What about uiEvent->SetTrusted(?), should these events be - // trusted or not? + nsXFormsUtils::SetEventTrusted(uiEvent, mElement); PRBool cancelled; return target->DispatchEvent(uiEvent, &cancelled); @@ -328,6 +330,9 @@ nsXFormsSubmitElement::HandleDefault(nsIDOMEvent *aEvent, PRBool *aHandled) return NS_OK; } + if (!nsXFormsUtils::EventHandlingAllowed(aEvent, mElement)) + return NS_OK; + nsAutoString type; aEvent->GetType(type); if (!(*aHandled = type.EqualsLiteral("DOMActivate"))) diff --git a/extensions/xforms/nsXFormsUploadElement.cpp b/extensions/xforms/nsXFormsUploadElement.cpp index 7282db6a354..482be16e752 100644 --- a/extensions/xforms/nsXFormsUploadElement.cpp +++ b/extensions/xforms/nsXFormsUploadElement.cpp @@ -211,7 +211,8 @@ nsXFormsUploadElement::Focus(nsIDOMEvent *aEvent) NS_IMETHODIMP nsXFormsUploadElement::Blur(nsIDOMEvent *aEvent) { - if (!mInput || !mBoundNode || !mModel) + if (!mInput || !mBoundNode || !mModel || + !nsXFormsUtils::EventHandlingAllowed(aEvent, mElement)) return NS_OK; nsAutoString value; diff --git a/extensions/xforms/nsXFormsUtils.cpp b/extensions/xforms/nsXFormsUtils.cpp index bc87ccd8d78..2714e2b6e55 100644 --- a/extensions/xforms/nsXFormsUtils.cpp +++ b/extensions/xforms/nsXFormsUtils.cpp @@ -80,6 +80,9 @@ #include "nsIDOM3Node.h" #include "nsIConsoleService.h" #include "nsIStringBundle.h" +#include "nsIDOMNSEvent.h" +#include "nsIURI.h" +#include "nsIPrivateDOMEvent.h" #define CANCELABLE 0x01 #define BUBBLES 0x02 @@ -719,17 +722,75 @@ nsXFormsUtils::DispatchEvent(nsIDOMNode* aTarget, nsXFormsEvent aEvent) const EventData *data = &sXFormsEventsEntries[aEvent]; event->InitEvent(NS_ConvertUTF8toUTF16(data->name), data->canBubble, data->canCancel); - - // XXX: What about event->SetTrusted(?) here? Should all these - // events be trusted? Right now they're never trusted. - + nsCOMPtr target = do_QueryInterface(aTarget); NS_ENSURE_STATE(target); + SetEventTrusted(event, aTarget); + PRBool defaultActionEnabled; return target->DispatchEvent(event, &defaultActionEnabled); } +/* static */ nsresult +nsXFormsUtils::SetEventTrusted(nsIDOMEvent* aEvent, nsIDOMNode* aRelatedNode) +{ + nsCOMPtr event(do_QueryInterface(aEvent)); + if (event) { + PRBool isTrusted = PR_FALSE; + event->GetIsTrusted(&isTrusted); + if (!isTrusted && aRelatedNode) { + nsCOMPtr domDoc; + aRelatedNode->GetOwnerDocument(getter_AddRefs(domDoc)); + nsCOMPtr doc(do_QueryInterface(domDoc)); + if (doc) { + nsIURI* uri = doc->GetDocumentURI(); + if (uri) { + PRBool isChrome = PR_FALSE; + uri->SchemeIs("chrome", &isChrome); + if (isChrome) { + nsCOMPtr privateEvent(do_QueryInterface(aEvent)); + NS_ENSURE_STATE(privateEvent); + privateEvent->SetTrusted(PR_TRUE); + } + } + } + } + } + return NS_OK; +} + +/* static */ PRBool +nsXFormsUtils::EventHandlingAllowed(nsIDOMEvent* aEvent, nsIDOMNode* aTarget) +{ + PRBool allow = PR_FALSE; + if (aEvent && aTarget) { + nsCOMPtr related(do_QueryInterface(aEvent)); + if (related) { + PRBool isTrusted = PR_FALSE; + if (NS_SUCCEEDED(related->GetIsTrusted(&isTrusted))) { + if (isTrusted) { + allow = PR_TRUE; + } else { + nsCOMPtr domDoc; + aTarget->GetOwnerDocument(getter_AddRefs(domDoc)); + nsCOMPtr doc(do_QueryInterface(domDoc)); + if (doc) { + nsIURI* uri = doc->GetDocumentURI(); + if (uri) { + PRBool isChrome = PR_FALSE; + uri->SchemeIs("chrome", &isChrome); + allow = !isChrome; + } + } + } + } + } + } + NS_WARN_IF_FALSE(allow, "Event handling not allowed!"); + return allow; +} + /* static */ PRBool nsXFormsUtils::IsXFormsEvent(const nsAString& aEvent, PRBool& aCancelable, diff --git a/extensions/xforms/nsXFormsUtils.h b/extensions/xforms/nsXFormsUtils.h index d0ec9275848..e7cd6349230 100644 --- a/extensions/xforms/nsXFormsUtils.h +++ b/extensions/xforms/nsXFormsUtils.h @@ -54,6 +54,7 @@ class nsIXFormsModelElement; class nsIURI; class nsString; class nsIMutableArray; +class nsIDOMEvent; #define NS_NAMESPACE_XFORMS "http://www.w3.org/2002/xforms" #define NS_NAMESPACE_XHTML "http://www.w3.org/1999/xhtml" @@ -257,7 +258,27 @@ public: */ static NS_HIDDEN_(nsresult) DispatchEvent(nsIDOMNode* aTarget, nsXFormsEvent aEvent); - + + /** + * Sets aEvent trusted if aRelatedNode is in chrome. + * When dispatching events in chrome, they should be set trusted + * because by default event listeners in chrome handle only trusted + * events. + * Should be called before any event dispatching in XForms. + */ + static NS_HIDDEN_(nsresult) + SetEventTrusted(nsIDOMEvent* aEvent, nsIDOMNode* aRelatedNode); + + /** + * Returns PR_TRUE unless aTarget is in chrome and aEvent is not trusted. + * This should be used always before handling events. Otherwise if XForms + * is used in chrome, it may try to handle events that can be synthesized + * by untrusted content. I.e. content documents may create events using + * document.createEvent() and then fire them using target.dispatchEvent(); + */ + static NS_HIDDEN_(PRBool) + EventHandlingAllowed(nsIDOMEvent* aEvent, nsIDOMNode* aTarget); + /** * Returns PR_TRUE, if aEvent is an XForms event, and sets the values * of aCancelable and aBubbles parameters according to the event type.