--- a/browser/extensions/formautofill/FormAutofillHandler.jsm
+++ b/browser/extensions/formautofill/FormAutofillHandler.jsm
@@ -48,62 +48,50 @@ FormAutofillHandler.prototype = {
* the same exact combination of these values.
*
* A direct reference to the associated element cannot be sent to the user
* interface because processing may be done in the parent process.
*/
fieldDetails: null,
/**
- * Returns information from the form about fields that can be autofilled, and
- * populates the fieldDetails array on this object accordingly.
- *
- * @returns {Array<Object>} Serializable data structure that can be sent to the user
- * interface, or null if the operation failed because the constraints
- * on the allowed fields were not honored.
+ * Set fieldDetails from the form about fields that can be autofilled.
*/
collectFormFields() {
- let autofillData = [];
-
for (let element of this.form.elements) {
// Exclude elements to which no autocomplete field has been assigned.
let info = FormAutofillHeuristics.getInfo(element);
if (!info) {
+ log.debug("Not collecting because no info from heuristics");
continue;
}
// Store the association between the field metadata and the element.
if (this.fieldDetails.some(f => f.section == info.section &&
f.addressType == info.addressType &&
f.contactType == info.contactType &&
f.fieldName == info.fieldName)) {
// A field with the same identifier already exists.
log.debug("Not collecting a field matching another with the same info:", info);
- return null;
+ continue;
}
- let inputFormat = {
+ let formatWithElement = {
section: info.section,
addressType: info.addressType,
contactType: info.contactType,
fieldName: info.fieldName,
+ state: null,
+ element, // TODO: Apply Cu.getWeakReference and use get API for strong ref.
};
- // Clone the inputFormat for caching the fields and elements together
- let formatWithElement = Object.assign({}, inputFormat);
- inputFormat.index = autofillData.length;
- autofillData.push(inputFormat);
-
- formatWithElement.element = element;
this.fieldDetails.push(formatWithElement);
}
- log.debug("Collected details on", autofillData.length, "fields");
-
- return autofillData;
+ log.debug("Collected details on", this.fieldDetails.length, "fields");
},
/**
* Processes form fields that can be autofilled, and populates them with the
* profile provided by backend.
*
* @param {Object} profile
* A profile to be filled in.
--- a/browser/extensions/formautofill/test/unit/test_collectFormFields.js
+++ b/browser/extensions/formautofill/test/unit/test_collectFormFields.js
@@ -19,92 +19,69 @@ const TESTCASES = [
description: "Form with autocomplete properties and 1 token",
document: `<form><input id="given-name" autocomplete="given-name">
<input id="family-name" autocomplete="family-name">
<input id="street-addr" autocomplete="street-address">
<input id="city" autocomplete="address-level2">
<input id="country" autocomplete="country">
<input id="email" autocomplete="email">
<input id="tel" autocomplete="tel"></form>`,
- returnedFormat: [
- {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address", "index": 0},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2", "index": 1},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "country", "index": 2},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "email", "index": 3},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "tel", "index": 4},
- ],
fieldDetails: [
- {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address", "element": {}},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2", "element": {}},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "country", "element": {}},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "email", "element": {}},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "tel", "element": {}},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address", "state": null, "element": {}},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2", "state": null, "element": {}},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "country", "state": null, "element": {}},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "email", "state": null, "element": {}},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "tel", "state": null, "element": {}},
],
},
{
description: "Form with autocomplete properties and 2 tokens",
document: `<form><input id="given-name" autocomplete="shipping given-name">
<input id="family-name" autocomplete="shipping family-name">
<input id="street-addr" autocomplete="shipping street-address">
<input id="city" autocomplete="shipping address-level2">
<input id="country" autocomplete="shipping country">
<input id='email' autocomplete="shipping email">
<input id="tel" autocomplete="shipping tel"></form>`,
- returnedFormat: [
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "street-address", "index": 0},
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "address-level2", "index": 1},
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "country", "index": 2},
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "email", "index": 3},
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel", "index": 4},
- ],
fieldDetails: [
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "street-address", "element": {}},
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "address-level2", "element": {}},
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "country", "element": {}},
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "email", "element": {}},
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel", "element": {}},
+ {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "street-address", "state": null, "element": {}},
+ {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "address-level2", "state": null, "element": {}},
+ {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "country", "state": null, "element": {}},
+ {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "email", "state": null, "element": {}},
+ {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel", "state": null, "element": {}},
],
},
{
description: "Form with autocomplete properties and profile is partly matched",
document: `<form><input id="given-name" autocomplete="shipping given-name">
<input id="family-name" autocomplete="shipping family-name">
<input id="street-addr" autocomplete="shipping street-address">
<input id="city" autocomplete="shipping address-level2">
<input id="country" autocomplete="shipping country">
<input id='email' autocomplete="shipping email">
<input id="tel" autocomplete="shipping tel"></form>`,
- returnedFormat: [
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "street-address", "index": 0},
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "address-level2", "index": 1},
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "country", "index": 2},
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "email", "index": 3},
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel", "index": 4},
- ],
fieldDetails: [
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "street-address", "element": {}},
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "address-level2", "element": {}},
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "country", "element": {}},
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "email", "element": {}},
- {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel", "element": {}},
+ {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "street-address", "state": null, "element": {}},
+ {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "address-level2", "state": null, "element": {}},
+ {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "country", "state": null, "element": {}},
+ {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "email", "state": null, "element": {}},
+ {"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel", "state": null, "element": {}},
],
},
];
for (let tc of TESTCASES) {
(function() {
let testcase = tc;
add_task(function* () {
do_print("Starting testcase: " + testcase.description);
let doc = MockDocument.createTestDocument("http://localhost:8080/test/",
testcase.document);
let form = doc.querySelector("form");
let handler = new FormAutofillHandler(form);
- Assert.deepEqual(handler.collectFormFields(), testcase.returnedFormat,
- "Check the format of form autofill were returned correctly");
-
+ handler.collectFormFields();
Assert.deepEqual(handler.fieldDetails, testcase.fieldDetails,
"Check the fieldDetails were set correctly");
});
})();
}
--- a/browser/extensions/formautofill/test/unit/test_getFormInputDetails.js
+++ b/browser/extensions/formautofill/test/unit/test_getFormInputDetails.js
@@ -9,35 +9,35 @@ const TESTCASES = [
<input id="street-addr" autocomplete="street-address">
<input id="city" autocomplete="address-level2">
<input id="country" autocomplete="country">
<input id="email" autocomplete="email">
<input id="tel" autocomplete="tel">
</form>`,
targetInput: ["street-addr", "country"],
expectedResult: [{
- input: {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
+ input: {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address", "state": null},
formId: "form1",
form: [
- {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "country"},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address", "state": null},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2", "state": null},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "country", "state": null},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "email", "state": null},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "tel", "state": null},
],
},
{
- input: {"section": "", "addressType": "", "contactType": "", "fieldName": "country"},
+ input: {"section": "", "addressType": "", "contactType": "", "fieldName": "country", "state": null},
formId: "form1",
form: [
- {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "country"},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address", "state": null},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2", "state": null},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "country", "state": null},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "email", "state": null},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "tel", "state": null},
],
}],
},
{
description: "2 forms that are able to be auto filled",
document: `<form id="form2">
<input id="home-addr" autocomplete="street-address">
<input id="city" autocomplete="address-level2">
@@ -45,31 +45,31 @@ const TESTCASES = [
</form>
<form id="form3">
<input id="office-addr" autocomplete="street-address">
<input id="email" autocomplete="email">
<input id="tel" autocomplete="tel">
</form>`,
targetInput: ["home-addr", "office-addr"],
expectedResult: [{
- input: {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
+ input: {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address", "state": null},
formId: "form2",
form: [
- {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "country"},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address", "state": null},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2", "state": null},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "country", "state": null},
],
},
{
- input: {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
+ input: {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address", "state": null},
formId: "form3",
form: [
- {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
- {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address", "state": null},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "email", "state": null},
+ {"section": "", "addressType": "", "contactType": "", "fieldName": "tel", "state": null},
],
}],
},
];
TESTCASES.forEach(testcase => {
add_task(function* () {