Bug 1407759 - SELECT element supports some fieldNames only. (e.g. cc-exp*, country, address-level*) r=lchang,ralin
MozReview-Commit-ID: KtGO4TseJwH
--- a/browser/extensions/formautofill/FormAutofillHeuristics.jsm
+++ b/browser/extensions/formautofill/FormAutofillHeuristics.jsm
@@ -560,16 +560,79 @@ this.FormAutofillHeuristics = {
if (allowDuplicates) {
return fieldScanner.fieldDetails;
}
return fieldScanner.trimmedFieldDetail;
},
+ _regExpTableHashValue(...signBits) {
+ return signBits.reduce((p, c, i) => p | !!c << i, 0);
+ },
+
+ _setRegExpListCache(regexps, b0, b1, b2) {
+ if (!this._regexpList) {
+ this._regexpList = [];
+ }
+ this._regexpList[this._regExpTableHashValue(b0, b1, b2)] = regexps;
+ },
+
+ _getRegExpListCache(b0, b1, b2) {
+ if (!this._regexpList) {
+ return null;
+ }
+ return this._regexpList[this._regExpTableHashValue(b0, b1, b2)];
+ },
+
+ _getRegExpList(isAutoCompleteOff, elementTagName) {
+ let isSelectElem = elementTagName == "SELECT";
+ let regExpListCache = this._getRegExpListCache(
+ isAutoCompleteOff,
+ FormAutofillUtils.isAutofillCreditCardsAvailable,
+ isSelectElem
+ );
+ if (regExpListCache) {
+ return regExpListCache;
+ }
+ const FIELDNAMES_IGNORING_AUTOCOMPLETE_OFF = [
+ "cc-name",
+ "cc-number",
+ "cc-exp-month",
+ "cc-exp-year",
+ "cc-exp",
+ ];
+ let regexps = isAutoCompleteOff ? FIELDNAMES_IGNORING_AUTOCOMPLETE_OFF : Object.keys(this.RULES);
+
+ if (!FormAutofillUtils.isAutofillCreditCardsAvailable) {
+ regexps = regexps.filter(name => !FormAutofillUtils.isCreditCardField(name));
+ }
+
+ if (isSelectElem) {
+ const FIELDNAMES_FOR_SELECT_ELEMENT = [
+ "address-level1",
+ "address-level2",
+ "country",
+ "cc-exp-month",
+ "cc-exp-year",
+ "cc-exp",
+ ];
+ regexps = regexps.filter(name => FIELDNAMES_FOR_SELECT_ELEMENT.includes(name));
+ }
+
+ this._setRegExpListCache(
+ regexps,
+ isAutoCompleteOff,
+ FormAutofillUtils.isAutofillCreditCardsAvailable,
+ isSelectElem
+ );
+
+ return regexps;
+ },
+
getInfo(element) {
if (!FormAutofillUtils.isFieldEligibleForAutofill(element)) {
return null;
}
let info = element.getAutocompleteInfo();
// An input[autocomplete="on"] will not be early return here since it stll
// needs to find the field name.
@@ -593,38 +656,17 @@ this.FormAutofillHeuristics = {
return {
fieldName: "email",
section: "",
addressType: "",
contactType: "",
};
}
- const FIELDNAMES_IGNORING_AUTOCOMPLETE_OFF = [
- "cc-name",
- "cc-number",
- "cc-exp-month",
- "cc-exp-year",
- "cc-exp",
- ];
- let regexps = isAutoCompleteOff ? FIELDNAMES_IGNORING_AUTOCOMPLETE_OFF : Object.keys(this.RULES);
-
- if (!FormAutofillUtils.isAutofillCreditCardsAvailable) {
- if (isAutoCompleteOff) {
- if (!this._regexpListOf_CcUnavailable_AcOff) {
- this._regexpListOf_CcUnavailable_AcOff = regexps.filter(name => !FormAutofillUtils.isCreditCardField(name));
- }
- regexps = this._regexpListOf_CcUnavailable_AcOff;
- } else {
- if (!this._regexpListOf_CcUnavailable_AcOn) {
- this._regexpListOf_CcUnavailable_AcOn = regexps.filter(name => !FormAutofillUtils.isCreditCardField(name));
- }
- regexps = this._regexpListOf_CcUnavailable_AcOn;
- }
- }
+ let regexps = this._getRegExpList(isAutoCompleteOff, element.tagName);
if (regexps.length == 0) {
return null;
}
let labelStrings;
let getElementStrings = {};
getElementStrings[Symbol.iterator] = function* () {
yield element.id;
--- a/browser/extensions/formautofill/test/unit/test_getInfo.js
+++ b/browser/extensions/formautofill/test/unit/test_getInfo.js
@@ -250,8 +250,58 @@ TESTCASES.forEach(testcase => {
let element = doc.getElementById(testcase.elementId);
let value = FormAutofillHeuristics.getInfo(element);
Assert.deepEqual(value, testcase.expectedReturnValue);
LabelUtils.clearLabelMap();
});
});
+
+add_task(async function test_regexp_list() {
+ do_print("Verify the fieldName support for select element.");
+ let SUPPORT_LIST = {
+ "email": null, // email
+ "tel-extension": null, // tel-extension
+ "phone": null, // tel
+ "organization": null, // organization
+ "street-address": null, // street-address
+ "address1": null, // address-line1
+ "address2": null, // address-line2
+ "address3": null, // address-line3
+ "city": "address-level2",
+ "region": "address-level1",
+ "postal-code": null, // postal-code
+ "country": "country",
+ "fullname": null, // name
+ "fname": null, // given-name
+ "mname": null, // additional-name
+ "lname": null, // family-name
+ "cardholder": null, // cc-name
+ "cc-number": null, // cc-number
+ "addmonth": "cc-exp-month",
+ "addyear": "cc-exp-year",
+ };
+ for (let label of Object.keys(SUPPORT_LIST)) {
+ let testcase = {
+ description: `A select element supports ${label} or not`,
+ document: `<select id="${label}"></select>`,
+ elementId: label,
+ expectedReturnValue: (SUPPORT_LIST[label] ? {
+ fieldName: SUPPORT_LIST[label],
+ section: "",
+ addressType: "",
+ contactType: "",
+ } : null),
+ };
+ do_print(testcase.description);
+ do_print(testcase.document);
+ let doc = MockDocument.createTestDocument(
+ "http://localhost:8080/test/", testcase.document);
+
+ let element = doc.getElementById(testcase.elementId);
+ let value = FormAutofillHeuristics.getInfo(element);
+
+ Assert.deepEqual(value, testcase.expectedReturnValue, label);
+ }
+ LabelUtils.clearLabelMap();
+});
+