Bug 1339721 - Use FormAutofillHandler.autofillFormFields to fill in fields.; r=MattN

MozReview-Commit-ID: KgphpgQ4FNp

--HG--
extra : rebase_source : 7d8dc62c683ccc439385db78ecdde62a999e8978
This commit is contained in:
Sean Lee 2017-02-15 16:27:45 +08:00
Родитель d80bc035b4
Коммит 214ce08657
3 изменённых файлов: 82 добавлений и 91 удалений

Просмотреть файл

@ -233,20 +233,9 @@ let ProfileAutocomplete = {
}
let profile = JSON.parse(this._lastAutoCompleteResult.getCommentAt(selectedIndex));
let formHandler = FormAutofillContent.getFormHandler(focusedInput);
// TODO: FormAutofillHandler.autofillFormFields will be used for filling
// fields logic eventually.
for (let inputInfo of formDetails) {
// Skip filling the value of focused input which is filled in
// FormFillController.
if (inputInfo.element === focusedInput) {
continue;
}
let value = profile[inputInfo.fieldName];
if (value) {
inputInfo.element.setUserInput(value);
}
}
formHandler.autofillFormFields(profile, focusedInput);
},
};
@ -295,19 +284,32 @@ var FormAutofillContent = {
return null;
},
/**
* Get the form's handler from cache which is created after page identified.
*
* @param {HTMLInputElement} element Focused input which triggered profile searching
* @returns {Array<Object>|null}
* Return target form's handler from content cache
* (or return null if the information is not found in the cache).
*
*/
getFormHandler(element) {
let rootElement = FormLikeFactory.findRootForField(element);
return this._formsDetails.get(rootElement);
},
/**
* Get the form's information from cache which is created after page identified.
*
* @param {HTMLInputElement} element Focused input which triggered profile searching
* @returns {Array<Object>|null}
* Return target form's information that cloned from content cache
* Return target form's information from content cache
* (or return null if the information is not found in the cache).
*
*/
getFormDetails(element) {
let rootElement = FormLikeFactory.findRootForField(element);
let formDetails = this._formsDetails.get(rootElement);
return formDetails ? formDetails.fieldDetails : null;
let formHandler = this.getFormHandler(element);
return formHandler ? formHandler.fieldDetails : null;
},
getAllFieldNames(element) {

Просмотреть файл

@ -103,45 +103,30 @@ FormAutofillHandler.prototype = {
/**
* Processes form fields that can be autofilled, and populates them with the
* data provided by backend.
* profile provided by backend.
*
* @param {Array<Object>} autofillResult
* Data returned by the user interface.
* [{
* section: Value originally provided to the user interface.
* addressType: Value originally provided to the user interface.
* contactType: Value originally provided to the user interface.
* fieldName: Value originally provided to the user interface.
* value: String with which the field should be updated.
* index: Index to match the input in fieldDetails
* }],
* }
* @param {Object} profile
* A profile to be filled in.
* @param {Object} focusedInput
* A focused input element which is skipped for filling.
*/
autofillFormFields(autofillResult) {
log.debug("autofillFormFields:", autofillResult);
for (let field of autofillResult) {
// TODO: Skip filling the value of focused input which is filled in
// FormFillController.
autofillFormFields(profile, focusedInput) {
log.debug("profile in autofillFormFields:", profile);
for (let fieldDetail of this.fieldDetails) {
// Avoid filling field value in the following cases:
// 1. the focused input which is filled in FormFillController.
// 2. a non-empty input field
// 3. the invalid value set
// Get the field details, if it was processed by the user interface.
let fieldDetail = this.fieldDetails[field.index];
// Avoid the invalid value set
if (!fieldDetail || !field.value) {
if (fieldDetail.element === focusedInput ||
fieldDetail.element.value) {
continue;
}
let info = FormAutofillHeuristics.getInfo(fieldDetail.element);
if (!info ||
field.section != info.section ||
field.addressType != info.addressType ||
field.contactType != info.contactType ||
field.fieldName != info.fieldName) {
Cu.reportError("Autocomplete tokens mismatched");
continue;
let value = profile[fieldDetail.fieldName];
if (value) {
fieldDetail.element.setUserInput(value);
}
fieldDetail.element.setUserInput(field.value);
}
},
};

Просмотреть файл

@ -13,7 +13,7 @@ const TESTCASES = [
<input id="street-addr"><input id="city"><input id="country">
<input id='email'><input id="tel"></form>`,
fieldDetails: [],
profileData: [],
profileData: {},
expectedResult: {
"street-addr": "",
"city": "",
@ -40,15 +40,13 @@ const TESTCASES = [
{"section": "", "addressType": "", "contactType": "", "fieldName": "email", "element": {}},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel", "element": {}},
],
profileData: [
{"section": "", "addressType": "", "fieldName": "given-name", "contactType": "", "index": 0, "value": "foo"},
{"section": "", "addressType": "", "fieldName": "family-name", "contactType": "", "index": 1, "value": "bar"},
{"section": "", "addressType": "", "fieldName": "street-address", "contactType": "", "index": 2, "value": "2 Harrison St"},
{"section": "", "addressType": "", "fieldName": "address-level2", "contactType": "", "index": 3, "value": "San Francisco"},
{"section": "", "addressType": "", "fieldName": "country", "contactType": "", "index": 4, "value": "US"},
{"section": "", "addressType": "", "fieldName": "email", "contactType": "", "index": 5, "value": "foo@mozilla.com"},
{"section": "", "addressType": "", "fieldName": "tel", "contactType": "", "index": 6, "value": "1234567"},
],
profileData: {
"street-address": "2 Harrison St",
"address-level2": "San Francisco",
"country": "US",
"email": "foo@mozilla.com",
"tel": "1234567",
},
expectedResult: {
"street-addr": "2 Harrison St",
"city": "San Francisco",
@ -75,15 +73,13 @@ const TESTCASES = [
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "email", "element": {}},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel", "element": {}},
],
profileData: [
{"section": "", "addressType": "shipping", "fieldName": "given-name", "contactType": "", "index": 0, "value": "foo"},
{"section": "", "addressType": "shipping", "fieldName": "family-name", "contactType": "", "index": 1, "value": "bar"},
{"section": "", "addressType": "shipping", "fieldName": "street-address", "contactType": "", "index": 2, "value": "2 Harrison St"},
{"section": "", "addressType": "shipping", "fieldName": "address-level2", "contactType": "", "index": 3, "value": "San Francisco"},
{"section": "", "addressType": "shipping", "fieldName": "country", "contactType": "", "index": 4, "value": "US"},
{"section": "", "addressType": "shipping", "fieldName": "email", "contactType": "", "index": 5, "value": "foo@mozilla.com"},
{"section": "", "addressType": "shipping", "fieldName": "tel", "contactType": "", "index": 6, "value": "1234567"},
],
profileData: {
"street-address": "2 Harrison St",
"address-level2": "San Francisco",
"country": "US",
"email": "foo@mozilla.com",
"tel": "1234567",
},
expectedResult: {
"street-addr": "2 Harrison St",
"city": "San Francisco",
@ -110,15 +106,13 @@ const TESTCASES = [
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "email", "element": {}},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel", "element": {}},
],
profileData: [
{"section": "", "addressType": "shipping", "fieldName": "given-name", "contactType": "", "index": 0, "value": "foo"},
{"section": "", "addressType": "shipping", "fieldName": "family-name", "contactType": "", "index": 1, "value": "bar"},
{"section": "", "addressType": "shipping", "fieldName": "street-address", "contactType": "", "index": 2, "value": "2 Harrison St"},
{"section": "", "addressType": "shipping", "fieldName": "address-level2", "contactType": "", "index": 3, "value": "San Francisco"},
{"section": "", "addressType": "shipping", "fieldName": "country", "contactType": "", "index": 4, "value": "US"},
{"section": "", "addressType": "shipping", "fieldName": "email", "contactType": "", "index": 5},
{"section": "", "addressType": "shipping", "fieldName": "tel", "contactType": "", "index": 6},
],
profileData: {
"street-address": "2 Harrison St",
"address-level2": "San Francisco",
"country": "US",
"email": "",
"tel": "",
},
expectedResult: {
"street-addr": "2 Harrison St",
"city": "San Francisco",
@ -145,15 +139,13 @@ const TESTCASES = [
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "email", "element": {}},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel", "element": {}},
],
profileData: [
{"section": "", "addressType": "shipping", "fieldName": "given-name", "contactType": "", "index": 0, "value": "foo"},
{"section": "", "addressType": "shipping", "fieldName": "family-name", "contactType": "", "index": 1, "value": "bar"},
{"section": "", "addressType": "shipping", "fieldName": "street-address", "contactType": "", "index": 2, "value": "2 Harrison St"},
{"section": "", "addressType": "shipping", "fieldName": "address-level2", "contactType": "", "index": 3, "value": "San Francisco"},
{"section": "", "addressType": "shipping", "fieldName": "country", "contactType": "", "index": 4, "value": "US"},
{"section": "", "addressType": "shipping", "fieldName": "email", "contactType": "", "index": 5, "value": "foo@mozilla.com"},
{"section": "", "addressType": "shipping", "fieldName": "tel", "contactType": "", "index": 6, "value": "1234567"},
],
profileData: {
"street-address": "",
"address-level2": "",
"country": "",
"email": "foo@mozilla.com",
"tel": "1234567",
},
expectedResult: {
"street-addr": "",
"city": "",
@ -174,17 +166,29 @@ for (let tc of TESTCASES) {
testcase.document);
let form = doc.querySelector("form");
let handler = new FormAutofillHandler(form);
let onChangePromises = [];
handler.fieldDetails = testcase.fieldDetails;
handler.fieldDetails.forEach((field, index) => {
field.element = doc.querySelectorAll("input")[index];
let element = doc.querySelectorAll("input")[index];
field.element = element;
if (!testcase.profileData[field.fieldName]) {
// Avoid waiting for `change` event of a input with a blank value to
// be filled.
return;
}
onChangePromises.push(new Promise(resolve => {
element.addEventListener("change", () => {
let id = element.id;
Assert.equal(element.value, testcase.expectedResult[id],
"Check the " + id + " fields were filled with correct data");
resolve();
}, {once: true});
}));
});
handler.autofillFormFields(testcase.profileData);
for (let id in testcase.expectedResult) {
Assert.equal(doc.getElementById(id).value, testcase.expectedResult[id],
"Check the " + id + " fields were filled with correct data");
}
yield Promise.all(onChangePromises);
});
})();
}