Bug 1389413 - [Form Autofill] Part 1: Handle credit card number decryption while calling getByFilter. r=lchang draft
authorsteveck-chung <schung@mozilla.com>
Wed, 16 Aug 2017 12:47:09 +0800
changeset 651105 56423dab78aff6f86e4cadd823d442eee138a0a0
parent 649622 7dddbd85047c6dc73ddbe1e423cd643a217845b3
child 651106 f07c01f7a24cce6531c39ed92cfcb6b0341c2efb
child 651153 1050c083b84e1139ea983e848ae712d40c75602a
child 651154 b44a54eab685d1a9162bad7c3e51652b7137c90e
child 651222 5f919b7f3f50d87b5590daaa29ea34840e3cf6c4
push id75585
push userbmo:schung@mozilla.com
push dateWed, 23 Aug 2017 06:47:44 +0000
reviewerslchang
bugs1389413
milestone57.0a1
Bug 1389413 - [Form Autofill] Part 1: Handle credit card number decryption while calling getByFilter. r=lchang MozReview-Commit-ID: Lt8dGJQBsMw
browser/extensions/formautofill/FormAutofillParent.jsm
browser/extensions/formautofill/ProfileStorage.jsm
--- a/browser/extensions/formautofill/FormAutofillParent.jsm
+++ b/browser/extensions/formautofill/FormAutofillParent.jsm
@@ -37,16 +37,18 @@ Cu.import("resource://gre/modules/Servic
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 Cu.import("resource://formautofill/FormAutofillUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "FormAutofillPreferences",
                                   "resource://formautofill/FormAutofillPreferences.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "FormAutofillDoorhanger",
                                   "resource://formautofill/FormAutofillDoorhanger.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "MasterPassword",
+                                  "resource://formautofill/MasterPassword.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
                                   "resource:///modules/RecentWindow.jsm");
 
 this.log = null;
 FormAutofillUtils.defineLazyLogGetter(this, this.EXPORTED_SYMBOLS[0]);
 
 const ENABLED_PREF = "extensions.formautofill.addresses.enabled";
 
@@ -240,24 +242,50 @@ FormAutofillParent.prototype = {
    *         The name used to specify which collection to retrieve records.
    * @param  {string} data.searchString
    *         The typed string for filtering out the matched records.
    * @param  {string} data.info
    *         The input autocomplete property's information.
    * @param  {nsIFrameMessageManager} target
    *         Content's message manager.
    */
-  _getRecords({collectionName, searchString, info}, target) {
-    let records;
+  async _getRecords({collectionName, searchString, info}, target) {
     let collection = this.profileStorage[collectionName];
+    if (!collection) {
+      target.sendAsyncMessage("FormAutofill:Records", []);
+      return;
+    }
 
-    if (!collection) {
-      records = [];
-    } else if (info && info.fieldName) {
-      records = collection.getByFilter({searchString, info});
+    let records = [];
+    if (info && info.fieldName &&
+      !(MasterPassword.isEnabled && info.fieldName == "cc-number")) {
+      if (info.fieldName == "cc-number") {
+        for (let record of collection.getAll()) {
+          let number = await MasterPassword.decrypt(record["cc-number-encrypted"]);
+          if (number.startsWith(searchString)) {
+            records.push(record);
+          }
+        }
+      } else {
+        let lcSearchString = searchString.toLowerCase();
+        let result = collection.getAll().filter(record => {
+          // Return true if string is not provided and field exists.
+          // TODO: We'll need to check if the address is for billing or shipping.
+          //       (Bug 1358941)
+          let name = record[info.fieldName];
+
+          if (!searchString) {
+            return !!name;
+          }
+
+          return name && name.toLowerCase().startsWith(lcSearchString);
+        });
+
+        records = result;
+      }
     } else {
       records = collection.getAll();
     }
 
     target.sendAsyncMessage("FormAutofill:Records", records);
   },
 
   _updateSavedFieldNames() {
--- a/browser/extensions/formautofill/ProfileStorage.jsm
+++ b/browser/extensions/formautofill/ProfileStorage.jsm
@@ -529,43 +529,16 @@ class AutofillRecords {
       } else {
         this._recordReadProcessor(record);
       }
     });
     return clonedRecords;
   }
 
   /**
-   * Returns the filtered records based on input's information and searchString.
-   *
-   * @returns {Array.<Object>}
-   *          An array containing clones of matched record.
-   */
-  getByFilter({info, searchString}) {
-    this.log.debug("getByFilter:", info, searchString);
-
-    let lcSearchString = searchString.toLowerCase();
-    let result = this.getAll().filter(record => {
-      // Return true if string is not provided and field exists.
-      // TODO: We'll need to check if the address is for billing or shipping.
-      //       (Bug 1358941)
-      let name = record[info.fieldName];
-
-      if (!searchString) {
-        return !!name;
-      }
-
-      return name && name.toLowerCase().startsWith(lcSearchString);
-    });
-
-    this.log.debug("getByFilter:", "Returning", result.length, "result(s)");
-    return result;
-  }
-
-  /**
    * Functions intended to be used in the support of Sync.
    */
 
   /**
    * Stores a hash of the last synced value for a field in a locally updated
    * record. We use this value to rebuild the shared parent, or base, when
    * reconciling incoming records that may have changed on another device.
    *
@@ -1539,17 +1512,17 @@ class CreditCards extends AutofillRecord
 
       // Based on the information on wiki[1], the shortest valid length should be
       // 12 digits(Maestro).
       // [1] https://en.wikipedia.org/wiki/Payment_card_number
       if (ccNumber.length < 12) {
         throw new Error("Invalid credit card number because length is under 12 digits.");
       }
 
-      creditCard["cc-number-encrypted"] = await MasterPassword.encrypt(creditCard["cc-number"]);
+      creditCard["cc-number-encrypted"] = await MasterPassword.encrypt(ccNumber);
       creditCard["cc-number"] = "*".repeat(ccNumber.length - 4) + ccNumber.substr(-4);
     }
   }
 }
 
 function ProfileStorage(path) {
   this._path = path;
   this._initializePromise = null;