Skip to content

Commit

Permalink
Bug 1383058 - Always adopt the info from autocomplete attribute. r=MattN
Browse files Browse the repository at this point in the history
MozReview-Commit-ID: CdAX9XZX7R0

--HG--
extra : rebase_source : 9578235ea3622c645e993a261cbad7bee09f0c1f
  • Loading branch information
weilonge committed Jul 21, 2017
1 parent b6545ac commit c24c7ab
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 35 deletions.
9 changes: 6 additions & 3 deletions browser/extensions/formautofill/FormAutofillHandler.jsm
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,16 @@ FormAutofillHandler.prototype = {

/**
* Set fieldDetails from the form about fields that can be autofilled.
*
* @param {boolean} allowDuplicates
* true to remain any duplicated field details otherwise to remove the
* duplicated ones.
* @returns {Array} The valid address and credit card details.
*/
collectFormFields() {
collectFormFields(allowDuplicates = false) {
this._cacheValue.allFieldNames = null;
this._formFieldCount = this.form.elements.length;
let fieldDetails = FormAutofillHeuristics.getFormInfo(this.form);
let fieldDetails = FormAutofillHeuristics.getFormInfo(this.form, allowDuplicates);
this.fieldDetails = fieldDetails ? fieldDetails : [];
log.debug("Collected details on", this.fieldDetails.length, "fields");

Expand Down
31 changes: 28 additions & 3 deletions browser/extensions/formautofill/FormAutofillHeuristics.jsm
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ class FieldScanner {
elementWeakRef: Cu.getWeakReference(element),
};

if (info._reason) {
fieldInfo._reason = info._reason;
}

// Store the association between the field metadata and the element.
if (this.findSameField(info) != -1) {
// A field with the same identifier already exists.
Expand Down Expand Up @@ -204,7 +208,7 @@ this.FormAutofillHeuristics = {
let ruleStart = i;
for (; i < GRAMMARS.length && GRAMMARS[i][0] && fieldScanner.elementExisting(detailStart); i++, detailStart++) {
let detail = fieldScanner.getFieldDetailByIndex(detailStart);
if (!detail || GRAMMARS[i][0] != detail.fieldName) {
if (!detail || GRAMMARS[i][0] != detail.fieldName || detail._reason == "autocomplete") {
break;
}
let element = detail.elementWeakRef.get();
Expand Down Expand Up @@ -288,7 +292,23 @@ this.FormAutofillHeuristics = {
return parsedFields;
},

getFormInfo(form) {
/**
* This function should provide all field details of a form. The details
* contain the autocomplete info (e.g. fieldName, section, etc).
*
* `allowDuplicates` is used for the xpcshell-test purpose currently because
* the heuristics should be verified that some duplicated elements still can
* be predicted correctly.
*
* @param {HTMLFormElement} form
* the elements in this form to be predicted the field info.
* @param {boolean} allowDuplicates
* true to remain any duplicated field details otherwise to remove the
* duplicated ones.
* @returns {Array<Object>}
* all field details in the form.
*/
getFormInfo(form, allowDuplicates = false) {
if (form.autocomplete == "off" || form.elements.length <= 0) {
return [];
}
Expand All @@ -304,7 +324,11 @@ this.FormAutofillHeuristics = {
fieldScanner.parsingIndex++;
}
}
return fieldScanner.trimmedFieldDetail;
if (allowDuplicates) {
return fieldScanner.fieldDetails;
} else {
return fieldScanner.trimmedFieldDetail;
}
},

getInfo(element) {
Expand All @@ -316,6 +340,7 @@ this.FormAutofillHeuristics = {
// An input[autocomplete="on"] will not be early return here since it stll
// needs to find the field name.
if (info && info.fieldName && info.fieldName != "on") {
info._reason = "autocomplete";
return info;
}

Expand Down
1 change: 1 addition & 0 deletions browser/extensions/formautofill/test/unit/head.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ function runHeuristicsTest(patterns, fixturePathPrefix) {
Assert.equal(formInfo.length, testPattern.expectedResult[formIndex].length, "Expected field count.");
formInfo.forEach((field, fieldIndex) => {
let expectedField = testPattern.expectedResult[formIndex][fieldIndex];
delete field._reason;
expectedField.elementWeakRef = field.elementWeakRef;
Assert.deepEqual(field, expectedField);
});
Expand Down
81 changes: 52 additions & 29 deletions browser/extensions/formautofill/test/unit/test_collectFormFields.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,51 +174,52 @@ const TESTCASES = [
{
description: "Three sets of adjacent phone number fields",
document: `<form>
<input id="shippingAreaCode" autocomplete="shipping tel" maxlength="3">
<input id="shippingPrefix" autocomplete="shipping tel" maxlength="3">
<input id="shippingSuffix" autocomplete="shipping tel" maxlength="4">
<input id="shippingTelExt" autocomplete="shipping tel-extension">
<input id="shippingAC" name="phone" maxlength="3">
<input id="shippingPrefix" name="phone" maxlength="3">
<input id="shippingSuffix" name="phone" maxlength="4">
<input id="shippingTelExt" name="extension">
<input id="billingAreaCode" autocomplete="billing tel" maxlength="3">
<input id="billingPrefix" autocomplete="billing tel" maxlength="3">
<input id="billingSuffix" autocomplete="billing tel" maxlength="4">
<input id="billingAC" name="phone" maxlength="3">
<input id="billingPrefix" name="phone" maxlength="3">
<input id="billingSuffix" name="phone" maxlength="4">
<input id="otherCountryCode" autocomplete="tel" maxlength="3">
<input id="otherAreaCode" autocomplete="tel" maxlength="3">
<input id="otherPrefix" autocomplete="tel" maxlength="3">
<input id="otherSuffix" autocomplete="tel" maxlength="4">
<input id="otherCC" name="phone" maxlength="3">
<input id="otherAC" name="phone" maxlength="3">
<input id="otherPrefix" name="phone" maxlength="3">
<input id="otherSuffix" name="phone" maxlength="4">
</form>`,
allowDuplicates: true,
addressFieldDetails: [
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel-area-code"},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel-local-prefix"},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel-local-suffix"},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel-extension"},
{"section": "", "addressType": "billing", "contactType": "", "fieldName": "tel-area-code"},
{"section": "", "addressType": "billing", "contactType": "", "fieldName": "tel-local-prefix"},
{"section": "", "addressType": "billing", "contactType": "", "fieldName": "tel-local-suffix"},
{"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": "tel-area-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-prefix"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-suffix"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-country-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-area-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-prefix"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-suffix"},
],
creditCardFieldDetails: [],
validFieldDetails: [
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel-area-code"},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel-local-prefix"},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel-local-suffix"},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel-extension"},
{"section": "", "addressType": "billing", "contactType": "", "fieldName": "tel-area-code"},
{"section": "", "addressType": "billing", "contactType": "", "fieldName": "tel-local-prefix"},
{"section": "", "addressType": "billing", "contactType": "", "fieldName": "tel-local-suffix"},
{"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": "tel-area-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-prefix"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-suffix"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-country-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-area-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-prefix"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-suffix"},
],
ids: [
"shippingAreaCode", "shippingPrefix", "shippingSuffix", "shippingTelExt",
"billingAreaCode", "billingPrefix", "billingSuffix",
"otherCountryCode", "otherAreaCode", "otherPrefix", "otherSuffix",
"shippingAC", "shippingPrefix", "shippingSuffix", "shippingTelExt",
"billingAC", "billingPrefix", "billingSuffix",
"otherCC", "otherAC", "otherPrefix", "otherSuffix",
],
},
{
Expand Down Expand Up @@ -290,6 +291,28 @@ const TESTCASES = [
ids: ["i1", "i2", "i3", "i4", "singlePhone",
"shippingAreaCode", "shippingPrefix", "shippingSuffix"],
},
{
description: "Always adopt the info from autocomplete attribute.",
document: `<form>
<input id="given-name" autocomplete="shipping given-name">
<input id="family-name" autocomplete="shipping family-name">
<input id="dummyAreaCode" autocomplete="shipping tel" maxlength="3">
<input id="dummyPrefix" autocomplete="shipping tel" maxlength="3">
<input id="dummySuffix" autocomplete="shipping tel" maxlength="4">
</form>`,
addressFieldDetails: [
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "given-name"},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "family-name"},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel"},
],
creditCardFieldDetails: [],
validFieldDetails: [
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "given-name"},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "family-name"},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel"},
],
ids: ["given-name", "family-name", "dummyAreaCode"],
},
];

for (let tc of TESTCASES) {
Expand Down Expand Up @@ -340,7 +363,7 @@ for (let tc of TESTCASES) {
].forEach(details => setElementWeakRef(details));

let handler = new FormAutofillHandler(formLike);
let validFieldDetails = handler.collectFormFields();
let validFieldDetails = handler.collectFormFields(testcase.allowDuplicates);

verifyDetails(handler.address.fieldDetails, testcase.addressFieldDetails);
verifyDetails(handler.creditCard.fieldDetails, testcase.creditCardFieldDetails);
Expand Down

0 comments on commit c24c7ab

Please sign in to comment.