Bug 1489440 - Fix nsFormFillController in presence of Shadow DOM. r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D17121

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Emilio Cobos Álvarez 2019-01-21 14:29:16 +00:00
parent d93a655764
commit 375a43132d
3 changed files with 128 additions and 3 deletions

View File

@ -789,7 +789,7 @@ nsFormFillController::HandleEvent(Event* aEvent) {
case eKeyPress: case eKeyPress:
return KeyPress(aEvent); return KeyPress(aEvent);
case eEditorInput: { case eEditorInput: {
nsCOMPtr<nsINode> input = do_QueryInterface(aEvent->GetTarget()); nsCOMPtr<nsINode> input = do_QueryInterface(aEvent->GetComposedTarget());
if (!IsTextControl(input)) { if (!IsTextControl(input)) {
return NS_OK; return NS_OK;
} }
@ -927,7 +927,7 @@ void nsFormFillController::MaybeStartControllingInput(
} }
nsresult nsFormFillController::Focus(Event* aEvent) { nsresult nsFormFillController::Focus(Event* aEvent) {
nsCOMPtr<nsIContent> input = do_QueryInterface(aEvent->GetTarget()); nsCOMPtr<nsIContent> input = do_QueryInterface(aEvent->GetComposedTarget());
MaybeStartControllingInput(HTMLInputElement::FromNodeOrNull(input)); MaybeStartControllingInput(HTMLInputElement::FromNodeOrNull(input));
// Bail if we didn't start controlling the input. // Bail if we didn't start controlling the input.
@ -1094,7 +1094,7 @@ nsresult nsFormFillController::MouseDown(Event* aEvent) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
nsCOMPtr<nsINode> targetNode = do_QueryInterface(aEvent->GetTarget()); nsCOMPtr<nsINode> targetNode = do_QueryInterface(aEvent->GetComposedTarget());
if (!HTMLInputElement::FromNodeOrNull(targetNode)) { if (!HTMLInputElement::FromNodeOrNull(targetNode)) {
return NS_OK; return NS_OK;
} }

View File

@ -11,6 +11,7 @@ skip-if = os == 'linux' # bug 1022386
[test_bug_787624.html] [test_bug_787624.html]
skip-if = os == 'linux' # bug 1022386 skip-if = os == 'linux' # bug 1022386
[test_datalist_with_caching.html] [test_datalist_with_caching.html]
[test_datalist_shadow_dom.html]
[test_form_autocomplete.html] [test_form_autocomplete.html]
skip-if = (verify && debug && (os == 'win')) || os == 'linux' # linux - bug 1022386 skip-if = (verify && debug && (os == 'win')) || os == 'linux' # linux - bug 1022386
[test_form_autocomplete_with_list.html] [test_form_autocomplete_with_list.html]

View File

@ -0,0 +1,124 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for datalist in Shadow DOM</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/AddTask.js"></script>
<script type="text/javascript" src="satchel_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content">
<div id="host"></div>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
const host = document.getElementById("host");
host.attachShadow({ mode: "open" }).innerHTML = `
<form id="form1" onsubmit="return false;">
<input list="suggest" type="text" name="field1">
<button type="submit">Submit</button>
</form>
<datalist id="suggest">
<option value="First"></option>
<option value="Second"></option>
<option value="Secomundo"></option>
</datalist><Paste>
`;
let input = host.shadowRoot.querySelector("input");
function setForm(value) {
input.value = value;
input.focus();
}
// Restore the form to the default state.
function restoreForm() {
setForm("");
}
// Check for expected form data.
function checkForm(expectedValue) {
let formID = input.parentNode.id;
is(input.value, expectedValue, "Checking " + formID + " input");
}
SimpleTest.waitForExplicitFinish();
var expectingPopup = null;
function expectPopup() {
info("expecting a popup");
return new Promise(resolve => {
expectingPopup = resolve;
});
}
var testNum = 0;
function popupShownListener() {
info("popup shown for test " + testNum);
if (expectingPopup) {
expectingPopup();
expectingPopup = null;
} else {
ok(false, "Autocomplete popup not expected during test " + testNum);
}
}
function waitForMenuChange(expectedCount) {
return new Promise(resolve => {
notifyMenuChanged(expectedCount, null, resolve);
});
}
registerPopupShownListener(popupShownListener);
function checkMenuEntries(expectedValues) {
let actualValues = getMenuEntries();
is(actualValues.length, expectedValues.length, testNum + " Checking length of expected menu");
for (let i = 0; i < expectedValues.length; i++) {
is(actualValues[i], expectedValues[i], testNum + " Checking menu entry #" + i);
}
}
async function runTests() {
testNum++;
restoreForm();
synthesizeKey("KEY_ArrowDown");
await expectPopup();
checkMenuEntries(["First", "Second", "Secomundo"]);
synthesizeKey("KEY_ArrowDown");
synthesizeKey("KEY_Enter");
checkForm("First");
testNum++;
restoreForm();
sendString("Sec");
synthesizeKey("KEY_ArrowDown");
await expectPopup();
testNum++;
checkMenuEntries(["Second", "Secomundo"]);
sendString("o");
await waitForMenuChange(2);
testNum++;
checkMenuEntries(["Second", "Secomundo"]);
synthesizeKey("KEY_ArrowDown");
synthesizeKey("KEY_Enter");
checkForm("Second");
SimpleTest.finish();
}
window.onload = runTests();
</script>
</pre>
</body>
</html>