diff --git a/browser/extensions/formautofill/FormAutofillHeuristics.jsm b/browser/extensions/formautofill/FormAutofillHeuristics.jsm index 969dca5390c0..420db4f4281e 100644 --- a/browser/extensions/formautofill/FormAutofillHeuristics.jsm +++ b/browser/extensions/formautofill/FormAutofillHeuristics.jsm @@ -565,6 +565,69 @@ this.FormAutofillHeuristics = { 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; @@ -598,28 +661,7 @@ this.FormAutofillHeuristics = { }; } - 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; } diff --git a/browser/extensions/formautofill/test/unit/test_getInfo.js b/browser/extensions/formautofill/test/unit/test_getInfo.js index 6f2171e37a2b..1c63d3ceca7c 100644 --- a/browser/extensions/formautofill/test/unit/test_getInfo.js +++ b/browser/extensions/formautofill/test/unit/test_getInfo.js @@ -255,3 +255,53 @@ TESTCASES.forEach(testcase => { 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: ``, + 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(); +}); +