Bug 1370429 - Part 5: Add tel-extension support. r=MattN
authorSean Lee <selee@mozilla.com>
Wed, 19 Jul 2017 10:18:57 +0800
changeset 422773 986bb6e88919374f8447c1a645b308ab54f731e3
parent 422772 8225d170ecb25c94575c081814d9c2e2a2e20c7e
child 422774 06cffb11dedacd9a8f2e062887a9a4194aa3659f
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMattN
bugs1370429
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1370429 - Part 5: Add tel-extension support. r=MattN MozReview-Commit-ID: 7XdiwYWERBC
browser/extensions/formautofill/FormAutofillHeuristics.jsm
browser/extensions/formautofill/FormAutofillUtils.jsm
browser/extensions/formautofill/content/heuristicsRegexp.js
--- a/browser/extensions/formautofill/FormAutofillHeuristics.jsm
+++ b/browser/extensions/formautofill/FormAutofillHeuristics.jsm
@@ -177,38 +177,16 @@ class FieldScanner {
     return index < this._elements.length;
   }
 }
 
 /**
  * Returns the autocomplete information of fields according to heuristics.
  */
 this.FormAutofillHeuristics = {
-  FIELD_GROUPS: {
-    NAME: [
-      "name",
-      "given-name",
-      "additional-name",
-      "family-name",
-    ],
-    ADDRESS: [
-      "organization",
-      "street-address",
-      "address-line1",
-      "address-line2",
-      "address-line3",
-      "address-level2",
-      "address-level1",
-      "postal-code",
-      "country",
-    ],
-    TEL: ["tel"],
-    EMAIL: ["email"],
-  },
-
   RULES: null,
 
   /**
    * Try to match the telephone related fields to the grammar
    * list to see if there is any valid telephone set and correct their
    * field names.
    *
    * @param {FieldScanner} fieldScanner
@@ -264,16 +242,26 @@ this.FormAutofillHeuristics = {
       for (let i = ruleFrom; i < ruleTo; i++) {
         fieldScanner.updateFieldName(detailStart, GRAMMARS[i][1]);
         fieldScanner.parsingIndex++;
         detailStart++;
         parsedField = true;
       }
     }
 
+    if (fieldScanner.parsingFinished) {
+      return parsedField;
+    }
+
+    let nextField = fieldScanner.getFieldDetailByIndex(fieldScanner.parsingIndex);
+    if (nextField && nextField.fieldName == "tel-extension") {
+      fieldScanner.parsingIndex++;
+      parsedField = true;
+    }
+
     return parsedField;
   },
 
   /**
    * Try to find the correct address-line[1-3] sequence and correct their field
    * names.
    *
    * @param {FieldScanner} fieldScanner
@@ -314,55 +302,16 @@ this.FormAutofillHeuristics = {
       // forward to the next one.
       if (!parsedPhoneFields && !parsedAddressFields) {
         fieldScanner.parsingIndex++;
       }
     }
     return fieldScanner.trimmedFieldDetail;
   },
 
-  /**
-   * Get the autocomplete info (e.g. fieldName) determined by the regexp
-   * (this.RULES) matching to a feature string.
-   *
-   * @param {string} string a feature string to be determined.
-   * @returns {Object}
-   *          Provide the predicting result including the field name.
-   *
-   */
-  _matchStringToFieldName(string) {
-    let result = {
-      fieldName: "",
-      section: "",
-      addressType: "",
-      contactType: "",
-    };
-    if (this.RULES.email.test(string)) {
-      result.fieldName = "email";
-      return result;
-    }
-    if (this.RULES.tel.test(string)) {
-      result.fieldName = "tel";
-      return result;
-    }
-    for (let fieldName of this.FIELD_GROUPS.ADDRESS) {
-      if (this.RULES[fieldName].test(string)) {
-        result.fieldName = fieldName;
-        return result;
-      }
-    }
-    for (let fieldName of this.FIELD_GROUPS.NAME) {
-      if (this.RULES[fieldName].test(string)) {
-        result.fieldName = fieldName;
-        return result;
-      }
-    }
-    return null;
-  },
-
   getInfo(element) {
     if (!FormAutofillUtils.isFieldEligibleForAutofill(element)) {
       return null;
     }
 
     let info = element.getAutocompleteInfo();
     // An input[autocomplete="on"] will not be early return here since it stll
     // needs to find the field name.
@@ -382,33 +331,42 @@ this.FormAutofillHeuristics = {
       return {
         fieldName: "email",
         section: "",
         addressType: "",
         contactType: "",
       };
     }
 
-    for (let elementString of [element.id, element.name]) {
-      let fieldNameResult = this._matchStringToFieldName(elementString);
-      if (fieldNameResult) {
-        return fieldNameResult;
+    let regexps = Object.keys(this.RULES);
+
+    let labelStrings;
+    let getElementStrings = {};
+    getElementStrings[Symbol.iterator] = function* () {
+      yield element.id;
+      yield element.name;
+      if (!labelStrings) {
+        labelStrings = [];
+        let labels = FormAutofillUtils.findLabelElements(element);
+        for (let label of labels) {
+          labelStrings.push(...FormAutofillUtils.extractLabelStrings(label));
+        }
       }
-    }
-    let labels = FormAutofillUtils.findLabelElements(element);
-    if (!labels || labels.length == 0) {
-      log.debug("No label found for", element);
-      return null;
-    }
-    for (let label of labels) {
-      let strings = FormAutofillUtils.extractLabelStrings(label);
-      for (let string of strings) {
-        let fieldNameResult = this._matchStringToFieldName(string);
-        if (fieldNameResult) {
-          return fieldNameResult;
+      yield *labelStrings;
+    };
+
+    for (let regexp of regexps) {
+      for (let string of getElementStrings) {
+        if (this.RULES[regexp].test(string)) {
+          return {
+            fieldName: regexp,
+            section: "",
+            addressType: "",
+            contactType: "",
+          };
         }
       }
     }
 
     return null;
   },
 
 /**
--- a/browser/extensions/formautofill/FormAutofillUtils.jsm
+++ b/browser/extensions/formautofill/FormAutofillUtils.jsm
@@ -33,16 +33,17 @@ this.FormAutofillUtils = {
     "country-name": "address",
     "tel": "tel",
     "tel-country-code": "tel",
     "tel-national": "tel",
     "tel-area-code": "tel",
     "tel-local": "tel",
     "tel-local-prefix": "tel",
     "tel-local-suffix": "tel",
+    "tel-extension": "tel",
     "email": "email",
     "cc-name": "creditCard",
     "cc-number": "creditCard",
     "cc-exp-month": "creditCard",
     "cc-exp-year": "creditCard",
   },
   _addressDataLoaded: false,
 
--- a/browser/extensions/formautofill/content/heuristicsRegexp.js
+++ b/browser/extensions/formautofill/content/heuristicsRegexp.js
@@ -24,16 +24,21 @@ var HeuristicsRegExp = {
       "|Электронной.?Почты" +                       // ru
       "|邮件|邮箱" +                                // zh-CN
       "|電郵地址" +                                 // zh-TW
       "|(?:이메일|전자.?우편|[Ee]-?mail)(.?주소)?", // ko-KR
       "iu"
     ),
 
     // ==== Telephone ====
+    "tel-extension": new RegExp(
+      "\\bext|ext\\b|extension" +
+      "|ramal",                     // pt-BR, pt-PT
+      "iu"
+    ),
     "tel": new RegExp(
       "phone|mobile|contact.?number" +
       "|telefonnummer" +                             // de-DE
       "|telefono|teléfono" +                         // es
       "|telfixe" +                                   // fr-FR
       "|電話" +                                      // ja-JP
       "|telefone|telemovel" +                        // pt-BR, pt-PT
       "|телефон" +                                   // ru
@@ -150,16 +155,27 @@ var HeuristicsRegExp = {
       "|país|pais" + // es
       "|国" +        // ja-JP
       "|国家" +      // zh-CN
       "|국가|나라",  // ko-KR
       "iu"
     ),
 
     // ==== Name Fields ====
+    "name": new RegExp(
+      "^name|full.?name|your.?name|customer.?name|bill.?name|ship.?name" +
+      "|name.*first.*last|firstandlastname" +
+      "|nombre.*y.*apellidos" + // es
+      "|^nom" +                 // fr-FR
+      "|お名前|氏名" +          // ja-JP
+      "|^nome" +                // pt-BR, pt-PT
+      "|姓名" +                 // zh-CN
+      "|성명",                  // ko-KR
+      "iu"
+    ),
     "given-name": new RegExp(
       "first.*name|initials|fname|first$|given.*name" +
       "|vorname" +                // de-DE
       "|nombre" +                 // es
       "|forename|prénom|prenom" + // fr-FR
       "|名" +                     // ja-JP
       "|nome" +                   // pt-BR, pt-PT
       "|Имя" +                    // ru
@@ -181,21 +197,10 @@ var HeuristicsRegExp = {
       "|famille|^nom" +                       // fr-FR
       "|cognome" +                            // it-IT
       "|姓" +                                 // ja-JP
       "|morada|apelidos|surename|sobrenome" + // pt-BR, pt-PT
       "|Фамилия" +                            // ru
       "|\\b성(?:[^명]|\\b)",                  // ko-KR
       "iu"
     ),
-    "name": new RegExp(
-      "^name|full.?name|your.?name|customer.?name|bill.?name|ship.?name" +
-      "|name.*first.*last|firstandlastname" +
-      "|nombre.*y.*apellidos" + // es
-      "|^nom" +                 // fr-FR
-      "|お名前|氏名" +          // ja-JP
-      "|^nome" +                // pt-BR, pt-PT
-      "|姓名" +                 // zh-CN
-      "|성명",                  // ko-KR
-      "iu"
-    ),
   },
 };