Bug 1388152 - Save displayed text of select element rather than its value in form autofill submission. r=lchang draft
authorRay Lin <ralin@mozilla.com>
Mon, 14 Aug 2017 18:08:44 +0800
changeset 648144 bd0a38932a72cf448591478ab1b8a25d8858d526
parent 647817 63ca686c3f1e870649b6d9c559973d100573aec2
child 726722 ee78a8130d5a0bb3fd9a51a92b2e87860900a272
push id74641
push userbmo:ralin@mozilla.com
push dateThu, 17 Aug 2017 09:22:58 +0000
reviewerslchang
bugs1388152
milestone57.0a1
Bug 1388152 - Save displayed text of select element rather than its value in form autofill submission. r=lchang MozReview-Commit-ID: IjZKzEdLlq5
browser/extensions/formautofill/FormAutofillHandler.jsm
browser/extensions/formautofill/test/unit/test_onFormSubmitted.js
--- a/browser/extensions/formautofill/FormAutofillHandler.jsm
+++ b/browser/extensions/formautofill/FormAutofillHandler.jsm
@@ -476,16 +476,30 @@ FormAutofillHandler.prototype = {
         record: {},
         untouchedFields: [],
       };
 
       details.forEach(detail => {
         let element = detail.elementWeakRef.get();
         // Remove the unnecessary spaces
         let value = element && element.value.trim();
+
+        // Save displayed text instead of actual value of select
+        // element.
+        if (type == "address" && element instanceof Ci.nsIDOMHTMLSelectElement) {
+          // Don't save the record when the option value is empty *OR* there
+          // are multiple options being selected. The empty option is usually
+          // assumed to be default along with a meaningless text to users.
+          if (!value || element.selectedOptions.length != 1) {
+            return;
+          }
+
+          value = element.selectedOptions[0].text.trim();
+        }
+
         if (!value) {
           return;
         }
 
         data[type].record[detail.fieldName] = value;
 
         if (detail.state == "AUTO_FILLED") {
           data[type].untouchedFields.push(detail.fieldName);
--- a/browser/extensions/formautofill/test/unit/test_onFormSubmitted.js
+++ b/browser/extensions/formautofill/test/unit/test_onFormSubmitted.js
@@ -1,15 +1,26 @@
 "use strict";
 
 Cu.import("resource://formautofill/FormAutofillContent.jsm");
 
 const MOCK_DOC = MockDocument.createTestDocument("http://localhost:8080/test/",
                    `<form id="form1">
                       <input id="street-addr" autocomplete="street-address">
+                      <select id="address-level1" autocomplete="address-level1">
+                        <option value=""></option>
+                        <option value="AL">Alabama</option>
+                        <option value="AK">Alaska</option>
+                        <option value="AP">Armed Forces Pacific</option>
+                        <option value="AE">Armed Force Europe</option>
+                        <option value="AA">Armed Forces America</option>
+                        <option value="AZ">Arizona</option>
+                        <option value="AR">Arkansas</option>
+                        <option value="CA">California</option>
+                      </select>
                       <input id="city" autocomplete="address-level2">
                       <input id="country" autocomplete="country">
                       <input id="email" autocomplete="email">
                       <input id="tel" autocomplete="tel">
                       <input id="cc-name" autocomplete="cc-name">
                       <input id="cc-number" autocomplete="cc-number">
                       <input id="cc-exp-month" autocomplete="cc-exp-month">
                       <input id="cc-exp-year" autocomplete="cc-exp-year">
@@ -161,16 +172,61 @@ const TESTCASES = [
             "country": "USA",
             "tel": "1-650-903-0800",
           },
           untouchedFields: [],
         },
       },
     },
   },
+  {
+    description: "Should save displayed text of select option instead of its value",
+    formValue: {
+      "address-level1": "CA",
+      "street-addr": "331 E. Evelyn Avenue",
+      "country": "USA",
+    },
+    expectedResult: {
+      formSubmission: true,
+      records: {
+        address: {
+          guid: null,
+          record: {
+            "address-level1": "California",
+            "street-address": "331 E. Evelyn Avenue",
+            "country": "USA",
+          },
+          untouchedFields: [],
+        },
+      },
+    },
+  },
+  {
+    description: "Shouldn't save select with multiple selections",
+    formValue: {
+      "address-level1": ["AL", "AK", "AP"],
+      "street-addr": "331 E. Evelyn Avenue",
+      "country": "USA",
+      "tel": "1-650-903-0800",
+    },
+    expectedResult: {
+      formSubmission: true,
+      records: {
+        address: {
+          guid: null,
+          record: {
+            "street-address": "331 E. Evelyn Avenue",
+            "country": "USA",
+            "tel": "1-650-903-0800",
+          },
+          untouchedFields: [],
+        },
+      },
+    },
+  },
 ];
 
 add_task(async function handle_earlyformsubmit_event() {
   do_print("Starting testcase: Test an invalid form element");
   let fakeForm = MOCK_DOC.createElement("form");
   sinon.spy(FormAutofillContent, "_onFormSubmit");
 
   do_check_eq(FormAutofillContent.notify(fakeForm), true);
@@ -181,17 +237,26 @@ add_task(async function handle_earlyform
 TESTCASES.forEach(testcase => {
   add_task(async function check_records_saving_is_called_correctly() {
     do_print("Starting testcase: " + testcase.description);
 
     let form = MOCK_DOC.getElementById("form1");
     form.reset();
     for (let key in testcase.formValue) {
       let input = MOCK_DOC.getElementById(key);
-      input.value = testcase.formValue[key];
+      let value = testcase.formValue[key];
+
+      if (input instanceof Ci.nsIDOMHTMLSelectElement && value) {
+        input.multiple = Array.isArray(value);
+        [...input.options].forEach(option => {
+          option.selected = value.includes(option.value);
+        });
+      } else {
+        input.value = testcase.formValue[key];
+      }
     }
     sinon.stub(FormAutofillContent, "_onFormSubmit");
 
     let element = MOCK_DOC.getElementById(TARGET_ELEMENT_ID);
     FormAutofillContent.identifyAutofillFields(element);
     FormAutofillContent.notify(form);
 
     do_check_eq(FormAutofillContent._onFormSubmit.called,