зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1387988 - [Form Autofill] Move "findLabelElements" function to FormAutofillHeuristics.jsm. r=MattN
MozReview-Commit-ID: 93c9R7JaCLA --HG-- extra : rebase_source : 2cb9276901c4f2ff91da55cc5d0dc095a74524dd
This commit is contained in:
Родитель
179961b3c9
Коммит
04df87ad05
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
this.EXPORTED_SYMBOLS = ["FormAutofillHeuristics"];
|
this.EXPORTED_SYMBOLS = ["FormAutofillHeuristics", "LabelUtils"];
|
||||||
|
|
||||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||||
|
|
||||||
|
@ -182,6 +182,84 @@ class FieldScanner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.LabelUtils = {
|
||||||
|
// The tag name list is from Chromium except for "STYLE":
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
|
// https://cs.chromium.org/chromium/src/components/autofill/content/renderer/form_autofill_util.cc?l=216&rcl=d33a171b7c308a64dc3372fac3da2179c63b419e
|
||||||
|
EXCLUDED_TAGS: ["SCRIPT", "NOSCRIPT", "OPTION", "STYLE"],
|
||||||
|
/**
|
||||||
|
* Extract all strings of an element's children to an array.
|
||||||
|
* "element.textContent" is a string which is merged of all children nodes,
|
||||||
|
* and this function provides an array of the strings contains in an element.
|
||||||
|
*
|
||||||
|
* @param {Object} element
|
||||||
|
* A DOM element to be extracted.
|
||||||
|
* @returns {Array}
|
||||||
|
* All strings in an element.
|
||||||
|
*/
|
||||||
|
extractLabelStrings(element) {
|
||||||
|
let strings = [];
|
||||||
|
let _extractLabelStrings = (el) => {
|
||||||
|
if (this.EXCLUDED_TAGS.includes(el.tagName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (el.nodeType == Ci.nsIDOMNode.TEXT_NODE ||
|
||||||
|
el.childNodes.length == 0) {
|
||||||
|
let trimmedText = el.textContent.trim();
|
||||||
|
if (trimmedText) {
|
||||||
|
strings.push(trimmedText);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let node of el.childNodes) {
|
||||||
|
if (node.nodeType != Ci.nsIDOMNode.ELEMENT_NODE &&
|
||||||
|
node.nodeType != Ci.nsIDOMNode.TEXT_NODE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_extractLabelStrings(node);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
_extractLabelStrings(element);
|
||||||
|
return strings;
|
||||||
|
},
|
||||||
|
|
||||||
|
findLabelElements(element) {
|
||||||
|
let document = element.ownerDocument;
|
||||||
|
let labels = [];
|
||||||
|
// TODO: querySelectorAll is inefficient here. However, bug 1339726 is for
|
||||||
|
// a more efficient implementation from DOM API perspective. This function
|
||||||
|
// should be refined after input.labels API landed.
|
||||||
|
for (let label of document.querySelectorAll("label[for]")) {
|
||||||
|
if (element.id == label.htmlFor) {
|
||||||
|
labels.push(label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (labels.length > 0) {
|
||||||
|
log.debug("Label found by ID", element.id);
|
||||||
|
return labels;
|
||||||
|
}
|
||||||
|
|
||||||
|
let parent = element.parentNode;
|
||||||
|
if (!parent) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
if (parent.tagName == "LABEL" &&
|
||||||
|
parent.control == element &&
|
||||||
|
!parent.hasAttribute("for")) {
|
||||||
|
log.debug("Label found in input's parent or ancestor.");
|
||||||
|
return [parent];
|
||||||
|
}
|
||||||
|
parent = parent.parentNode;
|
||||||
|
} while (parent);
|
||||||
|
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the autocomplete information of fields according to heuristics.
|
* Returns the autocomplete information of fields according to heuristics.
|
||||||
*/
|
*/
|
||||||
|
@ -370,9 +448,9 @@ this.FormAutofillHeuristics = {
|
||||||
yield element.name;
|
yield element.name;
|
||||||
if (!labelStrings) {
|
if (!labelStrings) {
|
||||||
labelStrings = [];
|
labelStrings = [];
|
||||||
let labels = FormAutofillUtils.findLabelElements(element);
|
let labels = LabelUtils.findLabelElements(element);
|
||||||
for (let label of labels) {
|
for (let label of labels) {
|
||||||
labelStrings.push(...FormAutofillUtils.extractLabelStrings(label));
|
labelStrings.push(...LabelUtils.extractLabelStrings(label));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yield *labelStrings;
|
yield *labelStrings;
|
||||||
|
|
|
@ -128,82 +128,6 @@ this.FormAutofillUtils = {
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
// The tag name list is from Chromium except for "STYLE":
|
|
||||||
// eslint-disable-next-line max-len
|
|
||||||
// https://cs.chromium.org/chromium/src/components/autofill/content/renderer/form_autofill_util.cc?l=216&rcl=d33a171b7c308a64dc3372fac3da2179c63b419e
|
|
||||||
EXCLUDED_TAGS: ["SCRIPT", "NOSCRIPT", "OPTION", "STYLE"],
|
|
||||||
/**
|
|
||||||
* Extract all strings of an element's children to an array.
|
|
||||||
* "element.textContent" is a string which is merged of all children nodes,
|
|
||||||
* and this function provides an array of the strings contains in an element.
|
|
||||||
*
|
|
||||||
* @param {Object} element
|
|
||||||
* A DOM element to be extracted.
|
|
||||||
* @returns {Array}
|
|
||||||
* All strings in an element.
|
|
||||||
*/
|
|
||||||
extractLabelStrings(element) {
|
|
||||||
let strings = [];
|
|
||||||
let _extractLabelStrings = (el) => {
|
|
||||||
if (this.EXCLUDED_TAGS.includes(el.tagName)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (el.nodeType == Ci.nsIDOMNode.TEXT_NODE ||
|
|
||||||
el.childNodes.length == 0) {
|
|
||||||
let trimmedText = el.textContent.trim();
|
|
||||||
if (trimmedText) {
|
|
||||||
strings.push(trimmedText);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let node of el.childNodes) {
|
|
||||||
if (node.nodeType != Ci.nsIDOMNode.ELEMENT_NODE &&
|
|
||||||
node.nodeType != Ci.nsIDOMNode.TEXT_NODE) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
_extractLabelStrings(node);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
_extractLabelStrings(element);
|
|
||||||
return strings;
|
|
||||||
},
|
|
||||||
|
|
||||||
findLabelElements(element) {
|
|
||||||
let document = element.ownerDocument;
|
|
||||||
let labels = [];
|
|
||||||
// TODO: querySelectorAll is inefficient here. However, bug 1339726 is for
|
|
||||||
// a more efficient implementation from DOM API perspective. This function
|
|
||||||
// should be refined after input.labels API landed.
|
|
||||||
for (let label of document.querySelectorAll("label[for]")) {
|
|
||||||
if (element.id == label.htmlFor) {
|
|
||||||
labels.push(label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (labels.length > 0) {
|
|
||||||
log.debug("Label found by ID", element.id);
|
|
||||||
return labels;
|
|
||||||
}
|
|
||||||
|
|
||||||
let parent = element.parentNode;
|
|
||||||
if (!parent) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
if (parent.tagName == "LABEL" &&
|
|
||||||
parent.control == element &&
|
|
||||||
!parent.hasAttribute("for")) {
|
|
||||||
log.debug("Label found in input's parent or ancestor.");
|
|
||||||
return [parent];
|
|
||||||
}
|
|
||||||
parent = parent.parentNode;
|
|
||||||
} while (parent);
|
|
||||||
|
|
||||||
return [];
|
|
||||||
},
|
|
||||||
|
|
||||||
loadDataFromScript(url, sandbox = {}) {
|
loadDataFromScript(url, sandbox = {}) {
|
||||||
let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||||
.getService(Ci.mozIJSSubScriptLoader);
|
.getService(Ci.mozIJSSubScriptLoader);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
Cu.import("resource://formautofill/FormAutofillUtils.jsm");
|
Cu.import("resource://formautofill/FormAutofillHeuristics.jsm");
|
||||||
|
|
||||||
const TESTCASES = [
|
const TESTCASES = [
|
||||||
{
|
{
|
||||||
|
@ -59,7 +59,7 @@ TESTCASES.forEach(testcase => {
|
||||||
"http://localhost:8080/test/", testcase.document);
|
"http://localhost:8080/test/", testcase.document);
|
||||||
|
|
||||||
let element = doc.getElementById(testcase.inputId);
|
let element = doc.getElementById(testcase.inputId);
|
||||||
let strings = FormAutofillUtils.extractLabelStrings(element);
|
let strings = LabelUtils.extractLabelStrings(element);
|
||||||
|
|
||||||
Assert.deepEqual(strings, testcase.expectedStrings);
|
Assert.deepEqual(strings, testcase.expectedStrings);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
Cu.import("resource://formautofill/FormAutofillUtils.jsm");
|
Cu.import("resource://formautofill/FormAutofillHeuristics.jsm");
|
||||||
|
|
||||||
const TESTCASES = [
|
const TESTCASES = [
|
||||||
{
|
{
|
||||||
|
@ -83,7 +83,7 @@ TESTCASES.forEach(testcase => {
|
||||||
"http://localhost:8080/test/", testcase.document);
|
"http://localhost:8080/test/", testcase.document);
|
||||||
|
|
||||||
let input = doc.getElementById(testcase.inputId);
|
let input = doc.getElementById(testcase.inputId);
|
||||||
let labels = FormAutofillUtils.findLabelElements(input);
|
let labels = LabelUtils.findLabelElements(input);
|
||||||
|
|
||||||
Assert.deepEqual(labels.map(l => l.id), testcase.expectedLabelIds);
|
Assert.deepEqual(labels.map(l => l.id), testcase.expectedLabelIds);
|
||||||
});
|
});
|
||||||
|
|
|
@ -77,6 +77,7 @@
|
||||||
"Finder.jsm": ["Finder", "GetClipboardSearchString"],
|
"Finder.jsm": ["Finder", "GetClipboardSearchString"],
|
||||||
"forms.js": ["FormEngine", "FormRec", "FormValidator"],
|
"forms.js": ["FormEngine", "FormRec", "FormValidator"],
|
||||||
"forms.jsm": ["FormData"],
|
"forms.jsm": ["FormData"],
|
||||||
|
"FormAutofillHeuristics.jsm": ["FormAutofillHeuristics", "LabelUtils"],
|
||||||
"FormAutofillSync.jsm": ["AddressesEngine", "CreditCardsEngine"],
|
"FormAutofillSync.jsm": ["AddressesEngine", "CreditCardsEngine"],
|
||||||
"frame.js": ["Collector", "Runner", "events", "runTestFile", "log", "timers", "persisted", "shutdownApplication"],
|
"frame.js": ["Collector", "Runner", "events", "runTestFile", "log", "timers", "persisted", "shutdownApplication"],
|
||||||
"FrameScriptManager.jsm": ["getNewLoaderID"],
|
"FrameScriptManager.jsm": ["getNewLoaderID"],
|
||||||
|
|
Загрузка…
Ссылка в новой задаче