--- a/browser/extensions/formautofill/FormAutofillHeuristics.jsm
+++ b/browser/extensions/formautofill/FormAutofillHeuristics.jsm
@@ -144,30 +144,31 @@ class FieldScanner {
* able to identify all sections in the heuristic way.
*
* @returns {Array<Object>}
* The array with the sections, and the belonging fieldDetails are in
* each section.
*/
getSectionFieldDetails() {
// When the section feature is disabled, `getSectionFieldDetails` should
- // provide a single section result.
+ // provide a single address and credit card section result.
if (!this._sectionEnabled) {
- return [this._getFinalDetails(this.fieldDetails)];
+ return this._getFinalDetails(this.fieldDetails);
}
if (this._sections.length == 0) {
return [];
}
if (this._sections.length == 1 && this._sections[0].name == DEFAULT_SECTION_NAME) {
this._classifySections();
}
- return this._sections.map(section =>
- this._getFinalDetails(section.fieldDetails)
- );
+ return this._sections.reduce((sections, current) => {
+ sections.push(...this._getFinalDetails(current.fieldDetails));
+ return sections;
+ }, []);
}
/**
* This function will prepare an autocomplete info object with getInfo
* function and push the detail to fieldDetails property.
* Any field will be pushed into `this._sections` based on the section name
* in `autocomplete` attribute.
*
@@ -234,36 +235,60 @@ class FieldScanner {
}
/**
* Provide the final field details without invalid field name, and the
* duplicated fields will be removed as well. For the debugging purpose,
* the final `fieldDetails` will include the duplicated fields if
* `_allowDuplicates` is true.
*
+ * Each item should contain one type of fields only, and the two valid types
+ * are Address and CreditCard.
+ *
* @param {Array<Object>} fieldDetails
* The field details for trimming.
* @returns {Array<Object>}
* The array with the field details without invalid field name and
* duplicated fields.
*/
_getFinalDetails(fieldDetails) {
- if (this._allowDuplicates) {
- return fieldDetails.filter(f => f.fieldName);
+ let addressFieldDetails = [];
+ let creditCardFieldDetails = [];
+ for (let fieldDetail of fieldDetails) {
+ let fieldName = fieldDetail.fieldName;
+ if (FormAutofillUtils.isAddressField(fieldName)) {
+ addressFieldDetails.push(fieldDetail);
+ } else if (FormAutofillUtils.isCreditCardField(fieldName)) {
+ creditCardFieldDetails.push(fieldDetail);
+ } else {
+ log.debug("Not collecting a field with a unknown fieldName", fieldDetail);
+ }
}
- let dedupedFieldDetails = [];
- for (let fieldDetail of fieldDetails) {
- if (fieldDetail.fieldName && !dedupedFieldDetails.find(f => this._isSameField(fieldDetail, f))) {
- dedupedFieldDetails.push(fieldDetail);
- } else {
- log.debug("Not collecting an invalid field or matching another with the same info:", fieldDetail);
+ return [
+ {
+ type: FormAutofillUtils.SECTION_TYPES.ADDRESS,
+ fieldDetails: addressFieldDetails,
+ },
+ {
+ type: FormAutofillUtils.SECTION_TYPES.CREDIT_CARD,
+ fieldDetails: creditCardFieldDetails,
+ },
+ ].map(section => {
+ if (this._allowDuplicates) {
+ return section;
}
- }
- return dedupedFieldDetails;
+ // Deduplicate each set of fieldDetails
+ let details = section.fieldDetails;
+ section.fieldDetails = details.filter((detail, index) => {
+ let previousFields = details.slice(0, index);
+ return !previousFields.find(f => this._isSameField(detail, f));
+ });
+ return section;
+ }).filter(section => section.fieldDetails.length > 0);
}
elementExisting(index) {
return index < this._elements.length;
}
}
this.LabelUtils = {
--- a/browser/extensions/formautofill/FormAutofillUtils.jsm
+++ b/browser/extensions/formautofill/FormAutofillUtils.jsm
@@ -28,16 +28,20 @@ const EDIT_ADDRESS_KEYWORDS = [
];
const MANAGE_CREDITCARDS_KEYWORDS = ["manageCreditCardsTitle", "addNewCreditCardTitle", "showCreditCardsBtnLabel"];
const EDIT_CREDITCARD_KEYWORDS = ["cardNumber", "nameOnCard", "cardExpires"];
const FIELD_STATES = {
NORMAL: "NORMAL",
AUTO_FILLED: "AUTO_FILLED",
PREVIEW: "PREVIEW",
};
+const SECTION_TYPES = {
+ ADDRESS: "address",
+ CREDIT_CARD: "creditCard",
+};
// The maximum length of data to be saved in a single field for preventing DoS
// attacks that fill the user's hard drive(s).
const MAX_FIELD_VALUE_LENGTH = 200;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
@@ -175,16 +179,17 @@ this.FormAutofillUtils = {
ADDRESSES_FIRST_TIME_USE_PREF,
CREDITCARDS_USED_STATUS_PREF,
MANAGE_ADDRESSES_KEYWORDS,
EDIT_ADDRESS_KEYWORDS,
MANAGE_CREDITCARDS_KEYWORDS,
EDIT_CREDITCARD_KEYWORDS,
MAX_FIELD_VALUE_LENGTH,
FIELD_STATES,
+ SECTION_TYPES,
_fieldNameInfo: {
"name": "name",
"given-name": "name",
"additional-name": "name",
"family-name": "name",
"organization": "organization",
"street-address": "address",
--- a/browser/extensions/formautofill/test/unit/head.js
+++ b/browser/extensions/formautofill/test/unit/head.js
@@ -113,17 +113,20 @@ function runHeuristicsTest(patterns, fix
forms.push(formLike);
}
}
Assert.equal(forms.length, testPattern.expectedResult.length, "Expected form count.");
forms.forEach((form, formIndex) => {
let sections = FormAutofillHeuristics.getFormInfo(form);
- verifySectionFieldDetails(sections, testPattern.expectedResult[formIndex]);
+ verifySectionFieldDetails(
+ sections.map(section => section.fieldDetails),
+ testPattern.expectedResult[formIndex],
+ );
});
});
});
}
/**
* Returns the Sync change counter for a profile storage record. Synced records
* store additional metadata for tracking changes and resolving merge conflicts.
--- a/browser/extensions/formautofill/test/unit/heuristics/test_basic.js
+++ b/browser/extensions/formautofill/test/unit/heuristics/test_basic.js
@@ -22,16 +22,17 @@ runHeuristicsTest([
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-line3"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "country"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
+ ], [
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"},
]],
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"},
--- a/browser/extensions/formautofill/test/unit/heuristics/test_cc_exp.js
+++ b/browser/extensions/formautofill/test/unit/heuristics/test_cc_exp.js
@@ -6,17 +6,16 @@ runHeuristicsTest([
{
fixturePath: "heuristics_cc_exp.html",
expectedResult: [
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"},
]],
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp"},
]],
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp"},
--- a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_CDW.js
+++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_CDW.js
@@ -37,16 +37,17 @@ runHeuristicsTest([
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, // city
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // state
{"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"},
// FIXME: bug 1392932 - misdetect ZIP ext string
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"},
+ ], [
// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-type"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"},
], [
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"},
--- a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_HomeDepot.js
+++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_HomeDepot.js
@@ -9,17 +9,17 @@ runHeuristicsTest([
[
[
{"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"},
-
+ ], [
// FIXME: bug 1392944 - the uncommented cc-exp-month and cc-exp-year are
// both invisible <input> elements, and the following two <select>
// elements are the correct ones. BTW, they are both applied
// autocomplete attr.
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"},
--- a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Macys.js
+++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Macys.js
@@ -17,31 +17,32 @@ runHeuristicsTest([
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel"},
]],
[],
],
}, {
fixturePath: "Checkout_Payment.html",
expectedResult: [
[[
-// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-type"}, // ac-off
- {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off
- {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"}, // ac-off
- {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"}, // ac-off
-// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"}, // ac-off
-// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"}, // ac-off
{"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"}, // city
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // state
{"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
+ ], [
+// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-type"}, // ac-off
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"}, // ac-off
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"}, // ac-off
+// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"}, // ac-off
+// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"}, // ac-off
]],
[],
],
}, {
fixturePath: "SignIn.html",
expectedResult: [
[[ // Sign in
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
--- a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_NewEgg.js
+++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_NewEgg.js
@@ -22,28 +22,29 @@ runHeuristicsTest([
],
}, {
fixturePath: "BillingInfo.html",
expectedResult: [
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off
], [
- {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-name"},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off
- {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"},
-// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "country"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // state
{"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel"},
+ ], [
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-name"},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"},
+// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"},
]],
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"},
]],
[],
--- a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_OfficeDepot.js
+++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_OfficeDepot.js
@@ -24,34 +24,34 @@ runHeuristicsTest([
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
]],
[],
],
}, {
fixturePath: "Payment.html",
expectedResult: [
[[
- {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "organization"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-line2"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"}, // state
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-area-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-prefix"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-suffix"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
-
+ ], [
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"},
// FIXME: bug 1392950 - the membership number should not be detected
// as cc-number.
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"},
]],
],
}, {
fixturePath: "SignIn.html",
expectedResult: [
--- a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_QVC.js
+++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_QVC.js
@@ -7,16 +7,17 @@ runHeuristicsTest([
fixturePath: "YourInformation.html",
expectedResult: [
[[
// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, // ac-off
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-month"}, // select
// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-day"}, // select
// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-year"},
+ ], [
// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-type"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"},
], [
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"},
]],
[[
@@ -27,16 +28,17 @@ runHeuristicsTest([
fixturePath: "PaymentMethod.html",
expectedResult: [
[[
// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"}, // ac-off
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-month"}, // select
// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-day"}, // select
// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-year"}, // select
+ ], [
// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-type"}, // select
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"},
], [
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off
]],
[[
--- a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Sears.js
+++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Sears.js
@@ -70,27 +70,27 @@ runHeuristicsTest([
{"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"},
]],
[[ // check out
{"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"},
- // FIXME: bug 1392950 - the bank routing number should not be detected
- // as cc-number.
- {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"},
-
// FIXME: bug 1392934 - this should be detected as address-level1 since
// it's for Driver's license or state identification.
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-month"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-day"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-year"},
+ ], [
+ // FIXME: bug 1392950 - the bank routing number should not be detected
+ // as cc-number.
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"},
]],
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
]],
],
},
], "../../../fixtures/third_party/Sears/");
--- a/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Walmart.js
+++ b/browser/extensions/formautofill/test/unit/heuristics/third_party/test_Walmart.js
@@ -25,21 +25,22 @@ runHeuristicsTest([
}, {
fixturePath: "Payment.html",
expectedResult: [
[],
[
[
{"section": "section-payment", "addressType": "", "contactType": "", "fieldName": "given-name"},
{"section": "section-payment", "addressType": "", "contactType": "", "fieldName": "family-name"},
+ {"section": "section-payment", "addressType": "", "contactType": "", "fieldName": "tel"},
+ ], [
{"section": "section-payment", "addressType": "", "contactType": "", "fieldName": "cc-number"},
{"section": "section-payment", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"},
{"section": "section-payment", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"},
// {"section": "section-payment", "addressType": "", "contactType": "", "fieldName": "cc-csc"},
- {"section": "section-payment", "addressType": "", "contactType": "", "fieldName": "tel"},
], [
// FIXME bug 1392932 - the following field shouldn't be recognized as
// "tel-extension".
// The wrong prediction is caused by the name attr "brwsrAutofillText"
// which matches the regexp "ext\\b".
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"},
],
],