Bug 1349490 - Part 1: Implement FormAutofillUtil.extractLabelStrings function.; r?MattN
MozReview-Commit-ID: 9kCZkgnqOfF
--- a/browser/extensions/formautofill/FormAutofillUtils.jsm
+++ b/browser/extensions/formautofill/FormAutofillUtils.jsm
@@ -57,16 +57,58 @@ this.FormAutofillUtils = {
let ConsoleAPI = Cu.import("resource://gre/modules/Console.jsm", {}).ConsoleAPI;
return new ConsoleAPI({
maxLogLevelPref: "extensions.formautofill.loglevel",
prefix: logPrefix,
});
});
},
+ // 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) {
new file mode 100644
--- /dev/null
+++ b/browser/extensions/formautofill/test/unit/test_extractLabelStrings.js
@@ -0,0 +1,66 @@
+"use strict";
+
+Cu.import("resource://formautofill/FormAutofillUtils.jsm");
+
+const TESTCASES = [
+ {
+ description: "A label element contains one input element.",
+ document: `<label id="typeA"> label type A
+ <!-- This comment should not be extracted. -->
+ <input type="text">
+ <script>FOO</script>
+ <noscript>FOO</noscript>
+ <option>FOO</option>
+ <style>FOO</style>
+ </label>`,
+ inputId: "typeA",
+ expectedStrings: ["label type A"],
+ },
+ {
+ description: "A label element with inner div contains one input element.",
+ document: `<label id="typeB"> label type B
+ <!-- This comment should not be extracted. -->
+ <script>FOO</script>
+ <noscript>FOO</noscript>
+ <option>FOO</option>
+ <style>FOO</style>
+ <div> inner div
+ <input type="text">
+ </div>
+ </label>`,
+ inputId: "typeB",
+ expectedStrings: ["label type B", "inner div"],
+ },
+ {
+ description: "A label element with inner prefix/postfix strings contains span elements.",
+ document: `<label id="typeC"> label type C
+ <!-- This comment should not be extracted. -->
+ <script>FOO</script>
+ <noscript>FOO</noscript>
+ <option>FOO</option>
+ <style>FOO</style>
+ <div> inner div prefix
+ <span>test C-1 </span>
+ <span> test C-2</span>
+ inner div postfix
+ </div>
+ </label>`,
+ inputId: "typeC",
+ expectedStrings: ["label type C", "inner div prefix", "test C-1",
+ "test C-2", "inner div postfix"],
+ },
+];
+
+TESTCASES.forEach(testcase => {
+ add_task(function* () {
+ do_print("Starting testcase: " + testcase.description);
+
+ let doc = MockDocument.createTestDocument(
+ "http://localhost:8080/test/", testcase.document);
+
+ let element = doc.getElementById(testcase.inputId);
+ let strings = FormAutofillUtils.extractLabelStrings(element);
+
+ Assert.deepEqual(strings, testcase.expectedStrings);
+ });
+});
--- a/browser/extensions/formautofill/test/unit/xpcshell.ini
+++ b/browser/extensions/formautofill/test/unit/xpcshell.ini
@@ -16,16 +16,17 @@ support-files =
[heuristics/third_party/test_Sears.js]
[heuristics/third_party/test_Staples.js]
[heuristics/third_party/test_Walmart.js]
[test_activeStatus.js]
[test_addressRecords.js]
[test_autofillFormFields.js]
[test_collectFormFields.js]
[test_creditCardRecords.js]
+[test_extractLabelStrings.js]
[test_findLabelElements.js]
[test_getCategoriesFromFieldNames.js]
[test_getFormInputDetails.js]
[test_isCJKName.js]
[test_markAsAutofillField.js]
[test_nameUtils.js]
[test_onFormSubmitted.js]
[test_profileAutocompleteResult.js]