commit 7327b348bc17d738ef574344d23b9098a3188d83
parent 7a28250b0fb54e67b44de756b226faaf69223494
Author: Cristian Tuns <ctuns@mozilla.com>
Date: Mon, 27 Oct 2025 04:50:52 -0400
Revert "Bug 1767228 - Add showPicker Support for Input with Data List. r=emilio,credential-management-reviewers,dimi" for causing mochitest failures in test_input_text_show_picker.html
This reverts commit 5d7a4cf9ed9c80f1ba4a3b846fd9661fd7d1cd14.
Revert "Bug 1767228 - Refactor: Rename nsFormFillController focusedElement to controlledElement. r=emilio,credential-management-reviewers,dimi"
This reverts commit 427097407647f4af6fb5526a802e6cd6273d665d.
Diffstat:
12 files changed, 94 insertions(+), 207 deletions(-)
diff --git a/browser/extensions/formautofill/test/browser/browser_cancel_attribute_change_task.js b/browser/extensions/formautofill/test/browser/browser_cancel_attribute_change_task.js
@@ -58,7 +58,7 @@ add_task(
"@mozilla.org/satchel/form-fill-controller;1"
].getService(Ci.nsIFormFillController);
Assert.equal(
- formFillController.controlledElement?.id,
+ formFillController.focusedElement?.id,
"address-level1",
"formFillController has correct focusedInput"
);
diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp
@@ -65,7 +65,6 @@
#include "nsIEditor.h"
#include "nsIFilePicker.h"
#include "nsIFormControl.h"
-#include "nsIFormFillController.h"
#include "nsIFrame.h"
#include "nsIMutationObserver.h"
#include "nsIPromptCollection.h"
@@ -5900,7 +5899,7 @@ void HTMLInputElement::ShowPicker(ErrorResult& aRv) {
// InitFilePicker() and InitColorPicker() consume it themselves,
// so only consume in this function if not those.
- // Step 5. If element's type attribute is in the File Upload state, then run
+ // Step 4. If element's type attribute is in the File Upload state, then run
// these steps in parallel:
if (mType == FormControlType::InputFile) {
FilePickerType type = FILE_PICKER_FILE;
@@ -5912,11 +5911,9 @@ void HTMLInputElement::ShowPicker(ErrorResult& aRv) {
return;
}
- // Step 6. Otherwise, the user agent should show any relevant user interface
+ // Step 5. Otherwise, the user agent should show any relevant user interface
// for selecting a value for element, in the way it normally would when the
// user interacts with the control
-
- // Step 6 for color
if (mType == FormControlType::InputColor) {
InitColorPicker();
return;
@@ -5929,7 +5926,6 @@ void HTMLInputElement::ShowPicker(ErrorResult& aRv) {
return;
}
- // Step 6 for date and time types
if (IsDateTimeTypeSupported(mType)) {
if (CreatesDateTimeWidget()) {
if (RefPtr<Element> dateTimeBoxElement = GetDateTimeBoxElement()) {
@@ -5944,18 +5940,6 @@ void HTMLInputElement::ShowPicker(ErrorResult& aRv) {
GetDateTimeInputBoxValue(value);
OpenDateTimePicker(value);
}
- return;
- }
-
- // Step 6 for input elements with a suggestions source element.
- // I.e. show the autocomplete dropdown based on the list attribute.
- // XXX Form-fill support on android is bug 1535985.
- if (IsSingleLineTextControl(true) && GetList()) {
- if (nsCOMPtr<nsIFormFillController> controller =
- do_GetService("@mozilla.org/satchel/form-fill-controller;1")) {
- controller->SetControlledElement(this);
- controller->ShowPopup();
- }
}
}
diff --git a/dom/html/HTMLInputElement.h b/dom/html/HTMLInputElement.h
@@ -720,7 +720,7 @@ class HTMLInputElement final : public TextControlElement,
SelectionMode aSelectMode,
ErrorResult& aRv);
- MOZ_CAN_RUN_SCRIPT void ShowPicker(ErrorResult& aRv);
+ void ShowPicker(ErrorResult& aRv);
bool WebkitDirectoryAttr() const {
return HasAttr(nsGkAtoms::webkitdirectory);
diff --git a/dom/html/test/forms/mochitest.toml b/dom/html/test/forms/mochitest.toml
@@ -135,9 +135,6 @@ skip-if = ["os == 'mac' && os_version == '10.15' && processor == 'x86_64' && deb
["test_input_setting_value.html"]
-["test_input_text_show_picker.html"]
-skip-if = ["os == 'android'"] # Bug 1535985
-
["test_input_textarea_set_value_no_scroll.html"]
["test_input_time_key_events.html"]
diff --git a/dom/html/test/forms/test_input_text_show_picker.html b/dom/html/test/forms/test_input_text_show_picker.html
@@ -1,56 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
- <meta charset="utf-8">
- <title>input.showPicker() with datalist shows the autocomplete popup</title>
- <script src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
- <script>
- const controller = SpecialPowers.Cc["@mozilla.org/autocomplete/controller;1"].getService(
- SpecialPowers.Ci.nsIAutoCompleteController
- );
-
- async function testWithInputType(aType) {
- const inp = document.querySelector("input");
- inp.type = aType;
-
- ok(!controller.input?.popupOpen, `Initially no input popup`);
-
- SpecialPowers.wrap(document).notifyUserGestureActivation();
- inp.showPicker();
-
- await SimpleTest.promiseWaitForCondition(
- () => controller.input?.popupOpen,
- `input[type=${aType}] popup was not opened`
- );
- ok(controller.input?.popupOpen, `input[type=${aType}] popup open`);
-
- inp.type = "date";
- await SimpleTest.promiseWaitForCondition(
- () => !controller.input?.popupOpen,
- `input[type=${aType}] popup was closed`
- );
- }
-
- SimpleTest.waitForExplicitFinish();
- window.onload = async function() {
- for (const type of ["text", "search", "email", "url", "tel", "number"]) {
- await testWithInputType(type);
- }
- SimpleTest.finish();
- };
- </script>
-</head>
-<body>
-<p id="display"></p>
-<div id="content" style="display: none"></div>
-<pre id="test"></pre>
-
-<input list="id-list" />
-<datalist id="id-list">
- <option value="Chocolate"></option>
- <option value="Coconut"></option>
-</datalist>
-
-</body>
-</html>
diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/show-picker-does-not-focus.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/show-picker-does-not-focus.html
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<title>Test showPicker() does not focus the element</title>
-<meta name="timeout" content="long">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/resources/testdriver.js"></script>
-<script src="/resources/testdriver-vendor.js"></script>
-
-<body>
-<script type=module>
-import inputTypes from "./input-types.js";
-
-function createElement(t, type) {
- const input = document.createElement("input");
- input.type = type;
- document.body.append(input);
- t.add_cleanup(() => input.remove());
- return input;
-}
-
-for (const inputType of inputTypes) {
- promise_test(async (t) => {
- const input = createElement(t, inputType);
- await test_driver.bless('show picker');
- input.showPicker();
- assert_not_equals(input, document.activeElement, "Input element was not focused");
- }, `input[type=${inputType}].showPicker() does not focus the element`);
-}
-</script>
diff --git a/toolkit/components/formautofill/FormAutofillChild.sys.mjs b/toolkit/components/formautofill/FormAutofillChild.sys.mjs
@@ -138,7 +138,7 @@ export class FormAutofillChild extends JSWindowActorChild {
this.#markAsAutofillField(fieldDetail);
if (
- fieldDetail.element == lazy.FormAutofillContent.controlledElement &&
+ fieldDetail.element == lazy.FormAutofillContent.focusedElement &&
!isUpdate
) {
this.showPopupIfEmpty(fieldDetail.element, fieldDetail.fieldName);
@@ -494,7 +494,7 @@ export class FormAutofillChild extends JSWindowActorChild {
this._hasDOMContentLoadedHandler = true;
doc.addEventListener(
"DOMContentLoaded",
- () => this.onFocusIn(lazy.FormAutofillContent.controlledElement),
+ () => this.onFocusIn(lazy.FormAutofillContent.focusedElement),
{ once: true }
);
}
diff --git a/toolkit/components/formautofill/FormAutofillContent.sys.mjs b/toolkit/components/formautofill/FormAutofillContent.sys.mjs
@@ -30,8 +30,8 @@ export var FormAutofillContent = {
return Services.cpmm.sharedData.get("FormAutofill:savedFieldNames");
},
- get controlledElement() {
- return formFillController.controlledElement;
+ get focusedElement() {
+ return formFillController.focusedElement;
},
/**
diff --git a/toolkit/components/passwordmgr/LoginManagerChild.sys.mjs b/toolkit/components/passwordmgr/LoginManagerChild.sys.mjs
@@ -1401,19 +1401,19 @@ export class LoginManagerChild extends JSWindowActorChild {
break;
}
case "PasswordManager:OnFieldAutoComplete": {
- const { controlledElement } = lazy.gFormFillService;
+ const { focusedElement } = lazy.gFormFillService;
const login = lazy.LoginHelper.vanillaObjectToLogin(msg.data);
- this.onFieldAutoComplete(controlledElement, login);
+ this.onFieldAutoComplete(focusedElement, login);
break;
}
case "PasswordManager:FillGeneratedPassword": {
- const { controlledElement } = lazy.gFormFillService;
- this.filledWithGeneratedPassword(controlledElement);
+ const { focusedElement } = lazy.gFormFillService;
+ this.filledWithGeneratedPassword(focusedElement);
break;
}
case "PasswordManager:FillRelayUsername": {
- const { controlledElement } = lazy.gFormFillService;
- this.fillRelayUsername(controlledElement, msg.data);
+ const { focusedElement } = lazy.gFormFillService;
+ this.fillRelayUsername(focusedElement, msg.data);
break;
}
}
@@ -1428,7 +1428,7 @@ export class LoginManagerChild extends JSWindowActorChild {
return;
}
- if (inputElement != lazy.gFormFillService.controlledElement) {
+ if (inputElement != lazy.gFormFillService.focusedElement) {
lazy.log("Could not open popup on input that's no longer focused.");
return;
}
@@ -3090,9 +3090,9 @@ export class LoginManagerChild extends JSWindowActorChild {
Glean.pwmgr.formAutofillResult[autofillResult].add(1);
if (usernameField) {
- let controlledElement = lazy.gFormFillService.controlledElement;
+ let focusedElement = lazy.gFormFillService.focusedElement;
if (
- usernameField == controlledElement &&
+ usernameField == focusedElement &&
![
AUTOFILL_RESULT.FILLED,
AUTOFILL_RESULT.FILLED_USERNAME_ONLY_FORM,
diff --git a/toolkit/components/satchel/nsFormFillController.cpp b/toolkit/components/satchel/nsFormFillController.cpp
@@ -67,7 +67,7 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFormFillController)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFormFillController)
nsFormFillController::nsFormFillController()
- : mControlledElement(nullptr),
+ : mFocusedElement(nullptr),
mRestartAfterAttributeChangeTask(nullptr),
mListNode(nullptr),
// The amount of time a context menu event supresses showing a
@@ -99,9 +99,9 @@ nsFormFillController::~nsFormFillController() {
mListNode->RemoveMutationObserver(this);
mListNode = nullptr;
}
- if (mControlledElement) {
- MaybeRemoveMutationObserver(mControlledElement);
- mControlledElement = nullptr;
+ if (mFocusedElement) {
+ MaybeRemoveMutationObserver(mFocusedElement);
+ mFocusedElement = nullptr;
}
RemoveForDocument(nullptr);
}
@@ -128,7 +128,7 @@ void nsFormFillController::AttributeChanged(mozilla::dom::Element* aElement,
if ((aAttribute == nsGkAtoms::type || aAttribute == nsGkAtoms::readonly ||
aAttribute == nsGkAtoms::autocomplete) &&
aNameSpaceID == kNameSpaceID_None) {
- RefPtr<Element> controlledElement(mControlledElement);
+ RefPtr<Element> focusedElement(mFocusedElement);
// Reset the current state of the controller, unconditionally.
StopControllingInput();
// Then restart based on the new values. We have to delay this
@@ -141,7 +141,7 @@ void nsFormFillController::AttributeChanged(mozilla::dom::Element* aElement,
mozilla::NewCancelableRunnableMethod<RefPtr<Element>>(
"nsFormFillController::MaybeStartControllingInput", this,
&nsFormFillController::MaybeStartControllingInputScheduled,
- controlledElement);
+ focusedElement);
RefPtr<Runnable> addrefedRunnable = mRestartAfterAttributeChangeTask;
aElement->OwnerDoc()->Dispatch(addrefedRunnable.forget());
}
@@ -217,8 +217,8 @@ void nsFormFillController::NodeWillBeDestroyed(nsINode* aNode) {
if (aNode == mListNode) {
mListNode = nullptr;
RevalidateDataList();
- } else if (aNode == mControlledElement) {
- mControlledElement = nullptr;
+ } else if (aNode == mFocusedElement) {
+ mFocusedElement = nullptr;
}
}
@@ -258,7 +258,7 @@ nsFormFillController::MarkAsAutoCompletableField(Element* aElement) {
EnablePreview(aElement);
if (nsFocusManager::GetFocusedElementStatic() == aElement) {
- if (!mControlledElement) {
+ if (!mFocusedElement) {
MaybeStartControllingInput(aElement);
} else {
// See `MarkAsLoginManagerField` for why this is needed.
@@ -271,29 +271,8 @@ nsFormFillController::MarkAsAutoCompletableField(Element* aElement) {
}
NS_IMETHODIMP
-nsFormFillController::SetControlledElement(Element* aElement) {
- if (!aElement ||
- !aElement->IsAnyOfHTMLElements(nsGkAtoms::input, nsGkAtoms::textarea)) {
- return NS_OK;
- }
-
- MaybeStartControllingInput(aElement);
-
- // Bail if we didn't start controlling the input.
- if (!mControlledElement) {
- return NS_OK;
- }
-
- // if there is a delayed task to restart the controller after an attribute
- // change, cancel it to prevent it overriding the controlled input
- MaybeCancelAttributeChangeTask();
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFormFillController::GetControlledElement(Element** aElement) {
- *aElement = mControlledElement;
+nsFormFillController::GetFocusedElement(Element** aElement) {
+ *aElement = mFocusedElement;
NS_IF_ADDREF(*aElement);
return NS_OK;
}
@@ -335,9 +314,9 @@ nsFormFillController::SetPopupOpen(bool aPopupOpen) {
if (mFocusedPopup) {
if (aPopupOpen) {
// make sure input field is visible before showing popup (bug 320938)
- nsCOMPtr<nsIContent> content = mControlledElement;
+ nsCOMPtr<nsIContent> content = mFocusedElement;
NS_ENSURE_STATE(content);
- nsCOMPtr<nsIDocShell> docShell = GetDocShellForInput(mControlledElement);
+ nsCOMPtr<nsIDocShell> docShell = GetDocShellForInput(mFocusedElement);
NS_ENSURE_STATE(docShell);
RefPtr<PresShell> presShell = docShell->GetPresShell();
NS_ENSURE_STATE(presShell);
@@ -349,7 +328,7 @@ nsFormFillController::SetPopupOpen(bool aPopupOpen) {
// mFocusedPopup can be destroyed after ScrollContentIntoView, see bug
// 420089
if (mFocusedPopup) {
- mFocusedPopup->OpenAutocompletePopup(this, mControlledElement);
+ mFocusedPopup->OpenAutocompletePopup(this, mFocusedElement);
}
} else {
mFocusedPopup->ClosePopup();
@@ -449,17 +428,17 @@ nsFormFillController::SetSearchParam(const nsAString& aSearchParam) {
NS_IMETHODIMP
nsFormFillController::GetSearchParam(nsAString& aSearchParam) {
- if (!mControlledElement) {
+ if (!mFocusedElement) {
NS_WARNING(
- "mControlledElement is null for some reason! avoiding a crash. should "
+ "mFocusedElement is null for some reason! avoiding a crash. should "
"find "
"out why... - ben");
return NS_ERROR_FAILURE; // XXX why? fix me.
}
- GetName(mControlledElement, aSearchParam);
+ GetName(mFocusedElement, aSearchParam);
if (aSearchParam.IsEmpty()) {
- mControlledElement->GetId(aSearchParam);
+ mFocusedElement->GetId(aSearchParam);
}
return NS_OK;
@@ -487,8 +466,8 @@ nsFormFillController::GetSearchAt(uint32_t index, nsACString& _retval) {
NS_IMETHODIMP
nsFormFillController::GetTextValue(nsAString& aTextValue) {
- if (mControlledElement) {
- GetValue(mControlledElement, aTextValue);
+ if (mFocusedElement) {
+ GetValue(mFocusedElement, aTextValue);
} else {
aTextValue.Truncate();
}
@@ -497,9 +476,9 @@ nsFormFillController::GetTextValue(nsAString& aTextValue) {
NS_IMETHODIMP
nsFormFillController::SetTextValue(const nsAString& aTextValue) {
- if (mControlledElement) {
+ if (mFocusedElement) {
mSuppressOnInput = true;
- SetUserInput(mControlledElement, aTextValue,
+ SetUserInput(mFocusedElement, aTextValue,
*nsContentUtils::GetSystemPrincipal());
mSuppressOnInput = false;
}
@@ -509,32 +488,32 @@ nsFormFillController::SetTextValue(const nsAString& aTextValue) {
NS_IMETHODIMP
nsFormFillController::GetSelectionStart(int32_t* aSelectionStart) {
- if (!mControlledElement) {
+ if (!mFocusedElement) {
return NS_ERROR_UNEXPECTED;
}
ErrorResult rv;
- *aSelectionStart = GetSelectionStartInternal(mControlledElement, rv);
+ *aSelectionStart = GetSelectionStartInternal(mFocusedElement, rv);
return rv.StealNSResult();
}
NS_IMETHODIMP
nsFormFillController::GetSelectionEnd(int32_t* aSelectionEnd) {
- if (!mControlledElement) {
+ if (!mFocusedElement) {
return NS_ERROR_UNEXPECTED;
}
ErrorResult rv;
- *aSelectionEnd = GetSelectionEndInternal(mControlledElement, rv);
+ *aSelectionEnd = GetSelectionEndInternal(mFocusedElement, rv);
return rv.StealNSResult();
}
MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMP
nsFormFillController::SelectTextRange(int32_t aStartIndex, int32_t aEndIndex) {
- if (!mControlledElement) {
+ if (!mFocusedElement) {
return NS_ERROR_UNEXPECTED;
}
- RefPtr<Element> controlledElement(mControlledElement);
+ RefPtr<Element> focusedInput(mFocusedElement);
ErrorResult rv;
- SetSelectionRange(controlledElement, aStartIndex, aEndIndex, rv);
+ SetSelectionRange(focusedInput, aStartIndex, aEndIndex, rv);
return rv.StealNSResult();
}
@@ -546,7 +525,7 @@ nsFormFillController::OnSearchComplete() { return NS_OK; }
NS_IMETHODIMP
nsFormFillController::OnTextEntered(Event* aEvent) {
- NS_ENSURE_TRUE(mControlledElement, NS_OK);
+ NS_ENSURE_TRUE(mFocusedElement, NS_OK);
return NS_OK;
}
@@ -564,12 +543,12 @@ nsFormFillController::GetConsumeRollupEvent(bool* aConsumeRollupEvent) {
NS_IMETHODIMP
nsFormFillController::GetInPrivateContext(bool* aInPrivateContext) {
- if (!mControlledElement) {
+ if (!mFocusedElement) {
*aInPrivateContext = false;
return NS_OK;
}
- RefPtr<Document> doc = mControlledElement->OwnerDoc();
+ RefPtr<Document> doc = mFocusedElement->OwnerDoc();
nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
*aInPrivateContext = loadContext && loadContext->UsePrivateBrowsing();
return NS_OK;
@@ -583,8 +562,8 @@ nsFormFillController::GetNoRollupOnCaretMove(bool* aNoRollupOnCaretMove) {
NS_IMETHODIMP
nsFormFillController::GetNoRollupOnEmptySearch(bool* aNoRollupOnEmptySearch) {
- if (mControlledElement && mFocusedPopup) {
- return mFocusedPopup->GetNoRollupOnEmptySearch(mControlledElement,
+ if (mFocusedElement && mFocusedPopup) {
+ return mFocusedPopup->GetNoRollupOnEmptySearch(mFocusedElement,
aNoRollupOnEmptySearch);
}
@@ -613,37 +592,36 @@ nsFormFillController::StartSearch(const nsAString& aSearchString,
const nsAString& aSearchParam,
nsIAutoCompleteResult* aPreviousResult,
nsIAutoCompleteObserver* aListener) {
- MOZ_LOG(sLogger, LogLevel::Debug, ("StartSearch for %p", mControlledElement));
+ MOZ_LOG(sLogger, LogLevel::Debug, ("StartSearch for %p", mFocusedElement));
mLastListener = aListener;
- if (mControlledElement && mFocusedPopup) {
- if (mAutoCompleteInputs.Get(mControlledElement) ||
- HasBeenTypePassword(mControlledElement)) {
+ if (mFocusedElement && mFocusedPopup) {
+ if (mAutoCompleteInputs.Get(mFocusedElement) ||
+ HasBeenTypePassword(mFocusedElement)) {
MOZ_LOG(sLogger, LogLevel::Debug,
("StartSearch: formautofill or login field"));
- return mFocusedPopup->StartSearch(aSearchString, mControlledElement,
- this);
+ return mFocusedPopup->StartSearch(aSearchString, mFocusedElement, this);
}
}
MOZ_LOG(sLogger, LogLevel::Debug, ("StartSearch: form history field"));
- bool addDataList = IsTextControl(mControlledElement);
+ bool addDataList = IsTextControl(mFocusedElement);
if (addDataList) {
MaybeObserveDataListMutations();
}
- return mFocusedPopup->StartSearch(aSearchString, mControlledElement, this);
+ return mFocusedPopup->StartSearch(aSearchString, mFocusedElement, this);
}
void nsFormFillController::MaybeObserveDataListMutations() {
- // If an <input> is controlled, check if it has a list="<datalist>" which can
+ // If an <input> is focused, check if it has a list="<datalist>" which can
// provide the list of suggestions.
- if (mControlledElement) {
- Element* list = GetList(mControlledElement);
+ if (mFocusedElement) {
+ Element* list = GetList(mFocusedElement);
// Add a mutation observer to check for changes to the items in the
// <datalist> and update the suggestions accordingly.
@@ -770,7 +748,7 @@ nsFormFillController::HandleEvent(Event* aEvent) {
return NS_OK;
}
case eBlur:
- if (mControlledElement && !StaticPrefs::ui_popup_disable_autohide()) {
+ if (mFocusedElement && !StaticPrefs::ui_popup_disable_autohide()) {
StopControllingInput();
}
return NS_OK;
@@ -799,7 +777,7 @@ nsFormFillController::HandleEvent(Event* aEvent) {
return NS_OK;
}
- if (mControlledElement && doc == mControlledElement->OwnerDoc()) {
+ if (mFocusedElement && doc == mFocusedElement->OwnerDoc()) {
StopControllingInput();
}
@@ -846,9 +824,9 @@ void nsFormFillController::RemoveForDocument(Document* aDoc) {
for (auto iter = mAutoCompleteInputs.Iter(); !iter.Done(); iter.Next()) {
const nsINode* key = iter.Key();
if (key && (!aDoc || key->OwnerDoc() == aDoc)) {
- // mControlledElement's observer is tracked separately, so don't remove it
+ // mFocusedElement's observer is tracked separately, so don't remove it
// here.
- if (key != mControlledElement) {
+ if (key != mFocusedElement) {
const_cast<nsINode*>(key)->RemoveMutationObserver(this);
}
iter.Remove();
@@ -885,7 +863,21 @@ void nsFormFillController::MaybeStartControllingInput(Element* aElement) {
}
nsresult nsFormFillController::HandleFocus(Element* aElement) {
- MOZ_TRY(SetControlledElement(aElement));
+ if (!aElement ||
+ !aElement->IsAnyOfHTMLElements(nsGkAtoms::input, nsGkAtoms::textarea)) {
+ return NS_OK;
+ }
+
+ MaybeStartControllingInput(aElement);
+
+ // Bail if we didn't start controlling the input.
+ if (!mFocusedElement) {
+ return NS_OK;
+ }
+
+ // if there is a delayed task to restart the controller after an attribute
+ // change, cancel it to prevent it overriding the focused input
+ MaybeCancelAttributeChangeTask();
// If this focus doesn't follow a right click within our specified
// threshold then show the autocomplete popup for all password fields.
@@ -895,7 +887,7 @@ nsresult nsFormFillController::HandleFocus(Element* aElement) {
// multiple input forms and the fact that a mousedown into an already focused
// field does not trigger another focus.
- if (!HasBeenTypePassword(mControlledElement)) {
+ if (!HasBeenTypePassword(mFocusedElement)) {
return NS_OK;
}
@@ -983,8 +975,8 @@ nsresult nsFormFillController::KeyDown(Event* aEvent) {
// Get the writing-mode of the relevant input element,
// so that we can remap arrow keys if necessary.
mozilla::WritingMode wm;
- if (mControlledElement) {
- nsIFrame* frame = mControlledElement->GetPrimaryFrame();
+ if (mFocusedElement) {
+ nsIFrame* frame = mFocusedElement->GetPrimaryFrame();
if (frame) {
wm = frame->GetWritingMode();
}
@@ -1128,22 +1120,21 @@ void nsFormFillController::StartControllingInput(Element* aElement) {
mFocusedPopup = popup;
aElement->AddMutationObserverUnlessExists(this);
- mControlledElement = aElement;
+ mFocusedElement = aElement;
- if (Element* list = GetList(mControlledElement)) {
+ if (Element* list = GetList(mFocusedElement)) {
list->AddMutationObserverUnlessExists(this);
mListNode = list;
}
- if (!ReadOnly(mControlledElement)) {
+ if (!ReadOnly(mFocusedElement)) {
nsCOMPtr<nsIAutoCompleteController> controller = mController;
controller->SetInput(this);
}
}
bool nsFormFillController::IsFocusedInputControlled() const {
- return mControlledElement && mController && !ReadOnly(mControlledElement) &&
- nsFocusManager::GetFocusedElementStatic() == mControlledElement;
+ return mFocusedElement && mController && !ReadOnly(mFocusedElement);
}
void nsFormFillController::StopControllingInput() {
@@ -1168,10 +1159,10 @@ void nsFormFillController::StopControllingInput() {
}
MOZ_LOG(sLogger, LogLevel::Verbose,
- ("StopControllingInput: Stopped controlling %p", mControlledElement));
- if (mControlledElement) {
- MaybeRemoveMutationObserver(mControlledElement);
- mControlledElement = nullptr;
+ ("StopControllingInput: Stopped controlling %p", mFocusedElement));
+ if (mFocusedElement) {
+ MaybeRemoveMutationObserver(mFocusedElement);
+ mFocusedElement = nullptr;
}
if (mFocusedPopup) {
diff --git a/toolkit/components/satchel/nsFormFillController.h b/toolkit/components/satchel/nsFormFillController.h
@@ -72,7 +72,7 @@ class nsFormFillController final : public nsIFormFillController,
bool IsFocusedInputControlled() const;
MOZ_CAN_RUN_SCRIPT
- nsresult HandleFocus(mozilla::dom::Element* aElement);
+ nsresult HandleFocus(mozilla::dom::Element* aInput);
void AttachListeners(mozilla::dom::EventTarget* aEventTarget);
@@ -110,7 +110,7 @@ class nsFormFillController final : public nsIFormFillController,
// members //////////////////////////////////////////
nsCOMPtr<nsIAutoCompleteController> mController;
- mozilla::dom::Element* mControlledElement;
+ mozilla::dom::Element* mFocusedElement;
RefPtr<mozilla::CancelableRunnable> mRestartAfterAttributeChangeTask;
// mListNode is a <datalist> element which, is set, has the form fill
diff --git a/toolkit/components/satchel/nsIFormFillController.idl b/toolkit/components/satchel/nsIFormFillController.idl
@@ -26,7 +26,7 @@ interface nsIFormFillController : nsISupports
/*
* The input or textarea element the form fill controller is currently bound to.
*/
- [setter_can_run_script] attribute Element controlledElement;
+ readonly attribute Element focusedElement;
/*
* Whether the autocomplete popup on a password field was automatically opened