Bug 1405997 - Fill a non-autocomplete tel field with tel-national value. r=lchang
authorSean Lee <selee@mozilla.com>
Fri, 06 Oct 2017 02:24:48 +0800
changeset 679115 d305adca613e2b2377307292fe4b0b8e9e3be11b
parent 679114 2ebd11851adf2b09c4bdf38c3270a8eb7d6d9441
child 679116 b581fa3d8e7a2b853d171c4dc6ae1ecdf2ad44d3
push id84141
push userbmo:schien@mozilla.com
push dateThu, 12 Oct 2017 11:13:04 +0000
reviewerslchang
bugs1405997
milestone58.0a1
Bug 1405997 - Fill a non-autocomplete tel field with tel-national value. r=lchang MozReview-Commit-ID: JpTqy42Y1ej
browser/extensions/formautofill/FormAutofillHandler.jsm
browser/extensions/formautofill/test/unit/test_getAdaptedProfiles.js
--- a/browser/extensions/formautofill/FormAutofillHandler.jsm
+++ b/browser/extensions/formautofill/FormAutofillHandler.jsm
@@ -231,16 +231,70 @@ FormAutofillHandler.prototype = {
             profile[f] = FormAutofillUtils.toOneLineAddress(waitForConcat);
           }
           waitForConcat = [];
         }
       }
     }
   },
 
+  /**
+   * Replace tel with tel-national if tel violates the input element's
+   * restriction.
+   * @param {Object} profile
+   *        A profile to be converted.
+   */
+  _telTransformer(profile) {
+    if (!profile.tel || !profile["tel-national"]) {
+      return;
+    }
+
+    let detail = this.getFieldDetailByName("tel");
+    if (!detail) {
+      return;
+    }
+
+    let element = detail.elementWeakRef.get();
+    let _pattern;
+    let testPattern = str => {
+      if (!_pattern) {
+        // The pattern has to match the entire value.
+        _pattern = new RegExp("^(?:" + element.pattern + ")$", "u");
+      }
+      return _pattern.test(str);
+    };
+    if (element.pattern) {
+      if (testPattern(profile.tel)) {
+        return;
+      }
+    } else if (element.maxLength) {
+      if (profile.tel.length <= element.maxLength) {
+        return;
+      }
+    }
+
+    if (detail._reason != "autocomplete") {
+      // Since we only target people living in US and using en-US websites in
+      // MVP, it makes more sense to fill `tel-national` instead of `tel`
+      // if the field is identified by heuristics and no other clues to
+      // determine which one is better.
+      // TODO: [Bug 1407545] This should be improved once more countries are
+      // supported.
+      profile.tel = profile["tel-national"];
+    } else if (element.pattern) {
+      if (testPattern(profile["tel-national"])) {
+        profile.tel = profile["tel-national"];
+      }
+    } else if (element.maxLength) {
+      if (profile["tel-national"].length <= element.maxLength) {
+        profile.tel = profile["tel-national"];
+      }
+    }
+  },
+
   _matchSelectOptions(profile) {
     if (!this._cacheValue.matchingSelectOption) {
       this._cacheValue.matchingSelectOption = new WeakMap();
     }
 
     for (let fieldName in profile) {
       let fieldDetail = this.getFieldDetailByName(fieldName);
       if (!fieldDetail) {
@@ -272,16 +326,17 @@ FormAutofillHandler.prototype = {
         delete profile[fieldName];
       }
     }
   },
 
   getAdaptedProfiles(originalProfiles) {
     for (let profile of originalProfiles) {
       this._addressTransformer(profile);
+      this._telTransformer(profile);
       this._matchSelectOptions(profile);
     }
     return originalProfiles;
   },
 
   /**
    * Processes form fields that can be autofilled, and populates them with the
    * profile provided by backend.
--- a/browser/extensions/formautofill/test/unit/test_getAdaptedProfiles.js
+++ b/browser/extensions/formautofill/test/unit/test_getAdaptedProfiles.js
@@ -9,16 +9,18 @@ Cu.import("resource://formautofill/FormA
 const DEFAULT_ADDRESS_RECORD = {
   "guid": "123",
   "street-address": "2 Harrison St\nline2\nline3",
   "address-line1": "2 Harrison St",
   "address-line2": "line2",
   "address-line3": "line3",
   "address-level1": "CA",
   "country": "US",
+  "tel": "+19876543210",
+  "tel-national": "9876543210",
 };
 
 const DEFAULT_CREDITCARD_RECORD = {
   "guid": "123",
   "cc-exp-month": 1,
   "cc-exp-year": 2025,
   "cc-exp": "2025-01",
 };
@@ -34,16 +36,18 @@ const TESTCASES = [
       "guid": "123",
       "street-address": "2 Harrison St line2 line3",
       "-moz-street-address-one-line": "2 Harrison St line2 line3",
       "address-line1": "2 Harrison St",
       "address-line2": "line2",
       "address-line3": "line3",
       "address-level1": "CA",
       "country": "US",
+      "tel": "+19876543210",
+      "tel-national": "9876543210",
     }],
   },
   {
     description: "Address form with street-address, address-line[1, 2, 3]",
     document: `<form>
                <input id="street-addr" autocomplete="street-address">
                <input id="line1" autocomplete="address-line1">
                <input id="line2" autocomplete="address-line2">
@@ -54,16 +58,18 @@ const TESTCASES = [
       "guid": "123",
       "street-address": "2 Harrison St line2 line3",
       "-moz-street-address-one-line": "2 Harrison St line2 line3",
       "address-line1": "2 Harrison St",
       "address-line2": "line2",
       "address-line3": "line3",
       "address-level1": "CA",
       "country": "US",
+      "tel": "+19876543210",
+      "tel-national": "9876543210",
     }],
   },
   {
     description: "Address form with street-address, address-line1",
     document: `<form>
                <input id="street-addr" autocomplete="street-address">
                <input id="line1" autocomplete="address-line1">
                </form>`,
@@ -72,16 +78,18 @@ const TESTCASES = [
       "guid": "123",
       "street-address": "2 Harrison St line2 line3",
       "-moz-street-address-one-line": "2 Harrison St line2 line3",
       "address-line1": "2 Harrison St line2 line3",
       "address-line2": "line2",
       "address-line3": "line3",
       "address-level1": "CA",
       "country": "US",
+      "tel": "+19876543210",
+      "tel-national": "9876543210",
     }],
   },
   {
     description: "Address form with street-address, address-line[1, 2]",
     document: `<form>
                <input id="street-addr" autocomplete="street-address">
                <input id="line1" autocomplete="address-line1">
                <input id="line2" autocomplete="address-line2">
@@ -91,16 +99,18 @@ const TESTCASES = [
       "guid": "123",
       "street-address": "2 Harrison St line2 line3",
       "-moz-street-address-one-line": "2 Harrison St line2 line3",
       "address-line1": "2 Harrison St",
       "address-line2": "line2 line3",
       "address-line3": "line3",
       "address-level1": "CA",
       "country": "US",
+      "tel": "+19876543210",
+      "tel-national": "9876543210",
     }],
   },
   {
     description: "Address form with street-address, address-line[1, 3]",
     document: `<form>
                <input id="street-addr" autocomplete="street-address">
                <input id="line1" autocomplete="address-line1">
                <input id="line3" autocomplete="address-line3">
@@ -110,16 +120,18 @@ const TESTCASES = [
       "guid": "123",
       "street-address": "2 Harrison St line2 line3",
       "-moz-street-address-one-line": "2 Harrison St line2 line3",
       "address-line1": "2 Harrison St",
       "address-line2": "line2 line3",
       "address-line3": "line3",
       "address-level1": "CA",
       "country": "US",
+      "tel": "+19876543210",
+      "tel-national": "9876543210",
     }],
   },
   {
     description: "Address form with exact matching options in select",
     document: `<form>
                <select autocomplete="address-level1">
                  <option id="option-address-level1-XX" value="XX">Dummy</option>
                  <option id="option-address-level1-CA" value="CA">California</option>
@@ -134,16 +146,18 @@ const TESTCASES = [
       "guid": "123",
       "street-address": "2 Harrison St\nline2\nline3",
       "-moz-street-address-one-line": "2 Harrison St line2 line3",
       "address-line1": "2 Harrison St",
       "address-line2": "line2",
       "address-line3": "line3",
       "address-level1": "CA",
       "country": "US",
+      "tel": "+19876543210",
+      "tel-national": "9876543210",
     }],
     expectedOptionElements: [{
       "address-level1": "option-address-level1-CA",
       "country": "option-country-US",
     }],
   },
   {
     description: "Address form with inexact matching options in select",
@@ -162,16 +176,18 @@ const TESTCASES = [
       "guid": "123",
       "street-address": "2 Harrison St\nline2\nline3",
       "-moz-street-address-one-line": "2 Harrison St line2 line3",
       "address-line1": "2 Harrison St",
       "address-line2": "line2",
       "address-line3": "line3",
       "address-level1": "CA",
       "country": "US",
+      "tel": "+19876543210",
+      "tel-national": "9876543210",
     }],
     expectedOptionElements: [{
       "address-level1": "option-address-level1-OO",
       "country": "option-country-OO",
     }],
   },
   {
     description: "Address form with value-omitted options in select",
@@ -190,16 +206,18 @@ const TESTCASES = [
       "guid": "123",
       "street-address": "2 Harrison St\nline2\nline3",
       "-moz-street-address-one-line": "2 Harrison St line2 line3",
       "address-line1": "2 Harrison St",
       "address-line2": "line2",
       "address-line3": "line3",
       "address-level1": "CA",
       "country": "US",
+      "tel": "+19876543210",
+      "tel-national": "9876543210",
     }],
     expectedOptionElements: [{
       "address-level1": "option-address-level1-2",
       "country": "option-country-2",
     }],
   },
   {
     description: "Address form with options with the same value in select ",
@@ -218,16 +236,18 @@ const TESTCASES = [
       "guid": "123",
       "street-address": "2 Harrison St\nline2\nline3",
       "-moz-street-address-one-line": "2 Harrison St line2 line3",
       "address-line1": "2 Harrison St",
       "address-line2": "line2",
       "address-line3": "line3",
       "address-level1": "CA",
       "country": "US",
+      "tel": "+19876543210",
+      "tel-national": "9876543210",
     }],
     expectedOptionElements: [{
       "address-level1": "option-address-level1-same2",
       "country": "option-country-same2",
     }],
   },
   {
     description: "Address form without matching options in select for address-level1 and country",
@@ -244,16 +264,186 @@ const TESTCASES = [
     profileData: [Object.assign({}, DEFAULT_ADDRESS_RECORD)],
     expectedResult: [{
       "guid": "123",
       "street-address": "2 Harrison St\nline2\nline3",
       "-moz-street-address-one-line": "2 Harrison St line2 line3",
       "address-line1": "2 Harrison St",
       "address-line2": "line2",
       "address-line3": "line3",
+      "tel": "+19876543210",
+      "tel-national": "9876543210",
+    }],
+  },
+  {
+    description: "Change the tel value of a profile to tel-national for a field without pattern and maxlength.",
+    document: `<form>
+               <input id="telephone">
+               <input id="line1" autocomplete="address-line1">
+               <input id="line2" autocomplete="address-line2">
+               </form>`,
+    profileData: [Object.assign({}, DEFAULT_ADDRESS_RECORD)],
+    expectedResult: [{
+      "guid": "123",
+      "street-address": "2 Harrison St\nline2\nline3",
+      "-moz-street-address-one-line": "2 Harrison St line2 line3",
+      "address-line1": "2 Harrison St",
+      "address-line2": "line2 line3",
+      "address-line3": "line3",
+      "address-level1": "CA",
+      "country": "US",
+      "tel": "9876543210",
+      "tel-national": "9876543210",
+    }],
+  },
+  {
+    description: "Do not change the profile for an autocomplete=\"tel\" field without patern and maxlength.",
+    document: `<form>
+               <input id="tel" autocomplete="tel">
+               <input id="line1" autocomplete="address-line1">
+               <input id="line2" autocomplete="address-line2">
+               </form>`,
+    profileData: [Object.assign({}, DEFAULT_ADDRESS_RECORD)],
+    expectedResult: [{
+      "guid": "123",
+      "street-address": "2 Harrison St\nline2\nline3",
+      "-moz-street-address-one-line": "2 Harrison St line2 line3",
+      "address-line1": "2 Harrison St",
+      "address-line2": "line2 line3",
+      "address-line3": "line3",
+      "address-level1": "CA",
+      "country": "US",
+      "tel": "+19876543210",
+      "tel-national": "9876543210",
+    }],
+  },
+  {
+    description: "`tel` field with `maxlength` can be filled with `tel` value.",
+    document: `<form>
+               <input id="telephone" maxlength="12">
+               <input id="line1" autocomplete="address-line1">
+               <input id="line2" autocomplete="address-line2">
+               </form>`,
+    profileData: [Object.assign({}, DEFAULT_ADDRESS_RECORD)],
+    expectedResult: [{
+      "guid": "123",
+      "street-address": "2 Harrison St\nline2\nline3",
+      "-moz-street-address-one-line": "2 Harrison St line2 line3",
+      "address-line1": "2 Harrison St",
+      "address-line2": "line2 line3",
+      "address-line3": "line3",
+      "address-level1": "CA",
+      "country": "US",
+      "tel": "+19876543210",
+      "tel-national": "9876543210",
+    }],
+  },
+  {
+    description: "`tel` field with `maxlength` can be filled with `tel-national` value.",
+    document: `<form>
+               <input id="telephone" maxlength="10">
+               <input id="line1" autocomplete="address-line1">
+               <input id="line2" autocomplete="address-line2">
+               </form>`,
+    profileData: [Object.assign({}, DEFAULT_ADDRESS_RECORD)],
+    expectedResult: [{
+      "guid": "123",
+      "street-address": "2 Harrison St\nline2\nline3",
+      "-moz-street-address-one-line": "2 Harrison St line2 line3",
+      "address-line1": "2 Harrison St",
+      "address-line2": "line2 line3",
+      "address-line3": "line3",
+      "address-level1": "CA",
+      "country": "US",
+      "tel": "9876543210",
+      "tel-national": "9876543210",
+    }],
+  },
+  {
+    description: "`tel` field with `pattern` attr can be filled with `tel` value.",
+    document: `<form>
+               <input id="telephone" pattern="[+][0-9]+">
+               <input id="line1" autocomplete="address-line1">
+               <input id="line2" autocomplete="address-line2">
+               </form>`,
+    profileData: [Object.assign({}, DEFAULT_ADDRESS_RECORD)],
+    expectedResult: [{
+      "guid": "123",
+      "street-address": "2 Harrison St\nline2\nline3",
+      "-moz-street-address-one-line": "2 Harrison St line2 line3",
+      "address-line1": "2 Harrison St",
+      "address-line2": "line2 line3",
+      "address-line3": "line3",
+      "address-level1": "CA",
+      "country": "US",
+      "tel": "+19876543210",
+      "tel-national": "9876543210",
+    }],
+  },
+  {
+    description: "Change the tel value of a profile to tel-national one when the pattern is matched.",
+    document: `<form>
+               <input id="telephone" pattern="\d*">
+               <input id="line1" autocomplete="address-line1">
+               <input id="line2" autocomplete="address-line2">
+               </form>`,
+    profileData: [Object.assign({}, DEFAULT_ADDRESS_RECORD)],
+    expectedResult: [{
+      "guid": "123",
+      "street-address": "2 Harrison St\nline2\nline3",
+      "-moz-street-address-one-line": "2 Harrison St line2 line3",
+      "address-line1": "2 Harrison St",
+      "address-line2": "line2 line3",
+      "address-line3": "line3",
+      "address-level1": "CA",
+      "country": "US",
+      "tel": "9876543210",
+      "tel-national": "9876543210",
+    }],
+  },
+  {
+    description: "Matching pattern when a field is with autocomplete=\"tel\".",
+    document: `<form>
+               <input id="tel" autocomplete="tel" pattern="[0-9]+">
+               <input id="line1" autocomplete="address-line1">
+               <input id="line2" autocomplete="address-line2">
+               </form>`,
+    profileData: [Object.assign({}, DEFAULT_ADDRESS_RECORD)],
+    expectedResult: [{
+      "guid": "123",
+      "street-address": "2 Harrison St\nline2\nline3",
+      "-moz-street-address-one-line": "2 Harrison St line2 line3",
+      "address-line1": "2 Harrison St",
+      "address-line2": "line2 line3",
+      "address-line3": "line3",
+      "address-level1": "CA",
+      "country": "US",
+      "tel": "9876543210",
+      "tel-national": "9876543210",
+    }],
+  },
+  {
+    description: "Checking maxlength first when a field is with maxlength.",
+    document: `<form>
+               <input id="tel" autocomplete="tel" maxlength="10">
+               <input id="line1" autocomplete="address-line1">
+               <input id="line2" autocomplete="address-line2">
+               </form>`,
+    profileData: [Object.assign({}, DEFAULT_ADDRESS_RECORD)],
+    expectedResult: [{
+      "guid": "123",
+      "street-address": "2 Harrison St\nline2\nline3",
+      "-moz-street-address-one-line": "2 Harrison St line2 line3",
+      "address-line1": "2 Harrison St",
+      "address-line2": "line2 line3",
+      "address-line3": "line3",
+      "address-level1": "CA",
+      "country": "US",
+      "tel": "9876543210",
+      "tel-national": "9876543210",
     }],
   },
   {
     description: "Credit Card form with matching options of cc-exp-year and cc-exp-month",
     document: `<form>
                <select autocomplete="cc-exp-month">
                  <option id="option-cc-exp-month-01" value="1">01</option>
                  <option id="option-cc-exp-month-02" value="2">02</option>