--- a/browser/extensions/formautofill/FormAutofillContent.jsm
+++ b/browser/extensions/formautofill/FormAutofillContent.jsm
@@ -103,78 +103,77 @@ AutofillProfileAutoCompleteSearch.protot
let isAddressField = FormAutofillUtils.isAddressField(activeFieldDetail.fieldName);
let isInputAutofilled = activeFieldDetail.state == FIELD_STATES.AUTO_FILLED;
let allFieldNames = activeSection.allFieldNames;
let filledRecordGUID = activeSection.filledRecordGUID;
let searchPermitted = isAddressField ?
FormAutofillUtils.isAutofillAddressesEnabled :
FormAutofillUtils.isAutofillCreditCardsEnabled;
let AutocompleteResult = isAddressField ? AddressResult : CreditCardResult;
+ let pendingSearchResult = null;
ProfileAutocomplete.lastProfileAutoCompleteFocusedInput = activeInput;
// Fallback to form-history if ...
// - specified autofill feature is pref off.
// - no profile can fill the currently-focused input.
// - the current form has already been populated.
// - (address only) less than 3 inputs are covered by all saved fields in the storage.
if (!searchPermitted || !savedFieldNames.has(activeFieldDetail.fieldName) ||
(!isInputAutofilled && filledRecordGUID) || (isAddressField &&
allFieldNames.filter(field => savedFieldNames.has(field)).length < FormAutofillUtils.AUTOFILL_FIELDS_THRESHOLD)) {
if (activeInput.autocomplete == "off") {
// Create a dummy result as an empty search result.
- let result = new AutocompleteResult("", "", [], [], {});
- listener.onSearchResult(this, result);
- return;
+ pendingSearchResult = new AutocompleteResult("", "", [], [], {});
+ } else {
+ pendingSearchResult = new Promise(resolve => {
+ let formHistory = Cc["@mozilla.org/autocomplete/search;1?name=form-history"]
+ .createInstance(Ci.nsIAutoCompleteSearch);
+ formHistory.startSearch(searchString, searchParam, previousResult, {
+ onSearchResult: (_, result) => resolve(result),
+ });
+ });
}
- let formHistory = Cc["@mozilla.org/autocomplete/search;1?name=form-history"]
- .createInstance(Ci.nsIAutoCompleteSearch);
- formHistory.startSearch(searchString, searchParam, previousResult, {
- onSearchResult: (search, result) => {
- listener.onSearchResult(this, result);
- ProfileAutocomplete.lastProfileAutoCompleteResult = result;
- },
- });
- return;
- }
-
- if (isInputAutofilled) {
- let result = new AutocompleteResult(searchString, "", [], [], {isInputAutofilled});
- listener.onSearchResult(this, result);
- ProfileAutocomplete.lastProfileAutoCompleteResult = result;
- return;
- }
+ } else if (isInputAutofilled) {
+ pendingSearchResult = new AutocompleteResult(searchString, "", [], [], {isInputAutofilled});
+ } else {
+ let infoWithoutElement = {...activeFieldDetail};
+ delete infoWithoutElement.elementWeakRef;
- let infoWithoutElement = Object.assign({}, activeFieldDetail);
- delete infoWithoutElement.elementWeakRef;
-
- let data = {
- collectionName: isAddressField ? ADDRESSES_COLLECTION_NAME : CREDITCARDS_COLLECTION_NAME,
- info: infoWithoutElement,
- searchString,
- };
+ let data = {
+ collectionName: isAddressField ? ADDRESSES_COLLECTION_NAME : CREDITCARDS_COLLECTION_NAME,
+ info: infoWithoutElement,
+ searchString,
+ };
- this._getRecords(data).then((records) => {
- if (this.forceStop) {
- return;
- }
- // Sort addresses by timeLastUsed for showing the lastest used address at top.
- records.sort((a, b) => b.timeLastUsed - a.timeLastUsed);
+ pendingSearchResult = this._getRecords(data).then((records) => {
+ if (this.forceStop) {
+ return null;
+ }
+ // Sort addresses by timeLastUsed for showing the lastest used address at top.
+ records.sort((a, b) => b.timeLastUsed - a.timeLastUsed);
- let adaptedRecords = activeSection.getAdaptedProfiles(records);
- let result = null;
- let handler = FormAutofillContent.activeHandler;
- let isSecure = InsecurePasswordUtils.isFormSecure(handler.form);
+ let adaptedRecords = activeSection.getAdaptedProfiles(records);
+ let handler = FormAutofillContent.activeHandler;
+ let isSecure = InsecurePasswordUtils.isFormSecure(handler.form);
- result = new AutocompleteResult(searchString,
+ return new AutocompleteResult(searchString,
activeFieldDetail.fieldName,
allFieldNames,
adaptedRecords,
{isSecure, isInputAutofilled});
+ });
+ }
+
+ Promise.resolve(pendingSearchResult).then((result) => {
listener.onSearchResult(this, result);
ProfileAutocomplete.lastProfileAutoCompleteResult = result;
+ // Reset AutoCompleteController's state at the end of startSearch to ensure that
+ // none of form autofill result will be cached in other places and make the
+ // result out of sync.
+ autocompleteController.resetInternalState();
});
},
/**
* Stops an asynchronous search that is in progress
*/
stopSearch() {
ProfileAutocomplete.lastProfileAutoCompleteResult = null;
@@ -288,21 +287,18 @@ let ProfileAutocomplete = {
let selectedIndex = this._getSelectedIndex(focusedInput.ownerGlobal);
if (selectedIndex == -1 ||
!this.lastProfileAutoCompleteResult ||
this.lastProfileAutoCompleteResult.getStyleAt(selectedIndex) != "autofill-profile") {
return;
}
let profile = JSON.parse(this.lastProfileAutoCompleteResult.getCommentAt(selectedIndex));
- let {fieldName} = FormAutofillContent.activeFieldDetail;
- FormAutofillContent.activeHandler.autofillFormFields(profile).then(() => {
- autocompleteController.searchString = profile[fieldName];
- });
+ FormAutofillContent.activeHandler.autofillFormFields(profile);
},
_clearProfilePreview() {
if (!this.lastProfileAutoCompleteFocusedInput || !FormAutofillContent.activeSection) {
return;
}
FormAutofillContent.activeSection.clearPreviewedFormFields();
@@ -560,17 +556,16 @@ var FormAutofillContent = {
clearForm() {
let focusedInput = this.activeInput || ProfileAutocomplete._lastAutoCompleteFocusedInput;
if (!focusedInput) {
return;
}
this.activeSection.clearPopulatedForm();
- autocompleteController.searchString = "";
},
previewProfile(doc) {
let docWin = doc.ownerGlobal;
let selectedIndex = ProfileAutocomplete._getSelectedIndex(docWin);
let lastAutoCompleteResult = ProfileAutocomplete.lastProfileAutoCompleteResult;
let focusedInput = this.activeInput;
let mm = this._messageManagerFromWindow(docWin);