Bug 1420169 - Move the ownership of input handler from form to section. r=lchang
MozReview-Commit-ID: FZgLNAqg1hR
--- a/browser/extensions/formautofill/FormAutofillHandler.jsm
+++ b/browser/extensions/formautofill/FormAutofillHandler.jsm
@@ -388,36 +388,36 @@ class FormAutofillSection {
// For the focused input element, it will be filled with a valid value
// anyway.
// For the others, the fields should be only filled when their values
// are empty.
if (element == focusedInput ||
(element != focusedInput && !element.value)) {
element.setUserInput(value);
this.changeFieldState(fieldDetail, FIELD_STATES.AUTO_FILLED);
- continue;
}
- }
-
- if (ChromeUtils.getClassName(element) === "HTMLSelectElement") {
+ } else if (ChromeUtils.getClassName(element) === "HTMLSelectElement") {
let cache = this._cacheValue.matchingSelectOption.get(element) || {};
let option = cache[value] && cache[value].get();
if (!option) {
continue;
}
// Do not change value or dispatch events if the option is already selected.
// Use case for multiple select is not considered here.
if (!option.selected) {
option.selected = true;
element.dispatchEvent(new element.ownerGlobal.UIEvent("input", {bubbles: true}));
element.dispatchEvent(new element.ownerGlobal.Event("change", {bubbles: true}));
}
// Autofill highlight appears regardless if value is changed or not
this.changeFieldState(fieldDetail, FIELD_STATES.AUTO_FILLED);
}
+ if (fieldDetail.state == FIELD_STATES.AUTO_FILLED) {
+ element.addEventListener("input", this);
+ }
}
}
/**
* Populates result to the preview layers with given profile.
*
* @param {Object} profile
* A profile to be previewed with
@@ -549,28 +549,20 @@ class FormAutofillSection {
} else {
this.winUtils.removeManuallyManagedState(element, mmStateValue);
}
}
fieldDetail.state = nextState;
}
- clearFieldState(focusedInput) {
- let fieldDetail = this.getFieldDetailByElement(focusedInput);
- this.changeFieldState(fieldDetail, FIELD_STATES.NORMAL);
- let targetSet = this._getTargetSet(focusedInput);
-
- if (!targetSet.fieldDetails.some(detail => detail.state == FIELD_STATES.AUTO_FILLED)) {
- targetSet.filledRecordGUID = null;
- }
- }
-
resetFieldStates() {
for (let fieldDetail of this._validDetails) {
+ const element = fieldDetail.elementWeakRef.get();
+ element.removeEventListener("input", this);
this.changeFieldState(fieldDetail, FIELD_STATES.NORMAL);
}
this.address.filledRecordGUID = null;
this.creditCard.filledRecordGUID = null;
}
isFilled() {
return !!(this.address.filledRecordGUID || this.creditCard.filledRecordGUID);
@@ -738,16 +730,36 @@ class FormAutofillSection {
Services.cpmm.addMessageListener("FormAutofill:DecryptedString", function getResult(result) {
Services.cpmm.removeMessageListener("FormAutofill:DecryptedString", getResult);
resolve(result.data);
});
Services.cpmm.sendAsyncMessage("FormAutofill:GetDecryptedString", {cipherText, reauth});
});
}
+
+ handleEvent(event) {
+ switch (event.type) {
+ case "input": {
+ if (!event.isTrusted) {
+ return;
+ }
+ const target = event.target;
+ const fieldDetail = this.getFieldDetailByElement(target);
+ const targetSet = this._getTargetSet(target);
+ this.changeFieldState(fieldDetail, FIELD_STATES.NORMAL);
+
+ if (!targetSet.fieldDetails.some(detail => detail.state == FIELD_STATES.AUTO_FILLED)) {
+ targetSet.filledRecordGUID = null;
+ }
+ target.removeEventListener("input", this);
+ break;
+ }
+ }
+ }
}
/**
* Handles profile autofill for a DOM Form element.
*/
class FormAutofillHandler {
/**
* Initialize the form from `FormLike` object to handle the section or form
@@ -923,43 +935,38 @@ class FormAutofillHandler {
*
* @param {Object} profile
* A profile to be filled in.
* @param {HTMLElement} focusedInput
* A focused input element needed to determine the address or credit
* card field.
*/
async autofillFormFields(profile, focusedInput) {
- let noFilledSections = !this.hasFilledSection();
+ let noFilledSectionsPreviously = !this.hasFilledSection();
await this.getSectionByElement(focusedInput).autofillFields(profile, focusedInput);
- // Handle the highlight style resetting caused by user's correction afterward.
- log.debug("register change handler for filled form:", this.form);
const onChangeHandler = e => {
if (!e.isTrusted) {
return;
}
-
- if (e.type == "input") {
- let section = this.getSectionByElement(e.target);
- section.clearFieldState(e.target);
- } else if (e.type == "reset") {
+ if (e.type == "reset") {
for (let section of this.sections) {
section.resetFieldStates();
}
}
-
// Unregister listeners once no field is in AUTO_FILLED state.
if (!this.hasFilledSection()) {
this.form.rootElement.removeEventListener("input", onChangeHandler);
this.form.rootElement.removeEventListener("reset", onChangeHandler);
}
};
- if (noFilledSections) {
+ if (noFilledSectionsPreviously) {
+ // Handle the highlight style resetting caused by user's correction afterward.
+ log.debug("register change handler for filled form:", this.form);
this.form.rootElement.addEventListener("input", onChangeHandler);
this.form.rootElement.addEventListener("reset", onChangeHandler);
}
}
handleEvent(event) {
switch (event.type) {
case "input":