mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 816340 - Propagate events to chrome even if there is a disabled form control in the event target chain, r=jst,gavin
This commit is contained in:
parent
8f2b88b111
commit
116d0e2688
@ -432,7 +432,8 @@ nsContextMenu.prototype = {
|
||||
setTarget: function (aNode, aRangeParent, aRangeOffset) {
|
||||
const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
if (aNode.namespaceURI == xulNS ||
|
||||
aNode.nodeType == Node.DOCUMENT_NODE) {
|
||||
aNode.nodeType == Node.DOCUMENT_NODE ||
|
||||
this.isDisabledForEvents(aNode)) {
|
||||
this.shouldDisplay = false;
|
||||
return;
|
||||
}
|
||||
@ -1290,6 +1291,16 @@ nsContextMenu.prototype = {
|
||||
"contextMenu.hasBGImage = " + this.hasBGImage + "\n";
|
||||
},
|
||||
|
||||
isDisabledForEvents: function(aNode) {
|
||||
let ownerDoc = aNode.ownerDocument;
|
||||
return
|
||||
ownerDoc.defaultView &&
|
||||
ownerDoc.defaultView
|
||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils)
|
||||
.isNodeDisabledForEvents(aNode);
|
||||
},
|
||||
|
||||
isTargetATextBox: function(node) {
|
||||
if (node instanceof HTMLInputElement)
|
||||
return node.mozIsTextField(false);
|
||||
|
@ -95,6 +95,9 @@ ContentAreaDropListener.prototype =
|
||||
|
||||
canDropLink: function(aEvent, aAllowSameDocument)
|
||||
{
|
||||
if (this._eventTargetIsDisabled(aEvent))
|
||||
return false;
|
||||
|
||||
let dataTransfer = aEvent.dataTransfer;
|
||||
let types = dataTransfer.types;
|
||||
if (!types.contains("application/x-moz-file") &&
|
||||
@ -131,6 +134,8 @@ ContentAreaDropListener.prototype =
|
||||
dropLink: function(aEvent, aName, aDisallowInherit)
|
||||
{
|
||||
aName.value = "";
|
||||
if (this._eventTargetIsDisabled(aEvent))
|
||||
return "";
|
||||
|
||||
let dataTransfer = aEvent.dataTransfer;
|
||||
let [url, name] = this._getDropURL(dataTransfer);
|
||||
@ -147,6 +152,18 @@ ContentAreaDropListener.prototype =
|
||||
aName.value = name;
|
||||
|
||||
return url;
|
||||
},
|
||||
|
||||
_eventTargetIsDisabled: function(aEvent)
|
||||
{
|
||||
let ownerDoc = aEvent.originalTarget.ownerDocument;
|
||||
if (!ownerDoc || !ownerDoc.defaultView)
|
||||
return false;
|
||||
|
||||
return ownerDoc.defaultView
|
||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils)
|
||||
.isNodeDisabledForEvents(aEvent.originalTarget);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -49,6 +49,8 @@ MOCHITEST_CHROME_FILES = \
|
||||
test_csp_bug768029.html \
|
||||
test_bug800386.xul \
|
||||
test_csp_bug773891.html \
|
||||
test_bug816340.xul \
|
||||
file_bug816340.xul \
|
||||
test_domparsing.xul \
|
||||
test_bug814638.xul \
|
||||
host_bug814638.xul \
|
||||
|
70
content/base/test/chrome/file_bug816340.xul
Normal file
70
content/base/test/chrome/file_bug816340.xul
Normal file
@ -0,0 +1,70 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=816340
|
||||
-->
|
||||
<window title="Mozilla Bug 816340"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="start();">
|
||||
<label value="Mozilla Bug 816340"/>
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript"><![CDATA[
|
||||
|
||||
function ok(val, msg) {
|
||||
opener.wrappedJSObject.ok(val, msg);
|
||||
}
|
||||
|
||||
var elems =
|
||||
[
|
||||
"input",
|
||||
"textarea",
|
||||
"select",
|
||||
"fieldset",
|
||||
"button",
|
||||
];
|
||||
|
||||
var chromeDidGetEvent = false;
|
||||
function chromeListener() {
|
||||
chromeDidGetEvent = true;
|
||||
}
|
||||
|
||||
function testElement(el, disabled, contentShouldGetEvent) {
|
||||
chromeDidGetEvent = false;
|
||||
var b = document.getElementById("browser");
|
||||
b.contentDocument.body.innerHTML = null;
|
||||
var e = b.contentDocument.createElement(el);
|
||||
if (disabled) {
|
||||
e.setAttribute("disabled", "true");
|
||||
}
|
||||
b.contentDocument.body.appendChild(e);
|
||||
var contentDidGetEvent = false;
|
||||
b.contentDocument.body.addEventListener("foo",
|
||||
function() { contentDidGetEvent = true }, true);
|
||||
|
||||
b.addEventListener("foo", chromeListener, true);
|
||||
e.dispatchEvent(new Event("foo"));
|
||||
b.removeEventListener("foo", chromeListener, true);
|
||||
ok(contentDidGetEvent == contentShouldGetEvent, "content: " + el + (disabled ? " disabled" : ""));
|
||||
ok(chromeDidGetEvent, "chrome: " + el + (disabled ? " disabled" : ""));
|
||||
}
|
||||
|
||||
function start() {
|
||||
// Test common element.
|
||||
testElement("div", false, true);
|
||||
testElement("div", true, true);
|
||||
|
||||
for (var i = 0; i < elems.length; ++i) {
|
||||
testElement(elems[i], false, true);
|
||||
testElement(elems[i], true, false);
|
||||
}
|
||||
ok(true, "done");
|
||||
opener.setTimeout("done()", 0);
|
||||
window.close();
|
||||
}
|
||||
|
||||
]]></script>
|
||||
|
||||
<browser id="browser" type="content" src="about:blank"/>
|
||||
</window>
|
31
content/base/test/chrome/test_bug816340.xul
Normal file
31
content/base/test/chrome/test_bug816340.xul
Normal file
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=816340
|
||||
-->
|
||||
<window title="Mozilla Bug 816340"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=816340"
|
||||
target="_blank">Mozilla Bug 816340</a>
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript"><![CDATA[
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function done() {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
addLoadEvent(function() {
|
||||
window.open("file_bug816340.xul", "", "chrome");
|
||||
});
|
||||
]]></script>
|
||||
</window>
|
@ -100,15 +100,17 @@ public:
|
||||
nsEventStatus aEventStatus,
|
||||
bool aIsInAnon)
|
||||
: nsEventChainVisitor(aPresContext, aEvent, aDOMEvent, aEventStatus),
|
||||
mCanHandle(true), mForceContentDispatch(false),
|
||||
mRelatedTargetIsInAnon(false), mOriginalTargetIsInAnon(aIsInAnon),
|
||||
mWantsWillHandleEvent(false), mMayHaveListenerManager(true),
|
||||
mParentTarget(nullptr), mEventTargetAtParent(nullptr) {}
|
||||
mCanHandle(true), mAutomaticChromeDispatch(true),
|
||||
mForceContentDispatch(false), mRelatedTargetIsInAnon(false),
|
||||
mOriginalTargetIsInAnon(aIsInAnon), mWantsWillHandleEvent(false),
|
||||
mMayHaveListenerManager(true), mParentTarget(nullptr),
|
||||
mEventTargetAtParent(nullptr) {}
|
||||
|
||||
void Reset() {
|
||||
mItemFlags = 0;
|
||||
mItemData = nullptr;
|
||||
mCanHandle = true;
|
||||
mAutomaticChromeDispatch = true;
|
||||
mForceContentDispatch = false;
|
||||
mWantsWillHandleEvent = false;
|
||||
mMayHaveListenerManager = true;
|
||||
@ -124,6 +126,12 @@ public:
|
||||
*/
|
||||
bool mCanHandle;
|
||||
|
||||
/**
|
||||
* If mCanHandle is false and mAutomaticChromeDispatch is also false
|
||||
* event will not be dispatched to the chrome event handler.
|
||||
*/
|
||||
bool mAutomaticChromeDispatch;
|
||||
|
||||
/**
|
||||
* If mForceContentDispatch is set to true,
|
||||
* content dispatching is not disabled for this event target.
|
||||
|
@ -197,7 +197,7 @@ public:
|
||||
|
||||
static void ResetMaxEtciCount()
|
||||
{
|
||||
NS_ASSERTION(!sCurrentEtciCount, "Wrong time to call ResetMaxEtciCount()!");
|
||||
MOZ_ASSERT(!sCurrentEtciCount, "Wrong time to call ResetMaxEtciCount()!");
|
||||
sMaxEtciCount = 0;
|
||||
}
|
||||
|
||||
@ -438,6 +438,30 @@ int32_t ChainItemPool::sEtciPoolUsers = 0;
|
||||
|
||||
void NS_ShutdownChainItemPool() { ChainItemPool::Shutdown(); }
|
||||
|
||||
nsEventTargetChainItem*
|
||||
EventTargetChainItemForChromeTarget(ChainItemPool& aPool,
|
||||
nsINode* aNode,
|
||||
nsEventTargetChainItem* aChild = nullptr)
|
||||
{
|
||||
if (!aNode->IsInDoc()) {
|
||||
return nullptr;
|
||||
}
|
||||
nsPIDOMWindow* win = aNode->OwnerDoc()->GetInnerWindow();
|
||||
nsIDOMEventTarget* piTarget = win ? win->GetParentTarget() : nullptr;
|
||||
NS_ENSURE_TRUE(piTarget, nullptr);
|
||||
|
||||
nsEventTargetChainItem* etci =
|
||||
nsEventTargetChainItem::Create(aPool.GetPool(),
|
||||
piTarget->GetTargetForEventTargetChain(),
|
||||
aChild);
|
||||
NS_ENSURE_TRUE(etci, nullptr);
|
||||
if (!etci->IsValid()) {
|
||||
nsEventTargetChainItem::Destroy(aPool.GetPool(), etci);
|
||||
return nullptr;
|
||||
}
|
||||
return etci;
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
nsEventDispatcher::Dispatch(nsISupports* aTarget,
|
||||
nsPresContext* aPresContext,
|
||||
@ -577,6 +601,13 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
|
||||
isInAnon);
|
||||
targetEtci->PreHandleEvent(preVisitor);
|
||||
|
||||
if (!preVisitor.mCanHandle && preVisitor.mAutomaticChromeDispatch && content) {
|
||||
// Event target couldn't handle the event. Try to propagate to chrome.
|
||||
nsEventTargetChainItem::Destroy(pool.GetPool(), targetEtci);
|
||||
targetEtci = EventTargetChainItemForChromeTarget(pool, content);
|
||||
NS_ENSURE_STATE(targetEtci);
|
||||
targetEtci->PreHandleEvent(preVisitor);
|
||||
}
|
||||
if (preVisitor.mCanHandle) {
|
||||
// At least the original target can handle the event.
|
||||
// Setting the retarget to the |target| simplifies retargeting code.
|
||||
@ -584,6 +615,7 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
|
||||
targetEtci->SetNewTarget(t);
|
||||
nsEventTargetChainItem* topEtci = targetEtci;
|
||||
while (preVisitor.mParentTarget) {
|
||||
nsIDOMEventTarget* parentTarget = preVisitor.mParentTarget;
|
||||
nsEventTargetChainItem* parentEtci =
|
||||
nsEventTargetChainItem::Create(pool.GetPool(), preVisitor.mParentTarget,
|
||||
topEtci);
|
||||
@ -610,6 +642,24 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
|
||||
} else {
|
||||
nsEventTargetChainItem::Destroy(pool.GetPool(), parentEtci);
|
||||
parentEtci = nullptr;
|
||||
if (preVisitor.mAutomaticChromeDispatch && content) {
|
||||
// Even if the current target can't handle the event, try to
|
||||
// propagate to chrome.
|
||||
nsCOMPtr<nsINode> disabledTarget = do_QueryInterface(parentTarget);
|
||||
if (disabledTarget) {
|
||||
parentEtci = EventTargetChainItemForChromeTarget(pool,
|
||||
disabledTarget,
|
||||
topEtci);
|
||||
if (parentEtci) {
|
||||
parentEtci->PreHandleEvent(preVisitor);
|
||||
if (preVisitor.mCanHandle) {
|
||||
targetEtci->SetNewTarget(parentTarget);
|
||||
topEtci = parentEtci;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -70,8 +70,8 @@ PR_STATIC_ASSERT((uint32_t)eButtonElementTypesMax < (uint32_t)NS_FORM_INPUT_ELEM
|
||||
PR_STATIC_ASSERT((uint32_t)eInputElementTypesMax < 1<<8);
|
||||
|
||||
#define NS_IFORMCONTROL_IID \
|
||||
{ 0xbc53dcf5, 0xbd4f, 0x4991, \
|
||||
{ 0xa1, 0x87, 0xc4, 0x57, 0x98, 0x54, 0xda, 0x6e } }
|
||||
{ 0x4b89980c, 0x4dcd, 0x428f, \
|
||||
{ 0xb7, 0xad, 0x43, 0x5b, 0x93, 0x29, 0x79, 0xec } }
|
||||
|
||||
/**
|
||||
* Interface which all form controls (e.g. buttons, checkboxes, text,
|
||||
@ -182,6 +182,10 @@ public:
|
||||
*/
|
||||
inline bool AllowDraggableChildren() const;
|
||||
|
||||
virtual bool IsDisabledForEvents(uint32_t aMessage)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
protected:
|
||||
|
||||
/**
|
||||
|
@ -1178,7 +1178,7 @@ protected:
|
||||
void* aData);
|
||||
|
||||
// Returns true if the event should not be handled from PreHandleEvent
|
||||
virtual bool IsElementDisabledForEvents(uint32_t aMessage, nsIFrame* aFrame);
|
||||
bool IsElementDisabledForEvents(uint32_t aMessage, nsIFrame* aFrame);
|
||||
|
||||
// The focusability state of this form control. eUnfocusable means that it
|
||||
// shouldn't be focused at all, eInactiveWindow means it's in an inactive
|
||||
|
@ -82,6 +82,7 @@ public:
|
||||
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission);
|
||||
NS_IMETHOD SaveState();
|
||||
bool RestoreState(nsPresState* aState);
|
||||
virtual bool IsDisabledForEvents(uint32_t aMessage);
|
||||
|
||||
nsEventStates IntrinsicState() const;
|
||||
|
||||
@ -251,17 +252,22 @@ nsHTMLButtonElement::ParseAttribute(int32_t aNamespaceID,
|
||||
aResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLButtonElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
||||
bool
|
||||
nsHTMLButtonElement::IsDisabledForEvents(uint32_t aMessage)
|
||||
{
|
||||
nsIFormControlFrame* formControlFrame = GetFormControlFrame(false);
|
||||
nsIFrame* formFrame = NULL;
|
||||
if (formControlFrame) {
|
||||
formFrame = do_QueryFrame(formControlFrame);
|
||||
}
|
||||
return IsElementDisabledForEvents(aMessage, formFrame);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLButtonElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
||||
{
|
||||
aVisitor.mCanHandle = false;
|
||||
if (IsElementDisabledForEvents(aVisitor.mEvent->message, formFrame)) {
|
||||
if (IsDisabledForEvents(aVisitor.mEvent->message)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -74,13 +74,19 @@ NS_IMPL_STRING_ATTR(nsHTMLFieldSetElement, Name, name)
|
||||
// nsIConstraintValidation
|
||||
NS_IMPL_NSICONSTRAINTVALIDATION(nsHTMLFieldSetElement)
|
||||
|
||||
bool
|
||||
nsHTMLFieldSetElement::IsDisabledForEvents(uint32_t aMessage)
|
||||
{
|
||||
return IsElementDisabledForEvents(aMessage, nullptr);
|
||||
}
|
||||
|
||||
// nsIContent
|
||||
nsresult
|
||||
nsHTMLFieldSetElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
||||
{
|
||||
// Do not process any DOM events if the element is disabled.
|
||||
aVisitor.mCanHandle = false;
|
||||
if (IsElementDisabledForEvents(aVisitor.mEvent->message, NULL)) {
|
||||
if (IsDisabledForEvents(aVisitor.mEvent->message)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,7 @@ public:
|
||||
NS_IMETHOD_(uint32_t) GetType() const { return NS_FORM_FIELDSET; }
|
||||
NS_IMETHOD Reset();
|
||||
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission);
|
||||
virtual bool IsDisabledForEvents(uint32_t aMessage);
|
||||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
|
||||
virtual nsXPCClassInfo* GetClassInfo();
|
||||
virtual nsIDOMNode* AsDOMNode() { return this; }
|
||||
|
@ -2243,12 +2243,18 @@ nsHTMLInputElement::NeedToInitializeEditorForEvent(nsEventChainPreVisitor& aVisi
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsHTMLInputElement::IsDisabledForEvents(uint32_t aMessage)
|
||||
{
|
||||
return IsElementDisabledForEvents(aMessage, GetPrimaryFrame());
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLInputElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
||||
{
|
||||
// Do not process any DOM events if the element is disabled
|
||||
aVisitor.mCanHandle = false;
|
||||
if (IsElementDisabledForEvents(aVisitor.mEvent->message, GetPrimaryFrame())) {
|
||||
if (IsDisabledForEvents(aVisitor.mEvent->message)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -104,6 +104,7 @@ public:
|
||||
NS_IMETHOD SaveState();
|
||||
virtual bool RestoreState(nsPresState* aState);
|
||||
virtual bool AllowDrop();
|
||||
virtual bool IsDisabledForEvents(uint32_t aMessage);
|
||||
|
||||
virtual void FieldSetDisabledChanged(bool aNotify);
|
||||
|
||||
|
@ -1483,18 +1483,22 @@ nsHTMLSelectElement::GetAttributeMappingFunction() const
|
||||
return &MapAttributesIntoRule;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLSelectElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
||||
bool
|
||||
nsHTMLSelectElement::IsDisabledForEvents(uint32_t aMessage)
|
||||
{
|
||||
nsIFormControlFrame* formControlFrame = GetFormControlFrame(false);
|
||||
nsIFrame* formFrame = nullptr;
|
||||
if (formControlFrame) {
|
||||
formFrame = do_QueryFrame(formControlFrame);
|
||||
}
|
||||
return IsElementDisabledForEvents(aMessage, formFrame);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLSelectElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
||||
{
|
||||
aVisitor.mCanHandle = false;
|
||||
if (IsElementDisabledForEvents(aVisitor.mEvent->message, formFrame)) {
|
||||
if (IsDisabledForEvents(aVisitor.mEvent->message)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -271,6 +271,7 @@ public:
|
||||
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission);
|
||||
NS_IMETHOD SaveState();
|
||||
virtual bool RestoreState(nsPresState* aState);
|
||||
virtual bool IsDisabledForEvents(uint32_t aMessage);
|
||||
|
||||
virtual void FieldSetDisabledChanged(bool aNotify);
|
||||
|
||||
|
@ -97,6 +97,7 @@ public:
|
||||
NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission);
|
||||
NS_IMETHOD SaveState();
|
||||
virtual bool RestoreState(nsPresState* aState);
|
||||
virtual bool IsDisabledForEvents(uint32_t aMessage);
|
||||
|
||||
virtual void FieldSetDisabledChanged(bool aNotify);
|
||||
|
||||
@ -665,17 +666,22 @@ nsHTMLTextAreaElement::GetAttributeMappingFunction() const
|
||||
return &MapAttributesIntoRule;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLTextAreaElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
||||
bool
|
||||
nsHTMLTextAreaElement::IsDisabledForEvents(uint32_t aMessage)
|
||||
{
|
||||
nsIFormControlFrame* formControlFrame = GetFormControlFrame(false);
|
||||
nsIFrame* formFrame = NULL;
|
||||
if (formControlFrame) {
|
||||
formFrame = do_QueryFrame(formControlFrame);
|
||||
}
|
||||
return IsElementDisabledForEvents(aMessage, formFrame);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLTextAreaElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
||||
{
|
||||
aVisitor.mCanHandle = false;
|
||||
if (IsElementDisabledForEvents(aVisitor.mEvent->message, formFrame)) {
|
||||
if (IsDisabledForEvents(aVisitor.mEvent->message)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1126,6 +1126,7 @@ nsXULElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
||||
// Stop building the event target chain for the original event.
|
||||
// We don't want it to propagate to any DOM nodes.
|
||||
aVisitor.mCanHandle = false;
|
||||
aVisitor.mAutomaticChromeDispatch = false;
|
||||
|
||||
// XXX sXBL/XBL2 issue! Owner or current document?
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(GetCurrentDoc()));
|
||||
|
@ -67,6 +67,7 @@
|
||||
#include "nsIDOMFileHandle.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsViewportInfo.h"
|
||||
#include "nsIFormControl.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -3090,3 +3091,26 @@ nsDOMWindowUtils::AllowScriptsToClose()
|
||||
static_cast<nsGlobalWindow*>(window.get())->AllowScriptsToClose();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::IsNodeDisabledForEvents(nsIDOMNode* aNode, bool* aRetVal)
|
||||
{
|
||||
*aRetVal = false;
|
||||
if (!nsContentUtils::IsCallerChrome()) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
nsCOMPtr<nsINode> n = do_QueryInterface(aNode);
|
||||
nsINode* node = n;
|
||||
while (node) {
|
||||
if (node->IsNodeOfType(nsINode::eHTML_FORM_CONTROL)) {
|
||||
nsCOMPtr<nsIFormControl> fc = do_QueryInterface(node);
|
||||
if (fc && fc->IsDisabledForEvents(NS_EVENT_NULL)) {
|
||||
*aRetVal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
node = node->GetParentNode();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ interface nsIDOMTouch;
|
||||
interface nsIDOMClientRect;
|
||||
interface nsIURI;
|
||||
|
||||
[scriptable, uuid(C98B7275-93C4-4EAD-B7CF-573D872C1071)]
|
||||
[scriptable, uuid(2196a216-ed3c-46dd-aa24-9f5b3ac17539)]
|
||||
interface nsIDOMWindowUtils : nsISupports {
|
||||
|
||||
/**
|
||||
@ -1285,4 +1285,11 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
* was created can be closed using scripts.
|
||||
*/
|
||||
void allowScriptsToClose();
|
||||
|
||||
/**
|
||||
* In certain cases the event handling of nodes, form controls in practice,
|
||||
* may be disabled. Such cases are for example the existence of disabled
|
||||
* attribute or -moz-user-input: none/disabled.
|
||||
*/
|
||||
boolean isNodeDisabledForEvents(in nsIDOMNode aNode);
|
||||
};
|
||||
|
@ -6563,34 +6563,6 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsEventStatus* aStatus)
|
||||
}
|
||||
}
|
||||
if (eventTarget) {
|
||||
#ifdef MOZ_B2G
|
||||
// Horrible hack for B2G to propagate events even from
|
||||
// disabled form elements to chrome. See bug 804811.
|
||||
// See also nsGenericHTMLFormElement::IsElementDisabledForEvents.
|
||||
if (aEvent->message != NS_MOUSE_MOVE) {
|
||||
nsINode* possibleFormElement = eventTarget->ChromeOnlyAccess() ?
|
||||
static_cast<nsIContent*>(eventTarget.get())->
|
||||
FindFirstNonChromeOnlyAccessContent() :
|
||||
eventTarget;
|
||||
if (possibleFormElement &&
|
||||
possibleFormElement->IsNodeOfType(nsINode::eHTML_FORM_CONTROL)) {
|
||||
nsEvent event(true, NS_EVENT_TYPE_NULL);
|
||||
nsCOMArray<nsIDOMEventTarget> targets;
|
||||
nsEventDispatcher::Dispatch(eventTarget, nullptr, &event, nullptr,
|
||||
nullptr, nullptr, &targets);
|
||||
nsCOMPtr<nsIContent> last;
|
||||
if (targets.Count()) {
|
||||
last = do_QueryInterface(targets[targets.Count() - 1]);
|
||||
}
|
||||
if (!targets.Count() ||
|
||||
(last &&
|
||||
nsContentUtils::ContentIsDescendantOf(last,
|
||||
possibleFormElement))) {
|
||||
aEvent->mFlags.mOnlyChromeDispatch = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (aEvent->eventStructType == NS_COMPOSITION_EVENT ||
|
||||
aEvent->eventStructType == NS_TEXT_EVENT) {
|
||||
nsIMEStateManager::DispatchCompositionEvent(eventTarget,
|
||||
|
Loading…
Reference in New Issue
Block a user