diff --git a/toolkit/components/autocomplete/nsAutoCompleteController.cpp b/toolkit/components/autocomplete/nsAutoCompleteController.cpp index 64791fd756f1..aab27651fd06 100644 --- a/toolkit/components/autocomplete/nsAutoCompleteController.cpp +++ b/toolkit/components/autocomplete/nsAutoCompleteController.cpp @@ -1149,6 +1149,9 @@ nsresult nsAutoCompleteController::EnterMatch(bool aIsPopupSelection, bool forceComplete; input->GetForceComplete(&forceComplete); + int32_t selectedIndex; + popup->GetSelectedIndex(&selectedIndex); + // Ask the popup if it wants to enter a special value into the textbox nsAutoString value; popup->GetOverrideValue(value); @@ -1158,8 +1161,6 @@ nsresult nsAutoCompleteController::EnterMatch(bool aIsPopupSelection, bool completeSelection; input->GetCompleteSelectedIndex(&completeSelection); - int32_t selectedIndex; - popup->GetSelectedIndex(&selectedIndex); if (selectedIndex >= 0) { nsAutoString inputValue; input->GetTextValue(inputValue); @@ -1268,7 +1269,8 @@ nsresult nsAutoCompleteController::EnterMatch(bool aIsPopupSelection, ClosePopup(); bool cancel; - input->OnTextEntered(aEvent, &cancel); + bool itemWasSelected = selectedIndex >= 0; + input->OnTextEntered(aEvent, itemWasSelected, &cancel); return NS_OK; } diff --git a/toolkit/components/autocomplete/nsIAutoCompleteInput.idl b/toolkit/components/autocomplete/nsIAutoCompleteInput.idl index 2326ad137a09..eddc3baac7c5 100644 --- a/toolkit/components/autocomplete/nsIAutoCompleteInput.idl +++ b/toolkit/components/autocomplete/nsIAutoCompleteInput.idl @@ -137,9 +137,12 @@ interface nsIAutoCompleteInput : nsISupports * * @param aEvent * The event that triggered the enter. + * @param itemWasSelected + * A boolean value that indicates whether + * an item was selected from the autocomplete popup. * @return True if the user wishes to prevent the enter */ - boolean onTextEntered([optional] in Event aEvent); + boolean onTextEntered([optional] in Event aEvent, [optional] in boolean itemWasSelected); /* * Notification that the user cancelled the autocomplete session diff --git a/toolkit/components/passwordmgr/LoginManagerContent.jsm b/toolkit/components/passwordmgr/LoginManagerContent.jsm index a25b4db0e069..cd99ccb83f64 100644 --- a/toolkit/components/passwordmgr/LoginManagerContent.jsm +++ b/toolkit/components/passwordmgr/LoginManagerContent.jsm @@ -104,6 +104,14 @@ var observer = { } switch (aEvent.type) { + case "keydown": { + if (aEvent.keyCode == aEvent.DOM_VK_TAB || + aEvent.keyCode == aEvent.DOM_VK_RETURN) { + LoginManagerContent.onUsernameInput(aEvent); + } + break; + } + // Only used for username fields. case "focus": { LoginManagerContent._onUsernameFocus(aEvent); @@ -716,6 +724,8 @@ var LoginManagerContent = { if (LoginHelper.isUsernameFieldType(acInputField)) { this.onUsernameInput(event); + } else if (acInputField.hasBeenTypePassword) { + this._highlightFilledField(event.target); } }, @@ -1238,6 +1248,7 @@ var LoginManagerContent = { // warning, regardless of saved login. if (usernameField) { this._formFillService.markAsLoginManagerField(usernameField); + usernameField.addEventListener("keydown", observer); } // Nothing to do if we have no matching logins available. diff --git a/toolkit/components/passwordmgr/test/mochitest/test_autocomplete_highlight.html b/toolkit/components/passwordmgr/test/mochitest/test_autocomplete_highlight.html index 8514e2b4170c..9586a2861416 100644 --- a/toolkit/components/passwordmgr/test/mochitest/test_autocomplete_highlight.html +++ b/toolkit/components/passwordmgr/test/mochitest/test_autocomplete_highlight.html @@ -69,8 +69,8 @@ add_task(async function test_field_highlight_on_autocomplete() { "Highlight was successfully applied to the password field on username autocomplete"); // Clear existing highlight on login fields. We check by pressing the tab key after backspace - // (by shifting focus to the next element) because the tab key is known to cause a bug where the - // highlight is applied once again. + // (by shifting focus to the next element) because the tab key was known to cause a bug where the + // highlight is applied once again. See Bug 1526522. username.focus(); synthesizeKey("KEY_Backspace"); synthesizeKey("KEY_Tab"); @@ -81,6 +81,31 @@ add_task(async function test_field_highlight_on_autocomplete() { synthesizeKey("KEY_Tab"); is(document.defaultView.getComputedStyle(password).getPropertyValue("filter"), "none", "Highlight was successfully removed on the password field"); + + // Clear login fields. + username.value = ""; + password.value = ""; + + // Test password field autocomplete. + password.focus(); + shownPromise = promiseACShown(); + synthesizeKey("KEY_ArrowDown"); + await shownPromise; + synthesizeKey("KEY_ArrowDown"); + synthesizeKey("KEY_Enter"); + + await ContentTaskUtils.waitForCondition(() => { + return document.defaultView.getComputedStyle(password).getPropertyValue("filter") !== "none"; + }, "Highlight was successfully applied to the password field on password autocomplete"); + + // Clear existing highlight on the password field. We check by pressing the tab key after backspace + // (by shifting focus to the next element) because the tab key was known to cause a bug where the + // highlight is applied once again. See Bug 1526522. + synthesizeKey("KEY_Backspace"); + synthesizeKey("KEY_Tab"); + + is(document.defaultView.getComputedStyle(password).getPropertyValue("filter"), "none", + "Highlight was successfully removed on the password field"); }); diff --git a/toolkit/components/satchel/nsFormFillController.cpp b/toolkit/components/satchel/nsFormFillController.cpp index 146754d9189f..900c880b7d68 100644 --- a/toolkit/components/satchel/nsFormFillController.cpp +++ b/toolkit/components/satchel/nsFormFillController.cpp @@ -592,9 +592,21 @@ NS_IMETHODIMP nsFormFillController::OnSearchComplete() { return NS_OK; } NS_IMETHODIMP -nsFormFillController::OnTextEntered(Event* aEvent, bool* aPrevent) { +nsFormFillController::OnTextEntered(Event* aEvent, bool itemWasSelected, + bool* aPrevent) { NS_ENSURE_ARG(aPrevent); NS_ENSURE_TRUE(mFocusedInput, NS_OK); + + /** + * This function can get called when text wasn't actually entered + * into the field (e.g. if an autocomplete item wasn't selected) so + * we don't fire DOMAutoComplete in that case since nothing + * was actually autocompleted. + */ + if (!itemWasSelected) { + return NS_OK; + } + // Fire off a DOMAutoComplete event IgnoredErrorResult ignored;