Bug 1338482 - Part 2: Add state while filling the form and check state at startSearch. r?MattN draft
authorsteveck-chung <schung@mozilla.com>
Tue, 07 Mar 2017 16:41:47 +0800
changeset 495111 8f6dbcce5fbb7418b3b899d21df6f8971abf6a3e
parent 495110 49a5afe13d8802c7cadaa546d3370e9173b025a9
child 548286 7aa7bb58fcda80a3dee573fa78be82ce45a87961
push id48236
push userbmo:schung@mozilla.com
push dateWed, 08 Mar 2017 09:02:57 +0000
reviewersMattN
bugs1338482
milestone54.0a1
Bug 1338482 - Part 2: Add state while filling the form and check state at startSearch. r?MattN MozReview-Commit-ID: 20xQrDOKPKF
browser/extensions/formautofill/FormAutofillContent.jsm
browser/extensions/formautofill/FormAutofillHandler.jsm
browser/extensions/formautofill/ProfileStorage.jsm
browser/extensions/formautofill/test/unit/test_autofillFormFields.js
--- a/browser/extensions/formautofill/FormAutofillContent.jsm
+++ b/browser/extensions/formautofill/FormAutofillContent.jsm
@@ -89,19 +89,25 @@ AutofillProfileAutoCompleteSearch.protot
    */
   startSearch(searchString, searchParam, previousResult, listener) {
     this.log.debug("startSearch: for", searchString, "with input", formFillController.focusedInput);
     let focusedInput = formFillController.focusedInput;
     this.forceStop = false;
     let info = FormAutofillContent.getInputDetails(focusedInput);
 
     if (!Services.cpmm.initialProcessData.existedFields.has(info.fieldName)) {
+      info.state = "fall-back";
+    }
+
+    // The search will switch to history if:
+    // 1) It already need to fall back when no profile data
+    // 2) The field is filled (no matter it's automatic or manual)
+    if (info.state) {
       let formHistory = Cc["@mozilla.org/autocomplete/search;1?name=form-history"]
                           .createInstance(Ci.nsIAutoCompleteSearch);
-      info.state = "fall-back";
       formHistory.startSearch(searchString, searchParam, previousResult, {
         onSearchResult: (search, result) => {
           listener.onSearchResult(this, result);
         },
       });
       return;
     }
 
--- a/browser/extensions/formautofill/FormAutofillHandler.jsm
+++ b/browser/extensions/formautofill/FormAutofillHandler.jsm
@@ -108,20 +108,28 @@ FormAutofillHandler.prototype = {
 
     this.filledProfileGUID = profile.guid;
     for (let fieldDetail of this.fieldDetails) {
       // Avoid filling field value in the following cases:
       // 1. the focused input which is filled in FormFillController.
       // 2. a non-empty input field
       // 3. the invalid value set
 
-      if (fieldDetail.element === focusedInput ||
-          fieldDetail.element.value) {
+      if (fieldDetail.element === focusedInput) {
+        fieldDetail.state = "auto-filled";
+        continue;
+      }
+
+      if (fieldDetail.element.value) {
+        fieldDetail.state = "fall-back";
         continue;
       }
 
       let value = profile[fieldDetail.fieldName];
       if (value) {
         fieldDetail.element.setUserInput(value);
+        fieldDetail.state = "auto-filled";
+      } else {
+        fieldDetail.state = "fall-back";
       }
     }
   },
 };
--- a/browser/extensions/formautofill/ProfileStorage.jsm
+++ b/browser/extensions/formautofill/ProfileStorage.jsm
@@ -80,16 +80,17 @@ const MOCK_STORAGE = [{
   organization: "Sesame Street",
   "street-address": "123 Sesame Street.",
   tel: "1-345-345-3456",
 }, {
   guid: "test-guid-2",
   organization: "Mozilla",
   "street-address": "331 E. Evelyn Avenue",
   tel: "1-650-903-0800",
+  country: "US",
 }];
 
 function ProfileStorage(path) {
   this._path = path;
 }
 
 ProfileStorage.prototype = {
   /**
--- a/browser/extensions/formautofill/test/unit/test_autofillFormFields.js
+++ b/browser/extensions/formautofill/test/unit/test_autofillFormFields.js
@@ -10,21 +10,22 @@ const TESTCASES = [
   {
     description: "Form without autocomplete property",
     document: `<form><input id="given-name"><input id="family-name">
                <input id="street-addr"><input id="city"><input id="country">
                <input id='email'><input id="tel"></form>`,
     fieldDetails: [],
     profileData: {},
     expectedResult: {
-      "street-addr": "",
-      "city": "",
-      "country": "",
-      "email": "",
-      "tel": "",
+      "family-name": {value: "", state: "fall-back"},
+      "street-addr": {value: "", state: "fall-back"},
+      "city": {value: "", state: "fall-back"},
+      "country": {value: "", state: "fall-back"},
+      "email": {value: "", state: "fall-back"},
+      "tel": {value: "", state: "fall-back"},
     },
   },
   {
     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">
@@ -44,21 +45,23 @@ const TESTCASES = [
       "guid": "123",
       "street-address": "2 Harrison St",
       "address-level2": "San Francisco",
       "country": "US",
       "email": "foo@mozilla.com",
       "tel": "1234567",
     },
     expectedResult: {
-      "street-addr": "2 Harrison St",
-      "city": "San Francisco",
-      "country": "US",
-      "email": "foo@mozilla.com",
-      "tel": "1234567",
+      "given-name": {value: "", state: "fall-back"},
+      "family-name": {value: "", state: "fall-back"},
+      "street-addr": {value: "2 Harrison St", state: "auto-filled"},
+      "city": {value: "San Francisco", state: "auto-filled"},
+      "country": {value: "US", state: "auto-filled"},
+      "email": {value: "foo@mozilla.com", state: "auto-filled"},
+      "tel": {value: "1234567", state: "auto-filled"},
     },
   },
   {
     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">
@@ -78,21 +81,23 @@ const TESTCASES = [
       "guid": "123",
       "street-address": "2 Harrison St",
       "address-level2": "San Francisco",
       "country": "US",
       "email": "foo@mozilla.com",
       "tel": "1234567",
     },
     expectedResult: {
-      "street-addr": "2 Harrison St",
-      "city": "San Francisco",
-      "country": "US",
-      "email": "foo@mozilla.com",
-      "tel": "1234567",
+      "given-name": {value: "", state: "fall-back"},
+      "family-name": {value: "", state: "fall-back"},
+      "street-addr": {value: "2 Harrison St", state: "auto-filled"},
+      "city": {value: "San Francisco", state: "auto-filled"},
+      "country": {value: "US", state: "auto-filled"},
+      "email": {value: "foo@mozilla.com", state: "auto-filled"},
+      "tel": {value: "1234567", state: "auto-filled"},
     },
   },
   {
     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">
@@ -112,21 +117,23 @@ const TESTCASES = [
       "guid": "123",
       "street-address": "2 Harrison St",
       "address-level2": "San Francisco",
       "country": "US",
       "email": "",
       "tel": "",
     },
     expectedResult: {
-      "street-addr": "2 Harrison St",
-      "city": "San Francisco",
-      "country": "US",
-      "email": "",
-      "tel": "",
+      "given-name": {value: "", state: "fall-back"},
+      "family-name": {value: "", state: "fall-back"},
+      "street-addr": {value: "2 Harrison St", state: "auto-filled"},
+      "city": {value: "San Francisco", state: "auto-filled"},
+      "country": {value: "US", state: "auto-filled"},
+      "email": {value: "", state: "fall-back"},
+      "tel": {value: "", state: "fall-back"},
     },
   },
   {
     description: "Form with autocomplete properties but mismatched",
     document: `<form><input id="given-name" autocomplete="shipping given-name">
                <input id="family-name" autocomplete="shipping family-name">
                <input id="street-addr" autocomplete="billing street-address">
                <input id="city" autocomplete="billing address-level2">
@@ -146,21 +153,23 @@ const TESTCASES = [
       "guid": "123",
       "street-address": "",
       "address-level2": "",
       "country": "",
       "email": "foo@mozilla.com",
       "tel": "1234567",
     },
     expectedResult: {
-      "street-addr": "",
-      "city": "",
-      "country": "",
-      "email": "foo@mozilla.com",
-      "tel": "1234567",
+      "given-name": {value: "", state: "fall-back"},
+      "family-name": {value: "", state: "fall-back"},
+      "street-addr": {value: "", state: "fall-back"},
+      "city": {value: "", state: "fall-back"},
+      "country": {value: "", state: "fall-back"},
+      "email": {value: "foo@mozilla.com", state: "auto-filled"},
+      "tel": {value: "1234567", state: "auto-filled"},
     },
   },
 ];
 
 for (let tc of TESTCASES) {
   (function() {
     let testcase = tc;
     add_task(function* () {
@@ -179,23 +188,28 @@ for (let tc of TESTCASES) {
         if (!testcase.profileData[field.fieldName]) {
           // Avoid waiting for `change` event of a input with a blank value to
           // be filled.
           return;
         }
         onChangePromises.push(new Promise(resolve => {
           element.addEventListener("change", () => {
             let id = element.id;
-            Assert.equal(element.value, testcase.expectedResult[id],
+            Assert.equal(element.value, testcase.expectedResult[id].value,
                         "Check the " + id + " fields were filled with correct data");
             resolve();
           }, {once: true});
         }));
       });
 
       handler.autofillFormFields(testcase.profileData);
 
       Assert.equal(handler.filledProfileGUID, testcase.profileData.guid,
                    "Check if filledProfileGUID is set correctly");
+
+      handler.fieldDetails.forEach((detail) => {
+        Assert.equal(detail.state, testcase.expectedResult[detail.element.id].state,
+                     "Check if state is set correctly");
+      });
       yield Promise.all(onChangePromises);
     });
   })();
 }