Bug 1928604 - P3. Make FormFillController to support textarea r=NeilDeakin,credential-management-reviewers,edgar
Depends on D240335 Differential Revision: https://phabricator.services.mozilla.com/D240337
This commit is contained in:
@@ -58,7 +58,7 @@ add_task(
|
|||||||
"@mozilla.org/satchel/form-fill-controller;1"
|
"@mozilla.org/satchel/form-fill-controller;1"
|
||||||
].getService(Ci.nsIFormFillController);
|
].getService(Ci.nsIFormFillController);
|
||||||
Assert.equal(
|
Assert.equal(
|
||||||
formFillController.focusedInput?.id,
|
formFillController.focusedElement?.id,
|
||||||
"address-level1",
|
"address-level1",
|
||||||
"formFillController has correct focusedInput"
|
"formFillController has correct focusedInput"
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1308,15 +1308,20 @@ nsresult nsContentUtils::Atob(const nsAString& aAsciiBase64String,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsContentUtils::IsAutocompleteEnabled(
|
bool nsContentUtils::IsAutocompleteEnabled(mozilla::dom::Element* aElement) {
|
||||||
mozilla::dom::HTMLInputElement* aInput) {
|
MOZ_ASSERT(aElement, "aElement should not be null!");
|
||||||
MOZ_ASSERT(aInput, "aInput should not be null!");
|
|
||||||
|
|
||||||
nsAutoString autocomplete;
|
nsAutoString autocomplete;
|
||||||
aInput->GetAutocomplete(autocomplete);
|
|
||||||
|
if (auto* input = HTMLInputElement::FromNodeOrNull(aElement)) {
|
||||||
|
input->GetAutocomplete(autocomplete);
|
||||||
|
} else if (auto* textarea = HTMLTextAreaElement::FromNodeOrNull(aElement)) {
|
||||||
|
textarea->GetAutocomplete(autocomplete);
|
||||||
|
}
|
||||||
|
|
||||||
if (autocomplete.IsEmpty()) {
|
if (autocomplete.IsEmpty()) {
|
||||||
auto* form = aInput->GetForm();
|
auto* control = nsGenericHTMLFormControlElement::FromNode(aElement);
|
||||||
|
auto* form = control->GetForm();
|
||||||
if (!form) {
|
if (!form) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2652,10 +2652,11 @@ class nsContentUtils {
|
|||||||
* NOTE: the caller has to make sure autocomplete makes sense for the
|
* NOTE: the caller has to make sure autocomplete makes sense for the
|
||||||
* element's type.
|
* element's type.
|
||||||
*
|
*
|
||||||
* @param aInput the input element to check. NOTE: aInput can't be null.
|
* @param aElement the input or textarea element to check. NOTE: aElement
|
||||||
|
* can't be null.
|
||||||
* @return whether the input element has autocomplete enabled.
|
* @return whether the input element has autocomplete enabled.
|
||||||
*/
|
*/
|
||||||
static bool IsAutocompleteEnabled(mozilla::dom::HTMLInputElement* aInput);
|
static bool IsAutocompleteEnabled(mozilla::dom::Element* aElement);
|
||||||
|
|
||||||
enum AutocompleteAttrState : uint8_t {
|
enum AutocompleteAttrState : uint8_t {
|
||||||
eAutocompleteAttrState_Unknown = 1,
|
eAutocompleteAttrState_Unknown = 1,
|
||||||
|
|||||||
@@ -1131,7 +1131,8 @@ JSObject* HTMLTextAreaElement::WrapNode(JSContext* aCx,
|
|||||||
return HTMLTextAreaElement_Binding::Wrap(aCx, this, aGivenProto);
|
return HTMLTextAreaElement_Binding::Wrap(aCx, this, aGivenProto);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLTextAreaElement::GetAutocomplete(DOMString& aValue) {
|
void HTMLTextAreaElement::GetAutocomplete(nsAString& aValue) {
|
||||||
|
aValue.Truncate();
|
||||||
const nsAttrValue* attributeVal = GetParsedAttr(nsGkAtoms::autocomplete);
|
const nsAttrValue* attributeVal = GetParsedAttr(nsGkAtoms::autocomplete);
|
||||||
|
|
||||||
mAutocompleteAttrState = nsContentUtils::SerializeAutocompleteAttribute(
|
mAutocompleteAttrState = nsContentUtils::SerializeAutocompleteAttribute(
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ class HTMLTextAreaElement final : public TextControlElement,
|
|||||||
ValidityStateType aType) override;
|
ValidityStateType aType) override;
|
||||||
|
|
||||||
// Web IDL binding methods
|
// Web IDL binding methods
|
||||||
void GetAutocomplete(DOMString& aValue);
|
void GetAutocomplete(nsAString& aValue);
|
||||||
void SetAutocomplete(const nsAString& aValue, ErrorResult& aRv) {
|
void SetAutocomplete(const nsAString& aValue, ErrorResult& aRv) {
|
||||||
SetHTMLAttr(nsGkAtoms::autocomplete, aValue, aRv);
|
SetHTMLAttr(nsGkAtoms::autocomplete, aValue, aRv);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ export class FormAutofillChild extends JSWindowActorChild {
|
|||||||
this.#markAsAutofillField(fieldDetail);
|
this.#markAsAutofillField(fieldDetail);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
fieldDetail.element == lazy.FormAutofillContent.focusedInput &&
|
fieldDetail.element == lazy.FormAutofillContent.focusedElement &&
|
||||||
!isUpdate
|
!isUpdate
|
||||||
) {
|
) {
|
||||||
this.showPopupIfEmpty(fieldDetail.element, fieldDetail.fieldName);
|
this.showPopupIfEmpty(fieldDetail.element, fieldDetail.fieldName);
|
||||||
@@ -484,7 +484,7 @@ export class FormAutofillChild extends JSWindowActorChild {
|
|||||||
this._hasDOMContentLoadedHandler = true;
|
this._hasDOMContentLoadedHandler = true;
|
||||||
doc.addEventListener(
|
doc.addEventListener(
|
||||||
"DOMContentLoaded",
|
"DOMContentLoaded",
|
||||||
() => this.onFocusIn(lazy.FormAutofillContent.focusedInput),
|
() => this.onFocusIn(lazy.FormAutofillContent.focusedElement),
|
||||||
{ once: true }
|
{ once: true }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ export var FormAutofillContent = {
|
|||||||
return Services.cpmm.sharedData.get("FormAutofill:savedFieldNames");
|
return Services.cpmm.sharedData.get("FormAutofill:savedFieldNames");
|
||||||
},
|
},
|
||||||
|
|
||||||
get focusedInput() {
|
get focusedElement() {
|
||||||
return formFillController.focusedInput;
|
return formFillController.focusedElement;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1401,19 +1401,19 @@ export class LoginManagerChild extends JSWindowActorChild {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "PasswordManager:OnFieldAutoComplete": {
|
case "PasswordManager:OnFieldAutoComplete": {
|
||||||
const { focusedInput } = lazy.gFormFillService;
|
const { focusedElement } = lazy.gFormFillService;
|
||||||
const login = lazy.LoginHelper.vanillaObjectToLogin(msg.data);
|
const login = lazy.LoginHelper.vanillaObjectToLogin(msg.data);
|
||||||
this.onFieldAutoComplete(focusedInput, login);
|
this.onFieldAutoComplete(focusedElement, login);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "PasswordManager:FillGeneratedPassword": {
|
case "PasswordManager:FillGeneratedPassword": {
|
||||||
const { focusedInput } = lazy.gFormFillService;
|
const { focusedElement } = lazy.gFormFillService;
|
||||||
this.filledWithGeneratedPassword(focusedInput);
|
this.filledWithGeneratedPassword(focusedElement);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "PasswordManager:FillRelayUsername": {
|
case "PasswordManager:FillRelayUsername": {
|
||||||
const { focusedInput } = lazy.gFormFillService;
|
const { focusedElement } = lazy.gFormFillService;
|
||||||
this.fillRelayUsername(focusedInput, msg.data);
|
this.fillRelayUsername(focusedElement, msg.data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1428,7 +1428,7 @@ export class LoginManagerChild extends JSWindowActorChild {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inputElement != lazy.gFormFillService.focusedInput) {
|
if (inputElement != lazy.gFormFillService.focusedElement) {
|
||||||
lazy.log("Could not open popup on input that's no longer focused.");
|
lazy.log("Could not open popup on input that's no longer focused.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3041,7 +3041,7 @@ export class LoginManagerChild extends JSWindowActorChild {
|
|||||||
Glean.pwmgr.formAutofillResult[autofillResult].add(1);
|
Glean.pwmgr.formAutofillResult[autofillResult].add(1);
|
||||||
|
|
||||||
if (usernameField) {
|
if (usernameField) {
|
||||||
let focusedElement = lazy.gFormFillService.focusedInput;
|
let focusedElement = lazy.gFormFillService.focusedElement;
|
||||||
if (
|
if (
|
||||||
usernameField == focusedElement &&
|
usernameField == focusedElement &&
|
||||||
![
|
![
|
||||||
|
|||||||
@@ -9,11 +9,14 @@
|
|||||||
#include "mozilla/ClearOnShutdown.h"
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
#include "mozilla/ErrorResult.h"
|
#include "mozilla/ErrorResult.h"
|
||||||
#include "mozilla/EventListenerManager.h"
|
#include "mozilla/EventListenerManager.h"
|
||||||
|
#include "mozilla/TextControlElement.h"
|
||||||
#include "mozilla/dom/Document.h"
|
#include "mozilla/dom/Document.h"
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
#include "mozilla/dom/Event.h" // for Event
|
#include "mozilla/dom/Event.h" // for Event
|
||||||
#include "mozilla/dom/HTMLDataListElement.h"
|
#include "mozilla/dom/HTMLDataListElement.h"
|
||||||
#include "mozilla/dom/HTMLInputElement.h"
|
#include "mozilla/dom/HTMLInputElement.h"
|
||||||
|
#include "mozilla/dom/HTMLTextAreaElement.h"
|
||||||
|
#include "mozilla/dom/Element.h"
|
||||||
#include "mozilla/dom/KeyboardEvent.h"
|
#include "mozilla/dom/KeyboardEvent.h"
|
||||||
#include "mozilla/dom/KeyboardEventBinding.h"
|
#include "mozilla/dom/KeyboardEventBinding.h"
|
||||||
#include "mozilla/dom/MouseEvent.h"
|
#include "mozilla/dom/MouseEvent.h"
|
||||||
@@ -64,7 +67,7 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFormFillController)
|
|||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFormFillController)
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFormFillController)
|
||||||
|
|
||||||
nsFormFillController::nsFormFillController()
|
nsFormFillController::nsFormFillController()
|
||||||
: mFocusedInput(nullptr),
|
: mFocusedElement(nullptr),
|
||||||
mRestartAfterAttributeChangeTask(nullptr),
|
mRestartAfterAttributeChangeTask(nullptr),
|
||||||
mListNode(nullptr),
|
mListNode(nullptr),
|
||||||
// The amount of time a context menu event supresses showing a
|
// The amount of time a context menu event supresses showing a
|
||||||
@@ -96,9 +99,9 @@ nsFormFillController::~nsFormFillController() {
|
|||||||
mListNode->RemoveMutationObserver(this);
|
mListNode->RemoveMutationObserver(this);
|
||||||
mListNode = nullptr;
|
mListNode = nullptr;
|
||||||
}
|
}
|
||||||
if (mFocusedInput) {
|
if (mFocusedElement) {
|
||||||
MaybeRemoveMutationObserver(mFocusedInput);
|
MaybeRemoveMutationObserver(mFocusedElement);
|
||||||
mFocusedInput = nullptr;
|
mFocusedElement = nullptr;
|
||||||
}
|
}
|
||||||
RemoveForDocument(nullptr);
|
RemoveForDocument(nullptr);
|
||||||
}
|
}
|
||||||
@@ -126,7 +129,7 @@ void nsFormFillController::AttributeChanged(mozilla::dom::Element* aElement,
|
|||||||
if ((aAttribute == nsGkAtoms::type || aAttribute == nsGkAtoms::readonly ||
|
if ((aAttribute == nsGkAtoms::type || aAttribute == nsGkAtoms::readonly ||
|
||||||
aAttribute == nsGkAtoms::autocomplete) &&
|
aAttribute == nsGkAtoms::autocomplete) &&
|
||||||
aNameSpaceID == kNameSpaceID_None) {
|
aNameSpaceID == kNameSpaceID_None) {
|
||||||
RefPtr<HTMLInputElement> focusedInput(mFocusedInput);
|
RefPtr<Element> focusedElement(mFocusedElement);
|
||||||
// Reset the current state of the controller, unconditionally.
|
// Reset the current state of the controller, unconditionally.
|
||||||
StopControllingInput();
|
StopControllingInput();
|
||||||
// Then restart based on the new values. We have to delay this
|
// Then restart based on the new values. We have to delay this
|
||||||
@@ -136,10 +139,10 @@ void nsFormFillController::AttributeChanged(mozilla::dom::Element* aElement,
|
|||||||
// attribute change, cancel it.
|
// attribute change, cancel it.
|
||||||
MaybeCancelAttributeChangeTask();
|
MaybeCancelAttributeChangeTask();
|
||||||
mRestartAfterAttributeChangeTask =
|
mRestartAfterAttributeChangeTask =
|
||||||
mozilla::NewCancelableRunnableMethod<RefPtr<HTMLInputElement>>(
|
mozilla::NewCancelableRunnableMethod<RefPtr<Element>>(
|
||||||
"nsFormFillController::MaybeStartControllingInput", this,
|
"nsFormFillController::MaybeStartControllingInput", this,
|
||||||
&nsFormFillController::MaybeStartControllingInputScheduled,
|
&nsFormFillController::MaybeStartControllingInputScheduled,
|
||||||
focusedInput);
|
focusedElement);
|
||||||
RefPtr<Runnable> addrefedRunnable = mRestartAfterAttributeChangeTask;
|
RefPtr<Runnable> addrefedRunnable = mRestartAfterAttributeChangeTask;
|
||||||
aElement->OwnerDoc()->Dispatch(addrefedRunnable.forget());
|
aElement->OwnerDoc()->Dispatch(addrefedRunnable.forget());
|
||||||
}
|
}
|
||||||
@@ -151,9 +154,9 @@ void nsFormFillController::AttributeChanged(mozilla::dom::Element* aElement,
|
|||||||
|
|
||||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
void nsFormFillController::MaybeStartControllingInputScheduled(
|
void nsFormFillController::MaybeStartControllingInputScheduled(
|
||||||
HTMLInputElement* aInput) {
|
Element* aElement) {
|
||||||
mRestartAfterAttributeChangeTask = nullptr;
|
mRestartAfterAttributeChangeTask = nullptr;
|
||||||
MaybeStartControllingInput(aInput);
|
MaybeStartControllingInput(aElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
@@ -215,8 +218,8 @@ void nsFormFillController::NodeWillBeDestroyed(nsINode* aNode) {
|
|||||||
if (aNode == mListNode) {
|
if (aNode == mListNode) {
|
||||||
mListNode = nullptr;
|
mListNode = nullptr;
|
||||||
RevalidateDataList();
|
RevalidateDataList();
|
||||||
} else if (aNode == mFocusedInput) {
|
} else if (aNode == mFocusedElement) {
|
||||||
mFocusedInput = nullptr;
|
mFocusedElement = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,28 +235,32 @@ void nsFormFillController::MaybeRemoveMutationObserver(nsINode* aNode) {
|
|||||||
//// nsIFormFillController
|
//// nsIFormFillController
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsFormFillController::MarkAsAutoCompletableField(HTMLInputElement* aInput) {
|
nsFormFillController::MarkAsAutoCompletableField(Element* aElement) {
|
||||||
/*
|
/*
|
||||||
* Support other components implementing form autofill and handle autocomplete
|
* Support other components implementing form autofill and handle autocomplete
|
||||||
* for the field.
|
* for the field.
|
||||||
*/
|
*/
|
||||||
NS_ENSURE_STATE(aInput);
|
NS_ENSURE_STATE(aElement);
|
||||||
|
|
||||||
|
if (!aElement->IsAnyOfHTMLElements(nsGkAtoms::input, nsGkAtoms::textarea)) {
|
||||||
|
return NS_ERROR_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
MOZ_LOG(sLogger, LogLevel::Verbose,
|
MOZ_LOG(sLogger, LogLevel::Verbose,
|
||||||
("MarkAsAutoCompletableField: aInput = %p", aInput));
|
("MarkAsAutoCompletableField: aElement = %p", aElement));
|
||||||
|
|
||||||
if (mAutoCompleteInputs.Get(aInput)) {
|
if (mAutoCompleteInputs.Get(aElement)) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
mAutoCompleteInputs.InsertOrUpdate(aInput, true);
|
mAutoCompleteInputs.InsertOrUpdate(aElement, true);
|
||||||
aInput->AddMutationObserverUnlessExists(this);
|
aElement->AddMutationObserverUnlessExists(this);
|
||||||
|
|
||||||
aInput->EnablePreview();
|
EnablePreview(aElement);
|
||||||
|
|
||||||
if (nsFocusManager::GetFocusedElementStatic() == aInput) {
|
if (nsFocusManager::GetFocusedElementStatic() == aElement) {
|
||||||
if (!mFocusedInput) {
|
if (!mFocusedElement) {
|
||||||
MaybeStartControllingInput(aInput);
|
MaybeStartControllingInput(aElement);
|
||||||
} else {
|
} else {
|
||||||
// See `MarkAsLoginManagerField` for why this is needed.
|
// See `MarkAsLoginManagerField` for why this is needed.
|
||||||
nsCOMPtr<nsIAutoCompleteController> controller = mController;
|
nsCOMPtr<nsIAutoCompleteController> controller = mController;
|
||||||
@@ -265,9 +272,9 @@ nsFormFillController::MarkAsAutoCompletableField(HTMLInputElement* aInput) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsFormFillController::GetFocusedInput(HTMLInputElement** aInput) {
|
nsFormFillController::GetFocusedElement(Element** aElement) {
|
||||||
*aInput = mFocusedInput;
|
*aElement = mFocusedElement;
|
||||||
NS_IF_ADDREF(*aInput);
|
NS_IF_ADDREF(*aElement);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,9 +315,9 @@ nsFormFillController::SetPopupOpen(bool aPopupOpen) {
|
|||||||
if (mFocusedPopup) {
|
if (mFocusedPopup) {
|
||||||
if (aPopupOpen) {
|
if (aPopupOpen) {
|
||||||
// make sure input field is visible before showing popup (bug 320938)
|
// make sure input field is visible before showing popup (bug 320938)
|
||||||
nsCOMPtr<nsIContent> content = mFocusedInput;
|
nsCOMPtr<nsIContent> content = mFocusedElement;
|
||||||
NS_ENSURE_STATE(content);
|
NS_ENSURE_STATE(content);
|
||||||
nsCOMPtr<nsIDocShell> docShell = GetDocShellForInput(mFocusedInput);
|
nsCOMPtr<nsIDocShell> docShell = GetDocShellForInput(mFocusedElement);
|
||||||
NS_ENSURE_STATE(docShell);
|
NS_ENSURE_STATE(docShell);
|
||||||
RefPtr<PresShell> presShell = docShell->GetPresShell();
|
RefPtr<PresShell> presShell = docShell->GetPresShell();
|
||||||
NS_ENSURE_STATE(presShell);
|
NS_ENSURE_STATE(presShell);
|
||||||
@@ -322,7 +329,7 @@ nsFormFillController::SetPopupOpen(bool aPopupOpen) {
|
|||||||
// mFocusedPopup can be destroyed after ScrollContentIntoView, see bug
|
// mFocusedPopup can be destroyed after ScrollContentIntoView, see bug
|
||||||
// 420089
|
// 420089
|
||||||
if (mFocusedPopup) {
|
if (mFocusedPopup) {
|
||||||
mFocusedPopup->OpenAutocompletePopup(this, mFocusedInput);
|
mFocusedPopup->OpenAutocompletePopup(this, mFocusedElement);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mFocusedPopup->ClosePopup();
|
mFocusedPopup->ClosePopup();
|
||||||
@@ -422,16 +429,17 @@ nsFormFillController::SetSearchParam(const nsAString& aSearchParam) {
|
|||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsFormFillController::GetSearchParam(nsAString& aSearchParam) {
|
nsFormFillController::GetSearchParam(nsAString& aSearchParam) {
|
||||||
if (!mFocusedInput) {
|
if (!mFocusedElement) {
|
||||||
NS_WARNING(
|
NS_WARNING(
|
||||||
"mFocusedInput is null for some reason! avoiding a crash. should find "
|
"mFocusedElement is null for some reason! avoiding a crash. should "
|
||||||
|
"find "
|
||||||
"out why... - ben");
|
"out why... - ben");
|
||||||
return NS_ERROR_FAILURE; // XXX why? fix me.
|
return NS_ERROR_FAILURE; // XXX why? fix me.
|
||||||
}
|
}
|
||||||
|
|
||||||
mFocusedInput->GetName(aSearchParam);
|
GetName(mFocusedElement, aSearchParam);
|
||||||
if (aSearchParam.IsEmpty()) {
|
if (aSearchParam.IsEmpty()) {
|
||||||
mFocusedInput->GetId(aSearchParam);
|
mFocusedElement->GetId(aSearchParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@@ -459,8 +467,8 @@ nsFormFillController::GetSearchAt(uint32_t index, nsACString& _retval) {
|
|||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsFormFillController::GetTextValue(nsAString& aTextValue) {
|
nsFormFillController::GetTextValue(nsAString& aTextValue) {
|
||||||
if (mFocusedInput) {
|
if (mFocusedElement) {
|
||||||
mFocusedInput->GetValue(aTextValue, CallerType::System);
|
GetValue(mFocusedElement, aTextValue);
|
||||||
} else {
|
} else {
|
||||||
aTextValue.Truncate();
|
aTextValue.Truncate();
|
||||||
}
|
}
|
||||||
@@ -469,9 +477,9 @@ nsFormFillController::GetTextValue(nsAString& aTextValue) {
|
|||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsFormFillController::SetTextValue(const nsAString& aTextValue) {
|
nsFormFillController::SetTextValue(const nsAString& aTextValue) {
|
||||||
if (mFocusedInput) {
|
if (mFocusedElement) {
|
||||||
mSuppressOnInput = true;
|
mSuppressOnInput = true;
|
||||||
mFocusedInput->SetUserInput(aTextValue,
|
SetUserInput(mFocusedElement, aTextValue,
|
||||||
*nsContentUtils::GetSystemPrincipal());
|
*nsContentUtils::GetSystemPrincipal());
|
||||||
mSuppressOnInput = false;
|
mSuppressOnInput = false;
|
||||||
}
|
}
|
||||||
@@ -481,33 +489,32 @@ nsFormFillController::SetTextValue(const nsAString& aTextValue) {
|
|||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsFormFillController::GetSelectionStart(int32_t* aSelectionStart) {
|
nsFormFillController::GetSelectionStart(int32_t* aSelectionStart) {
|
||||||
if (!mFocusedInput) {
|
if (!mFocusedElement) {
|
||||||
return NS_ERROR_UNEXPECTED;
|
return NS_ERROR_UNEXPECTED;
|
||||||
}
|
}
|
||||||
ErrorResult rv;
|
ErrorResult rv;
|
||||||
*aSelectionStart = mFocusedInput->GetSelectionStartIgnoringType(rv);
|
*aSelectionStart = GetSelectionStartInternal(mFocusedElement, rv);
|
||||||
return rv.StealNSResult();
|
return rv.StealNSResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsFormFillController::GetSelectionEnd(int32_t* aSelectionEnd) {
|
nsFormFillController::GetSelectionEnd(int32_t* aSelectionEnd) {
|
||||||
if (!mFocusedInput) {
|
if (!mFocusedElement) {
|
||||||
return NS_ERROR_UNEXPECTED;
|
return NS_ERROR_UNEXPECTED;
|
||||||
}
|
}
|
||||||
ErrorResult rv;
|
ErrorResult rv;
|
||||||
*aSelectionEnd = mFocusedInput->GetSelectionEndIgnoringType(rv);
|
*aSelectionEnd = GetSelectionEndInternal(mFocusedElement, rv);
|
||||||
return rv.StealNSResult();
|
return rv.StealNSResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMP
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMP
|
||||||
nsFormFillController::SelectTextRange(int32_t aStartIndex, int32_t aEndIndex) {
|
nsFormFillController::SelectTextRange(int32_t aStartIndex, int32_t aEndIndex) {
|
||||||
if (!mFocusedInput) {
|
if (!mFocusedElement) {
|
||||||
return NS_ERROR_UNEXPECTED;
|
return NS_ERROR_UNEXPECTED;
|
||||||
}
|
}
|
||||||
RefPtr<HTMLInputElement> focusedInput(mFocusedInput);
|
RefPtr<Element> focusedInput(mFocusedElement);
|
||||||
ErrorResult rv;
|
ErrorResult rv;
|
||||||
focusedInput->SetSelectionRange(aStartIndex, aEndIndex, Optional<nsAString>(),
|
SetSelectionRange(focusedInput, aStartIndex, aEndIndex, rv);
|
||||||
rv);
|
|
||||||
return rv.StealNSResult();
|
return rv.StealNSResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,7 +526,7 @@ nsFormFillController::OnSearchComplete() { return NS_OK; }
|
|||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsFormFillController::OnTextEntered(Event* aEvent) {
|
nsFormFillController::OnTextEntered(Event* aEvent) {
|
||||||
NS_ENSURE_TRUE(mFocusedInput, NS_OK);
|
NS_ENSURE_TRUE(mFocusedElement, NS_OK);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,12 +544,12 @@ nsFormFillController::GetConsumeRollupEvent(bool* aConsumeRollupEvent) {
|
|||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsFormFillController::GetInPrivateContext(bool* aInPrivateContext) {
|
nsFormFillController::GetInPrivateContext(bool* aInPrivateContext) {
|
||||||
if (!mFocusedInput) {
|
if (!mFocusedElement) {
|
||||||
*aInPrivateContext = false;
|
*aInPrivateContext = false;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<Document> doc = mFocusedInput->OwnerDoc();
|
RefPtr<Document> doc = mFocusedElement->OwnerDoc();
|
||||||
nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
|
nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
|
||||||
*aInPrivateContext = loadContext && loadContext->UsePrivateBrowsing();
|
*aInPrivateContext = loadContext && loadContext->UsePrivateBrowsing();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@@ -556,8 +563,8 @@ nsFormFillController::GetNoRollupOnCaretMove(bool* aNoRollupOnCaretMove) {
|
|||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsFormFillController::GetNoRollupOnEmptySearch(bool* aNoRollupOnEmptySearch) {
|
nsFormFillController::GetNoRollupOnEmptySearch(bool* aNoRollupOnEmptySearch) {
|
||||||
if (mFocusedInput && mFocusedPopup) {
|
if (mFocusedElement && mFocusedPopup) {
|
||||||
return mFocusedPopup->GetNoRollupOnEmptySearch(mFocusedInput,
|
return mFocusedPopup->GetNoRollupOnEmptySearch(mFocusedElement,
|
||||||
aNoRollupOnEmptySearch);
|
aNoRollupOnEmptySearch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -586,36 +593,36 @@ nsFormFillController::StartSearch(const nsAString& aSearchString,
|
|||||||
const nsAString& aSearchParam,
|
const nsAString& aSearchParam,
|
||||||
nsIAutoCompleteResult* aPreviousResult,
|
nsIAutoCompleteResult* aPreviousResult,
|
||||||
nsIAutoCompleteObserver* aListener) {
|
nsIAutoCompleteObserver* aListener) {
|
||||||
MOZ_LOG(sLogger, LogLevel::Debug, ("StartSearch for %p", mFocusedInput));
|
MOZ_LOG(sLogger, LogLevel::Debug, ("StartSearch for %p", mFocusedElement));
|
||||||
|
|
||||||
mLastListener = aListener;
|
mLastListener = aListener;
|
||||||
|
|
||||||
if (mFocusedInput && mFocusedPopup) {
|
if (mFocusedElement && mFocusedPopup) {
|
||||||
if (mAutoCompleteInputs.Get(mFocusedInput) ||
|
if (mAutoCompleteInputs.Get(mFocusedElement) ||
|
||||||
mFocusedInput->HasBeenTypePassword()) {
|
HasBeenTypePassword(mFocusedElement)) {
|
||||||
MOZ_LOG(sLogger, LogLevel::Debug,
|
MOZ_LOG(sLogger, LogLevel::Debug,
|
||||||
("StartSearch: formautofill or login field"));
|
("StartSearch: formautofill or login field"));
|
||||||
|
|
||||||
return mFocusedPopup->StartSearch(aSearchString, mFocusedInput, this);
|
return mFocusedPopup->StartSearch(aSearchString, mFocusedElement, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_LOG(sLogger, LogLevel::Debug, ("StartSearch: form history field"));
|
MOZ_LOG(sLogger, LogLevel::Debug, ("StartSearch: form history field"));
|
||||||
|
|
||||||
bool addDataList = IsTextControl(mFocusedInput);
|
bool addDataList = IsTextControl(mFocusedElement);
|
||||||
if (addDataList) {
|
if (addDataList) {
|
||||||
MaybeObserveDataListMutations();
|
MaybeObserveDataListMutations();
|
||||||
}
|
}
|
||||||
|
|
||||||
return mFocusedPopup->StartSearch(aSearchString, mFocusedInput, this);
|
return mFocusedPopup->StartSearch(aSearchString, mFocusedElement, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsFormFillController::MaybeObserveDataListMutations() {
|
void nsFormFillController::MaybeObserveDataListMutations() {
|
||||||
// If an <input> is focused, 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.
|
// provide the list of suggestions.
|
||||||
|
|
||||||
if (mFocusedInput) {
|
if (mFocusedElement) {
|
||||||
Element* list = mFocusedInput->GetList();
|
Element* list = GetList(mFocusedElement);
|
||||||
|
|
||||||
// Add a mutation observer to check for changes to the items in the
|
// Add a mutation observer to check for changes to the items in the
|
||||||
// <datalist> and update the suggestions accordingly.
|
// <datalist> and update the suggestions accordingly.
|
||||||
@@ -739,7 +746,7 @@ nsFormFillController::HandleEvent(Event* aEvent) {
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
case eBlur:
|
case eBlur:
|
||||||
if (mFocusedInput && !StaticPrefs::ui_popup_disable_autohide()) {
|
if (mFocusedElement && !StaticPrefs::ui_popup_disable_autohide()) {
|
||||||
StopControllingInput();
|
StopControllingInput();
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@@ -768,7 +775,7 @@ nsFormFillController::HandleEvent(Event* aEvent) {
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mFocusedInput && doc == mFocusedInput->OwnerDoc()) {
|
if (mFocusedElement && doc == mFocusedElement->OwnerDoc()) {
|
||||||
StopControllingInput();
|
StopControllingInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -815,9 +822,9 @@ void nsFormFillController::RemoveForDocument(Document* aDoc) {
|
|||||||
for (auto iter = mAutoCompleteInputs.Iter(); !iter.Done(); iter.Next()) {
|
for (auto iter = mAutoCompleteInputs.Iter(); !iter.Done(); iter.Next()) {
|
||||||
const nsINode* key = iter.Key();
|
const nsINode* key = iter.Key();
|
||||||
if (key && (!aDoc || key->OwnerDoc() == aDoc)) {
|
if (key && (!aDoc || key->OwnerDoc() == aDoc)) {
|
||||||
// mFocusedInput's observer is tracked separately, so don't remove it
|
// mFocusedElement's observer is tracked separately, so don't remove it
|
||||||
// here.
|
// here.
|
||||||
if (key != mFocusedInput) {
|
if (key != mFocusedElement) {
|
||||||
const_cast<nsINode*>(key)->RemoveMutationObserver(this);
|
const_cast<nsINode*>(key)->RemoveMutationObserver(this);
|
||||||
}
|
}
|
||||||
iter.Remove();
|
iter.Remove();
|
||||||
@@ -827,38 +834,42 @@ void nsFormFillController::RemoveForDocument(Document* aDoc) {
|
|||||||
|
|
||||||
bool nsFormFillController::IsTextControl(nsINode* aNode) {
|
bool nsFormFillController::IsTextControl(nsINode* aNode) {
|
||||||
const auto* formControl = nsIFormControl::FromNodeOrNull(aNode);
|
const auto* formControl = nsIFormControl::FromNodeOrNull(aNode);
|
||||||
return formControl && formControl->IsSingleLineTextControl(false);
|
return formControl && formControl->IsTextControl(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsFormFillController::MaybeStartControllingInput(
|
void nsFormFillController::MaybeStartControllingInput(Element* aElement) {
|
||||||
HTMLInputElement* aInput) {
|
|
||||||
MOZ_LOG(sLogger, LogLevel::Verbose,
|
MOZ_LOG(sLogger, LogLevel::Verbose,
|
||||||
("MaybeStartControllingInput for %p", aInput));
|
("MaybeStartControllingInput for %p", aElement));
|
||||||
if (!aInput) {
|
if (!aElement) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasList = !!aInput->GetList();
|
bool hasList = !!GetList(aElement);
|
||||||
|
|
||||||
if (!IsTextControl(aInput)) {
|
if (!IsTextControl(aElement)) {
|
||||||
// Even if this is not a text control yet, it can become one in the future
|
// Even if this is not a text control yet, it can become one in the future
|
||||||
if (hasList) {
|
if (hasList) {
|
||||||
StartControllingInput(aInput);
|
StartControllingInput(aElement);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mAutoCompleteInputs.Get(aInput) || aInput->HasBeenTypePassword() ||
|
if (mAutoCompleteInputs.Get(aElement) || HasBeenTypePassword(aElement) ||
|
||||||
hasList || nsContentUtils::IsAutocompleteEnabled(aInput)) {
|
hasList || nsContentUtils::IsAutocompleteEnabled(aElement)) {
|
||||||
StartControllingInput(aInput);
|
StartControllingInput(aElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsFormFillController::HandleFocus(HTMLInputElement* aInput) {
|
nsresult nsFormFillController::HandleFocus(Element* aElement) {
|
||||||
MaybeStartControllingInput(aInput);
|
if (!aElement ||
|
||||||
|
!aElement->IsAnyOfHTMLElements(nsGkAtoms::input, nsGkAtoms::textarea)) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaybeStartControllingInput(aElement);
|
||||||
|
|
||||||
// Bail if we didn't start controlling the input.
|
// Bail if we didn't start controlling the input.
|
||||||
if (!mFocusedInput) {
|
if (!mFocusedElement) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -874,7 +885,7 @@ nsresult nsFormFillController::HandleFocus(HTMLInputElement* aInput) {
|
|||||||
// multiple input forms and the fact that a mousedown into an already focused
|
// multiple input forms and the fact that a mousedown into an already focused
|
||||||
// field does not trigger another focus.
|
// field does not trigger another focus.
|
||||||
|
|
||||||
if (!mFocusedInput->HasBeenTypePassword()) {
|
if (!HasBeenTypePassword(mFocusedElement)) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -897,7 +908,7 @@ nsresult nsFormFillController::HandleFocus(HTMLInputElement* aInput) {
|
|||||||
|
|
||||||
nsresult nsFormFillController::Focus(Event* aEvent) {
|
nsresult nsFormFillController::Focus(Event* aEvent) {
|
||||||
nsCOMPtr<nsIContent> input = do_QueryInterface(aEvent->GetComposedTarget());
|
nsCOMPtr<nsIContent> input = do_QueryInterface(aEvent->GetComposedTarget());
|
||||||
return HandleFocus(MOZ_KnownLive(HTMLInputElement::FromNodeOrNull(input)));
|
return HandleFocus(MOZ_KnownLive(Element::FromNodeOrNull(input)));
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsFormFillController::KeyDown(Event* aEvent) {
|
nsresult nsFormFillController::KeyDown(Event* aEvent) {
|
||||||
@@ -962,8 +973,8 @@ nsresult nsFormFillController::KeyDown(Event* aEvent) {
|
|||||||
// Get the writing-mode of the relevant input element,
|
// Get the writing-mode of the relevant input element,
|
||||||
// so that we can remap arrow keys if necessary.
|
// so that we can remap arrow keys if necessary.
|
||||||
mozilla::WritingMode wm;
|
mozilla::WritingMode wm;
|
||||||
if (mFocusedInput) {
|
if (mFocusedElement) {
|
||||||
nsIFrame* frame = mFocusedInput->GetPrimaryFrame();
|
nsIFrame* frame = mFocusedElement->GetPrimaryFrame();
|
||||||
if (frame) {
|
if (frame) {
|
||||||
wm = frame->GetWritingMode();
|
wm = frame->GetWritingMode();
|
||||||
}
|
}
|
||||||
@@ -1024,7 +1035,10 @@ nsresult nsFormFillController::MouseDown(Event* aEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsINode> targetNode = do_QueryInterface(aEvent->GetComposedTarget());
|
nsCOMPtr<nsINode> targetNode = do_QueryInterface(aEvent->GetComposedTarget());
|
||||||
if (!HTMLInputElement::FromNodeOrNull(targetNode)) {
|
|
||||||
|
auto* element = Element::FromNodeOrNull(targetNode);
|
||||||
|
if (!element ||
|
||||||
|
!element->IsAnyOfHTMLElements(nsGkAtoms::input, nsGkAtoms::textarea)) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1085,39 +1099,40 @@ NS_IMETHODIMP nsFormFillController::GetPasswordPopupAutomaticallyOpened(
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsFormFillController::StartControllingInput(HTMLInputElement* aInput) {
|
void nsFormFillController::StartControllingInput(Element* aElement) {
|
||||||
MOZ_LOG(sLogger, LogLevel::Verbose, ("StartControllingInput for %p", aInput));
|
MOZ_LOG(sLogger, LogLevel::Verbose,
|
||||||
|
("StartControllingInput for %p", aElement));
|
||||||
// Make sure we're not still attached to an input
|
// Make sure we're not still attached to an input
|
||||||
StopControllingInput();
|
StopControllingInput();
|
||||||
|
|
||||||
if (!mController || !aInput) {
|
if (!mController || !aElement) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIAutoCompletePopup> popup =
|
nsCOMPtr<nsIAutoCompletePopup> popup =
|
||||||
do_QueryActor("AutoComplete", aInput->OwnerDoc());
|
do_QueryActor("AutoComplete", aElement->OwnerDoc());
|
||||||
if (!popup) {
|
if (!popup) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mFocusedPopup = popup;
|
mFocusedPopup = popup;
|
||||||
|
|
||||||
aInput->AddMutationObserverUnlessExists(this);
|
aElement->AddMutationObserverUnlessExists(this);
|
||||||
mFocusedInput = aInput;
|
mFocusedElement = aElement;
|
||||||
|
|
||||||
if (Element* list = mFocusedInput->GetList()) {
|
if (Element* list = GetList(mFocusedElement)) {
|
||||||
list->AddMutationObserverUnlessExists(this);
|
list->AddMutationObserverUnlessExists(this);
|
||||||
mListNode = list;
|
mListNode = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mFocusedInput->ReadOnly()) {
|
if (!ReadOnly(mFocusedElement)) {
|
||||||
nsCOMPtr<nsIAutoCompleteController> controller = mController;
|
nsCOMPtr<nsIAutoCompleteController> controller = mController;
|
||||||
controller->SetInput(this);
|
controller->SetInput(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsFormFillController::IsFocusedInputControlled() const {
|
bool nsFormFillController::IsFocusedInputControlled() const {
|
||||||
return mFocusedInput && mController && !mFocusedInput->ReadOnly();
|
return mFocusedElement && mController && !ReadOnly(mFocusedElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsFormFillController::StopControllingInput() {
|
void nsFormFillController::StopControllingInput() {
|
||||||
@@ -1142,10 +1157,10 @@ void nsFormFillController::StopControllingInput() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MOZ_LOG(sLogger, LogLevel::Verbose,
|
MOZ_LOG(sLogger, LogLevel::Verbose,
|
||||||
("StopControllingInput: Stopped controlling %p", mFocusedInput));
|
("StopControllingInput: Stopped controlling %p", mFocusedElement));
|
||||||
if (mFocusedInput) {
|
if (mFocusedElement) {
|
||||||
MaybeRemoveMutationObserver(mFocusedInput);
|
MaybeRemoveMutationObserver(mFocusedElement);
|
||||||
mFocusedInput = nullptr;
|
mFocusedElement = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mFocusedPopup) {
|
if (mFocusedPopup) {
|
||||||
@@ -1154,12 +1169,113 @@ void nsFormFillController::StopControllingInput() {
|
|||||||
mFocusedPopup = nullptr;
|
mFocusedPopup = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIDocShell* nsFormFillController::GetDocShellForInput(
|
nsIDocShell* nsFormFillController::GetDocShellForInput(Element* aElement) {
|
||||||
HTMLInputElement* aInput) {
|
NS_ENSURE_TRUE(aElement, nullptr);
|
||||||
NS_ENSURE_TRUE(aInput, nullptr);
|
|
||||||
|
|
||||||
nsCOMPtr<nsPIDOMWindowOuter> win = aInput->OwnerDoc()->GetWindow();
|
nsCOMPtr<nsPIDOMWindowOuter> win = aElement->OwnerDoc()->GetWindow();
|
||||||
NS_ENSURE_TRUE(win, nullptr);
|
NS_ENSURE_TRUE(win, nullptr);
|
||||||
|
|
||||||
return win->GetDocShell();
|
return win->GetDocShell();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nsFormFillController::GetName(mozilla::dom::Element* aElement,
|
||||||
|
nsAString& aValue) {
|
||||||
|
if (auto* input = HTMLInputElement::FromNodeOrNull(aElement)) {
|
||||||
|
input->GetName(aValue);
|
||||||
|
} else if (auto* textarea = HTMLTextAreaElement::FromNodeOrNull(aElement)) {
|
||||||
|
textarea->GetName(aValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsFormFillController::GetValue(mozilla::dom::Element* aElement,
|
||||||
|
nsAString& aValue) {
|
||||||
|
if (auto* input = HTMLInputElement::FromNodeOrNull(aElement)) {
|
||||||
|
input->GetValue(aValue, CallerType::System);
|
||||||
|
} else if (auto* textarea = HTMLTextAreaElement::FromNodeOrNull(aElement)) {
|
||||||
|
textarea->GetValue(aValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Element* nsFormFillController::GetList(mozilla::dom::Element* aElement) {
|
||||||
|
if (auto* input = HTMLInputElement::FromNodeOrNull(aElement)) {
|
||||||
|
return input->GetList();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nsFormFillController::HasBeenTypePassword(
|
||||||
|
mozilla::dom::Element* aElement) {
|
||||||
|
if (auto* input = HTMLInputElement::FromNodeOrNull(aElement)) {
|
||||||
|
return input->HasBeenTypePassword();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nsFormFillController::ReadOnly(mozilla::dom::Element* aElement) const {
|
||||||
|
if (auto* input = HTMLInputElement::FromNodeOrNull(aElement)) {
|
||||||
|
return input->ReadOnly();
|
||||||
|
} else if (auto* textarea = HTMLTextAreaElement::FromNodeOrNull(aElement)) {
|
||||||
|
return textarea->ReadOnly();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nsFormFillController::GetSelectionStartInternal(
|
||||||
|
mozilla::dom::Element* aElement, ErrorResult& aRv) {
|
||||||
|
if (auto* input = HTMLInputElement::FromNodeOrNull(aElement)) {
|
||||||
|
return input->GetSelectionStartIgnoringType(aRv);
|
||||||
|
} else if (auto* textarea = HTMLTextAreaElement::FromNodeOrNull(aElement)) {
|
||||||
|
Nullable<uint32_t> start = textarea->GetSelectionStart(aRv);
|
||||||
|
if (!start.IsNull()) {
|
||||||
|
return start.Value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nsFormFillController::GetSelectionEndInternal(
|
||||||
|
mozilla::dom::Element* aElement, ErrorResult& aRv) {
|
||||||
|
if (auto* input = HTMLInputElement::FromNodeOrNull(aElement)) {
|
||||||
|
return input->GetSelectionEndIgnoringType(aRv);
|
||||||
|
} else if (auto* textarea = HTMLTextAreaElement::FromNodeOrNull(aElement)) {
|
||||||
|
Nullable<uint32_t> end = textarea->GetSelectionEnd(aRv);
|
||||||
|
if (!end.IsNull()) {
|
||||||
|
return end.Value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsFormFillController::SetSelectionRange(mozilla::dom::Element* aElement,
|
||||||
|
uint32_t aSelectionStart,
|
||||||
|
uint32_t aSelectionEnd,
|
||||||
|
ErrorResult& aRv) {
|
||||||
|
if (RefPtr<HTMLInputElement> input =
|
||||||
|
HTMLInputElement::FromNodeOrNull(aElement)) {
|
||||||
|
return input->SetSelectionRange(aSelectionStart, aSelectionEnd,
|
||||||
|
Optional<nsAString>(), aRv);
|
||||||
|
} else if (RefPtr<HTMLTextAreaElement> textarea =
|
||||||
|
HTMLTextAreaElement::FromNodeOrNull(aElement)) {
|
||||||
|
return textarea->SetSelectionRange(aSelectionStart, aSelectionEnd,
|
||||||
|
Optional<nsAString>(), aRv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsFormFillController::SetUserInput(mozilla::dom::Element* aElement,
|
||||||
|
const nsAString& aValue,
|
||||||
|
nsIPrincipal& aSubjectPrincipal) {
|
||||||
|
if (auto* input = HTMLInputElement::FromNodeOrNull(aElement)) {
|
||||||
|
input->SetUserInput(aValue, aSubjectPrincipal);
|
||||||
|
} else if (auto* textarea = HTMLTextAreaElement::FromNodeOrNull(aElement)) {
|
||||||
|
textarea->SetUserInput(aValue, aSubjectPrincipal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsFormFillController::EnablePreview(mozilla::dom::Element* aElement) {
|
||||||
|
if (auto* input = HTMLInputElement::FromNodeOrNull(aElement)) {
|
||||||
|
input->EnablePreview();
|
||||||
|
} else if (auto* textarea = HTMLTextAreaElement::FromNodeOrNull(aElement)) {
|
||||||
|
textarea->EnablePreview();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,9 +27,10 @@ class nsINode;
|
|||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
class CancelableRunnable;
|
class CancelableRunnable;
|
||||||
|
class ErrorResult;
|
||||||
namespace dom {
|
namespace dom {
|
||||||
class EventTarget;
|
class EventTarget;
|
||||||
class HTMLInputElement;
|
class Element;
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
@@ -65,13 +66,13 @@ class nsFormFillController final : public nsIFormFillController,
|
|||||||
MOZ_CAN_RUN_SCRIPT virtual ~nsFormFillController();
|
MOZ_CAN_RUN_SCRIPT virtual ~nsFormFillController();
|
||||||
|
|
||||||
MOZ_CAN_RUN_SCRIPT
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void StartControllingInput(mozilla::dom::HTMLInputElement* aInput);
|
void StartControllingInput(mozilla::dom::Element* aInput);
|
||||||
MOZ_CAN_RUN_SCRIPT void StopControllingInput();
|
MOZ_CAN_RUN_SCRIPT void StopControllingInput();
|
||||||
|
|
||||||
bool IsFocusedInputControlled() const;
|
bool IsFocusedInputControlled() const;
|
||||||
|
|
||||||
MOZ_CAN_RUN_SCRIPT
|
MOZ_CAN_RUN_SCRIPT
|
||||||
nsresult HandleFocus(mozilla::dom::HTMLInputElement* aInput);
|
nsresult HandleFocus(mozilla::dom::Element* aInput);
|
||||||
|
|
||||||
void AttachListeners(mozilla::dom::EventTarget* aEventTarget);
|
void AttachListeners(mozilla::dom::EventTarget* aEventTarget);
|
||||||
|
|
||||||
@@ -80,13 +81,12 @@ class nsFormFillController final : public nsIFormFillController,
|
|||||||
* StartControllingInput on it.
|
* StartControllingInput on it.
|
||||||
*/
|
*/
|
||||||
MOZ_CAN_RUN_SCRIPT
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void MaybeStartControllingInput(mozilla::dom::HTMLInputElement* aElement);
|
void MaybeStartControllingInput(mozilla::dom::Element* aElement);
|
||||||
|
|
||||||
// clears the reference mRestartAfterAttributeChangeTask before running
|
// clears the reference mRestartAfterAttributeChangeTask before running
|
||||||
// MaybeStartControllingInput()
|
// MaybeStartControllingInput()
|
||||||
MOZ_CAN_RUN_SCRIPT
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void MaybeStartControllingInputScheduled(
|
void MaybeStartControllingInputScheduled(mozilla::dom::Element* aElement);
|
||||||
mozilla::dom::HTMLInputElement* aElement);
|
|
||||||
|
|
||||||
// cancels a scheduled AttributeChangeTask and clears the reference
|
// cancels a scheduled AttributeChangeTask and clears the reference
|
||||||
// mRestartAfterAttributeChangeTask
|
// mRestartAfterAttributeChangeTask
|
||||||
@@ -99,8 +99,7 @@ class nsFormFillController final : public nsIFormFillController,
|
|||||||
bool RowMatch(nsFormHistory* aHistory, uint32_t aIndex,
|
bool RowMatch(nsFormHistory* aHistory, uint32_t aIndex,
|
||||||
const nsAString& aInputName, const nsAString& aInputValue);
|
const nsAString& aInputName, const nsAString& aInputValue);
|
||||||
|
|
||||||
inline nsIDocShell* GetDocShellForInput(
|
inline nsIDocShell* GetDocShellForInput(mozilla::dom::Element* aInput);
|
||||||
mozilla::dom::HTMLInputElement* aInput);
|
|
||||||
|
|
||||||
void MaybeRemoveMutationObserver(nsINode* aNode);
|
void MaybeRemoveMutationObserver(nsINode* aNode);
|
||||||
|
|
||||||
@@ -111,7 +110,7 @@ class nsFormFillController final : public nsIFormFillController,
|
|||||||
// members //////////////////////////////////////////
|
// members //////////////////////////////////////////
|
||||||
|
|
||||||
nsCOMPtr<nsIAutoCompleteController> mController;
|
nsCOMPtr<nsIAutoCompleteController> mController;
|
||||||
mozilla::dom::HTMLInputElement* mFocusedInput;
|
mozilla::dom::Element* mFocusedElement;
|
||||||
RefPtr<mozilla::CancelableRunnable> mRestartAfterAttributeChangeTask;
|
RefPtr<mozilla::CancelableRunnable> mRestartAfterAttributeChangeTask;
|
||||||
|
|
||||||
// mListNode is a <datalist> element which, is set, has the form fill
|
// mListNode is a <datalist> element which, is set, has the form fill
|
||||||
@@ -141,6 +140,25 @@ class nsFormFillController final : public nsIFormFillController,
|
|||||||
bool mPasswordPopupAutomaticallyOpened;
|
bool mPasswordPopupAutomaticallyOpened;
|
||||||
bool mAutoCompleteActive = false;
|
bool mAutoCompleteActive = false;
|
||||||
bool mInvalidatePreviousResult = false;
|
bool mInvalidatePreviousResult = false;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void GetName(mozilla::dom::Element* aInput, nsAString& aValue);
|
||||||
|
void GetValue(mozilla::dom::Element* aInput, nsAString& aValue);
|
||||||
|
mozilla::dom::Element* GetList(mozilla::dom::Element* aInput);
|
||||||
|
bool HasBeenTypePassword(mozilla::dom::Element* aInput);
|
||||||
|
bool ReadOnly(mozilla::dom::Element* aInput) const;
|
||||||
|
uint32_t GetSelectionStartInternal(mozilla::dom::Element* aInput,
|
||||||
|
mozilla::ErrorResult& aRv);
|
||||||
|
uint32_t GetSelectionEndInternal(mozilla::dom::Element* aInput,
|
||||||
|
mozilla::ErrorResult& aRv);
|
||||||
|
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
|
void SetSelectionRange(mozilla::dom::Element* aInput,
|
||||||
|
uint32_t aSelectionStart, uint32_t aSelectionEnd,
|
||||||
|
mozilla::ErrorResult& aRv);
|
||||||
|
void SetUserInput(mozilla::dom::Element* aInput, const nsAString& aValue,
|
||||||
|
nsIPrincipal& aSubjectPrincipal);
|
||||||
|
void EnablePreview(mozilla::dom::Element* aInput);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __nsFormFillController__
|
#endif // __nsFormFillController__
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ interface nsIAutoCompleteResult;
|
|||||||
webidl Document;
|
webidl Document;
|
||||||
webidl Element;
|
webidl Element;
|
||||||
webidl Event;
|
webidl Event;
|
||||||
webidl HTMLInputElement;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nsIFormFillController is an interface for controlling form fill behavior
|
* nsIFormFillController is an interface for controlling form fill behavior
|
||||||
@@ -25,9 +24,9 @@ webidl HTMLInputElement;
|
|||||||
interface nsIFormFillController : nsISupports
|
interface nsIFormFillController : nsISupports
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* The input element the form fill controller is currently bound to.
|
* The input or textarea element the form fill controller is currently bound to.
|
||||||
*/
|
*/
|
||||||
readonly attribute HTMLInputElement focusedInput;
|
readonly attribute Element focusedElement;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Whether the autocomplete popup on a password field was automatically opened
|
* Whether the autocomplete popup on a password field was automatically opened
|
||||||
@@ -39,9 +38,9 @@ interface nsIFormFillController : nsISupports
|
|||||||
* Mark the specified <input> element as being managed by autocomplete entry provider.
|
* Mark the specified <input> element as being managed by autocomplete entry provider.
|
||||||
* Autocomplete requests will be handed off to the AutoCompleteChild.
|
* Autocomplete requests will be handed off to the AutoCompleteChild.
|
||||||
*
|
*
|
||||||
* @param aInput - The HTML <input> element to mark
|
* @param aElement - The HTML <input> or <textarea> element to mark
|
||||||
*/
|
*/
|
||||||
[can_run_script] void markAsAutoCompletableField(in HTMLInputElement aInput);
|
[can_run_script] void markAsAutoCompletableField(in Element aElement);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open the autocomplete popup, if possible.
|
* Open the autocomplete popup, if possible.
|
||||||
|
|||||||
Reference in New Issue
Block a user