Bug 1519486 - convert autocomplete-richlistitem XBL binding to CE, r=MattN

This commit is contained in:
Alexander Surkov 2019-01-24 08:40:36 -05:00
Родитель fccfd070c9
Коммит 599d3ecb6b
10 изменённых файлов: 195 добавлений и 40 удалений

Просмотреть файл

@ -37,9 +37,9 @@ if (AppConstants.DEBUG ||
EXPECTED_REFLOWS_FIRST_OPEN.push(
{
stack: [
"_handleOverflow@chrome://global/content/bindings/autocomplete.xml",
"handleOverUnderflow@chrome://global/content/bindings/autocomplete.xml",
"_reuseAcItem@chrome://global/content/bindings/autocomplete.xml",
"_handleOverflow@chrome://global/content/elements/autocomplete-richlistitem.js",
"handleOverUnderflow@chrome://global/content/elements/autocomplete-richlistitem.js",
"_reuseAcItem@chrome://global/content/elements/autocomplete-richlistitem.js",
"_appendCurrentResult@chrome://global/content/bindings/autocomplete.xml",
"_invalidate@chrome://global/content/bindings/autocomplete.xml",
"invalidate@chrome://global/content/bindings/autocomplete.xml",
@ -49,8 +49,8 @@ EXPECTED_REFLOWS_FIRST_OPEN.push(
{
stack: [
"_handleOverflow@chrome://global/content/bindings/autocomplete.xml",
"handleOverUnderflow@chrome://global/content/bindings/autocomplete.xml",
"_handleOverflow@chrome://global/content/elements/autocomplete-richlistitem.js",
"handleOverUnderflow@chrome://global/content/elements/autocomplete-richlistitem.js",
"_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
"openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
"openPopup@chrome://global/content/bindings/autocomplete.xml",
@ -91,8 +91,8 @@ if (AppConstants.RELEASE_OR_BETA) {
},
{
stack: [
"_handleOverflow@chrome://global/content/bindings/autocomplete.xml",
"_adjustAcItem@chrome://global/content/bindings/autocomplete.xml",
"_handleOverflow@chrome://global/content/elements/autocomplete-richlistitem.js",
"_adjustAcItem@chrome://global/content/elements/autocomplete-richlistitem.js",
"_appendCurrentResult@chrome://global/content/bindings/autocomplete.xml",
"_invalidate@chrome://global/content/bindings/autocomplete.xml",
"invalidate@chrome://global/content/bindings/autocomplete.xml",

Просмотреть файл

@ -38,9 +38,9 @@ if (AppConstants.DEBUG ||
EXPECTED_REFLOWS_FIRST_OPEN.push(
{
stack: [
"_handleOverflow@chrome://global/content/bindings/autocomplete.xml",
"handleOverUnderflow@chrome://global/content/bindings/autocomplete.xml",
"_reuseAcItem@chrome://global/content/bindings/autocomplete.xml",
"_handleOverflow@chrome://global/content/elements/autocomplete-richlistitem.js",
"handleOverUnderflow@chrome://global/content/elements/autocomplete-richlistitem.js",
"_reuseAcItem@chrome://global/content/elements/autocomplete-richlistitem.js",
"_appendCurrentResult@chrome://global/content/bindings/autocomplete.xml",
"_invalidate@chrome://global/content/bindings/autocomplete.xml",
"invalidate@chrome://global/content/bindings/autocomplete.xml",
@ -50,8 +50,8 @@ EXPECTED_REFLOWS_FIRST_OPEN.push(
{
stack: [
"_handleOverflow@chrome://global/content/bindings/autocomplete.xml",
"handleOverUnderflow@chrome://global/content/bindings/autocomplete.xml",
"_handleOverflow@chrome://global/content/elements/autocomplete-richlistitem.js",
"handleOverUnderflow@chrome://global/content/elements/autocomplete-richlistitem.js",
"_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
"openAutocompletePopup@chrome://browser/content/urlbarBindings.xml",
"openPopup@chrome://global/content/bindings/autocomplete.xml",
@ -75,9 +75,9 @@ EXPECTED_REFLOWS_FIRST_OPEN.push(
const EXPECTED_REFLOWS_SECOND_OPEN = [
{
stack: [
"_handleOverflow@chrome://global/content/bindings/autocomplete.xml",
"handleOverUnderflow@chrome://global/content/bindings/autocomplete.xml",
"_reuseAcItem@chrome://global/content/bindings/autocomplete.xml",
"_handleOverflow@chrome://global/content/elements/autocomplete-richlistitem.js",
"handleOverUnderflow@chrome://global/content/elements/autocomplete-richlistitem.js",
"_reuseAcItem@chrome://global/content/elements/autocomplete-richlistitem.js",
"_appendCurrentResult@chrome://global/content/bindings/autocomplete.xml",
"_invalidate@chrome://global/content/bindings/autocomplete.xml",
"invalidate@chrome://global/content/bindings/autocomplete.xml",

Просмотреть файл

@ -6,6 +6,7 @@ support-files =
formautofill_parent_utils.js
[test_address_level_1_submission.html]
[test_autofill_and_ordinal_forms.html]
[test_autofocus_form.html]
skip-if = verify
[test_basic_autocomplete_form.html]

Просмотреть файл

@ -0,0 +1,115 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test autofill submit</title>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/AddTask.js"></script>
<script type="text/javascript" src="formautofill_common.js"></script>
<script type="text/javascript" src="satchel_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script>
/* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */
"use strict";
let MOCK_STORAGE = [{
"given-name": "John",
"additional-name": "R",
"family-name": "Smith",
"organization": "Sesame Street",
"street-address": "123 Sesame Street.",
"tel": "+13453453456",
"country": "US",
"address-level1": "NY",
}];
initPopupListener();
add_task(async function setupStorage() {
await addAddress(MOCK_STORAGE[0]);
await updateFormHistory([
{op: "add", fieldname: "username", value: "petya"},
{op: "add", fieldname: "current-password", value: "abrh#25_,K"},
]);
});
add_task(async function check_switch_autofill_form_popup() {
await setInput("#tel", "");
synthesizeKey("KEY_ArrowDown");
await expectPopup();
checkMenuEntries(
[
`{"primary":"+13453453456","secondary":"123 Sesame Street."}`,
`{"primary":"","secondary":"","categories":["name","organization","address","tel"],"focusedCategory":"tel"}`,
],
false
);
await testMenuEntry(0, "!(el instanceof MozElements.MozAutocompleteRichlistitem)");
});
add_task(async function check_switch_oridnal_form_popup() {
// We need an intentional wait here before switching form.
await sleep();
await setInput("#username", "");
synthesizeKey("KEY_ArrowDown");
await expectPopup();
checkMenuEntries(["petya"], false);
await testMenuEntry(0, "el instanceof MozElements.MozAutocompleteRichlistitem");
});
add_task(async function check_switch_autofill_form_popup_back() {
// We need an intentional wait here before switching form.
await sleep();
await setInput("#tel", "");
synthesizeKey("KEY_ArrowDown");
await expectPopup();
checkMenuEntries(
[
`{"primary":"+13453453456","secondary":"123 Sesame Street."}`,
`{"primary":"","secondary":"","categories":["name","organization","address","tel"],"focusedCategory":"tel"}`,
],
false
);
await testMenuEntry(0, "!(el instanceof MozElements.MozAutocompleteRichlistitem)");
});
</script>
<div>
<h2>Address form</h2>
<form class="alignedLabels">
<label>given-name: <input autocomplete="given-name" autofocus></label>
<label>additional-name: <input id="additional-name" autocomplete="additional-name"></label>
<label>family-name: <input autocomplete="family-name"></label>
<label>organization: <input autocomplete="organization"></label>
<label>street-address: <input autocomplete="street-address"></label>
<label>address-level1: <input autocomplete="address-level1"></label>
<label>postal-code: <input autocomplete="postal-code"></label>
<label>country: <input autocomplete="country"></label>
<label>country-name: <input autocomplete="country-name"></label>
<label>tel: <input id="tel" autocomplete="tel"></label>
<p>
<input type="submit" value="Submit">
<button type="reset">Reset</button>
</p>
</form>
<h2>Ordinal form</h2>
<form class="alignedLabels">
<label>username: <input id="username" autocomplete="username"></label>
<p><input type="submit" value="Username"></p>
</form>
</div>
</body>
</html>

Просмотреть файл

@ -150,12 +150,12 @@ add_task(async function test_popup_url() {
results[1].removeAttribute("selected");
let urlText = document.getAnonymousElementByAttribute(results[1], "anonid", "url-text");
let urlText = results[1]._urlText;
Assert.equal(window.getComputedStyle(urlText).color,
`rgb(${hexToRGB(POPUP_URL_COLOR_DARK).join(", ")})`,
`Urlbar popup url color should be set to ${POPUP_URL_COLOR_DARK}`);
let actionText = document.getAnonymousElementByAttribute(results[1], "anonid", "action-text");
let actionText = results[1]._actionText;
Assert.equal(window.getComputedStyle(actionText).color,
`rgb(${hexToRGB(POPUP_ACTION_COLOR_DARK).join(", ")})`,
`Urlbar popup action color should be set to ${POPUP_ACTION_COLOR_DARK}`);
@ -203,19 +203,19 @@ add_task(async function test_popup_url() {
`rgb(${hexToRGB(POPUP_TEXT_COLOR_BRIGHT).join(", ")})`,
`Popup color should be set to ${POPUP_TEXT_COLOR_BRIGHT}`);
urlText = document.getAnonymousElementByAttribute(results[1], "anonid", "url-text");
urlText = results[1]._urlText;
Assert.equal(window.getComputedStyle(urlText).color,
`rgb(${hexToRGB(POPUP_URL_COLOR_BRIGHT).join(", ")})`,
`Urlbar popup url color should be set to ${POPUP_URL_COLOR_BRIGHT}`);
actionText = document.getAnonymousElementByAttribute(results[1], "anonid", "action-text");
actionText = results[1]._actionText;
Assert.equal(window.getComputedStyle(actionText).color,
`rgb(${hexToRGB(POPUP_ACTION_COLOR_BRIGHT).join(", ")})`,
`Urlbar popup action color should be set to ${POPUP_ACTION_COLOR_BRIGHT}`);
// Since brighttext is enabled, the seperator color should be
// POPUP_TEXT_COLOR_BRIGHT with added alpha.
let separator = document.getAnonymousElementByAttribute(results[1], "anonid", "separator");
let separator = results[1]._separator;
Assert.equal(window.getComputedStyle(separator).color,
`rgba(${hexToRGB(POPUP_TEXT_COLOR_BRIGHT).join(", ")}, 0.5)`,
`Urlbar popup separator color should be set to ${POPUP_TEXT_COLOR_BRIGHT} with alpha`);
@ -245,7 +245,7 @@ add_task(async function test_popup_url() {
let GRAY_TEXT = window.getComputedStyle(span).color;
span.remove();
separator = document.getAnonymousElementByAttribute(results[1], "anonid", "separator");
separator = results[1]._separator;
Assert.equal(window.getComputedStyle(separator).color,
GRAY_TEXT,
`Urlbar popup separator color should be set to ${GRAY_TEXT}`);

Просмотреть файл

@ -101,6 +101,16 @@ var ParentUtils = {
});
},
testMenuEntry(index, statement) {
ContentTaskUtils.waitForCondition(() => {
let el = gAutocompletePopup.richlistbox.getItemAtIndex(index);
let testFunc = new Services.ww.activeWindow.Function("el", `return ${statement}`);
return gAutocompletePopup.popupOpen && el && testFunc(el);
}, "Testing menu entry").then(() => {
sendAsyncMessage("menuEntryTested");
});
},
getPopupState() {
sendAsyncMessage("gotPopupState", {
open: gAutocompletePopup.popupOpen,
@ -142,6 +152,9 @@ addMessageListener("waitForMenuChange", ({ expectedCount, expectedFirstValue })
addMessageListener("waitForSelectedIndex", ({ expectedIndex }) => {
ParentUtils.checkSelectedIndex(expectedIndex);
});
addMessageListener("waitForMenuEntryTest", ({ index, statement }) => {
ParentUtils.testMenuEntry(index, statement);
});
addMessageListener("getPopupState", () => {
ParentUtils.getPopupState();

Просмотреть файл

@ -206,6 +206,16 @@ function notifySelectedIndex(expectedIndex, then = null) {
});
}
function testMenuEntry(index, statement) {
return new Promise(resolve => {
gChromeScript.sendAsyncMessage("waitForMenuEntryTest", { index, statement });
gChromeScript.addMessageListener("menuEntryTested", function changed() {
gChromeScript.removeMessageListener("menuEntryTested", changed);
resolve();
});
});
}
function getPopupState(then = null) {
return new Promise(resolve => {
gChromeScript.sendAsyncMessage("getPopupState");

Просмотреть файл

@ -9,7 +9,7 @@
{
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
class MozAutocompleteRichlistitem extends MozElements.MozRichlistitem {
MozElements.MozAutocompleteRichlistitem = class MozAutocompleteRichlistitem extends MozElements.MozRichlistitem {
constructor() {
super();
@ -62,8 +62,6 @@ class MozAutocompleteRichlistitem extends MozElements.MozRichlistitem {
this.textContent = "";
this.appendChild(MozXULElement.parseXULToFragment(this._markup));
this.setAttribute("align", "center");
this._boundaryCutoff = null;
this._inOverflow = false;
@ -908,14 +906,14 @@ class MozAutocompleteRichlistitem extends MozElements.MozRichlistitem {
return action;
}
}
};
MozXULElement.implementCustomInterface(
MozAutocompleteRichlistitem,
MozElements.MozAutocompleteRichlistitem,
[Ci.nsIDOMXULSelectControlItemElement]
);
class MozAutocompleteRichlistitemInsecureWarning extends MozAutocompleteRichlistitem {
class MozAutocompleteRichlistitemInsecureWarning extends MozElements.MozAutocompleteRichlistitem {
constructor() {
super();
@ -1019,6 +1017,10 @@ class MozAutocompleteRichlistitemInsecureWarning extends MozAutocompleteRichlist
}
}
customElements.define("autocomplete-richlistitem", MozElements.MozAutocompleteRichlistitem, {
extends: "richlistitem",
});
customElements.define("autocomplete-richlistitem-insecure-warning", MozAutocompleteRichlistitemInsecureWarning, {
extends: "richlistitem",
});

Просмотреть файл

@ -1014,7 +1014,6 @@
break;
}
let item;
let reusable = false;
let itemExists = this._currentIndex < existingItemsCount;
let originalValue, originalText, originalType;
@ -1029,6 +1028,7 @@
// trim the leading/trailing whitespace
let trimmedSearchString = controller.searchString.replace(/^\s+/, "").replace(/\s+$/, "");
let reusable = false;
if (itemExists) {
item = this.richlistbox.children[this._currentIndex];
@ -1049,11 +1049,26 @@
// neither of their style are in the UNREUSEABLE_STYLES.
reusable = originalType === style ||
!(UNREUSEABLE_STYLES.includes(style) || UNREUSEABLE_STYLES.includes(originalType));
} else {
// need to create a new item
let options = style == "insecureWarning" ?
{ is: "autocomplete-richlistitem-insecure-warning" } : null;
}
// If no reusable item available, then create a new item.
if (!reusable) {
let options = null;
switch (style) {
case "autofill-profile":
case "autofill-footer":
case "autofill-clear-button":
case "autofill-insecureWarning":
// implemented via XBL bindings, no CE for them
break;
case "insecureWarning":
options = { is: "autocomplete-richlistitem-insecure-warning" };
break;
default:
options = { is: "autocomplete-richlistitem" };
}
item = document.createXULElement("richlistitem", options);
item.className = "autocomplete-richlistitem";
}
item.setAttribute("dir", this.style.direction);
@ -1086,20 +1101,18 @@
item.setAttribute("originaltype", style);
}
if (itemExists) {
if (reusable) {
// Adjust only when the result's type is reusable for existing
// item's. Otherwise, we might insensibly call old _adjustAcItem()
// as new binding has not been attached yet.
// We don't need to worry about switching to new binding, since
// _adjustAcItem() will fired by its own constructor accordingly.
if (reusable) {
item._adjustAcItem();
}
item._adjustAcItem();
item.collapsed = false;
} else if (itemExists) {
let oldItem = this.richlistbox.children[this._currentIndex];
this.richlistbox.replaceChild(item, oldItem);
} else {
// set the class at the end so we can use the attributes
// in the xbl constructor
item.className = "autocomplete-richlistitem";
this.richlistbox.appendChild(item);
}

Просмотреть файл

@ -582,8 +582,9 @@ panel[type="autocomplete-richlistbox"] {
}
.autocomplete-richlistitem {
-moz-binding: url("chrome://global/content/bindings/autocomplete.xml#autocomplete-richlistitem");
-moz-binding: none;
-moz-box-orient: vertical;
-moz-box-align: center;
overflow: -moz-hidden-unscrollable;
}