mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 229925 - Do not dispatch event to label target if interactive content is found between the event target and the label. r=smaug
This commit is contained in:
parent
f7a9fc17d7
commit
b8a0cc4e4e
@ -1803,6 +1803,12 @@ Element::IsLabelable() const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Element::IsInteractiveHTMLContent() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
css::StyleRule*
|
||||
Element::GetInlineStyleRule()
|
||||
{
|
||||
|
@ -284,6 +284,11 @@ public:
|
||||
*/
|
||||
virtual bool IsLabelable() const;
|
||||
|
||||
/**
|
||||
* Returns if the element is interactive content as per HTML specification.
|
||||
*/
|
||||
virtual bool IsInteractiveHTMLContent() const;
|
||||
|
||||
/**
|
||||
* Is the attribute named stored in the mapped attributes?
|
||||
*
|
||||
|
@ -42,6 +42,12 @@ public:
|
||||
virtual int32_t TabIndexDefault() MOZ_OVERRIDE;
|
||||
virtual bool Draggable() const MOZ_OVERRIDE;
|
||||
|
||||
// Element
|
||||
virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// nsIDOMHTMLAnchorElement
|
||||
NS_DECL_NSIDOMHTMLANCHORELEMENT
|
||||
|
||||
|
@ -40,6 +40,12 @@ HTMLAudioElement::~HTMLAudioElement()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLAudioElement::IsInteractiveHTMLContent() const
|
||||
{
|
||||
return HasAttr(kNameSpaceID_None, nsGkAtoms::controls);
|
||||
}
|
||||
|
||||
already_AddRefed<HTMLAudioElement>
|
||||
HTMLAudioElement::Audio(const GlobalObject& aGlobal,
|
||||
const Optional<nsAString>& aSrc,
|
||||
|
@ -23,6 +23,9 @@ public:
|
||||
|
||||
explicit HTMLAudioElement(already_AddRefed<NodeInfo>& aNodeInfo);
|
||||
|
||||
// Element
|
||||
virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE;
|
||||
|
||||
// nsIDOMHTMLMediaElement
|
||||
using HTMLMediaElement::GetPaused;
|
||||
|
||||
|
@ -36,6 +36,12 @@ public:
|
||||
|
||||
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLButtonElement, button)
|
||||
|
||||
// Element
|
||||
virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// nsIDOMHTMLButtonElement
|
||||
NS_DECL_NSIDOMHTMLBUTTONELEMENT
|
||||
|
||||
|
@ -26,6 +26,12 @@ public:
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// Element
|
||||
virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// nsIDOMHTMLIFrameElement
|
||||
NS_DECL_NSIDOMHTMLIFRAMEELEMENT
|
||||
|
||||
|
@ -148,6 +148,12 @@ NS_IMPL_STRING_ATTR(HTMLImageElement, Srcset, srcset)
|
||||
NS_IMPL_STRING_ATTR(HTMLImageElement, UseMap, usemap)
|
||||
NS_IMPL_INT_ATTR(HTMLImageElement, Vspace, vspace)
|
||||
|
||||
bool
|
||||
HTMLImageElement::IsInteractiveHTMLContent() const
|
||||
{
|
||||
return HasAttr(kNameSpaceID_None, nsGkAtoms::usemap);
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLImageElement::IsSrcsetEnabled()
|
||||
{
|
||||
|
@ -46,6 +46,9 @@ public:
|
||||
|
||||
virtual bool Draggable() const MOZ_OVERRIDE;
|
||||
|
||||
// Element
|
||||
virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE;
|
||||
|
||||
// nsIDOMHTMLImageElement
|
||||
NS_DECL_NSIDOMHTMLIMAGEELEMENT
|
||||
|
||||
|
@ -3211,6 +3211,12 @@ HTMLInputElement::Focus(ErrorResult& aError)
|
||||
return;
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLInputElement::IsInteractiveHTMLContent() const
|
||||
{
|
||||
return mType != NS_FORM_INPUT_HIDDEN;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLInputElement::Select()
|
||||
{
|
||||
|
@ -119,6 +119,9 @@ public:
|
||||
virtual void Blur(ErrorResult& aError) MOZ_OVERRIDE;
|
||||
virtual void Focus(ErrorResult& aError) MOZ_OVERRIDE;
|
||||
|
||||
// Element
|
||||
virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE;
|
||||
|
||||
// nsIDOMHTMLInputElement
|
||||
NS_DECL_NSIDOMHTMLINPUTELEMENT
|
||||
|
||||
|
@ -83,19 +83,14 @@ HTMLLabelElement::Focus(ErrorResult& aError)
|
||||
}
|
||||
|
||||
static bool
|
||||
EventTargetIn(WidgetEvent* aEvent, nsIContent* aChild, nsIContent* aStop)
|
||||
InInteractiveHTMLContent(nsIContent* aContent, nsIContent* aStop)
|
||||
{
|
||||
nsCOMPtr<nsIContent> c = do_QueryInterface(aEvent->target);
|
||||
nsIContent *content = c;
|
||||
while (content) {
|
||||
if (content == aChild) {
|
||||
nsIContent* content = aContent;
|
||||
while (content && content != aStop) {
|
||||
if (content->IsElement() &&
|
||||
content->AsElement()->IsInteractiveHTMLContent()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (content == aStop) {
|
||||
break;
|
||||
}
|
||||
|
||||
content = content->GetParent();
|
||||
}
|
||||
return false;
|
||||
@ -115,10 +110,15 @@ HTMLLabelElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> target = do_QueryInterface(aVisitor.mEvent->target);
|
||||
if (InInteractiveHTMLContent(target, this)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Strong ref because event dispatch is going to happen.
|
||||
nsRefPtr<Element> content = GetLabeledElement();
|
||||
|
||||
if (content && !EventTargetIn(aVisitor.mEvent, content, this)) {
|
||||
if (content) {
|
||||
mHandlingEvent = true;
|
||||
switch (aVisitor.mEvent->message) {
|
||||
case NS_MOUSE_BUTTON_DOWN:
|
||||
|
@ -32,6 +32,12 @@ public:
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// Element
|
||||
virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// nsIDOMHTMLLabelElement
|
||||
NS_DECL_NSIDOMHTMLLABELELEMENT
|
||||
|
||||
|
@ -45,6 +45,12 @@ HTMLObjectElement::~HTMLObjectElement()
|
||||
DestroyImageLoadingContent();
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLObjectElement::IsInteractiveHTMLContent() const
|
||||
{
|
||||
return HasAttr(kNameSpaceID_None, nsGkAtoms::usemap);
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLObjectElement::IsDoneAddingChildren()
|
||||
{
|
||||
|
@ -30,6 +30,9 @@ public:
|
||||
|
||||
virtual int32_t TabIndexDefault() MOZ_OVERRIDE;
|
||||
|
||||
// Element
|
||||
virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE;
|
||||
|
||||
// nsIDOMHTMLObjectElement
|
||||
NS_DECL_NSIDOMHTMLOBJECTELEMENT
|
||||
|
||||
|
@ -147,6 +147,12 @@ public:
|
||||
|
||||
virtual int32_t TabIndexDefault() MOZ_OVERRIDE;
|
||||
|
||||
// Element
|
||||
virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// nsIDOMHTMLSelectElement
|
||||
NS_DECL_NSIDOMHTMLSELECTELEMENT
|
||||
|
||||
|
@ -53,6 +53,12 @@ public:
|
||||
|
||||
virtual int32_t TabIndexDefault() MOZ_OVERRIDE;
|
||||
|
||||
// Element
|
||||
virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// nsIDOMHTMLTextAreaElement
|
||||
NS_DECL_NSIDOMHTMLTEXTAREAELEMENT
|
||||
|
||||
|
@ -126,6 +126,12 @@ nsresult HTMLVideoElement::SetAcceptHeader(nsIHttpChannel* aChannel)
|
||||
false);
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLVideoElement::IsInteractiveHTMLContent() const
|
||||
{
|
||||
return HasAttr(kNameSpaceID_None, nsGkAtoms::controls);
|
||||
}
|
||||
|
||||
uint32_t HTMLVideoElement::MozParsedFrames() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
|
||||
|
@ -49,6 +49,9 @@ public:
|
||||
|
||||
virtual nsresult SetAcceptHeader(nsIHttpChannel* aChannel) MOZ_OVERRIDE;
|
||||
|
||||
// Element
|
||||
virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE;
|
||||
|
||||
// WebIDL
|
||||
|
||||
uint32_t Width() const
|
||||
|
@ -1791,6 +1791,15 @@ nsGenericHTMLElement::IsLabelable() const
|
||||
Tag() == nsGkAtoms::meter;
|
||||
}
|
||||
|
||||
bool
|
||||
nsGenericHTMLElement::IsInteractiveHTMLContent() const
|
||||
{
|
||||
return Tag() == nsGkAtoms::details ||
|
||||
Tag() == nsGkAtoms::embed ||
|
||||
Tag() == nsGkAtoms::keygen ||
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex);
|
||||
}
|
||||
|
||||
already_AddRefed<UndoManager>
|
||||
nsGenericHTMLElement::GetUndoManager()
|
||||
{
|
||||
|
@ -904,6 +904,7 @@ public:
|
||||
}
|
||||
|
||||
virtual bool IsLabelable() const MOZ_OVERRIDE;
|
||||
virtual bool IsInteractiveHTMLContent() const MOZ_OVERRIDE;
|
||||
|
||||
static bool TouchEventsEnabled(JSContext* /* unused */, JSObject* /* unused */);
|
||||
|
||||
|
@ -64,6 +64,7 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_input_untrusted_key_events.html]
|
||||
[test_input_url.html]
|
||||
[test_interactive_content_in_label.html]
|
||||
[test_label_control_attribute.html]
|
||||
[test_label_input_controls.html]
|
||||
[test_max_attribute.html]
|
||||
@ -81,6 +82,7 @@ skip-if = e10s
|
||||
[test_output_element.html]
|
||||
[test_pattern_attribute.html]
|
||||
[test_progress_element.html]
|
||||
[test_radio_in_label.html]
|
||||
[test_radio_radionodelist.html]
|
||||
[test_required_attribute.html]
|
||||
skip-if = e10s
|
||||
|
99
dom/html/test/forms/test_interactive_content_in_label.html
Normal file
99
dom/html/test/forms/test_interactive_content_in_label.html
Normal file
@ -0,0 +1,99 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=229925
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 229925</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=229925">Mozilla Bug 229925</a>
|
||||
<p id="display"></p>
|
||||
<form action="#">
|
||||
<label>
|
||||
<span id="text">label</span>
|
||||
<input type="button" id="target" value="target">
|
||||
|
||||
<a id="yes1" href="#">a</a>
|
||||
<audio id="yes2" controls></audio>
|
||||
<button id="yes3">button</button>
|
||||
<details id="yes4">details</details>
|
||||
<embed id="yes5">embed</embed>
|
||||
<iframe id="yes6" src="data:text/plain," style="width: 16px; height: 16px;"></iframe>
|
||||
<img id="yes7" src="data:image/png," usemap="#map">
|
||||
<input id="yes8" type="text" size="4">
|
||||
<keygen id="yes9">
|
||||
<label id="yes10">label</label>
|
||||
<object id="yes11" usemap="#map">object</object>
|
||||
<select id="yes12"><option>select</option></select>
|
||||
<textarea id="yes13" cols="1" rows="1"></textarea>
|
||||
<video id="yes14" controls></video>
|
||||
<span id="yes15" tabindex="1">tabindex</span>
|
||||
|
||||
<audio id="no1"></audio>
|
||||
<img id="no2" src="data:image/png,">
|
||||
<input id="no3" type="hidden">
|
||||
<object id="no4">object</object>
|
||||
<video id="no5"></video>
|
||||
</label>
|
||||
</form>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Bug 229925 **/
|
||||
|
||||
var target = document.getElementById("target");
|
||||
|
||||
var yes_nodes = [
|
||||
document.getElementById("yes1"),
|
||||
document.getElementById("yes2"),
|
||||
document.getElementById("yes3"),
|
||||
document.getElementById("yes4"),
|
||||
document.getElementById("yes5"),
|
||||
document.getElementById("yes6"),
|
||||
document.getElementById("yes7"),
|
||||
document.getElementById("yes8"),
|
||||
document.getElementById("yes9"),
|
||||
document.getElementById("yes10"),
|
||||
document.getElementById("yes11"),
|
||||
document.getElementById("yes12"),
|
||||
document.getElementById("yes13"),
|
||||
document.getElementById("yes14"),
|
||||
document.getElementById("yes15"),
|
||||
];
|
||||
|
||||
var no_nodes = [
|
||||
document.getElementById("text"),
|
||||
document.getElementById("no1"),
|
||||
document.getElementById("no2"),
|
||||
document.getElementById("no3"),
|
||||
document.getElementById("no4"),
|
||||
document.getElementById("no5"),
|
||||
];
|
||||
|
||||
var target_clicked = false;
|
||||
target.addEventListener("click", function() {
|
||||
target_clicked = true;
|
||||
});
|
||||
|
||||
var node;
|
||||
for (node of yes_nodes) {
|
||||
target_clicked = false;
|
||||
node.click();
|
||||
is(target_clicked, false, "mouse click on interactive content " + node.nodeName + " shouldn't dispatch event to label target");
|
||||
}
|
||||
|
||||
for (node of no_nodes) {
|
||||
target_clicked = false;
|
||||
node.click();
|
||||
is(target_clicked, true, "mouse click on non interactive content " + node.nodeName + " should dispatch event to label target");
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
51
dom/html/test/forms/test_radio_in_label.html
Normal file
51
dom/html/test/forms/test_radio_in_label.html
Normal file
@ -0,0 +1,51 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=229925
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 229925</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=229925">Mozilla Bug 229925</a>
|
||||
<p id="display"></p>
|
||||
<form>
|
||||
<label>
|
||||
<span id="s1">LABEL</span>
|
||||
<input type="radio" name="rdo" value="1" id="r1" onmousedown="document.body.appendChild(document.createTextNode('down'));">
|
||||
<input type="radio" name="rdo" value="2" id="r2" checked="checked">
|
||||
</label>
|
||||
</form>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Bug 229925 **/
|
||||
var r1 = document.getElementById("r1");
|
||||
var r2 = document.getElementById("r2");
|
||||
var s1 = document.getElementById("s1");
|
||||
|
||||
r1.click();
|
||||
ok(r1.checked,
|
||||
"The first radio input element should be checked by clicking the element");
|
||||
r2.click();
|
||||
ok(r2.checked,
|
||||
"The second radio input element should be checked by clicking the element");
|
||||
s1.click();
|
||||
ok(r1.checked,
|
||||
"The first radio input element should be checked by clicking other element");
|
||||
|
||||
r1.focus();
|
||||
synthesizeKey("VK_LEFT", {});
|
||||
ok(r2.checked,
|
||||
"The second radio input element should be checked by key");
|
||||
synthesizeKey("VK_LEFT", {});
|
||||
ok(r1.checked,
|
||||
"The first radio input element should be checked by key");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user