Bug 1338420 - Part 2: Add initial state for field details. r?MattN draft
authorsteveck-chung <schung@mozilla.com>
Mon, 27 Feb 2017 12:16:14 +0800
changeset 494949 bcb133bd2c5e5b806e11a17d0866326e687344c6
parent 493906 d939715c1c4c0a35ebb078cbdfca11df72c80ab6
child 494950 d1a3fdbc8419afad502a4f23df52a805c53a2633
push id48193
push userbmo:schung@mozilla.com
push dateWed, 08 Mar 2017 04:06:28 +0000
reviewersMattN
bugs1338420
milestone54.0a1
Bug 1338420 - Part 2: Add initial state for field details. r?MattN MozReview-Commit-ID: 9JFPan3qIox
browser/extensions/formautofill/FormAutofillHandler.jsm
browser/extensions/formautofill/test/unit/test_collectFormFields.js
browser/extensions/formautofill/test/unit/test_getFormInputDetails.js
--- 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* () {