Bug 1407508 - Part 4. Implement clear populated form function for form autofill clear button. r=lchang, seanlee
With this patch, we're able to clear the populated form already. However,
we need some ways to invalidate mResults in AutoCompleteController to get
new results instead of cached one for clear button once the form has been
populated.
MozReview-Commit-ID: 8No9FXWJv0p
--- a/browser/extensions/formautofill/FormAutofillContent.jsm
+++ b/browser/extensions/formautofill/FormAutofillContent.jsm
@@ -508,16 +508,26 @@ var FormAutofillContent = {
this._formsDetails.set(formHandler.form.rootElement, formHandler);
this.log.debug("Adding form handler to _formsDetails:", formHandler);
validDetails.forEach(detail =>
this._markAsAutofillField(detail.elementWeakRef.get())
);
},
+ clearForm() {
+ let focusedInput = formFillController.focusedInput || ProfileAutocomplete._lastAutoCompleteFocusedInput;
+ if (!focusedInput) {
+ return;
+ }
+
+ let formHandler = this.getFormHandler(focusedInput);
+ formHandler.clearPopulatedForm(focusedInput);
+ },
+
previewProfile(doc) {
let docWin = doc.ownerGlobal;
let selectedIndex = ProfileAutocomplete._getSelectedIndex(docWin);
let lastAutoCompleteResult = ProfileAutocomplete.lastProfileAutoCompleteResult;
let focusedInput = formFillController.focusedInput;
let mm = this._messageManagerFromWindow(docWin);
if (selectedIndex === -1 ||
@@ -572,18 +582,20 @@ var FormAutofillContent = {
if (e.keyCode != Ci.nsIDOMKeyEvent.DOM_VK_RETURN || !lastAutoCompleteResult ||
!focusedInput || focusedInput != ProfileAutocomplete.lastProfileAutoCompleteFocusedInput) {
return;
}
let selectedIndex = ProfileAutocomplete._getSelectedIndex(e.target.ownerGlobal);
let selectedRowStyle = lastAutoCompleteResult.getStyleAt(selectedIndex);
- if (selectedRowStyle == "autofill-footer") {
- focusedInput.addEventListener("DOMAutoComplete", () => {
+ focusedInput.addEventListener("DOMAutoComplete", () => {
+ if (selectedRowStyle == "autofill-footer") {
Services.cpmm.sendAsyncMessage("FormAutofill:OpenPreferences");
- }, {once: true});
- }
+ } else if (selectedRowStyle == "autofill-clear-button") {
+ FormAutofillContent.clearForm();
+ }
+ }, {once: true});
},
};
FormAutofillContent.init();
--- a/browser/extensions/formautofill/FormAutofillHandler.jsm
+++ b/browser/extensions/formautofill/FormAutofillHandler.jsm
@@ -489,16 +489,40 @@ class FormAutofillSection {
continue;
}
this.changeFieldState(fieldDetail, FIELD_STATES.NORMAL);
}
}
/**
+ * Clear value and highlight style of all filled fields.
+ *
+ * @param {Object} focusedInput
+ * A focused input element for determining credit card or address fields.
+ */
+ clearPopulatedForm(focusedInput) {
+ let fieldDetails = this.getFieldDetailsByElement(focusedInput);
+ for (let fieldDetail of fieldDetails) {
+ let element = fieldDetail.elementWeakRef.get();
+ if (!element) {
+ log.warn(fieldDetail.fieldName, "is unreachable");
+ continue;
+ }
+
+ // Only reset value for input element.
+ if (fieldDetail.state == FIELD_STATES.AUTO_FILLED &&
+ element instanceof Ci.nsIDOMHTMLInputElement) {
+ element.setUserInput("");
+ }
+ this.changeFieldState(fieldDetail, FIELD_STATES.NORMAL);
+ }
+ }
+
+ /**
* Change the state of a field to correspond with different presentations.
*
* @param {Object} fieldDetail
* A fieldDetail of which its element is about to update the state.
* @param {string} nextState
* Used to determine the next state
*/
changeFieldState(fieldDetail, nextState) {
@@ -868,16 +892,21 @@ class FormAutofillHandler {
section.previewFormFields(profile, focusedInput);
}
clearPreviewedFormFields(focusedInput) {
let section = this.getSectionByElement(focusedInput);
section.clearPreviewedFormFields(focusedInput);
}
+ clearPopulatedForm(focusedInput) {
+ let section = this.getSectionByElement(focusedInput);
+ section.clearPopulatedForm(focusedInput);
+ }
+
getFilledRecordGUID(focusedInput) {
let section = this.getSectionByElement(focusedInput);
return section.getFilledRecordGUID(focusedInput);
}
getAdaptedProfiles(originalProfiles, focusedInput) {
let section = this.getSectionByElement(focusedInput);
section.getAdaptedProfiles(originalProfiles);
--- a/browser/extensions/formautofill/content/FormAutofillFrameScript.js
+++ b/browser/extensions/formautofill/content/FormAutofillFrameScript.js
@@ -40,16 +40,17 @@ var FormAutofillFrameScript = {
// form has been identified, and ready to open popup.
sendAsyncMessage("FormAutofill:FieldsIdentified");
});
},
init() {
addEventListener("focusin", this);
addMessageListener("FormAutofill:PreviewProfile", this);
+ addMessageListener("FormAutofill:ClearForm", this);
addMessageListener("FormAutoComplete:PopupClosed", this);
addMessageListener("FormAutoComplete:PopupOpened", this);
},
handleEvent(evt) {
if (!evt.isTrusted || !FormAutofillUtils.isAutofillEnabled) {
return;
}
@@ -83,23 +84,28 @@ var FormAutofillFrameScript = {
const doc = content.document;
const {chromeEventHandler} = doc.ownerGlobal.getInterface(Ci.nsIDocShell);
switch (message.name) {
case "FormAutofill:PreviewProfile": {
FormAutofillContent.previewProfile(doc);
break;
}
+ case "FormAutofill:ClearForm": {
+ FormAutofillContent.clearForm();
+ break;
+ }
case "FormAutoComplete:PopupClosed": {
FormAutofillContent.onPopupClosed();
chromeEventHandler.removeEventListener("keydown", FormAutofillContent._onKeyDown,
{capturing: true});
break;
}
case "FormAutoComplete:PopupOpened": {
chromeEventHandler.addEventListener("keydown", FormAutofillContent._onKeyDown,
{capturing: true});
+ break;
}
}
},
};
FormAutofillFrameScript.init();