зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1362911 - [Form Autofill] Rename "profiles" to "addresses" in the storage. r=MattN
MozReview-Commit-ID: J5QnWv343xq --HG-- extra : rebase_source : 25bb9534f4f5aabd7f33875f52f2d00cd480fda8
This commit is contained in:
Родитель
43998dbb90
Коммит
0538cf7020
|
@ -106,7 +106,7 @@ AutofillProfileAutoCompleteSearch.prototype = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._getProfiles({info, searchString}).then((profiles) => {
|
this._getAddresses({info, searchString}).then((addresses) => {
|
||||||
if (this.forceStop) {
|
if (this.forceStop) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ AutofillProfileAutoCompleteSearch.prototype = {
|
||||||
let result = new ProfileAutoCompleteResult(searchString,
|
let result = new ProfileAutoCompleteResult(searchString,
|
||||||
info.fieldName,
|
info.fieldName,
|
||||||
allFieldNames,
|
allFieldNames,
|
||||||
profiles,
|
addresses,
|
||||||
{});
|
{});
|
||||||
|
|
||||||
listener.onSearchResult(this, result);
|
listener.onSearchResult(this, result);
|
||||||
|
@ -132,27 +132,27 @@ AutofillProfileAutoCompleteSearch.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the profile data from parent process for AutoComplete result.
|
* Get the address data from parent process for AutoComplete result.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* Parameters for querying the corresponding result.
|
* Parameters for querying the corresponding result.
|
||||||
* @param {string} data.searchString
|
* @param {string} data.searchString
|
||||||
* The typed string for filtering out the matched profile.
|
* The typed string for filtering out the matched address.
|
||||||
* @param {string} data.info
|
* @param {string} data.info
|
||||||
* The input autocomplete property's information.
|
* The input autocomplete property's information.
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
* Promise that resolves when profiles returned from parent process.
|
* Promise that resolves when addresses returned from parent process.
|
||||||
*/
|
*/
|
||||||
_getProfiles(data) {
|
_getAddresses(data) {
|
||||||
this.log.debug("_getProfiles with data:", data);
|
this.log.debug("_getAddresses with data:", data);
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
Services.cpmm.addMessageListener("FormAutofill:Profiles", function getResult(result) {
|
Services.cpmm.addMessageListener("FormAutofill:Addresses", function getResult(result) {
|
||||||
Services.cpmm.removeMessageListener("FormAutofill:Profiles", getResult);
|
Services.cpmm.removeMessageListener("FormAutofill:Addresses", getResult);
|
||||||
resolve(result.data);
|
resolve(result.data);
|
||||||
});
|
});
|
||||||
|
|
||||||
Services.cpmm.sendAsyncMessage("FormAutofill:GetProfiles", data);
|
Services.cpmm.sendAsyncMessage("FormAutofill:GetAddresses", data);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -76,9 +76,9 @@ FormAutofillParent.prototype = {
|
||||||
this._profileStore.initialize();
|
this._profileStore.initialize();
|
||||||
|
|
||||||
Services.obs.addObserver(this, "advanced-pane-loaded");
|
Services.obs.addObserver(this, "advanced-pane-loaded");
|
||||||
Services.ppmm.addMessageListener("FormAutofill:GetProfiles", this);
|
Services.ppmm.addMessageListener("FormAutofill:GetAddresses", this);
|
||||||
Services.ppmm.addMessageListener("FormAutofill:SaveProfile", this);
|
Services.ppmm.addMessageListener("FormAutofill:SaveAddress", this);
|
||||||
Services.ppmm.addMessageListener("FormAutofill:RemoveProfiles", this);
|
Services.ppmm.addMessageListener("FormAutofill:RemoveAddresses", this);
|
||||||
|
|
||||||
// Observing the pref and storage changes
|
// Observing the pref and storage changes
|
||||||
Services.prefs.addObserver(ENABLED_PREF, this);
|
Services.prefs.addObserver(ENABLED_PREF, this);
|
||||||
|
@ -182,19 +182,19 @@ FormAutofillParent.prototype = {
|
||||||
*/
|
*/
|
||||||
receiveMessage({name, data, target}) {
|
receiveMessage({name, data, target}) {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case "FormAutofill:GetProfiles": {
|
case "FormAutofill:GetAddresses": {
|
||||||
this._getProfiles(data, target);
|
this._getAddresses(data, target);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "FormAutofill:SaveProfile": {
|
case "FormAutofill:SaveAddress": {
|
||||||
if (data.guid) {
|
if (data.guid) {
|
||||||
this.getProfileStore().update(data.guid, data.profile);
|
this.getProfileStore().update(data.guid, data.address);
|
||||||
} else {
|
} else {
|
||||||
this.getProfileStore().add(data.profile);
|
this.getProfileStore().add(data.address);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "FormAutofill:RemoveProfiles": {
|
case "FormAutofill:RemoveAddresses": {
|
||||||
data.guids.forEach(guid => this.getProfileStore().remove(guid));
|
data.guids.forEach(guid => this.getProfileStore().remove(guid));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -223,34 +223,35 @@ FormAutofillParent.prototype = {
|
||||||
this._profileStore = null;
|
this._profileStore = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Services.ppmm.removeMessageListener("FormAutofill:GetProfiles", this);
|
Services.ppmm.removeMessageListener("FormAutofill:GetAddresses", this);
|
||||||
Services.ppmm.removeMessageListener("FormAutofill:SaveProfile", this);
|
Services.ppmm.removeMessageListener("FormAutofill:SaveAddress", this);
|
||||||
Services.ppmm.removeMessageListener("FormAutofill:RemoveProfiles", this);
|
Services.ppmm.removeMessageListener("FormAutofill:RemoveAddresses", this);
|
||||||
Services.obs.removeObserver(this, "advanced-pane-loaded");
|
Services.obs.removeObserver(this, "advanced-pane-loaded");
|
||||||
Services.prefs.removeObserver(ENABLED_PREF, this);
|
Services.prefs.removeObserver(ENABLED_PREF, this);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the profile data from profile store and return profiles back to content process.
|
* Get the address data from profile store and return addresses back to content
|
||||||
|
* process.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {string} data.searchString
|
* @param {string} data.searchString
|
||||||
* The typed string for filtering out the matched profile.
|
* The typed string for filtering out the matched address.
|
||||||
* @param {string} data.info
|
* @param {string} data.info
|
||||||
* The input autocomplete property's information.
|
* The input autocomplete property's information.
|
||||||
* @param {nsIFrameMessageManager} target
|
* @param {nsIFrameMessageManager} target
|
||||||
* Content's message manager.
|
* Content's message manager.
|
||||||
*/
|
*/
|
||||||
_getProfiles({searchString, info}, target) {
|
_getAddresses({searchString, info}, target) {
|
||||||
let profiles = [];
|
let addresses = [];
|
||||||
|
|
||||||
if (info && info.fieldName) {
|
if (info && info.fieldName) {
|
||||||
profiles = this._profileStore.getByFilter({searchString, info});
|
addresses = this._profileStore.getByFilter({searchString, info});
|
||||||
} else {
|
} else {
|
||||||
profiles = this._profileStore.getAll();
|
addresses = this._profileStore.getAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
target.sendAsyncMessage("FormAutofill:Profiles", profiles);
|
target.sendAsyncMessage("FormAutofill:Addresses", addresses);
|
||||||
},
|
},
|
||||||
|
|
||||||
_updateSavedFieldNames() {
|
_updateSavedFieldNames() {
|
||||||
|
@ -260,9 +261,9 @@ FormAutofillParent.prototype = {
|
||||||
Services.ppmm.initialProcessData.autofillSavedFieldNames.clear();
|
Services.ppmm.initialProcessData.autofillSavedFieldNames.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
this._profileStore.getAll().forEach((profile) => {
|
this._profileStore.getAll().forEach((address) => {
|
||||||
Object.keys(profile).forEach((fieldName) => {
|
Object.keys(address).forEach((fieldName) => {
|
||||||
if (!profile[fieldName]) {
|
if (!address[fieldName]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Services.ppmm.initialProcessData.autofillSavedFieldNames.add(fieldName);
|
Services.ppmm.initialProcessData.autofillSavedFieldNames.add(fieldName);
|
||||||
|
|
|
@ -11,11 +11,11 @@
|
||||||
*
|
*
|
||||||
* {
|
* {
|
||||||
* version: 1,
|
* version: 1,
|
||||||
* profiles: [
|
* addresses: [
|
||||||
* {
|
* {
|
||||||
* guid, // 12 character...
|
* guid, // 12 characters
|
||||||
*
|
*
|
||||||
* // profile
|
* // address fields
|
||||||
* given-name,
|
* given-name,
|
||||||
* additional-name,
|
* additional-name,
|
||||||
* family-name,
|
* family-name,
|
||||||
|
@ -30,6 +30,7 @@
|
||||||
*
|
*
|
||||||
* // computed fields (These fields are not stored in the file as they are
|
* // computed fields (These fields are not stored in the file as they are
|
||||||
* // generated at runtime.)
|
* // generated at runtime.)
|
||||||
|
* name,
|
||||||
* address-line1,
|
* address-line1,
|
||||||
* address-line2,
|
* address-line2,
|
||||||
* address-line3,
|
* address-line3,
|
||||||
|
@ -87,26 +88,12 @@ const VALID_FIELDS = [
|
||||||
"email",
|
"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",
|
|
||||||
"street-address": "123 Sesame Street.",
|
|
||||||
tel: "1-345-345-3456",
|
|
||||||
}, {
|
|
||||||
guid: "test-guid-2",
|
|
||||||
organization: "Mozilla",
|
|
||||||
"street-address": "331 E. Evelyn Avenue",
|
|
||||||
tel: "1-650-903-0800",
|
|
||||||
}];
|
|
||||||
|
|
||||||
function ProfileStorage(path) {
|
function ProfileStorage(path) {
|
||||||
this._path = path;
|
this._path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfileStorage.prototype = {
|
ProfileStorage.prototype = {
|
||||||
// These fields are defined internally for each profile.
|
// These fields are defined internally for each record.
|
||||||
INTERNAL_FIELDS:
|
INTERNAL_FIELDS:
|
||||||
["guid", "timeCreated", "timeLastUsed", "timeLastModified", "timesUsed"],
|
["guid", "timeCreated", "timeLastUsed", "timeLastModified", "timesUsed"],
|
||||||
/**
|
/**
|
||||||
|
@ -125,160 +112,160 @@ ProfileStorage.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new profile.
|
* Adds a new address.
|
||||||
*
|
*
|
||||||
* @param {Profile} profile
|
* @param {Address} address
|
||||||
* The new profile for saving.
|
* The new address for saving.
|
||||||
*/
|
*/
|
||||||
add(profile) {
|
add(address) {
|
||||||
log.debug("add:", profile);
|
log.debug("add:", address);
|
||||||
this._store.ensureDataReady();
|
this._store.ensureDataReady();
|
||||||
|
|
||||||
let profileToSave = this._clone(profile);
|
let addressToSave = this._clone(address);
|
||||||
this._normalizeProfile(profileToSave);
|
this._normalizeAddress(addressToSave);
|
||||||
|
|
||||||
profileToSave.guid = gUUIDGenerator.generateUUID().toString()
|
addressToSave.guid = gUUIDGenerator.generateUUID().toString()
|
||||||
.replace(/[{}-]/g, "").substring(0, 12);
|
.replace(/[{}-]/g, "").substring(0, 12);
|
||||||
|
|
||||||
// Metadata
|
// Metadata
|
||||||
let now = Date.now();
|
let now = Date.now();
|
||||||
profileToSave.timeCreated = now;
|
addressToSave.timeCreated = now;
|
||||||
profileToSave.timeLastModified = now;
|
addressToSave.timeLastModified = now;
|
||||||
profileToSave.timeLastUsed = 0;
|
addressToSave.timeLastUsed = 0;
|
||||||
profileToSave.timesUsed = 0;
|
addressToSave.timesUsed = 0;
|
||||||
|
|
||||||
this._store.data.profiles.push(profileToSave);
|
this._store.data.addresses.push(addressToSave);
|
||||||
|
|
||||||
this._store.saveSoon();
|
this._store.saveSoon();
|
||||||
Services.obs.notifyObservers(null, "formautofill-storage-changed", "add");
|
Services.obs.notifyObservers(null, "formautofill-storage-changed", "add");
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the specified profile.
|
* Update the specified address.
|
||||||
*
|
*
|
||||||
* @param {string} guid
|
* @param {string} guid
|
||||||
* Indicates which profile to update.
|
* Indicates which address to update.
|
||||||
* @param {Profile} profile
|
* @param {Address} address
|
||||||
* The new profile used to overwrite the old one.
|
* The new address used to overwrite the old one.
|
||||||
*/
|
*/
|
||||||
update(guid, profile) {
|
update(guid, address) {
|
||||||
log.debug("update:", guid, profile);
|
log.debug("update:", guid, address);
|
||||||
this._store.ensureDataReady();
|
this._store.ensureDataReady();
|
||||||
|
|
||||||
let profileFound = this._findByGUID(guid);
|
let addressFound = this._findByGUID(guid);
|
||||||
if (!profileFound) {
|
if (!addressFound) {
|
||||||
throw new Error("No matching profile.");
|
throw new Error("No matching record.");
|
||||||
}
|
}
|
||||||
|
|
||||||
let profileToUpdate = this._clone(profile);
|
let addressToUpdate = this._clone(address);
|
||||||
this._normalizeProfile(profileToUpdate);
|
this._normalizeAddress(addressToUpdate);
|
||||||
|
|
||||||
for (let field of VALID_FIELDS) {
|
for (let field of VALID_FIELDS) {
|
||||||
if (profileToUpdate[field] !== undefined) {
|
if (addressToUpdate[field] !== undefined) {
|
||||||
profileFound[field] = profileToUpdate[field];
|
addressFound[field] = addressToUpdate[field];
|
||||||
} else {
|
} else {
|
||||||
delete profileFound[field];
|
delete addressFound[field];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
profileFound.timeLastModified = Date.now();
|
addressFound.timeLastModified = Date.now();
|
||||||
|
|
||||||
this._store.saveSoon();
|
this._store.saveSoon();
|
||||||
Services.obs.notifyObservers(null, "formautofill-storage-changed", "update");
|
Services.obs.notifyObservers(null, "formautofill-storage-changed", "update");
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the stroage of the use of the specified profile, so we can update
|
* Notifies the stroage of the use of the specified address, so we can update
|
||||||
* the metadata accordingly.
|
* the metadata accordingly.
|
||||||
*
|
*
|
||||||
* @param {string} guid
|
* @param {string} guid
|
||||||
* Indicates which profile to be notified.
|
* Indicates which address to be notified.
|
||||||
*/
|
*/
|
||||||
notifyUsed(guid) {
|
notifyUsed(guid) {
|
||||||
this._store.ensureDataReady();
|
this._store.ensureDataReady();
|
||||||
|
|
||||||
let profileFound = this._findByGUID(guid);
|
let addressFound = this._findByGUID(guid);
|
||||||
if (!profileFound) {
|
if (!addressFound) {
|
||||||
throw new Error("No matching profile.");
|
throw new Error("No matching record.");
|
||||||
}
|
}
|
||||||
|
|
||||||
profileFound.timesUsed++;
|
addressFound.timesUsed++;
|
||||||
profileFound.timeLastUsed = Date.now();
|
addressFound.timeLastUsed = Date.now();
|
||||||
|
|
||||||
this._store.saveSoon();
|
this._store.saveSoon();
|
||||||
Services.obs.notifyObservers(null, "formautofill-storage-changed", "notifyUsed");
|
Services.obs.notifyObservers(null, "formautofill-storage-changed", "notifyUsed");
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the specified profile. No error occurs if the profile isn't found.
|
* Removes the specified address. No error occurs if the address isn't found.
|
||||||
*
|
*
|
||||||
* @param {string} guid
|
* @param {string} guid
|
||||||
* Indicates which profile to remove.
|
* Indicates which address to remove.
|
||||||
*/
|
*/
|
||||||
remove(guid) {
|
remove(guid) {
|
||||||
log.debug("remove:", guid);
|
log.debug("remove:", guid);
|
||||||
this._store.ensureDataReady();
|
this._store.ensureDataReady();
|
||||||
|
|
||||||
this._store.data.profiles =
|
this._store.data.addresses =
|
||||||
this._store.data.profiles.filter(profile => profile.guid != guid);
|
this._store.data.addresses.filter(address => address.guid != guid);
|
||||||
this._store.saveSoon();
|
this._store.saveSoon();
|
||||||
Services.obs.notifyObservers(null, "formautofill-storage-changed", "remove");
|
Services.obs.notifyObservers(null, "formautofill-storage-changed", "remove");
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the profile with the specified GUID.
|
* Returns the address with the specified GUID.
|
||||||
*
|
*
|
||||||
* @param {string} guid
|
* @param {string} guid
|
||||||
* Indicates which profile to retrieve.
|
* Indicates which address to retrieve.
|
||||||
* @returns {Profile}
|
* @returns {Address}
|
||||||
* A clone of the profile.
|
* A clone of the address.
|
||||||
*/
|
*/
|
||||||
get(guid) {
|
get(guid) {
|
||||||
log.debug("get:", guid);
|
log.debug("get:", guid);
|
||||||
this._store.ensureDataReady();
|
this._store.ensureDataReady();
|
||||||
|
|
||||||
let profileFound = this._findByGUID(guid);
|
let addressFound = this._findByGUID(guid);
|
||||||
if (!profileFound) {
|
if (!addressFound) {
|
||||||
throw new Error("No matching profile.");
|
throw new Error("No matching record.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Profile is cloned to avoid accidental modifications from outside.
|
// The record is cloned to avoid accidental modifications from outside.
|
||||||
let clonedProfile = this._clone(profileFound);
|
let clonedAddress = this._clone(addressFound);
|
||||||
this._computeFields(clonedProfile);
|
this._computeFields(clonedAddress);
|
||||||
return clonedProfile;
|
return clonedAddress;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all profiles.
|
* Returns all addresses.
|
||||||
*
|
*
|
||||||
* @returns {Array.<Profile>}
|
* @returns {Array.<Address>}
|
||||||
* An array containing clones of all profiles.
|
* An array containing clones of all addresses.
|
||||||
*/
|
*/
|
||||||
getAll() {
|
getAll() {
|
||||||
log.debug("getAll");
|
log.debug("getAll");
|
||||||
this._store.ensureDataReady();
|
this._store.ensureDataReady();
|
||||||
|
|
||||||
// Profiles are cloned to avoid accidental modifications from outside.
|
// Records are cloned to avoid accidental modifications from outside.
|
||||||
let clonedProfiles = this._store.data.profiles.map(this._clone);
|
let clonedAddresses = this._store.data.addresses.map(this._clone);
|
||||||
clonedProfiles.forEach(this._computeFields);
|
clonedAddresses.forEach(this._computeFields);
|
||||||
return clonedProfiles;
|
return clonedAddresses;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the filtered profiles based on input's information and searchString.
|
* Returns the filtered addresses based on input's information and searchString.
|
||||||
*
|
*
|
||||||
* @returns {Array.<Profile>}
|
* @returns {Array.<Address>}
|
||||||
* An array containing clones of matched profiles.
|
* An array containing clones of matched addresses.
|
||||||
*/
|
*/
|
||||||
getByFilter({info, searchString}) {
|
getByFilter({info, searchString}) {
|
||||||
log.debug("getByFilter:", info, searchString);
|
log.debug("getByFilter:", info, searchString);
|
||||||
|
|
||||||
let lcSearchString = searchString.toLowerCase();
|
let lcSearchString = searchString.toLowerCase();
|
||||||
let result = this.getAll().filter(profile => {
|
let result = this.getAll().filter(address => {
|
||||||
// Return true if string is not provided and field exists.
|
// Return true if string is not provided and field exists.
|
||||||
// TODO: We'll need to check if the address is for billing or shipping.
|
// TODO: We'll need to check if the address is for billing or shipping.
|
||||||
// (Bug 1358941)
|
// (Bug 1358941)
|
||||||
let name = profile[info.fieldName];
|
let name = address[info.fieldName];
|
||||||
|
|
||||||
if (!searchString) {
|
if (!searchString) {
|
||||||
return !!name;
|
return !!name;
|
||||||
|
@ -291,88 +278,88 @@ ProfileStorage.prototype = {
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
|
||||||
_clone(profile) {
|
_clone(record) {
|
||||||
return Object.assign({}, profile);
|
return Object.assign({}, record);
|
||||||
},
|
},
|
||||||
|
|
||||||
_findByGUID(guid) {
|
_findByGUID(guid) {
|
||||||
return this._store.data.profiles.find(profile => profile.guid == guid);
|
return this._store.data.addresses.find(address => address.guid == guid);
|
||||||
},
|
},
|
||||||
|
|
||||||
_computeFields(profile) {
|
_computeFields(address) {
|
||||||
// Compute name
|
// Compute name
|
||||||
profile.name = FormAutofillNameUtils.joinNameParts({
|
address.name = FormAutofillNameUtils.joinNameParts({
|
||||||
given: profile["given-name"],
|
given: address["given-name"],
|
||||||
middle: profile["additional-name"],
|
middle: address["additional-name"],
|
||||||
family: profile["family-name"],
|
family: address["family-name"],
|
||||||
});
|
});
|
||||||
|
|
||||||
// Compute address
|
// Compute address
|
||||||
if (profile["street-address"]) {
|
if (address["street-address"]) {
|
||||||
let streetAddress = profile["street-address"].split("\n");
|
let streetAddress = address["street-address"].split("\n");
|
||||||
// TODO: we should prevent the dataloss by concatenating the rest of lines
|
// TODO: we should prevent the dataloss by concatenating the rest of lines
|
||||||
// with a locale-specific character in the future (bug 1360114).
|
// with a locale-specific character in the future (bug 1360114).
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
if (streetAddress[i]) {
|
if (streetAddress[i]) {
|
||||||
profile["address-line" + (i + 1)] = streetAddress[i];
|
address["address-line" + (i + 1)] = streetAddress[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_normalizeAddress(profile) {
|
_normalizeAddressLines(address) {
|
||||||
if (profile["address-line1"] || profile["address-line2"] ||
|
if (address["address-line1"] || address["address-line2"] ||
|
||||||
profile["address-line3"]) {
|
address["address-line3"]) {
|
||||||
// Treat "street-address" as "address-line1" if it contains only one line
|
// Treat "street-address" as "address-line1" if it contains only one line
|
||||||
// and "address-line1" is omitted.
|
// and "address-line1" is omitted.
|
||||||
if (!profile["address-line1"] && profile["street-address"] &&
|
if (!address["address-line1"] && address["street-address"] &&
|
||||||
!profile["street-address"].includes("\n")) {
|
!address["street-address"].includes("\n")) {
|
||||||
profile["address-line1"] = profile["street-address"];
|
address["address-line1"] = address["street-address"];
|
||||||
delete profile["street-address"];
|
delete address["street-address"];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove "address-line*" but keep the values.
|
// Remove "address-line*" but keep the values.
|
||||||
let addressLines = [1, 2, 3].map(i => {
|
let addressLines = [1, 2, 3].map(i => {
|
||||||
let value = profile["address-line" + i];
|
let value = address["address-line" + i];
|
||||||
delete profile["address-line" + i];
|
delete address["address-line" + i];
|
||||||
return value;
|
return value;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Concatenate "address-line*" if "street-address" is omitted.
|
// Concatenate "address-line*" if "street-address" is omitted.
|
||||||
if (!profile["street-address"]) {
|
if (!address["street-address"]) {
|
||||||
profile["street-address"] = addressLines.join("\n");
|
address["street-address"] = addressLines.join("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_normalizeName(profile) {
|
_normalizeName(address) {
|
||||||
if (!profile.name) {
|
if (!address.name) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let nameParts = FormAutofillNameUtils.splitName(profile.name);
|
let nameParts = FormAutofillNameUtils.splitName(address.name);
|
||||||
if (!profile["given-name"] && nameParts.given) {
|
if (!address["given-name"] && nameParts.given) {
|
||||||
profile["given-name"] = nameParts.given;
|
address["given-name"] = nameParts.given;
|
||||||
}
|
}
|
||||||
if (!profile["additional-name"] && nameParts.middle) {
|
if (!address["additional-name"] && nameParts.middle) {
|
||||||
profile["additional-name"] = nameParts.middle;
|
address["additional-name"] = nameParts.middle;
|
||||||
}
|
}
|
||||||
if (!profile["family-name"] && nameParts.family) {
|
if (!address["family-name"] && nameParts.family) {
|
||||||
profile["family-name"] = nameParts.family;
|
address["family-name"] = nameParts.family;
|
||||||
}
|
}
|
||||||
delete profile.name;
|
delete address.name;
|
||||||
},
|
},
|
||||||
|
|
||||||
_normalizeProfile(profile) {
|
_normalizeAddress(address) {
|
||||||
this._normalizeName(profile);
|
this._normalizeName(address);
|
||||||
this._normalizeAddress(profile);
|
this._normalizeAddressLines(address);
|
||||||
|
|
||||||
for (let key in profile) {
|
for (let key in address) {
|
||||||
if (!VALID_FIELDS.includes(key)) {
|
if (!VALID_FIELDS.includes(key)) {
|
||||||
throw new Error(`"${key}" is not a valid field.`);
|
throw new Error(`"${key}" is not a valid field.`);
|
||||||
}
|
}
|
||||||
if (typeof profile[key] !== "string" &&
|
if (typeof address[key] !== "string" &&
|
||||||
typeof profile[key] !== "number") {
|
typeof address[key] !== "number") {
|
||||||
throw new Error(`"${key}" contains invalid data type.`);
|
throw new Error(`"${key}" contains invalid data type.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,8 +367,8 @@ ProfileStorage.prototype = {
|
||||||
|
|
||||||
_dataPostProcessor(data) {
|
_dataPostProcessor(data) {
|
||||||
data.version = SCHEMA_VERSION;
|
data.version = SCHEMA_VERSION;
|
||||||
if (!data.profiles) {
|
if (!data.addresses) {
|
||||||
data.profiles = MOCK_MODE ? MOCK_STORAGE : [];
|
data.addresses = [];
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,8 +9,8 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
Cu.import("resource://formautofill/FormAutofillUtils.jsm");
|
Cu.import("resource://formautofill/FormAutofillUtils.jsm");
|
||||||
|
|
||||||
function EditDialog(profile) {
|
function EditDialog(address) {
|
||||||
this._profile = profile;
|
this._address = address;
|
||||||
window.addEventListener("DOMContentLoaded", this, {once: true});
|
window.addEventListener("DOMContentLoaded", this, {once: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,26 +25,26 @@ EditDialog.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asks FormAutofillParent to save or update a profile.
|
* Asks FormAutofillParent to save or update an address.
|
||||||
* @param {object} data
|
* @param {object} data
|
||||||
* {
|
* {
|
||||||
* {string} guid [optional]
|
* {string} guid [optional]
|
||||||
* {object} profile
|
* {object} address
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
saveProfile(data) {
|
saveAddress(data) {
|
||||||
Services.cpmm.sendAsyncMessage("FormAutofill:SaveProfile", data);
|
Services.cpmm.sendAsyncMessage("FormAutofill:SaveAddress", data);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill the form with a profile object.
|
* Fill the form with an address object.
|
||||||
* @param {object} profile
|
* @param {object} address
|
||||||
*/
|
*/
|
||||||
loadInitialValues(profile) {
|
loadInitialValues(address) {
|
||||||
for (let field in profile) {
|
for (let field in address) {
|
||||||
let input = document.getElementById(field);
|
let input = document.getElementById(field);
|
||||||
if (input) {
|
if (input) {
|
||||||
input.value = profile[field];
|
input.value = address[field];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -53,7 +53,7 @@ EditDialog.prototype = {
|
||||||
* Get inputs from the form.
|
* Get inputs from the form.
|
||||||
* @returns {object}
|
* @returns {object}
|
||||||
*/
|
*/
|
||||||
buildProfileObject() {
|
buildAddressObject() {
|
||||||
return Array.from(document.forms[0].elements).reduce((obj, input) => {
|
return Array.from(document.forms[0].elements).reduce((obj, input) => {
|
||||||
if (input.value) {
|
if (input.value) {
|
||||||
obj[input.id] = input.value;
|
obj[input.id] = input.value;
|
||||||
|
@ -71,8 +71,8 @@ EditDialog.prototype = {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case "DOMContentLoaded": {
|
case "DOMContentLoaded": {
|
||||||
this.init();
|
this.init();
|
||||||
if (this._profile) {
|
if (this._address) {
|
||||||
this.loadInitialValues(this._profile);
|
this.loadInitialValues(this._address);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ EditDialog.prototype = {
|
||||||
case "input": {
|
case "input": {
|
||||||
// Toggle disabled attribute on the save button based on
|
// Toggle disabled attribute on the save button based on
|
||||||
// whether the form is filled or empty.
|
// whether the form is filled or empty.
|
||||||
if (Object.keys(this.buildProfileObject()).length == 0) {
|
if (Object.keys(this.buildAddressObject()).length == 0) {
|
||||||
this.refs.save.setAttribute("disabled", true);
|
this.refs.save.setAttribute("disabled", true);
|
||||||
} else {
|
} else {
|
||||||
this.refs.save.removeAttribute("disabled");
|
this.refs.save.removeAttribute("disabled");
|
||||||
|
@ -104,14 +104,14 @@ EditDialog.prototype = {
|
||||||
window.close();
|
window.close();
|
||||||
}
|
}
|
||||||
if (event.target == this.refs.save) {
|
if (event.target == this.refs.save) {
|
||||||
if (this._profile) {
|
if (this._address) {
|
||||||
this.saveProfile({
|
this.saveAddress({
|
||||||
guid: this._profile.guid,
|
guid: this._address.guid,
|
||||||
profile: this.buildProfileObject(),
|
address: this.buildAddressObject(),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.saveProfile({
|
this.saveAddress({
|
||||||
profile: this.buildProfileObject(),
|
address: this.buildAddressObject(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.detachEventListeners();
|
this.detachEventListeners();
|
||||||
|
|
|
@ -25,23 +25,23 @@ ManageProfileDialog.prototype = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count the number of "formautofill-storage-changed" events epected to
|
* Count the number of "formautofill-storage-changed" events epected to
|
||||||
* receive to prevent repeatedly loading profiles.
|
* receive to prevent repeatedly loading addresses.
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
_pendingChangeCount: 0,
|
_pendingChangeCount: 0,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the selected options on the profiles element.
|
* Get the selected options on the addresses element.
|
||||||
*
|
*
|
||||||
* @returns {array<DOMElement>}
|
* @returns {array<DOMElement>}
|
||||||
*/
|
*/
|
||||||
get _selectedOptions() {
|
get _selectedOptions() {
|
||||||
return Array.from(this._elements.profiles.selectedOptions);
|
return Array.from(this._elements.addresses.selectedOptions);
|
||||||
},
|
},
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this._elements = {
|
this._elements = {
|
||||||
profiles: document.getElementById("profiles"),
|
addresses: document.getElementById("profiles"),
|
||||||
controlsContainer: document.getElementById("controls-container"),
|
controlsContainer: document.getElementById("controls-container"),
|
||||||
remove: document.getElementById("remove"),
|
remove: document.getElementById("remove"),
|
||||||
add: document.getElementById("add"),
|
add: document.getElementById("add"),
|
||||||
|
@ -57,84 +57,84 @@ ManageProfileDialog.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load profiles and render them.
|
* Load addresses and render them.
|
||||||
*
|
*
|
||||||
* @returns {promise}
|
* @returns {promise}
|
||||||
*/
|
*/
|
||||||
loadProfiles() {
|
loadAddresses() {
|
||||||
return this.getProfiles().then(profiles => {
|
return this.getAddresses().then(addresses => {
|
||||||
log.debug("profiles:", profiles);
|
log.debug("addresses:", addresses);
|
||||||
// Sort by last modified time starting with most recent
|
// Sort by last modified time starting with most recent
|
||||||
profiles.sort((a, b) => b.timeLastModified - a.timeLastModified);
|
addresses.sort((a, b) => b.timeLastModified - a.timeLastModified);
|
||||||
this.renderProfileElements(profiles);
|
this.renderAddressElements(addresses);
|
||||||
this.updateButtonsStates(this._selectedOptions.length);
|
this.updateButtonsStates(this._selectedOptions.length);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get profiles from storage.
|
* Get addresses from storage.
|
||||||
*
|
*
|
||||||
* @returns {promise}
|
* @returns {promise}
|
||||||
*/
|
*/
|
||||||
getProfiles() {
|
getAddresses() {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
Services.cpmm.addMessageListener("FormAutofill:Profiles", function getResult(result) {
|
Services.cpmm.addMessageListener("FormAutofill:Addresses", function getResult(result) {
|
||||||
Services.cpmm.removeMessageListener("FormAutofill:Profiles", getResult);
|
Services.cpmm.removeMessageListener("FormAutofill:Addresses", getResult);
|
||||||
resolve(result.data);
|
resolve(result.data);
|
||||||
});
|
});
|
||||||
Services.cpmm.sendAsyncMessage("FormAutofill:GetProfiles", {});
|
Services.cpmm.sendAsyncMessage("FormAutofill:GetAddresses", {});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the profiles onto the page while maintaining selected options if
|
* Render the addresses onto the page while maintaining selected options if
|
||||||
* they still exist.
|
* they still exist.
|
||||||
*
|
*
|
||||||
* @param {array<object>} profiles
|
* @param {array<object>} addresses
|
||||||
*/
|
*/
|
||||||
renderProfileElements(profiles) {
|
renderAddressElements(addresses) {
|
||||||
let selectedGuids = this._selectedOptions.map(option => option.value);
|
let selectedGuids = this._selectedOptions.map(option => option.value);
|
||||||
this.clearProfileElements();
|
this.clearAddressElements();
|
||||||
for (let profile of profiles) {
|
for (let address of addresses) {
|
||||||
let option = new Option(this.getProfileLabel(profile),
|
let option = new Option(this.getAddressLabel(address),
|
||||||
profile.guid,
|
address.guid,
|
||||||
false,
|
false,
|
||||||
selectedGuids.includes(profile.guid));
|
selectedGuids.includes(address.guid));
|
||||||
option.profile = profile;
|
option.address = address;
|
||||||
this._elements.profiles.appendChild(option);
|
this._elements.addresses.appendChild(option);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all existing profile elements.
|
* Remove all existing address elements.
|
||||||
*/
|
*/
|
||||||
clearProfileElements() {
|
clearAddressElements() {
|
||||||
let parent = this._elements.profiles;
|
let parent = this._elements.addresses;
|
||||||
while (parent.lastChild) {
|
while (parent.lastChild) {
|
||||||
parent.removeChild(parent.lastChild);
|
parent.removeChild(parent.lastChild);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove profiles by guids.
|
* Remove addresses by guids.
|
||||||
* Keep track of the number of "formautofill-storage-changed" events to
|
* Keep track of the number of "formautofill-storage-changed" events to
|
||||||
* ignore before loading profiles.
|
* ignore before loading addresses.
|
||||||
*
|
*
|
||||||
* @param {array<string>} guids
|
* @param {array<string>} guids
|
||||||
*/
|
*/
|
||||||
removeProfiles(guids) {
|
removeAddresses(guids) {
|
||||||
this._pendingChangeCount += guids.length - 1;
|
this._pendingChangeCount += guids.length - 1;
|
||||||
Services.cpmm.sendAsyncMessage("FormAutofill:RemoveProfiles", {guids});
|
Services.cpmm.sendAsyncMessage("FormAutofill:RemoveAddresses", {guids});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get profile display label. It should display up to two pieces of
|
* Get address display label. It should display up to two pieces of
|
||||||
* information, separated by a comma.
|
* information, separated by a comma.
|
||||||
*
|
*
|
||||||
* @param {object} profile
|
* @param {object} address
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
getProfileLabel(profile) {
|
getAddressLabel(address) {
|
||||||
// TODO: Implement a smarter way for deciding what to display
|
// TODO: Implement a smarter way for deciding what to display
|
||||||
// as option text. Possibly improve the algorithm in
|
// as option text. Possibly improve the algorithm in
|
||||||
// ProfileAutoCompleteResult.jsm and reuse it here.
|
// ProfileAutoCompleteResult.jsm and reuse it here.
|
||||||
|
@ -152,7 +152,7 @@ ManageProfileDialog.prototype = {
|
||||||
|
|
||||||
let parts = [];
|
let parts = [];
|
||||||
for (const fieldName of fieldOrder) {
|
for (const fieldName of fieldOrder) {
|
||||||
let string = profile[fieldName];
|
let string = address[fieldName];
|
||||||
if (string) {
|
if (string) {
|
||||||
parts.push(string);
|
parts.push(string);
|
||||||
}
|
}
|
||||||
|
@ -164,14 +164,14 @@ ManageProfileDialog.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the edit profile dialog to create/edit a profile.
|
* Open the edit address dialog to create/edit an address.
|
||||||
*
|
*
|
||||||
* @param {object} profile [optional]
|
* @param {object} address [optional]
|
||||||
*/
|
*/
|
||||||
openEditDialog(profile) {
|
openEditDialog(address) {
|
||||||
window.openDialog(EDIT_PROFILE_URL, null,
|
window.openDialog(EDIT_PROFILE_URL, null,
|
||||||
"chrome,centerscreen,modal,width=600,height=450",
|
"chrome,centerscreen,modal,width=600,height=450",
|
||||||
profile);
|
address);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -203,7 +203,7 @@ ManageProfileDialog.prototype = {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case "DOMContentLoaded": {
|
case "DOMContentLoaded": {
|
||||||
this.init();
|
this.init();
|
||||||
this.loadProfiles();
|
this.loadAddresses();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "click": {
|
case "click": {
|
||||||
|
@ -228,11 +228,11 @@ ManageProfileDialog.prototype = {
|
||||||
*/
|
*/
|
||||||
handleClick(event) {
|
handleClick(event) {
|
||||||
if (event.target == this._elements.remove) {
|
if (event.target == this._elements.remove) {
|
||||||
this.removeProfiles(this._selectedOptions.map(option => option.value));
|
this.removeAddresses(this._selectedOptions.map(option => option.value));
|
||||||
} else if (event.target == this._elements.add) {
|
} else if (event.target == this._elements.add) {
|
||||||
this.openEditDialog();
|
this.openEditDialog();
|
||||||
} else if (event.target == this._elements.edit) {
|
} else if (event.target == this._elements.edit) {
|
||||||
this.openEditDialog(this._selectedOptions[0].profile);
|
this.openEditDialog(this._selectedOptions[0].address);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -243,7 +243,7 @@ ManageProfileDialog.prototype = {
|
||||||
this._pendingChangeCount -= 1;
|
this._pendingChangeCount -= 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.loadProfiles();
|
this.loadAddresses();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -253,7 +253,7 @@ ManageProfileDialog.prototype = {
|
||||||
*/
|
*/
|
||||||
attachEventListeners() {
|
attachEventListeners() {
|
||||||
window.addEventListener("unload", this, {once: true});
|
window.addEventListener("unload", this, {once: true});
|
||||||
this._elements.profiles.addEventListener("change", this);
|
this._elements.addresses.addEventListener("change", this);
|
||||||
this._elements.controlsContainer.addEventListener("click", this);
|
this._elements.controlsContainer.addEventListener("click", this);
|
||||||
Services.obs.addObserver(this, "formautofill-storage-changed");
|
Services.obs.addObserver(this, "formautofill-storage-changed");
|
||||||
},
|
},
|
||||||
|
@ -262,7 +262,7 @@ ManageProfileDialog.prototype = {
|
||||||
* Remove event listener
|
* Remove event listener
|
||||||
*/
|
*/
|
||||||
detachEventListeners() {
|
detachEventListeners() {
|
||||||
this._elements.profiles.removeEventListener("change", this);
|
this._elements.addresses.removeEventListener("change", this);
|
||||||
this._elements.controlsContainer.removeEventListener("click", this);
|
this._elements.controlsContainer.removeEventListener("click", this);
|
||||||
Services.obs.removeObserver(this, "formautofill-storage-changed");
|
Services.obs.removeObserver(this, "formautofill-storage-changed");
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
registerCleanupFunction(function* () {
|
registerCleanupFunction(function* () {
|
||||||
let profiles = yield getProfiles();
|
let addresses = yield getAddresses();
|
||||||
if (profiles.length) {
|
if (addresses.length) {
|
||||||
yield removeProfiles(profiles.map(profile => profile.guid));
|
yield removeAddresses(addresses.map(address => address.guid));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ add_task(function* test_cancelEditProfileDialog() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* test_saveProfile() {
|
add_task(function* test_saveAddress() {
|
||||||
yield new Promise(resolve => {
|
yield new Promise(resolve => {
|
||||||
let win = window.openDialog(EDIT_PROFILE_DIALOG_URL, null, null, null);
|
let win = window.openDialog(EDIT_PROFILE_DIALOG_URL, null, null, null);
|
||||||
win.addEventListener("load", () => {
|
win.addEventListener("load", () => {
|
||||||
|
@ -29,46 +29,46 @@ add_task(function* test_saveProfile() {
|
||||||
resolve();
|
resolve();
|
||||||
}, {once: true});
|
}, {once: true});
|
||||||
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
||||||
EventUtils.synthesizeKey(TEST_PROFILE_1["given-name"], {}, win);
|
EventUtils.synthesizeKey(TEST_ADDRESS_1["given-name"], {}, win);
|
||||||
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
||||||
EventUtils.synthesizeKey(TEST_PROFILE_1["additional-name"], {}, win);
|
EventUtils.synthesizeKey(TEST_ADDRESS_1["additional-name"], {}, win);
|
||||||
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
||||||
EventUtils.synthesizeKey(TEST_PROFILE_1["family-name"], {}, win);
|
EventUtils.synthesizeKey(TEST_ADDRESS_1["family-name"], {}, win);
|
||||||
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
||||||
EventUtils.synthesizeKey(TEST_PROFILE_1.organization, {}, win);
|
EventUtils.synthesizeKey(TEST_ADDRESS_1.organization, {}, win);
|
||||||
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
||||||
EventUtils.synthesizeKey(TEST_PROFILE_1["street-address"], {}, win);
|
EventUtils.synthesizeKey(TEST_ADDRESS_1["street-address"], {}, win);
|
||||||
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
||||||
EventUtils.synthesizeKey(TEST_PROFILE_1["address-level2"], {}, win);
|
EventUtils.synthesizeKey(TEST_ADDRESS_1["address-level2"], {}, win);
|
||||||
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
||||||
EventUtils.synthesizeKey(TEST_PROFILE_1["address-level1"], {}, win);
|
EventUtils.synthesizeKey(TEST_ADDRESS_1["address-level1"], {}, win);
|
||||||
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
||||||
EventUtils.synthesizeKey(TEST_PROFILE_1["postal-code"], {}, win);
|
EventUtils.synthesizeKey(TEST_ADDRESS_1["postal-code"], {}, win);
|
||||||
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
||||||
EventUtils.synthesizeKey(TEST_PROFILE_1.country, {}, win);
|
EventUtils.synthesizeKey(TEST_ADDRESS_1.country, {}, win);
|
||||||
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
||||||
EventUtils.synthesizeKey(TEST_PROFILE_1.email, {}, win);
|
EventUtils.synthesizeKey(TEST_ADDRESS_1.email, {}, win);
|
||||||
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
||||||
EventUtils.synthesizeKey(TEST_PROFILE_1.tel, {}, win);
|
EventUtils.synthesizeKey(TEST_ADDRESS_1.tel, {}, win);
|
||||||
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
||||||
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
EventUtils.synthesizeKey("VK_TAB", {}, win);
|
||||||
info("saving profile");
|
info("saving profile");
|
||||||
EventUtils.synthesizeKey("VK_RETURN", {}, win);
|
EventUtils.synthesizeKey("VK_RETURN", {}, win);
|
||||||
}, {once: true});
|
}, {once: true});
|
||||||
});
|
});
|
||||||
let profiles = yield getProfiles();
|
let addresses = yield getAddresses();
|
||||||
|
|
||||||
is(profiles.length, 1, "only one profile is in storage");
|
is(addresses.length, 1, "only one address is in storage");
|
||||||
is(Object.keys(TEST_PROFILE_1).length, 11, "Sanity check number of properties");
|
is(Object.keys(TEST_ADDRESS_1).length, 11, "Sanity check number of properties");
|
||||||
for (let [fieldName, fieldValue] of Object.entries(TEST_PROFILE_1)) {
|
for (let [fieldName, fieldValue] of Object.entries(TEST_ADDRESS_1)) {
|
||||||
is(profiles[0][fieldName], fieldValue, "check " + fieldName);
|
is(addresses[0][fieldName], fieldValue, "check " + fieldName);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* test_editProfile() {
|
add_task(function* test_editProfile() {
|
||||||
let profiles = yield getProfiles();
|
let addresses = yield getAddresses();
|
||||||
yield new Promise(resolve => {
|
yield new Promise(resolve => {
|
||||||
let win = window.openDialog(EDIT_PROFILE_DIALOG_URL, null, null, profiles[0]);
|
let win = window.openDialog(EDIT_PROFILE_DIALOG_URL, null, null, addresses[0]);
|
||||||
win.addEventListener("load", () => {
|
win.addEventListener("load", () => {
|
||||||
win.addEventListener("unload", () => {
|
win.addEventListener("unload", () => {
|
||||||
ok(true, "Edit profile dialog is closed");
|
ok(true, "Edit profile dialog is closed");
|
||||||
|
@ -79,12 +79,12 @@ add_task(function* test_editProfile() {
|
||||||
win.document.querySelector("#save").click();
|
win.document.querySelector("#save").click();
|
||||||
}, {once: true});
|
}, {once: true});
|
||||||
});
|
});
|
||||||
profiles = yield getProfiles();
|
addresses = yield getAddresses();
|
||||||
|
|
||||||
is(profiles.length, 1, "only one profile is in storage");
|
is(addresses.length, 1, "only one address is in storage");
|
||||||
is(profiles[0]["given-name"], TEST_PROFILE_1["given-name"] + "test", "given-name changed");
|
is(addresses[0]["given-name"], TEST_ADDRESS_1["given-name"] + "test", "given-name changed");
|
||||||
yield removeProfiles([profiles[0].guid]);
|
yield removeAddresses([addresses[0].guid]);
|
||||||
|
|
||||||
profiles = yield getProfiles();
|
addresses = yield getAddresses();
|
||||||
is(profiles.length, 0, "Profile storage is empty");
|
is(addresses.length, 0, "Address storage is empty");
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const TEST_SELECTORS = {
|
const TEST_SELECTORS = {
|
||||||
selProfiles: "#profiles",
|
selAddresses: "#profiles",
|
||||||
btnRemove: "#remove",
|
btnRemove: "#remove",
|
||||||
btnAdd: "#add",
|
btnAdd: "#add",
|
||||||
btnEdit: "#edit",
|
btnEdit: "#edit",
|
||||||
};
|
};
|
||||||
|
|
||||||
function waitForProfiles() {
|
function waitForAddresses() {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
Services.cpmm.addMessageListener("FormAutofill:Profiles", function getResult(result) {
|
Services.cpmm.addMessageListener("FormAutofill:Addresses", function getResult(result) {
|
||||||
Services.cpmm.removeMessageListener("FormAutofill:Profiles", getResult);
|
Services.cpmm.removeMessageListener("FormAutofill:Addresses", getResult);
|
||||||
// Wait for the next tick for elements to get rendered.
|
// Wait for the next tick for elements to get rendered.
|
||||||
SimpleTest.executeSoon(resolve.bind(null, result.data));
|
SimpleTest.executeSoon(resolve.bind(null, result.data));
|
||||||
});
|
});
|
||||||
|
@ -18,21 +18,21 @@ function waitForProfiles() {
|
||||||
}
|
}
|
||||||
|
|
||||||
registerCleanupFunction(function* () {
|
registerCleanupFunction(function* () {
|
||||||
let profiles = yield getProfiles();
|
let addresses = yield getAddresses();
|
||||||
if (profiles.length) {
|
if (addresses.length) {
|
||||||
yield removeProfiles(profiles.map(profile => profile.guid));
|
yield removeAddresses(addresses.map(address => address.guid));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* test_manageProfilesInitialState() {
|
add_task(function* test_manageProfilesInitialState() {
|
||||||
yield BrowserTestUtils.withNewTab({gBrowser, url: MANAGE_PROFILES_DIALOG_URL}, function* (browser) {
|
yield BrowserTestUtils.withNewTab({gBrowser, url: MANAGE_PROFILES_DIALOG_URL}, function* (browser) {
|
||||||
yield ContentTask.spawn(browser, TEST_SELECTORS, (args) => {
|
yield ContentTask.spawn(browser, TEST_SELECTORS, (args) => {
|
||||||
let selProfiles = content.document.querySelector(args.selProfiles);
|
let selAddresses = content.document.querySelector(args.selAddresses);
|
||||||
let btnRemove = content.document.querySelector(args.btnRemove);
|
let btnRemove = content.document.querySelector(args.btnRemove);
|
||||||
let btnEdit = content.document.querySelector(args.btnEdit);
|
let btnEdit = content.document.querySelector(args.btnEdit);
|
||||||
let btnAdd = content.document.querySelector(args.btnAdd);
|
let btnAdd = content.document.querySelector(args.btnAdd);
|
||||||
|
|
||||||
is(selProfiles.length, 0, "No profile");
|
is(selAddresses.length, 0, "No address");
|
||||||
is(btnAdd.disabled, false, "Add button enabled");
|
is(btnAdd.disabled, false, "Add button enabled");
|
||||||
is(btnRemove.disabled, true, "Remove button disabled");
|
is(btnRemove.disabled, true, "Remove button disabled");
|
||||||
is(btnEdit.disabled, true, "Edit button disabled");
|
is(btnEdit.disabled, true, "Edit button disabled");
|
||||||
|
@ -41,50 +41,50 @@ add_task(function* test_manageProfilesInitialState() {
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* test_removingSingleAndMultipleProfiles() {
|
add_task(function* test_removingSingleAndMultipleProfiles() {
|
||||||
yield saveProfile(TEST_PROFILE_1);
|
yield saveAddress(TEST_ADDRESS_1);
|
||||||
yield saveProfile(TEST_PROFILE_2);
|
yield saveAddress(TEST_ADDRESS_2);
|
||||||
yield saveProfile(TEST_PROFILE_3);
|
yield saveAddress(TEST_ADDRESS_3);
|
||||||
|
|
||||||
let win = window.openDialog(MANAGE_PROFILES_DIALOG_URL);
|
let win = window.openDialog(MANAGE_PROFILES_DIALOG_URL);
|
||||||
yield waitForProfiles();
|
yield waitForAddresses();
|
||||||
|
|
||||||
let selProfiles = win.document.querySelector(TEST_SELECTORS.selProfiles);
|
let selAddresses = win.document.querySelector(TEST_SELECTORS.selAddresses);
|
||||||
let btnRemove = win.document.querySelector(TEST_SELECTORS.btnRemove);
|
let btnRemove = win.document.querySelector(TEST_SELECTORS.btnRemove);
|
||||||
let btnEdit = win.document.querySelector(TEST_SELECTORS.btnEdit);
|
let btnEdit = win.document.querySelector(TEST_SELECTORS.btnEdit);
|
||||||
|
|
||||||
is(selProfiles.length, 3, "Three profiles");
|
is(selAddresses.length, 3, "Three addresses");
|
||||||
|
|
||||||
EventUtils.synthesizeMouseAtCenter(selProfiles.children[0], {}, win);
|
EventUtils.synthesizeMouseAtCenter(selAddresses.children[0], {}, win);
|
||||||
is(btnRemove.disabled, false, "Remove button enabled");
|
is(btnRemove.disabled, false, "Remove button enabled");
|
||||||
is(btnEdit.disabled, false, "Edit button enabled");
|
is(btnEdit.disabled, false, "Edit button enabled");
|
||||||
EventUtils.synthesizeMouseAtCenter(btnRemove, {}, win);
|
EventUtils.synthesizeMouseAtCenter(btnRemove, {}, win);
|
||||||
yield waitForProfiles();
|
yield waitForAddresses();
|
||||||
is(selProfiles.length, 2, "Two profiles left");
|
is(selAddresses.length, 2, "Two addresses left");
|
||||||
|
|
||||||
EventUtils.synthesizeMouseAtCenter(selProfiles.children[0], {}, win);
|
EventUtils.synthesizeMouseAtCenter(selAddresses.children[0], {}, win);
|
||||||
EventUtils.synthesizeMouseAtCenter(selProfiles.children[1],
|
EventUtils.synthesizeMouseAtCenter(selAddresses.children[1],
|
||||||
{shiftKey: true}, win);
|
{shiftKey: true}, win);
|
||||||
is(btnEdit.disabled, true, "Edit button disabled when multi-select");
|
is(btnEdit.disabled, true, "Edit button disabled when multi-select");
|
||||||
|
|
||||||
EventUtils.synthesizeMouseAtCenter(btnRemove, {}, win);
|
EventUtils.synthesizeMouseAtCenter(btnRemove, {}, win);
|
||||||
yield waitForProfiles();
|
yield waitForAddresses();
|
||||||
is(selProfiles.length, 0, "All profiles are removed");
|
is(selAddresses.length, 0, "All addresses are removed");
|
||||||
|
|
||||||
win.close();
|
win.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* test_profilesDialogWatchesStorageChanges() {
|
add_task(function* test_profilesDialogWatchesStorageChanges() {
|
||||||
let win = window.openDialog(MANAGE_PROFILES_DIALOG_URL);
|
let win = window.openDialog(MANAGE_PROFILES_DIALOG_URL);
|
||||||
yield waitForProfiles();
|
yield waitForAddresses();
|
||||||
|
|
||||||
let selProfiles = win.document.querySelector(TEST_SELECTORS.selProfiles);
|
let selAddresses = win.document.querySelector(TEST_SELECTORS.selAddresses);
|
||||||
|
|
||||||
yield saveProfile(TEST_PROFILE_1);
|
yield saveAddress(TEST_ADDRESS_1);
|
||||||
let profiles = yield waitForProfiles();
|
let addresses = yield waitForAddresses();
|
||||||
is(selProfiles.length, 1, "One profile is shown");
|
is(selAddresses.length, 1, "One address is shown");
|
||||||
|
|
||||||
yield removeProfiles([profiles[0].guid]);
|
yield removeAddresses([addresses[0].guid]);
|
||||||
yield waitForProfiles();
|
yield waitForAddresses();
|
||||||
is(selProfiles.length, 0, "Profile is removed");
|
is(selAddresses.length, 0, "Address is removed");
|
||||||
win.close();
|
win.close();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
/* exported MANAGE_PROFILES_DIALOG_URL, EDIT_PROFILE_DIALOG_URL,
|
/* exported MANAGE_PROFILES_DIALOG_URL, EDIT_PROFILE_DIALOG_URL,
|
||||||
TEST_PROFILE_1, TEST_PROFILE_2, TEST_PROFILE_3,
|
TEST_ADDRESS_1, TEST_ADDRESS_2, TEST_ADDRESS_3,
|
||||||
getProfiles, saveProfile, removeProfiles */
|
getAddresses, saveAddress, removeAddresses */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const MANAGE_PROFILES_DIALOG_URL = "chrome://formautofill/content/manageProfiles.xhtml";
|
const MANAGE_PROFILES_DIALOG_URL = "chrome://formautofill/content/manageProfiles.xhtml";
|
||||||
const EDIT_PROFILE_DIALOG_URL = "chrome://formautofill/content/editProfile.xhtml";
|
const EDIT_PROFILE_DIALOG_URL = "chrome://formautofill/content/editProfile.xhtml";
|
||||||
|
|
||||||
const TEST_PROFILE_1 = {
|
const TEST_ADDRESS_1 = {
|
||||||
"given-name": "John",
|
"given-name": "John",
|
||||||
"additional-name": "R.",
|
"additional-name": "R.",
|
||||||
"family-name": "Smith",
|
"family-name": "Smith",
|
||||||
|
@ -21,32 +21,32 @@ const TEST_PROFILE_1 = {
|
||||||
email: "timbl@w3.org",
|
email: "timbl@w3.org",
|
||||||
};
|
};
|
||||||
|
|
||||||
const TEST_PROFILE_2 = {
|
const TEST_ADDRESS_2 = {
|
||||||
"street-address": "Some Address",
|
"street-address": "Some Address",
|
||||||
country: "US",
|
country: "US",
|
||||||
};
|
};
|
||||||
|
|
||||||
const TEST_PROFILE_3 = {
|
const TEST_ADDRESS_3 = {
|
||||||
"street-address": "Other Address",
|
"street-address": "Other Address",
|
||||||
"postal-code": "12345",
|
"postal-code": "12345",
|
||||||
};
|
};
|
||||||
|
|
||||||
function getProfiles() {
|
function getAddresses() {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
Services.cpmm.addMessageListener("FormAutofill:Profiles", function getResult(result) {
|
Services.cpmm.addMessageListener("FormAutofill:Addresses", function getResult(result) {
|
||||||
Services.cpmm.removeMessageListener("FormAutofill:Profiles", getResult);
|
Services.cpmm.removeMessageListener("FormAutofill:Addresses", getResult);
|
||||||
resolve(result.data);
|
resolve(result.data);
|
||||||
});
|
});
|
||||||
Services.cpmm.sendAsyncMessage("FormAutofill:GetProfiles", {});
|
Services.cpmm.sendAsyncMessage("FormAutofill:GetAddresses", {});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveProfile(profile) {
|
function saveAddress(address) {
|
||||||
Services.cpmm.sendAsyncMessage("FormAutofill:SaveProfile", {profile});
|
Services.cpmm.sendAsyncMessage("FormAutofill:SaveAddress", {address});
|
||||||
return TestUtils.topicObserved("formautofill-storage-changed");
|
return TestUtils.topicObserved("formautofill-storage-changed");
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeProfiles(guids) {
|
function removeAddresses(guids) {
|
||||||
Services.cpmm.sendAsyncMessage("FormAutofill:RemoveProfiles", {guids});
|
Services.cpmm.sendAsyncMessage("FormAutofill:RemoveAddresses", {guids});
|
||||||
return TestUtils.topicObserved("formautofill-storage-changed");
|
return TestUtils.topicObserved("formautofill-storage-changed");
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,33 +21,33 @@ function checkMenuEntries(expectedValues) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addProfile(profile) {
|
function addAddress(address) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
formFillChromeScript.sendAsyncMessage("FormAutofillTest:AddProfile", {profile});
|
formFillChromeScript.sendAsyncMessage("FormAutofillTest:AddAddress", {address});
|
||||||
formFillChromeScript.addMessageListener("FormAutofillTest:ProfileAdded", function onAdded(data) {
|
formFillChromeScript.addMessageListener("FormAutofillTest:AddressAdded", function onAdded(data) {
|
||||||
formFillChromeScript.removeMessageListener("FormAutofillTest:ProfileAdded", onAdded);
|
formFillChromeScript.removeMessageListener("FormAutofillTest:AddressAdded", onAdded);
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeProfile(guid) {
|
function removeAddress(guid) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
formFillChromeScript.sendAsyncMessage("FormAutofillTest:RemoveProfile", {guid});
|
formFillChromeScript.sendAsyncMessage("FormAutofillTest:RemoveAddress", {guid});
|
||||||
formFillChromeScript.addMessageListener("FormAutofillTest:ProfileRemoved", function onDeleted(data) {
|
formFillChromeScript.addMessageListener("FormAutofillTest:AddressRemoved", function onDeleted(data) {
|
||||||
formFillChromeScript.removeMessageListener("FormAutofillTest:ProfileRemoved", onDeleted);
|
formFillChromeScript.removeMessageListener("FormAutofillTest:AddressRemoved", onDeleted);
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateProfile(guid, profile) {
|
function updateAddress(guid, address) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
formFillChromeScript.sendAsyncMessage("FormAutofillTest:UpdateProfile", {profile, guid});
|
formFillChromeScript.sendAsyncMessage("FormAutofillTest:UpdateAddress", {address, guid});
|
||||||
formFillChromeScript.addMessageListener("FormAutofillTest:ProfileUpdated", function onUpdated(data) {
|
formFillChromeScript.addMessageListener("FormAutofillTest:AddressUpdated", function onUpdated(data) {
|
||||||
formFillChromeScript.removeMessageListener("FormAutofillTest:ProfileUpdated", onUpdated);
|
formFillChromeScript.removeMessageListener("FormAutofillTest:AddressUpdated", onUpdated);
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,19 +8,19 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
var ParentUtils = {
|
var ParentUtils = {
|
||||||
cleanUpProfile() {
|
cleanUpAddress() {
|
||||||
Services.cpmm.addMessageListener("FormAutofill:Profiles", function getResult(result) {
|
Services.cpmm.addMessageListener("FormAutofill:Addresses", function getResult(result) {
|
||||||
Services.cpmm.removeMessageListener("FormAutofill:Profiles", getResult);
|
Services.cpmm.removeMessageListener("FormAutofill:Addresses", getResult);
|
||||||
|
|
||||||
let profiles = result.data;
|
let addresses = result.data;
|
||||||
Services.cpmm.sendAsyncMessage("FormAutofill:RemoveProfiles",
|
Services.cpmm.sendAsyncMessage("FormAutofill:RemoveAddresses",
|
||||||
{guids: profiles.map(profile => profile.guid)});
|
{guids: addresses.map(address => address.guid)});
|
||||||
});
|
});
|
||||||
|
|
||||||
Services.cpmm.sendAsyncMessage("FormAutofill:GetProfiles", {searchString: ""});
|
Services.cpmm.sendAsyncMessage("FormAutofill:GetAddresses", {searchString: ""});
|
||||||
},
|
},
|
||||||
|
|
||||||
updateProfile(type, chromeMsg, msgData, contentMsg) {
|
updateAddress(type, chromeMsg, msgData, contentMsg) {
|
||||||
Services.cpmm.sendAsyncMessage(chromeMsg, msgData);
|
Services.cpmm.sendAsyncMessage(chromeMsg, msgData);
|
||||||
Services.obs.addObserver(function observer(subject, topic, data) {
|
Services.obs.addObserver(function observer(subject, topic, data) {
|
||||||
if (data != type) {
|
if (data != type) {
|
||||||
|
@ -39,23 +39,23 @@ var ParentUtils = {
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
Services.obs.removeObserver(this, "formautofill-storage-changed");
|
Services.obs.removeObserver(this, "formautofill-storage-changed");
|
||||||
this.cleanUpProfile();
|
this.cleanUpAddress();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
ParentUtils.cleanUpProfile();
|
ParentUtils.cleanUpAddress();
|
||||||
Services.obs.addObserver(ParentUtils, "formautofill-storage-changed");
|
Services.obs.addObserver(ParentUtils, "formautofill-storage-changed");
|
||||||
|
|
||||||
addMessageListener("FormAutofillTest:AddProfile", (msg) => {
|
addMessageListener("FormAutofillTest:AddAddress", (msg) => {
|
||||||
ParentUtils.updateProfile("add", "FormAutofill:SaveProfile", msg, "FormAutofillTest:ProfileAdded");
|
ParentUtils.updateAddress("add", "FormAutofill:SaveAddress", msg, "FormAutofillTest:AddressAdded");
|
||||||
});
|
});
|
||||||
|
|
||||||
addMessageListener("FormAutofillTest:RemoveProfile", (msg) => {
|
addMessageListener("FormAutofillTest:RemoveAddress", (msg) => {
|
||||||
ParentUtils.updateProfile("remove", "FormAutofill:Removefile", msg, "FormAutofillTest:ProfileRemoved");
|
ParentUtils.updateAddress("remove", "FormAutofill:RemoveAddress", msg, "FormAutofillTest:AddressRemoved");
|
||||||
});
|
});
|
||||||
|
|
||||||
addMessageListener("FormAutofillTest:UpdateProfile", (msg) => {
|
addMessageListener("FormAutofillTest:UpdateAddress", (msg) => {
|
||||||
ParentUtils.updateProfile("update", "FormAutofill:SaveProfile", msg, "FormAutofillTest:ProfileUpdated");
|
ParentUtils.updateAddress("update", "FormAutofill:SaveAddress", msg, "FormAutofillTest:AddressUpdated");
|
||||||
});
|
});
|
||||||
|
|
||||||
addMessageListener("cleanup", () => {
|
addMessageListener("cleanup", () => {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
Form autofill test: simple form profile autofill
|
Form autofill test: simple form address autofill
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/SpawnTask.js */
|
/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/SpawnTask.js */
|
||||||
|
@ -63,23 +63,23 @@ function checkAutoCompleteInputFilled(element, expectedvalue) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkFormFilled(profile) {
|
function checkFormFilled(address) {
|
||||||
let promises = [];
|
let promises = [];
|
||||||
for (let prop in profile) {
|
for (let prop in address) {
|
||||||
let element = document.getElementById(prop);
|
let element = document.getElementById(prop);
|
||||||
if (document.activeElement == element) {
|
if (document.activeElement == element) {
|
||||||
promises.push(checkAutoCompleteInputFilled(element, profile[prop]));
|
promises.push(checkAutoCompleteInputFilled(element, address[prop]));
|
||||||
} else {
|
} else {
|
||||||
promises.push(checkInputFilled(element, profile[prop]));
|
promises.push(checkInputFilled(element, address[prop]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
doKey("return");
|
doKey("return");
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
function* setupProfileStorage() {
|
function* setupAddressStorage() {
|
||||||
yield addProfile(MOCK_STORAGE[0]);
|
yield addAddress(MOCK_STORAGE[0]);
|
||||||
yield addProfile(MOCK_STORAGE[1]);
|
yield addAddress(MOCK_STORAGE[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function* setupFormHistory() {
|
function* setupFormHistory() {
|
||||||
|
@ -99,33 +99,33 @@ add_task(function* history_only_menu_checking() {
|
||||||
checkMenuEntries(["1-234-567-890"]);
|
checkMenuEntries(["1-234-567-890"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Form with both history and profile storage.
|
// Form with both history and address storage.
|
||||||
add_task(function* check_menu_when_both_existed() {
|
add_task(function* check_menu_when_both_existed() {
|
||||||
yield setupProfileStorage();
|
yield setupAddressStorage();
|
||||||
|
|
||||||
setInput("#organization", "");
|
setInput("#organization", "");
|
||||||
doKey("down");
|
doKey("down");
|
||||||
yield expectPopup();
|
yield expectPopup();
|
||||||
checkMenuEntries(MOCK_STORAGE.map(profile =>
|
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||||
JSON.stringify({primary: profile.organization, secondary: profile["street-address"]})
|
JSON.stringify({primary: address.organization, secondary: address["street-address"]})
|
||||||
));
|
));
|
||||||
|
|
||||||
setInput("#street-address", "");
|
setInput("#street-address", "");
|
||||||
doKey("down");
|
doKey("down");
|
||||||
yield expectPopup();
|
yield expectPopup();
|
||||||
checkMenuEntries(MOCK_STORAGE.map(profile =>
|
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||||
JSON.stringify({primary: profile["street-address"], secondary: profile.organization})
|
JSON.stringify({primary: address["street-address"], secondary: address.organization})
|
||||||
));
|
));
|
||||||
|
|
||||||
setInput("#tel", "");
|
setInput("#tel", "");
|
||||||
doKey("down");
|
doKey("down");
|
||||||
yield expectPopup();
|
yield expectPopup();
|
||||||
checkMenuEntries(MOCK_STORAGE.map(profile =>
|
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||||
JSON.stringify({primary: profile.tel, secondary: profile["street-address"]})
|
JSON.stringify({primary: address.tel, secondary: address["street-address"]})
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Display history search result if no matched data in profiles.
|
// Display history search result if no matched data in addresses.
|
||||||
add_task(function* check_fallback_for_mismatched_field() {
|
add_task(function* check_fallback_for_mismatched_field() {
|
||||||
setInput("#country", "");
|
setInput("#country", "");
|
||||||
doKey("down");
|
doKey("down");
|
||||||
|
@ -133,19 +133,19 @@ add_task(function* check_fallback_for_mismatched_field() {
|
||||||
checkMenuEntries(["US"]);
|
checkMenuEntries(["US"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Autofill the profile from dropdown menu.
|
// Autofill the address from dropdown menu.
|
||||||
add_task(function* check_fields_after_form_autofill() {
|
add_task(function* check_fields_after_form_autofill() {
|
||||||
setInput("#organization", "Moz");
|
setInput("#organization", "Moz");
|
||||||
doKey("down");
|
doKey("down");
|
||||||
yield expectPopup();
|
yield expectPopup();
|
||||||
checkMenuEntries(MOCK_STORAGE.map(profile =>
|
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||||
JSON.stringify({primary: profile.organization, secondary: profile["street-address"]})
|
JSON.stringify({primary: address.organization, secondary: address["street-address"]})
|
||||||
).slice(1));
|
).slice(1));
|
||||||
doKey("down");
|
doKey("down");
|
||||||
yield checkFormFilled(MOCK_STORAGE[1]);
|
yield checkFormFilled(MOCK_STORAGE[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fallback to history search after autofill profile.
|
// Fallback to history search after autofill address.
|
||||||
add_task(function* check_fallback_after_form_autofill() {
|
add_task(function* check_fallback_after_form_autofill() {
|
||||||
setInput("#tel", "");
|
setInput("#tel", "");
|
||||||
doKey("down");
|
doKey("down");
|
||||||
|
|
|
@ -9,7 +9,7 @@ Cu.import("resource://formautofill/ProfileStorage.jsm");
|
||||||
|
|
||||||
const TEST_STORE_FILE_NAME = "test-profile.json";
|
const TEST_STORE_FILE_NAME = "test-profile.json";
|
||||||
|
|
||||||
const TEST_PROFILE_1 = {
|
const TEST_ADDRESS_1 = {
|
||||||
"given-name": "Timothy",
|
"given-name": "Timothy",
|
||||||
"additional-name": "John",
|
"additional-name": "John",
|
||||||
"family-name": "Berners-Lee",
|
"family-name": "Berners-Lee",
|
||||||
|
@ -23,36 +23,36 @@ const TEST_PROFILE_1 = {
|
||||||
email: "timbl@w3.org",
|
email: "timbl@w3.org",
|
||||||
};
|
};
|
||||||
|
|
||||||
const TEST_PROFILE_2 = {
|
const TEST_ADDRESS_2 = {
|
||||||
"street-address": "Some Address",
|
"street-address": "Some Address",
|
||||||
country: "US",
|
country: "US",
|
||||||
};
|
};
|
||||||
|
|
||||||
const TEST_PROFILE_3 = {
|
const TEST_ADDRESS_3 = {
|
||||||
"street-address": "Other Address",
|
"street-address": "Other Address",
|
||||||
"postal-code": "12345",
|
"postal-code": "12345",
|
||||||
};
|
};
|
||||||
|
|
||||||
const TEST_PROFILE_WITH_INVALID_FIELD = {
|
const TEST_ADDRESS_WITH_INVALID_FIELD = {
|
||||||
"street-address": "Another Address",
|
"street-address": "Another Address",
|
||||||
invalidField: "INVALID",
|
invalidField: "INVALID",
|
||||||
};
|
};
|
||||||
|
|
||||||
let prepareTestProfiles = Task.async(function* (path) {
|
let prepareTestRecords = Task.async(function* (path) {
|
||||||
let profileStorage = new ProfileStorage(path);
|
let profileStorage = new ProfileStorage(path);
|
||||||
yield profileStorage.initialize();
|
yield profileStorage.initialize();
|
||||||
|
|
||||||
let onChanged = TestUtils.topicObserved("formautofill-storage-changed",
|
let onChanged = TestUtils.topicObserved("formautofill-storage-changed",
|
||||||
(subject, data) => data == "add");
|
(subject, data) => data == "add");
|
||||||
profileStorage.add(TEST_PROFILE_1);
|
profileStorage.add(TEST_ADDRESS_1);
|
||||||
yield onChanged;
|
yield onChanged;
|
||||||
profileStorage.add(TEST_PROFILE_2);
|
profileStorage.add(TEST_ADDRESS_2);
|
||||||
yield profileStorage._saveImmediately();
|
yield profileStorage._saveImmediately();
|
||||||
});
|
});
|
||||||
|
|
||||||
let do_check_profile_matches = (profileWithMeta, profile) => {
|
let do_check_record_matches = (recordWithMeta, record) => {
|
||||||
for (let key in profile) {
|
for (let key in record) {
|
||||||
do_check_eq(profileWithMeta[key], profile[key]);
|
do_check_eq(recordWithMeta[key], record[key]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ add_task(function* test_initialize() {
|
||||||
yield profileStorage.initialize();
|
yield profileStorage.initialize();
|
||||||
|
|
||||||
do_check_eq(profileStorage._store.data.version, 1);
|
do_check_eq(profileStorage._store.data.version, 1);
|
||||||
do_check_eq(profileStorage._store.data.profiles.length, 0);
|
do_check_eq(profileStorage._store.data.addresses.length, 0);
|
||||||
|
|
||||||
let data = profileStorage._store.data;
|
let data = profileStorage._store.data;
|
||||||
|
|
||||||
|
@ -76,150 +76,150 @@ add_task(function* test_initialize() {
|
||||||
|
|
||||||
add_task(function* test_getAll() {
|
add_task(function* test_getAll() {
|
||||||
let path = getTempFile(TEST_STORE_FILE_NAME).path;
|
let path = getTempFile(TEST_STORE_FILE_NAME).path;
|
||||||
yield prepareTestProfiles(path);
|
yield prepareTestRecords(path);
|
||||||
|
|
||||||
let profileStorage = new ProfileStorage(path);
|
let profileStorage = new ProfileStorage(path);
|
||||||
yield profileStorage.initialize();
|
yield profileStorage.initialize();
|
||||||
|
|
||||||
let profiles = profileStorage.getAll();
|
let addresses = profileStorage.getAll();
|
||||||
|
|
||||||
do_check_eq(profiles.length, 2);
|
do_check_eq(addresses.length, 2);
|
||||||
do_check_profile_matches(profiles[0], TEST_PROFILE_1);
|
do_check_record_matches(addresses[0], TEST_ADDRESS_1);
|
||||||
do_check_profile_matches(profiles[1], TEST_PROFILE_2);
|
do_check_record_matches(addresses[1], TEST_ADDRESS_2);
|
||||||
|
|
||||||
// Modifying output shouldn't affect the storage.
|
// Modifying output shouldn't affect the storage.
|
||||||
profiles[0].organization = "test";
|
addresses[0].organization = "test";
|
||||||
do_check_profile_matches(profileStorage.getAll()[0], TEST_PROFILE_1);
|
do_check_record_matches(profileStorage.getAll()[0], TEST_ADDRESS_1);
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* test_get() {
|
add_task(function* test_get() {
|
||||||
let path = getTempFile(TEST_STORE_FILE_NAME).path;
|
let path = getTempFile(TEST_STORE_FILE_NAME).path;
|
||||||
yield prepareTestProfiles(path);
|
yield prepareTestRecords(path);
|
||||||
|
|
||||||
let profileStorage = new ProfileStorage(path);
|
let profileStorage = new ProfileStorage(path);
|
||||||
yield profileStorage.initialize();
|
yield profileStorage.initialize();
|
||||||
|
|
||||||
let profiles = profileStorage.getAll();
|
let addresses = profileStorage.getAll();
|
||||||
let guid = profiles[0].guid;
|
let guid = addresses[0].guid;
|
||||||
|
|
||||||
let profile = profileStorage.get(guid);
|
let address = profileStorage.get(guid);
|
||||||
do_check_profile_matches(profile, TEST_PROFILE_1);
|
do_check_record_matches(address, TEST_ADDRESS_1);
|
||||||
|
|
||||||
// Modifying output shouldn't affect the storage.
|
// Modifying output shouldn't affect the storage.
|
||||||
profile.organization = "test";
|
address.organization = "test";
|
||||||
do_check_profile_matches(profileStorage.get(guid), TEST_PROFILE_1);
|
do_check_record_matches(profileStorage.get(guid), TEST_ADDRESS_1);
|
||||||
|
|
||||||
Assert.throws(() => profileStorage.get("INVALID_GUID"),
|
Assert.throws(() => profileStorage.get("INVALID_GUID"),
|
||||||
/No matching profile\./);
|
/No matching record\./);
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* test_getByFilter() {
|
add_task(function* test_getByFilter() {
|
||||||
let path = getTempFile(TEST_STORE_FILE_NAME).path;
|
let path = getTempFile(TEST_STORE_FILE_NAME).path;
|
||||||
yield prepareTestProfiles(path);
|
yield prepareTestRecords(path);
|
||||||
|
|
||||||
let profileStorage = new ProfileStorage(path);
|
let profileStorage = new ProfileStorage(path);
|
||||||
yield profileStorage.initialize();
|
yield profileStorage.initialize();
|
||||||
|
|
||||||
let filter = {info: {fieldName: "street-address"}, searchString: "Some"};
|
let filter = {info: {fieldName: "street-address"}, searchString: "Some"};
|
||||||
let profiles = profileStorage.getByFilter(filter);
|
let addresses = profileStorage.getByFilter(filter);
|
||||||
do_check_eq(profiles.length, 1);
|
do_check_eq(addresses.length, 1);
|
||||||
do_check_profile_matches(profiles[0], TEST_PROFILE_2);
|
do_check_record_matches(addresses[0], TEST_ADDRESS_2);
|
||||||
|
|
||||||
filter = {info: {fieldName: "country"}, searchString: "u"};
|
filter = {info: {fieldName: "country"}, searchString: "u"};
|
||||||
profiles = profileStorage.getByFilter(filter);
|
addresses = profileStorage.getByFilter(filter);
|
||||||
do_check_eq(profiles.length, 2);
|
do_check_eq(addresses.length, 2);
|
||||||
do_check_profile_matches(profiles[0], TEST_PROFILE_1);
|
do_check_record_matches(addresses[0], TEST_ADDRESS_1);
|
||||||
do_check_profile_matches(profiles[1], TEST_PROFILE_2);
|
do_check_record_matches(addresses[1], TEST_ADDRESS_2);
|
||||||
|
|
||||||
filter = {info: {fieldName: "street-address"}, searchString: "test"};
|
filter = {info: {fieldName: "street-address"}, searchString: "test"};
|
||||||
profiles = profileStorage.getByFilter(filter);
|
addresses = profileStorage.getByFilter(filter);
|
||||||
do_check_eq(profiles.length, 0);
|
do_check_eq(addresses.length, 0);
|
||||||
|
|
||||||
filter = {info: {fieldName: "street-address"}, searchString: ""};
|
filter = {info: {fieldName: "street-address"}, searchString: ""};
|
||||||
profiles = profileStorage.getByFilter(filter);
|
addresses = profileStorage.getByFilter(filter);
|
||||||
do_check_eq(profiles.length, 2);
|
do_check_eq(addresses.length, 2);
|
||||||
|
|
||||||
// Check if the filtering logic is free from searching special chars.
|
// Check if the filtering logic is free from searching special chars.
|
||||||
filter = {info: {fieldName: "street-address"}, searchString: ".*"};
|
filter = {info: {fieldName: "street-address"}, searchString: ".*"};
|
||||||
profiles = profileStorage.getByFilter(filter);
|
addresses = profileStorage.getByFilter(filter);
|
||||||
do_check_eq(profiles.length, 0);
|
do_check_eq(addresses.length, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* test_add() {
|
add_task(function* test_add() {
|
||||||
let path = getTempFile(TEST_STORE_FILE_NAME).path;
|
let path = getTempFile(TEST_STORE_FILE_NAME).path;
|
||||||
yield prepareTestProfiles(path);
|
yield prepareTestRecords(path);
|
||||||
|
|
||||||
let profileStorage = new ProfileStorage(path);
|
let profileStorage = new ProfileStorage(path);
|
||||||
yield profileStorage.initialize();
|
yield profileStorage.initialize();
|
||||||
|
|
||||||
let profiles = profileStorage.getAll();
|
let addresses = profileStorage.getAll();
|
||||||
|
|
||||||
do_check_eq(profiles.length, 2);
|
do_check_eq(addresses.length, 2);
|
||||||
|
|
||||||
do_check_profile_matches(profiles[0], TEST_PROFILE_1);
|
do_check_record_matches(addresses[0], TEST_ADDRESS_1);
|
||||||
do_check_profile_matches(profiles[1], TEST_PROFILE_2);
|
do_check_record_matches(addresses[1], TEST_ADDRESS_2);
|
||||||
|
|
||||||
do_check_neq(profiles[0].guid, undefined);
|
do_check_neq(addresses[0].guid, undefined);
|
||||||
do_check_neq(profiles[0].timeCreated, undefined);
|
do_check_neq(addresses[0].timeCreated, undefined);
|
||||||
do_check_eq(profiles[0].timeLastModified, profiles[0].timeCreated);
|
do_check_eq(addresses[0].timeLastModified, addresses[0].timeCreated);
|
||||||
do_check_eq(profiles[0].timeLastUsed, 0);
|
do_check_eq(addresses[0].timeLastUsed, 0);
|
||||||
do_check_eq(profiles[0].timesUsed, 0);
|
do_check_eq(addresses[0].timesUsed, 0);
|
||||||
|
|
||||||
Assert.throws(() => profileStorage.add(TEST_PROFILE_WITH_INVALID_FIELD),
|
Assert.throws(() => profileStorage.add(TEST_ADDRESS_WITH_INVALID_FIELD),
|
||||||
/"invalidField" is not a valid field\./);
|
/"invalidField" is not a valid field\./);
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* test_update() {
|
add_task(function* test_update() {
|
||||||
let path = getTempFile(TEST_STORE_FILE_NAME).path;
|
let path = getTempFile(TEST_STORE_FILE_NAME).path;
|
||||||
yield prepareTestProfiles(path);
|
yield prepareTestRecords(path);
|
||||||
|
|
||||||
let profileStorage = new ProfileStorage(path);
|
let profileStorage = new ProfileStorage(path);
|
||||||
yield profileStorage.initialize();
|
yield profileStorage.initialize();
|
||||||
|
|
||||||
let profiles = profileStorage.getAll();
|
let addresses = profileStorage.getAll();
|
||||||
let guid = profiles[1].guid;
|
let guid = addresses[1].guid;
|
||||||
let timeLastModified = profiles[1].timeLastModified;
|
let timeLastModified = addresses[1].timeLastModified;
|
||||||
|
|
||||||
let onChanged = TestUtils.topicObserved("formautofill-storage-changed",
|
let onChanged = TestUtils.topicObserved("formautofill-storage-changed",
|
||||||
(subject, data) => data == "update");
|
(subject, data) => data == "update");
|
||||||
|
|
||||||
do_check_neq(profiles[1].country, undefined);
|
do_check_neq(addresses[1].country, undefined);
|
||||||
|
|
||||||
profileStorage.update(guid, TEST_PROFILE_3);
|
profileStorage.update(guid, TEST_ADDRESS_3);
|
||||||
yield onChanged;
|
yield onChanged;
|
||||||
yield profileStorage._saveImmediately();
|
yield profileStorage._saveImmediately();
|
||||||
|
|
||||||
profileStorage = new ProfileStorage(path);
|
profileStorage = new ProfileStorage(path);
|
||||||
yield profileStorage.initialize();
|
yield profileStorage.initialize();
|
||||||
|
|
||||||
let profile = profileStorage.get(guid);
|
let address = profileStorage.get(guid);
|
||||||
|
|
||||||
do_check_eq(profile.country, undefined);
|
do_check_eq(address.country, undefined);
|
||||||
do_check_neq(profile.timeLastModified, timeLastModified);
|
do_check_neq(address.timeLastModified, timeLastModified);
|
||||||
do_check_profile_matches(profile, TEST_PROFILE_3);
|
do_check_record_matches(address, TEST_ADDRESS_3);
|
||||||
|
|
||||||
Assert.throws(
|
Assert.throws(
|
||||||
() => profileStorage.update("INVALID_GUID", TEST_PROFILE_3),
|
() => profileStorage.update("INVALID_GUID", TEST_ADDRESS_3),
|
||||||
/No matching profile\./
|
/No matching record\./
|
||||||
);
|
);
|
||||||
|
|
||||||
Assert.throws(
|
Assert.throws(
|
||||||
() => profileStorage.update(guid, TEST_PROFILE_WITH_INVALID_FIELD),
|
() => profileStorage.update(guid, TEST_ADDRESS_WITH_INVALID_FIELD),
|
||||||
/"invalidField" is not a valid field\./
|
/"invalidField" is not a valid field\./
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* test_notifyUsed() {
|
add_task(function* test_notifyUsed() {
|
||||||
let path = getTempFile(TEST_STORE_FILE_NAME).path;
|
let path = getTempFile(TEST_STORE_FILE_NAME).path;
|
||||||
yield prepareTestProfiles(path);
|
yield prepareTestRecords(path);
|
||||||
|
|
||||||
let profileStorage = new ProfileStorage(path);
|
let profileStorage = new ProfileStorage(path);
|
||||||
yield profileStorage.initialize();
|
yield profileStorage.initialize();
|
||||||
|
|
||||||
let profiles = profileStorage.getAll();
|
let addresses = profileStorage.getAll();
|
||||||
let guid = profiles[1].guid;
|
let guid = addresses[1].guid;
|
||||||
let timeLastUsed = profiles[1].timeLastUsed;
|
let timeLastUsed = addresses[1].timeLastUsed;
|
||||||
let timesUsed = profiles[1].timesUsed;
|
let timesUsed = addresses[1].timesUsed;
|
||||||
|
|
||||||
let onChanged = TestUtils.topicObserved("formautofill-storage-changed",
|
let onChanged = TestUtils.topicObserved("formautofill-storage-changed",
|
||||||
(subject, data) => data == "notifyUsed");
|
(subject, data) => data == "notifyUsed");
|
||||||
|
@ -231,29 +231,29 @@ add_task(function* test_notifyUsed() {
|
||||||
profileStorage = new ProfileStorage(path);
|
profileStorage = new ProfileStorage(path);
|
||||||
yield profileStorage.initialize();
|
yield profileStorage.initialize();
|
||||||
|
|
||||||
let profile = profileStorage.get(guid);
|
let address = profileStorage.get(guid);
|
||||||
|
|
||||||
do_check_eq(profile.timesUsed, timesUsed + 1);
|
do_check_eq(address.timesUsed, timesUsed + 1);
|
||||||
do_check_neq(profile.timeLastUsed, timeLastUsed);
|
do_check_neq(address.timeLastUsed, timeLastUsed);
|
||||||
|
|
||||||
Assert.throws(() => profileStorage.notifyUsed("INVALID_GUID"),
|
Assert.throws(() => profileStorage.notifyUsed("INVALID_GUID"),
|
||||||
/No matching profile\./);
|
/No matching record\./);
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* test_remove() {
|
add_task(function* test_remove() {
|
||||||
let path = getTempFile(TEST_STORE_FILE_NAME).path;
|
let path = getTempFile(TEST_STORE_FILE_NAME).path;
|
||||||
yield prepareTestProfiles(path);
|
yield prepareTestRecords(path);
|
||||||
|
|
||||||
let profileStorage = new ProfileStorage(path);
|
let profileStorage = new ProfileStorage(path);
|
||||||
yield profileStorage.initialize();
|
yield profileStorage.initialize();
|
||||||
|
|
||||||
let profiles = profileStorage.getAll();
|
let addresses = profileStorage.getAll();
|
||||||
let guid = profiles[1].guid;
|
let guid = addresses[1].guid;
|
||||||
|
|
||||||
let onChanged = TestUtils.topicObserved("formautofill-storage-changed",
|
let onChanged = TestUtils.topicObserved("formautofill-storage-changed",
|
||||||
(subject, data) => data == "remove");
|
(subject, data) => data == "remove");
|
||||||
|
|
||||||
do_check_eq(profiles.length, 2);
|
do_check_eq(addresses.length, 2);
|
||||||
|
|
||||||
profileStorage.remove(guid);
|
profileStorage.remove(guid);
|
||||||
yield onChanged;
|
yield onChanged;
|
||||||
|
@ -262,9 +262,9 @@ add_task(function* test_remove() {
|
||||||
profileStorage = new ProfileStorage(path);
|
profileStorage = new ProfileStorage(path);
|
||||||
yield profileStorage.initialize();
|
yield profileStorage.initialize();
|
||||||
|
|
||||||
profiles = profileStorage.getAll();
|
addresses = profileStorage.getAll();
|
||||||
|
|
||||||
do_check_eq(profiles.length, 1);
|
do_check_eq(addresses.length, 1);
|
||||||
|
|
||||||
Assert.throws(() => profileStorage.get(guid), /No matching profile\./);
|
Assert.throws(() => profileStorage.get(guid), /No matching record\./);
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,8 +12,8 @@ const TEST_STORE_FILE_NAME = "test-profile.json";
|
||||||
const COMPUTE_TESTCASES = [
|
const COMPUTE_TESTCASES = [
|
||||||
// Empty
|
// Empty
|
||||||
{
|
{
|
||||||
description: "Empty profile",
|
description: "Empty address",
|
||||||
profile: {
|
address: {
|
||||||
},
|
},
|
||||||
expectedResult: {
|
expectedResult: {
|
||||||
},
|
},
|
||||||
|
@ -22,7 +22,7 @@ const COMPUTE_TESTCASES = [
|
||||||
// Name
|
// Name
|
||||||
{
|
{
|
||||||
description: "Has split names",
|
description: "Has split names",
|
||||||
profile: {
|
address: {
|
||||||
"given-name": "Timothy",
|
"given-name": "Timothy",
|
||||||
"additional-name": "John",
|
"additional-name": "John",
|
||||||
"family-name": "Berners-Lee",
|
"family-name": "Berners-Lee",
|
||||||
|
@ -38,7 +38,7 @@ const COMPUTE_TESTCASES = [
|
||||||
// Address
|
// Address
|
||||||
{
|
{
|
||||||
description: "\"street-address\" with single line",
|
description: "\"street-address\" with single line",
|
||||||
profile: {
|
address: {
|
||||||
"street-address": "single line",
|
"street-address": "single line",
|
||||||
},
|
},
|
||||||
expectedResult: {
|
expectedResult: {
|
||||||
|
@ -48,7 +48,7 @@ const COMPUTE_TESTCASES = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "\"street-address\" with multiple lines",
|
description: "\"street-address\" with multiple lines",
|
||||||
profile: {
|
address: {
|
||||||
"street-address": "line1\nline2\nline3",
|
"street-address": "line1\nline2\nline3",
|
||||||
},
|
},
|
||||||
expectedResult: {
|
expectedResult: {
|
||||||
|
@ -60,7 +60,7 @@ const COMPUTE_TESTCASES = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "\"street-address\" with multiple lines but line2 is omitted",
|
description: "\"street-address\" with multiple lines but line2 is omitted",
|
||||||
profile: {
|
address: {
|
||||||
"street-address": "line1\n\nline3",
|
"street-address": "line1\n\nline3",
|
||||||
},
|
},
|
||||||
expectedResult: {
|
expectedResult: {
|
||||||
|
@ -72,7 +72,7 @@ const COMPUTE_TESTCASES = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "\"street-address\" with 4 lines",
|
description: "\"street-address\" with 4 lines",
|
||||||
profile: {
|
address: {
|
||||||
"street-address": "line1\nline2\nline3\nline4",
|
"street-address": "line1\nline2\nline3\nline4",
|
||||||
},
|
},
|
||||||
expectedResult: {
|
expectedResult: {
|
||||||
|
@ -87,8 +87,8 @@ const COMPUTE_TESTCASES = [
|
||||||
const NORMALIZE_TESTCASES = [
|
const NORMALIZE_TESTCASES = [
|
||||||
// Empty
|
// Empty
|
||||||
{
|
{
|
||||||
description: "Empty profile",
|
description: "Empty address",
|
||||||
profile: {
|
address: {
|
||||||
},
|
},
|
||||||
expectedResult: {
|
expectedResult: {
|
||||||
},
|
},
|
||||||
|
@ -97,7 +97,7 @@ const NORMALIZE_TESTCASES = [
|
||||||
// Name
|
// Name
|
||||||
{
|
{
|
||||||
description: "Has \"name\", and the split names are omitted",
|
description: "Has \"name\", and the split names are omitted",
|
||||||
profile: {
|
address: {
|
||||||
"name": "Timothy John Berners-Lee",
|
"name": "Timothy John Berners-Lee",
|
||||||
},
|
},
|
||||||
expectedResult: {
|
expectedResult: {
|
||||||
|
@ -108,7 +108,7 @@ const NORMALIZE_TESTCASES = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Has both \"name\" and split names",
|
description: "Has both \"name\" and split names",
|
||||||
profile: {
|
address: {
|
||||||
"name": "John Doe",
|
"name": "John Doe",
|
||||||
"given-name": "Timothy",
|
"given-name": "Timothy",
|
||||||
"additional-name": "John",
|
"additional-name": "John",
|
||||||
|
@ -122,7 +122,7 @@ const NORMALIZE_TESTCASES = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Has \"name\", and some of split names are omitted",
|
description: "Has \"name\", and some of split names are omitted",
|
||||||
profile: {
|
address: {
|
||||||
"name": "John Doe",
|
"name": "John Doe",
|
||||||
"given-name": "Timothy",
|
"given-name": "Timothy",
|
||||||
},
|
},
|
||||||
|
@ -136,7 +136,7 @@ const NORMALIZE_TESTCASES = [
|
||||||
// Address
|
// Address
|
||||||
{
|
{
|
||||||
description: "Has \"address-line1~3\" and \"street-address\" is omitted",
|
description: "Has \"address-line1~3\" and \"street-address\" is omitted",
|
||||||
profile: {
|
address: {
|
||||||
"address-line1": "line1",
|
"address-line1": "line1",
|
||||||
"address-line2": "line2",
|
"address-line2": "line2",
|
||||||
"address-line3": "line3",
|
"address-line3": "line3",
|
||||||
|
@ -147,7 +147,7 @@ const NORMALIZE_TESTCASES = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Has both \"address-line1~3\" and \"street-address\"",
|
description: "Has both \"address-line1~3\" and \"street-address\"",
|
||||||
profile: {
|
address: {
|
||||||
"street-address": "street address",
|
"street-address": "street address",
|
||||||
"address-line1": "line1",
|
"address-line1": "line1",
|
||||||
"address-line2": "line2",
|
"address-line2": "line2",
|
||||||
|
@ -159,7 +159,7 @@ const NORMALIZE_TESTCASES = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Has \"address-line2~3\" and single-line \"street-address\"",
|
description: "Has \"address-line2~3\" and single-line \"street-address\"",
|
||||||
profile: {
|
address: {
|
||||||
"street-address": "street address",
|
"street-address": "street address",
|
||||||
"address-line2": "line2",
|
"address-line2": "line2",
|
||||||
"address-line3": "line3",
|
"address-line3": "line3",
|
||||||
|
@ -170,7 +170,7 @@ const NORMALIZE_TESTCASES = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Has \"address-line2~3\" and multiple-line \"street-address\"",
|
description: "Has \"address-line2~3\" and multiple-line \"street-address\"",
|
||||||
profile: {
|
address: {
|
||||||
"street-address": "street address\nstreet address line 2",
|
"street-address": "street address\nstreet address line 2",
|
||||||
"address-line2": "line2",
|
"address-line2": "line2",
|
||||||
"address-line3": "line3",
|
"address-line3": "line3",
|
||||||
|
@ -181,9 +181,9 @@ const NORMALIZE_TESTCASES = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
let do_check_profile_matches = (expectedProfile, profile) => {
|
let do_check_record_matches = (expectedRecord, record) => {
|
||||||
for (let key in expectedProfile) {
|
for (let key in expectedRecord) {
|
||||||
do_check_eq(expectedProfile[key], profile[key] || "");
|
do_check_eq(expectedRecord[key], record[key] || "");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -193,36 +193,36 @@ add_task(function* test_computeFields() {
|
||||||
let profileStorage = new ProfileStorage(path);
|
let profileStorage = new ProfileStorage(path);
|
||||||
yield profileStorage.initialize();
|
yield profileStorage.initialize();
|
||||||
|
|
||||||
COMPUTE_TESTCASES.forEach(testcase => profileStorage.add(testcase.profile));
|
COMPUTE_TESTCASES.forEach(testcase => profileStorage.add(testcase.address));
|
||||||
yield profileStorage._saveImmediately();
|
yield profileStorage._saveImmediately();
|
||||||
|
|
||||||
profileStorage = new ProfileStorage(path);
|
profileStorage = new ProfileStorage(path);
|
||||||
yield profileStorage.initialize();
|
yield profileStorage.initialize();
|
||||||
|
|
||||||
let profiles = profileStorage.getAll();
|
let addresses = profileStorage.getAll();
|
||||||
|
|
||||||
for (let i in profiles) {
|
for (let i in addresses) {
|
||||||
do_print("Verify testcase: " + COMPUTE_TESTCASES[i].description);
|
do_print("Verify testcase: " + COMPUTE_TESTCASES[i].description);
|
||||||
do_check_profile_matches(COMPUTE_TESTCASES[i].expectedResult, profiles[i]);
|
do_check_record_matches(COMPUTE_TESTCASES[i].expectedResult, addresses[i]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function* test_normalizeProfile() {
|
add_task(function* test_normalizeFields() {
|
||||||
let path = getTempFile(TEST_STORE_FILE_NAME).path;
|
let path = getTempFile(TEST_STORE_FILE_NAME).path;
|
||||||
|
|
||||||
let profileStorage = new ProfileStorage(path);
|
let profileStorage = new ProfileStorage(path);
|
||||||
yield profileStorage.initialize();
|
yield profileStorage.initialize();
|
||||||
|
|
||||||
NORMALIZE_TESTCASES.forEach(testcase => profileStorage.add(testcase.profile));
|
NORMALIZE_TESTCASES.forEach(testcase => profileStorage.add(testcase.address));
|
||||||
yield profileStorage._saveImmediately();
|
yield profileStorage._saveImmediately();
|
||||||
|
|
||||||
profileStorage = new ProfileStorage(path);
|
profileStorage = new ProfileStorage(path);
|
||||||
yield profileStorage.initialize();
|
yield profileStorage.initialize();
|
||||||
|
|
||||||
let profiles = profileStorage.getAll();
|
let addresses = profileStorage.getAll();
|
||||||
|
|
||||||
for (let i in profiles) {
|
for (let i in addresses) {
|
||||||
do_print("Verify testcase: " + NORMALIZE_TESTCASES[i].description);
|
do_print("Verify testcase: " + NORMALIZE_TESTCASES[i].description);
|
||||||
do_check_profile_matches(NORMALIZE_TESTCASES[i].expectedResult, profiles[i]);
|
do_check_record_matches(NORMALIZE_TESTCASES[i].expectedResult, addresses[i]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Загрузка…
Ссылка в новой задаче