mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 08:42:13 +00:00
Bug 1748975 - Don't trigger click event on untrusted keypresses for buttons and summaries. r=edgar
Differential Revision: https://phabricator.services.mozilla.com/D154942
This commit is contained in:
parent
8466c5994a
commit
867e24f2f7
@ -233,7 +233,11 @@ nsresult HTMLButtonElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
|
||||
}
|
||||
|
||||
if (nsEventStatus_eIgnore == aVisitor.mEventStatus) {
|
||||
HandleKeyboardActivation(aVisitor);
|
||||
WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent();
|
||||
if (keyEvent && keyEvent->IsTrusted()) {
|
||||
HandleKeyboardActivation(aVisitor);
|
||||
}
|
||||
|
||||
if (aVisitor.mItemFlags & NS_OUTER_ACTIVATE_EVENT) {
|
||||
if (mForm) {
|
||||
// Hold a strong ref while dispatching
|
||||
|
@ -62,7 +62,9 @@ nsresult HTMLSummaryElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
|
||||
}
|
||||
} // event->HasMouseEventMessage()
|
||||
|
||||
HandleKeyboardActivation(aVisitor);
|
||||
if (event->HasKeyEventMessage() && event->IsTrusted()) {
|
||||
HandleKeyboardActivation(aVisitor);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -2246,11 +2246,10 @@ Result<bool, nsresult> nsGenericHTMLElement::PerformAccesskey(
|
||||
|
||||
void nsGenericHTMLElement::HandleKeyboardActivation(
|
||||
EventChainPostVisitor& aVisitor) {
|
||||
const auto message = aVisitor.mEvent->mMessage;
|
||||
if (message != eKeyDown && message != eKeyUp && message != eKeyPress) {
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(aVisitor.mEvent->HasKeyEventMessage());
|
||||
MOZ_ASSERT(aVisitor.mEvent->IsTrusted());
|
||||
|
||||
const auto message = aVisitor.mEvent->mMessage;
|
||||
const WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent();
|
||||
if (nsEventStatus_eIgnore != aVisitor.mEventStatus) {
|
||||
if (message == eKeyUp && keyEvent->mKeyCode == NS_VK_SPACE) {
|
||||
|
@ -111,6 +111,10 @@ support-files =
|
||||
[test_image_selection_3.html]
|
||||
[test_image_selection_in_contenteditable.html]
|
||||
[test_intrinsic_size_on_loading.html]
|
||||
[test_key_enter_open_second_summary.html]
|
||||
[test_key_enter_prevent_default.html]
|
||||
[test_key_enter_single_summary.html]
|
||||
[test_key_space_single_summary.html]
|
||||
[test_movement_by_characters.html]
|
||||
[test_movement_by_words.html]
|
||||
# Disable the caret movement by word test on Linux because the shortcut keys
|
||||
|
28
layout/generic/test/test_key_enter_open_second_summary.html
Normal file
28
layout/generic/test/test_key_enter_open_second_summary.html
Normal file
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
function runTest() {
|
||||
// Dispatch 'return' key on second summary should not collapse details.
|
||||
const summary = document.getElementById("summary");
|
||||
summary.focus();
|
||||
synthesizeKey("KEY_Enter");
|
||||
|
||||
const details = document.querySelector("details");
|
||||
ok(details.open, "Dispatch 'return' key on second summary should not collapse details.");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="runTest();">
|
||||
<details open>
|
||||
<summary>Summary</summary>
|
||||
<summary id="summary">Second Summary</summary>
|
||||
<p>This is the details.</p>
|
||||
</details>
|
||||
</body>
|
||||
</html>
|
31
layout/generic/test/test_key_enter_prevent_default.html
Normal file
31
layout/generic/test/test_key_enter_prevent_default.html
Normal file
@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
function runTest() {
|
||||
const summary = document.querySelector("summary");
|
||||
summary.addEventListener('click', function(e) {
|
||||
// Prevent the details from toggling by key events.
|
||||
e.preventDefault();
|
||||
});
|
||||
// Dispatch 'return' key to the summary element.
|
||||
summary.focus();
|
||||
synthesizeKey("KEY_Enter");
|
||||
|
||||
const details = document.querySelector("details");
|
||||
ok(!details.open, "Prevent default on summary should not open details.");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="runTest();">
|
||||
<details>
|
||||
<summary>Summary</summary>
|
||||
<p>This is the details.</p>
|
||||
</details>
|
||||
</body>
|
||||
</html>
|
27
layout/generic/test/test_key_enter_single_summary.html
Normal file
27
layout/generic/test/test_key_enter_single_summary.html
Normal file
@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
function runTest() {
|
||||
// Dispatch 'return' key to the summary element.
|
||||
const summary = document.querySelector("summary");
|
||||
summary.focus();
|
||||
synthesizeKey("KEY_Enter");
|
||||
|
||||
const details = document.querySelector("details");
|
||||
ok(details.open, "Dispatch return key on summary should open details.");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="runTest();">
|
||||
<details>
|
||||
<summary>Summary</summary>
|
||||
<p>This is the details.</p>
|
||||
</details>
|
||||
</body>
|
||||
</html>
|
26
layout/generic/test/test_key_space_single_summary.html
Normal file
26
layout/generic/test/test_key_space_single_summary.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
function runTest() {
|
||||
const summary = document.querySelector("summary");
|
||||
summary.focus();
|
||||
synthesizeKey(" ");
|
||||
|
||||
const details = document.querySelector("details");
|
||||
ok(details.open, "Dispatch space key on summary should open details.");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="runTest();">
|
||||
<details>
|
||||
<summary>Summary</summary>
|
||||
<p>This is the details.</p>
|
||||
</details>
|
||||
</body>
|
||||
</html>
|
@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
|
||||
<html class="reftest-wait">
|
||||
<script>
|
||||
function runTest() {
|
||||
// Dispatch 'return' key on second summary should not collapse details.
|
||||
var summary = document.getElementById("summary");
|
||||
summary.dispatchEvent(new KeyboardEvent("keypress", {"keyCode": 13}));
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
</script>
|
||||
<body onload="runTest();">
|
||||
<details open>
|
||||
<summary>Summary</summary>
|
||||
<summary id="summary">Second Summary</summary>
|
||||
<p>This is the details.</p>
|
||||
</details>
|
||||
</body>
|
||||
</html>
|
@ -1,24 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
|
||||
<html class="reftest-wait">
|
||||
<script>
|
||||
function runTest() {
|
||||
var summary = document.getElementById("summary");
|
||||
summary.addEventListener('click', function(e) {
|
||||
// Prevent the details from toggling by key events.
|
||||
e.preventDefault();
|
||||
});
|
||||
// Dispatch 'return' key to the summary element.
|
||||
summary.dispatchEvent(new KeyboardEvent("keypress", {"keyCode": 13}));
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
</script>
|
||||
<body onload="runTest();">
|
||||
<details>
|
||||
<summary id="summary">Summary</summary>
|
||||
<p>This is the details.</p>
|
||||
</details>
|
||||
</body>
|
||||
</html>
|
@ -1,20 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
|
||||
<html class="reftest-wait">
|
||||
<script>
|
||||
function runTest() {
|
||||
var summary = document.getElementById("summary");
|
||||
// Dispatch 'return' key to the summary element.
|
||||
summary.dispatchEvent(new KeyboardEvent("keypress", {"keyCode": 13}));
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
</script>
|
||||
<body onload="runTest();">
|
||||
<details>
|
||||
<summary id="summary">Summary</summary>
|
||||
<p>This is the details.</p>
|
||||
</details>
|
||||
</body>
|
||||
</html>
|
@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
|
||||
<html class="reftest-wait">
|
||||
<script>
|
||||
function runTest() {
|
||||
var summary = document.getElementById("summary");
|
||||
// Dispatch 'space' keys to the summary element.
|
||||
summary.dispatchEvent(new KeyboardEvent("keydown", {"keyCode": 32}));
|
||||
summary.dispatchEvent(new KeyboardEvent("keyup", {"keyCode": 32}));
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
</script>
|
||||
<body onload="runTest();">
|
||||
<details>
|
||||
<summary id="summary">Summary</summary>
|
||||
<p>This is the details.</p>
|
||||
</details>
|
||||
</body>
|
||||
</html>
|
@ -84,12 +84,6 @@ fuzzy(0-1,0-172) == mouse-click-overflow-auto-details.html overflow-auto-open-de
|
||||
fuzzy-if(geckoview,0-7,0-1) == mouse-click-float-details.html open-float-details.html
|
||||
fuzzy(0-4,0-1) == mouse-click-twice-float-details.html float-details.html # Bug 1316430
|
||||
|
||||
# Dispatch keyboard event to summary
|
||||
== key-enter-single-summary.html open-single-summary.html
|
||||
== key-enter-open-second-summary.html open-multiple-summary.html
|
||||
== key-enter-prevent-default.html single-summary.html
|
||||
== key-space-single-summary.html open-single-summary.html
|
||||
|
||||
# Generated content bits
|
||||
== details-after.html single-summary.html
|
||||
== details-before.html single-summary.html
|
||||
|
@ -0,0 +1,112 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Forms</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<form id="input_form">
|
||||
<button name="submitButton" type="submit">Submit</button>
|
||||
<button name="resetButton" type="reset">Reset</button>
|
||||
<button name="buttonButton" type="button">Button</button>
|
||||
</form>
|
||||
<script type="module">
|
||||
const form = document.querySelector("form");
|
||||
form.addEventListener("submit", (e) => {
|
||||
e.preventDefault();
|
||||
assert_true(false, 'form should not be submitted');
|
||||
});
|
||||
|
||||
for (const button of document.querySelectorAll("button")) {
|
||||
button.addEventListener("click", function(e) {
|
||||
assert_true(false, `${button.type} button should not be clicked`);
|
||||
});
|
||||
}
|
||||
|
||||
// Create and append button elements
|
||||
for (const button of document.querySelectorAll("button")) {
|
||||
test(() => {
|
||||
// keyCode: Enter
|
||||
button.dispatchEvent(
|
||||
new KeyboardEvent("keypress", {
|
||||
keyCode: 13,
|
||||
})
|
||||
);
|
||||
|
||||
// key: Enter
|
||||
button.dispatchEvent(
|
||||
new KeyboardEvent("keypress", {
|
||||
key: "Enter",
|
||||
})
|
||||
);
|
||||
|
||||
// keyCode: Space
|
||||
button.dispatchEvent(
|
||||
new KeyboardEvent("keypress", {
|
||||
keyCode: 32,
|
||||
})
|
||||
);
|
||||
|
||||
// key: Space
|
||||
button.dispatchEvent(
|
||||
new KeyboardEvent("keypress", {
|
||||
key: " ",
|
||||
})
|
||||
);
|
||||
}, `Dispatching untrusted keypress events to ${button.type} button should not cause click event`);
|
||||
|
||||
test(() => {
|
||||
// keyCode: Enter
|
||||
button.dispatchEvent(
|
||||
new KeyboardEvent("keydown", {
|
||||
keyCode: 13,
|
||||
})
|
||||
);
|
||||
button.dispatchEvent(
|
||||
new KeyboardEvent("keyup", {
|
||||
keyCode: 13,
|
||||
})
|
||||
);
|
||||
|
||||
// key: Enter
|
||||
button.dispatchEvent(
|
||||
new KeyboardEvent("keydown", {
|
||||
key: "Enter",
|
||||
})
|
||||
);
|
||||
button.dispatchEvent(
|
||||
new KeyboardEvent("keyup", {
|
||||
key: "Enter",
|
||||
})
|
||||
);
|
||||
|
||||
// keyCode: Space
|
||||
button.dispatchEvent(
|
||||
new KeyboardEvent("keydown", {
|
||||
keyCode: 32,
|
||||
})
|
||||
);
|
||||
button.dispatchEvent(
|
||||
new KeyboardEvent("keyup", {
|
||||
keyCode: 32,
|
||||
})
|
||||
);
|
||||
|
||||
// key: Space
|
||||
button.dispatchEvent(
|
||||
new KeyboardEvent("keydown", {
|
||||
key: " ",
|
||||
})
|
||||
);
|
||||
button.dispatchEvent(
|
||||
new KeyboardEvent("keyup", {
|
||||
key: " ",
|
||||
})
|
||||
);
|
||||
}, `Dispatching untrusted keyup/keydown events to ${button.type} button should not cause click event`);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,104 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Summary</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<details>
|
||||
<summary>Summary</summary>
|
||||
Details
|
||||
</details>
|
||||
<script type="module">
|
||||
const details = document.querySelector("details");
|
||||
details.addEventListener("toggle",
|
||||
(e) => assert_true(false, 'details should not be toggled'));
|
||||
|
||||
const summary = document.querySelector("summary");
|
||||
summary.addEventListener("click",
|
||||
(e) => assert_true(false, `summary should not be clicked`));
|
||||
|
||||
test(() => {
|
||||
// keyCode: Enter
|
||||
summary.dispatchEvent(
|
||||
new KeyboardEvent("keypress", {
|
||||
keyCode: 13,
|
||||
})
|
||||
);
|
||||
|
||||
// key: Enter
|
||||
summary.dispatchEvent(
|
||||
new KeyboardEvent("keypress", {
|
||||
key: "Enter",
|
||||
})
|
||||
);
|
||||
|
||||
// keyCode: Space
|
||||
summary.dispatchEvent(
|
||||
new KeyboardEvent("keypress", {
|
||||
keyCode: 32,
|
||||
})
|
||||
);
|
||||
|
||||
// key: Space
|
||||
summary.dispatchEvent(
|
||||
new KeyboardEvent("keypress", {
|
||||
key: " ",
|
||||
})
|
||||
);
|
||||
}, `Dispatching untrusted keypress events to summary should not cause click event`);
|
||||
|
||||
test(() => {
|
||||
// keyCode: Enter
|
||||
summary.dispatchEvent(
|
||||
new KeyboardEvent("keydown", {
|
||||
keyCode: 13,
|
||||
})
|
||||
);
|
||||
summary.dispatchEvent(
|
||||
new KeyboardEvent("keyup", {
|
||||
keyCode: 13,
|
||||
})
|
||||
);
|
||||
|
||||
// key: Enter
|
||||
summary.dispatchEvent(
|
||||
new KeyboardEvent("keydown", {
|
||||
key: "Enter",
|
||||
})
|
||||
);
|
||||
summary.dispatchEvent(
|
||||
new KeyboardEvent("keyup", {
|
||||
key: "Enter",
|
||||
})
|
||||
);
|
||||
|
||||
// keyCode: Space
|
||||
summary.dispatchEvent(
|
||||
new KeyboardEvent("keydown", {
|
||||
keyCode: 32,
|
||||
})
|
||||
);
|
||||
summary.dispatchEvent(
|
||||
new KeyboardEvent("keyup", {
|
||||
keyCode: 32,
|
||||
})
|
||||
);
|
||||
|
||||
// key: Space
|
||||
summary.dispatchEvent(
|
||||
new KeyboardEvent("keydown", {
|
||||
key: " ",
|
||||
})
|
||||
);
|
||||
summary.dispatchEvent(
|
||||
new KeyboardEvent("keyup", {
|
||||
key: " ",
|
||||
})
|
||||
);
|
||||
}, `Dispatching untrusted keyup/keydown events to summary should not cause click event`);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user