Bug 1300992 - Part 2: Return the filtered profile result, r?MattN
MozReview-Commit-ID: 828bJhAGAAb
--- a/browser/extensions/formautofill/FormAutofillParent.jsm
+++ b/browser/extensions/formautofill/FormAutofillParent.jsm
@@ -130,29 +130,23 @@ let FormAutofillParent = {
* @param {string} data.searchString
* The typed string for filtering out the matched profile.
* @param {string} data.info
* The input autocomplete property's information.
* @param {nsIFrameMessageManager} target
* Content's message manager.
*/
_getProfiles({searchString, info}, target) {
- // TODO: These mock data should be replaced by form autofill API
- // let profiles = this._profileStore.getAll();
- let profiles = [{
- guid: "test-guid-1",
- organization: "Sesame Street",
- streetAddress: "123 Sesame Street.",
- tel: "1-345-345-3456",
- }, {
- guid: "test-guid-2",
- organization: "Mozilla",
- streetAddress: "331 E. Evelyn Avenue",
- tel: "1-650-903-0800",
- }];
+ let profiles = [];
+
+ if (info && info.fieldName) {
+ profiles = this._profileStore.getByFilter({searchString, info});
+ } else {
+ profiles = this._profileStore.getAll();
+ }
target.messageManager.sendAsyncMessage("FormAutofill:Profiles", profiles);
},
/**
* Transforms a word with hyphen into camel case.
* (e.g. transforms "address-type" into "addressType".)
*
--- a/browser/extensions/formautofill/ProfileStorage.jsm
+++ b/browser/extensions/formautofill/ProfileStorage.jsm
@@ -61,16 +61,30 @@ const VALID_FIELDS = [
"addressLevel2",
"addressLevel1",
"postalCode",
"country",
"tel",
"email",
];
+// TODO: Remove this once we can add profile from preference.
+const MOCK_MODE = false;
+const MOCK_STORAGE = [{
+ guid: "test-guid-1",
+ organization: "Sesame Street",
+ streetAddress: "123 Sesame Street.",
+ tel: "1-345-345-3456",
+}, {
+ guid: "test-guid-2",
+ organization: "Mozilla",
+ streetAddress: "331 E. Evelyn Avenue",
+ tel: "1-650-903-0800",
+}];
+
function ProfileStorage(path) {
this._path = path;
}
ProfileStorage.prototype = {
/**
* Loads the profile data from file to memory.
*
@@ -205,24 +219,54 @@ ProfileStorage.prototype = {
*/
getAll() {
this._store.ensureDataReady();
// Profiles are cloned to avoid accidental modifications from outside.
return this._store.data.profiles.map(this._clone);
},
+ /**
+ * Returns the filtered profiles based on input's information and searchString.
+ *
+ * @returns {Array.<Profile>}
+ * An array containing clones of matched profiles.
+ */
+ getByFilter({info, searchString}) {
+ this._store.ensureDataReady();
+
+ // Profiles are cloned to avoid accidental modifications from outside.
+ return this._findByFilter({info, searchString}).map(this._clone);
+ },
+
_clone(profile) {
return Object.assign({}, profile);
},
_findByGUID(guid) {
return this._store.data.profiles.find(profile => profile.guid == guid);
},
+ _findByFilter({info, searchString}) {
+ let profiles = MOCK_MODE ? MOCK_STORAGE : this._store.data.profiles;
+ let lcSearchString = searchString.toLowerCase();
+
+ return profiles.filter(profile => {
+ // Return true if string is not provided and field exists.
+ // TODO: We'll need to check if the address is for billing or shipping.
+ let name = profile[info.fieldName];
+
+ if (!searchString) {
+ return !!name;
+ }
+
+ return name.toLowerCase().startsWith(lcSearchString);
+ });
+ },
+
_normalizeProfile(profile) {
let result = {};
for (let key in profile) {
if (!VALID_FIELDS.includes(key)) {
throw new Error(`"${key}" is not a valid field.`);
}
if (typeof profile[key] !== "string" &&
typeof profile[key] !== "number") {
--- a/browser/extensions/formautofill/test/unit/test_profileStorage.js
+++ b/browser/extensions/formautofill/test/unit/test_profileStorage.js
@@ -104,16 +104,48 @@ add_task(function* test_get() {
// Modifying output shouldn't affect the storage.
profile.organization = "test";
do_check_profile_matches(profileStorage.get(guid), TEST_PROFILE_1);
Assert.throws(() => profileStorage.get("INVALID_GUID"),
/No matching profile\./);
});
+add_task(function* test_getByFilter() {
+ let path = getTempFile(TEST_STORE_FILE_NAME).path;
+ yield prepareTestProfiles(path);
+
+ let profileStorage = new ProfileStorage(path);
+ yield profileStorage.initialize();
+
+ let filter = {info: {fieldName: "streetAddress"}, searchString: "Some"};
+ let profiles = profileStorage.getByFilter(filter);
+ do_check_eq(profiles.length, 1);
+ do_check_profile_matches(profiles[0], TEST_PROFILE_2);
+
+ filter = {info: {fieldName: "country"}, searchString: "u"};
+ profiles = profileStorage.getByFilter(filter);
+ do_check_eq(profiles.length, 2);
+ do_check_profile_matches(profiles[0], TEST_PROFILE_1);
+ do_check_profile_matches(profiles[1], TEST_PROFILE_2);
+
+ filter = {info: {fieldName: "streetAddress"}, searchString: "test"};
+ profiles = profileStorage.getByFilter(filter);
+ do_check_eq(profiles.length, 0);
+
+ filter = {info: {fieldName: "streetAddress"}, searchString: ""};
+ profiles = profileStorage.getByFilter(filter);
+ do_check_eq(profiles.length, 2);
+
+ // Check if the filtering logic is free from searching special chars.
+ filter = {info: {fieldName: "streetAddress"}, searchString: ".*"};
+ profiles = profileStorage.getByFilter(filter);
+ do_check_eq(profiles.length, 0);
+});
+
add_task(function* test_add() {
let path = getTempFile(TEST_STORE_FILE_NAME).path;
yield prepareTestProfiles(path);
let profileStorage = new ProfileStorage(path);
yield profileStorage.initialize();
let profiles = profileStorage.getAll();