зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1681985 - Extract LabelUtils to FormAutofillUtils.jsm. r=zbraniecki
We need it from both FormAutofillHeuristics and CreditCardRuleset, and it would make a circular import otherwise: FormAutofillHeuristics -> CreditCardRuleset -> FormAutofillHeuristics. Differential Revision: https://phabricator.services.mozilla.com/D100140
This commit is contained in:
Родитель
fe5c743b15
Коммит
52703e294a
|
@ -8,7 +8,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["FormAutofillHeuristics", "LabelUtils"];
|
||||
var EXPORTED_SYMBOLS = ["FormAutofillHeuristics"];
|
||||
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
|
@ -25,6 +25,8 @@ ChromeUtils.defineModuleGetter(
|
|||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
CreditCard: "resource://gre/modules/CreditCard.jsm",
|
||||
creditCardRuleset: "resource://formautofill/CreditCardRuleset.jsm",
|
||||
LabelUtils: "resource://formautofill/FormAutofillUtils.jsm", // TODO: Is there a better way of importing multiple symbols from a single module? We already import from this one above.
|
||||
});
|
||||
|
||||
this.log = null;
|
||||
|
@ -332,116 +334,6 @@ class FieldScanner {
|
|||
}
|
||||
}
|
||||
|
||||
var 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"],
|
||||
|
||||
// A map object, whose keys are the id's of form fields and each value is an
|
||||
// array consisting of label elements correponding to the id.
|
||||
// @type {Map<string, array>}
|
||||
_mappedLabels: null,
|
||||
|
||||
// An array consisting of label elements whose correponding form field doesn't
|
||||
// have an id attribute.
|
||||
// @type {Array<HTMLLabelElement>}
|
||||
_unmappedLabels: null,
|
||||
|
||||
// A weak map consisting of label element and extracted strings pairs.
|
||||
// @type {WeakMap<HTMLLabelElement, array>}
|
||||
_labelStrings: null,
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
if (this._labelStrings.has(element)) {
|
||||
return this._labelStrings.get(element);
|
||||
}
|
||||
let strings = [];
|
||||
let _extractLabelStrings = el => {
|
||||
if (this.EXCLUDED_TAGS.includes(el.tagName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (el.nodeType == el.TEXT_NODE || !el.childNodes.length) {
|
||||
let trimmedText = el.textContent.trim();
|
||||
if (trimmedText) {
|
||||
strings.push(trimmedText);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (let node of el.childNodes) {
|
||||
let nodeType = node.nodeType;
|
||||
if (nodeType != node.ELEMENT_NODE && nodeType != node.TEXT_NODE) {
|
||||
continue;
|
||||
}
|
||||
_extractLabelStrings(node);
|
||||
}
|
||||
};
|
||||
_extractLabelStrings(element);
|
||||
this._labelStrings.set(element, strings);
|
||||
return strings;
|
||||
},
|
||||
|
||||
generateLabelMap(doc) {
|
||||
let mappedLabels = new Map();
|
||||
let unmappedLabels = [];
|
||||
|
||||
for (let label of doc.querySelectorAll("label")) {
|
||||
let id = label.htmlFor;
|
||||
if (!id) {
|
||||
let control = label.control;
|
||||
if (!control) {
|
||||
continue;
|
||||
}
|
||||
id = control.id;
|
||||
}
|
||||
if (id) {
|
||||
let labels = mappedLabels.get(id);
|
||||
if (labels) {
|
||||
labels.push(label);
|
||||
} else {
|
||||
mappedLabels.set(id, [label]);
|
||||
}
|
||||
} else {
|
||||
unmappedLabels.push(label);
|
||||
}
|
||||
}
|
||||
|
||||
this._mappedLabels = mappedLabels;
|
||||
this._unmappedLabels = unmappedLabels;
|
||||
this._labelStrings = new WeakMap();
|
||||
},
|
||||
|
||||
clearLabelMap() {
|
||||
this._mappedLabels = null;
|
||||
this._unmappedLabels = null;
|
||||
this._labelStrings = null;
|
||||
},
|
||||
|
||||
findLabelElements(element) {
|
||||
if (!this._mappedLabels) {
|
||||
this.generateLabelMap(element.ownerDocument);
|
||||
}
|
||||
|
||||
let id = element.id;
|
||||
if (!id) {
|
||||
return this._unmappedLabels.filter(label => label.control == element);
|
||||
}
|
||||
return this._mappedLabels.get(id) || [];
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the autocomplete information of fields according to heuristics.
|
||||
*/
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["FormAutofillUtils", "AddressDataLoader"];
|
||||
var EXPORTED_SYMBOLS = ["FormAutofillUtils", "AddressDataLoader", "LabelUtils"];
|
||||
|
||||
const ADDRESS_METADATA_PATH = "resource://formautofill/addressmetadata/";
|
||||
const ADDRESS_REFERENCES = "addressReferences.js";
|
||||
|
@ -1102,6 +1102,116 @@ this.FormAutofillUtils = {
|
|||
},
|
||||
};
|
||||
|
||||
const 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"],
|
||||
|
||||
// A map object, whose keys are the id's of form fields and each value is an
|
||||
// array consisting of label elements correponding to the id.
|
||||
// @type {Map<string, array>}
|
||||
_mappedLabels: null,
|
||||
|
||||
// An array consisting of label elements whose correponding form field doesn't
|
||||
// have an id attribute.
|
||||
// @type {Array<HTMLLabelElement>}
|
||||
_unmappedLabels: null,
|
||||
|
||||
// A weak map consisting of label element and extracted strings pairs.
|
||||
// @type {WeakMap<HTMLLabelElement, array>}
|
||||
_labelStrings: null,
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
if (this._labelStrings.has(element)) {
|
||||
return this._labelStrings.get(element);
|
||||
}
|
||||
let strings = [];
|
||||
let _extractLabelStrings = el => {
|
||||
if (this.EXCLUDED_TAGS.includes(el.tagName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (el.nodeType == el.TEXT_NODE || !el.childNodes.length) {
|
||||
let trimmedText = el.textContent.trim();
|
||||
if (trimmedText) {
|
||||
strings.push(trimmedText);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (let node of el.childNodes) {
|
||||
let nodeType = node.nodeType;
|
||||
if (nodeType != node.ELEMENT_NODE && nodeType != node.TEXT_NODE) {
|
||||
continue;
|
||||
}
|
||||
_extractLabelStrings(node);
|
||||
}
|
||||
};
|
||||
_extractLabelStrings(element);
|
||||
this._labelStrings.set(element, strings);
|
||||
return strings;
|
||||
},
|
||||
|
||||
generateLabelMap(doc) {
|
||||
let mappedLabels = new Map();
|
||||
let unmappedLabels = [];
|
||||
|
||||
for (let label of doc.querySelectorAll("label")) {
|
||||
let id = label.htmlFor;
|
||||
if (!id) {
|
||||
let control = label.control;
|
||||
if (!control) {
|
||||
continue;
|
||||
}
|
||||
id = control.id;
|
||||
}
|
||||
if (id) {
|
||||
let labels = mappedLabels.get(id);
|
||||
if (labels) {
|
||||
labels.push(label);
|
||||
} else {
|
||||
mappedLabels.set(id, [label]);
|
||||
}
|
||||
} else {
|
||||
unmappedLabels.push(label);
|
||||
}
|
||||
}
|
||||
|
||||
this._mappedLabels = mappedLabels;
|
||||
this._unmappedLabels = unmappedLabels;
|
||||
this._labelStrings = new WeakMap();
|
||||
},
|
||||
|
||||
clearLabelMap() {
|
||||
this._mappedLabels = null;
|
||||
this._unmappedLabels = null;
|
||||
this._labelStrings = null;
|
||||
},
|
||||
|
||||
findLabelElements(element) {
|
||||
if (!this._mappedLabels) {
|
||||
this.generateLabelMap(element.ownerDocument);
|
||||
}
|
||||
|
||||
let id = element.id;
|
||||
if (!id) {
|
||||
return this._unmappedLabels.filter(label => label.control == element);
|
||||
}
|
||||
return this._mappedLabels.get(id) || [];
|
||||
},
|
||||
};
|
||||
|
||||
this.log = null;
|
||||
FormAutofill.defineLazyLogGetter(this, EXPORTED_SYMBOLS[0]);
|
||||
|
||||
|
|
|
@ -208,10 +208,10 @@ var AddressDataLoader, FormAutofillUtils;
|
|||
|
||||
async function runHeuristicsTest(patterns, fixturePathPrefix) {
|
||||
add_task(async function setup() {
|
||||
({ FormAutofillHeuristics, LabelUtils } = ChromeUtils.import(
|
||||
({ FormAutofillHeuristics } = ChromeUtils.import(
|
||||
"resource://formautofill/FormAutofillHeuristics.jsm"
|
||||
));
|
||||
({ AddressDataLoader, FormAutofillUtils } = ChromeUtils.import(
|
||||
({ AddressDataLoader, FormAutofillUtils, LabelUtils } = ChromeUtils.import(
|
||||
"resource://formautofill/FormAutofillUtils.jsm"
|
||||
));
|
||||
});
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
var LabelUtils;
|
||||
add_task(async function() {
|
||||
({ LabelUtils } = ChromeUtils.import(
|
||||
"resource://formautofill/FormAutofillHeuristics.jsm"
|
||||
"resource://formautofill/FormAutofillUtils.jsm"
|
||||
));
|
||||
});
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
var LabelUtils;
|
||||
add_task(async function() {
|
||||
({ LabelUtils } = ChromeUtils.import(
|
||||
"resource://formautofill/FormAutofillHeuristics.jsm"
|
||||
"resource://formautofill/FormAutofillUtils.jsm"
|
||||
));
|
||||
});
|
||||
|
||||
|
|
|
@ -2,9 +2,12 @@
|
|||
|
||||
var FormAutofillHeuristics, LabelUtils;
|
||||
add_task(async function() {
|
||||
({ FormAutofillHeuristics, LabelUtils } = ChromeUtils.import(
|
||||
({ FormAutofillHeuristics } = ChromeUtils.import(
|
||||
"resource://formautofill/FormAutofillHeuristics.jsm"
|
||||
));
|
||||
({ LabelUtils } = ChromeUtils.import(
|
||||
"resource://formautofill/FormAutofillUtils.jsm"
|
||||
));
|
||||
});
|
||||
|
||||
const TESTCASES = [
|
||||
|
|
|
@ -69,10 +69,10 @@
|
|||
"Finder.jsm": ["Finder", "GetClipboardSearchString", "SetClipboardSearchString"],
|
||||
"format.js": ["pprint", "truncate"],
|
||||
"formautofill.jsm": ["Address", "CreditCard", "DumpAddresses", "DumpCreditCards"],
|
||||
"FormAutofillHeuristics.jsm": ["FormAutofillHeuristics", "LabelUtils"],
|
||||
"FormAutofillHeuristics.jsm": ["FormAutofillHeuristics"],
|
||||
"FormAutofillStorage.jsm": ["formAutofillStorage"],
|
||||
"FormAutofillSync.jsm": ["AddressesEngine", "CreditCardsEngine"],
|
||||
"FormAutofillUtils.jsm": ["FormAutofillUtils", "AddressDataLoader"],
|
||||
"FormAutofillUtils.jsm": ["FormAutofillUtils", "AddressDataLoader", "LabelUtils"],
|
||||
"forms.js": ["FormEngine", "FormRec", "FormValidator"],
|
||||
"forms.jsm": ["FormData"],
|
||||
"FrameScriptManager.jsm": ["getNewLoaderID"],
|
||||
|
|
Загрузка…
Ссылка в новой задаче