diff --git a/dom/events/EventStates.h b/dom/events/EventStates.h index 291530d86b..38a3618ba7 100644 --- a/dom/events/EventStates.h +++ b/dom/events/EventStates.h @@ -293,6 +293,9 @@ private: // Modal element #define NS_EVENT_STATE_MODAL_DIALOG NS_DEFINE_EVENT_STATE_MACRO(54) +// Autofilled input element (for :autofill pseudo-class) +#define NS_EVENT_STATE_AUTOFILL NS_DEFINE_EVENT_STATE_MACRO(55) + #define DIR_ATTR_STATES (NS_EVENT_STATE_HAS_DIR_ATTR | \ NS_EVENT_STATE_DIR_ATTR_LTR | \ NS_EVENT_STATE_DIR_ATTR_RTL | \ diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index 374fb14ef1..6a0979fce0 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -2832,6 +2832,16 @@ HTMLInputElement::SetUserInput(const nsAString& aValue) return NS_OK; } +void +HTMLInputElement::SetAutofilled(bool aAutofilled) +{ + if (aAutofilled) { + AddStates(NS_EVENT_STATE_AUTOFILL); + } else { + RemoveStates(NS_EVENT_STATE_AUTOFILL); + } +} + nsIEditor* HTMLInputElement::GetEditor() { @@ -8507,6 +8517,11 @@ HTMLInputElement::OnValueChanged(bool aNotify, bool aWasInteractiveUserChange) { mLastValueChangeWasInteractive = aWasInteractiveUserChange; + // Clear autofilled state if this was an interactive user change + if (aWasInteractiveUserChange && State().HasState(NS_EVENT_STATE_AUTOFILL)) { + RemoveStates(NS_EVENT_STATE_AUTOFILL); + } + UpdateAllValidityStates(aNotify); if (HasDirAuto()) { diff --git a/dom/html/HTMLInputElement.h b/dom/html/HTMLInputElement.h index e46be30ea7..36c4b06c0b 100644 --- a/dom/html/HTMLInputElement.h +++ b/dom/html/HTMLInputElement.h @@ -845,6 +845,16 @@ public: void SetUserInput(const nsAString& aInput, nsIPrincipal& aSubjectPrincipal); + /** + * Sets or clears the autofilled state of this input element. + * This is used by the browser's autofill system to indicate when + * a value has been automatically filled (e.g., from saved passwords + * or form data). + * + * @param aAutofilled Whether the element should be marked as autofilled + */ + void SetAutofilled(bool aAutofilled); + // XPCOM GetPhonetic() is OK /** diff --git a/dom/html/HTMLTextAreaElement.cpp b/dom/html/HTMLTextAreaElement.cpp index 48b28d3fe4..e34e56975f 100644 --- a/dom/html/HTMLTextAreaElement.cpp +++ b/dom/html/HTMLTextAreaElement.cpp @@ -366,6 +366,16 @@ HTMLTextAreaElement::SetUserInput(const nsAString& aValue) return SetValueInternal(aValue, nsTextEditorState::eSetValue_BySetUserInput); } +void +HTMLTextAreaElement::SetAutofilled(bool aAutofilled) +{ + if (aAutofilled) { + AddStates(NS_EVENT_STATE_AUTOFILL); + } else { + RemoveStates(NS_EVENT_STATE_AUTOFILL); + } +} + NS_IMETHODIMP HTMLTextAreaElement::SetValueChanged(bool aValueChanged) { @@ -1633,6 +1643,11 @@ HTMLTextAreaElement::OnValueChanged(bool aNotify, bool aWasInteractiveUserChange { mLastValueChangeWasInteractive = aWasInteractiveUserChange; + // Clear autofilled state if this was an interactive user change + if (aWasInteractiveUserChange && State().HasState(NS_EVENT_STATE_AUTOFILL)) { + RemoveStates(NS_EVENT_STATE_AUTOFILL); + } + // Update the validity state bool validBefore = IsValid(); UpdateTooLongValidityState(); diff --git a/dom/html/HTMLTextAreaElement.h b/dom/html/HTMLTextAreaElement.h index cc9c2b7c5c..4efc264e0b 100644 --- a/dom/html/HTMLTextAreaElement.h +++ b/dom/html/HTMLTextAreaElement.h @@ -70,6 +70,15 @@ public: } NS_IMETHOD SetUserInput(const nsAString& aInput) override; + /** + * Sets or clears the autofilled state of this textarea element. + * This is used by the browser's autofill system to indicate when + * a value has been automatically filled (e.g., from saved form data). + * + * @param aAutofilled Whether the element should be marked as autofilled + */ + void SetAutofilled(bool aAutofilled); + // nsIFormControl NS_IMETHOD_(uint32_t) GetType() const override { return NS_FORM_TEXTAREA; } NS_IMETHOD Reset() override; diff --git a/dom/webidl/HTMLInputElement.webidl b/dom/webidl/HTMLInputElement.webidl index 1eefaea61e..5d0d7895b9 100644 --- a/dom/webidl/HTMLInputElement.webidl +++ b/dom/webidl/HTMLInputElement.webidl @@ -200,6 +200,13 @@ partial interface HTMLInputElement { // for example will be dispatched when focusing out the element. [Func="IsChromeOrXBL", NeedsSubjectPrincipal] void setUserInput(DOMString input); + + // Sets or clears the autofilled state of this input element. + // This is used by the browser's autofill system to indicate when + // a value has been automatically filled (e.g., from saved passwords + // or form data). + [ChromeOnly] + void setAutofilled(boolean autofilled); }; partial interface HTMLInputElement { diff --git a/dom/webidl/HTMLTextAreaElement.webidl b/dom/webidl/HTMLTextAreaElement.webidl index 7a181bf394..5eb31b1dfa 100644 --- a/dom/webidl/HTMLTextAreaElement.webidl +++ b/dom/webidl/HTMLTextAreaElement.webidl @@ -97,4 +97,10 @@ partial interface HTMLTextAreaElement { // element. [ChromeOnly] void setUserInput(DOMString input); + + // Sets or clears the autofilled state of this textarea element. + // This is used by the browser's autofill system to indicate when + // a value has been automatically filled (e.g., from saved form data). + [ChromeOnly] + void setAutofilled(boolean autofilled); }; diff --git a/layout/style/nsCSSPseudoClassList.h b/layout/style/nsCSSPseudoClassList.h index 485a1a428d..b763be1283 100644 --- a/layout/style/nsCSSPseudoClassList.h +++ b/layout/style/nsCSSPseudoClassList.h @@ -194,6 +194,9 @@ CSS_STATE_PSEUDO_CLASS(mozFullScreen, ":-moz-full-screen", 0, "", NS_EVENT_STATE CSS_STATE_PSEUDO_CLASS(modal, ":modal", 0, "", NS_EVENT_STATE_MODAL_DIALOG) CSS_STATE_PSEUDO_CLASS(mozModalDialog, ":-moz-modal-dialog", 0, "", NS_EVENT_STATE_MODAL_DIALOG) +// Matches autofilled input elements +CSS_STATE_PSEUDO_CLASS(autofill, ":autofill", 0, "", NS_EVENT_STATE_AUTOFILL) + // Matches if the element is focused and should show a focus ring CSS_STATE_PSEUDO_CLASS(mozFocusRing, ":-moz-focusring", 0, "", NS_EVENT_STATE_FOCUSRING) diff --git a/toolkit/components/formautofill/FormAutofillContentService.js b/toolkit/components/formautofill/FormAutofillContentService.js index ee8e978ad9..273697f221 100644 --- a/toolkit/components/formautofill/FormAutofillContentService.js +++ b/toolkit/components/formautofill/FormAutofillContentService.js @@ -238,6 +238,11 @@ FormHandler.prototype = { } fieldDetail.element.value = field.value; + + // Set the autofilled state on the element + if (typeof fieldDetail.element.setAutofilled === 'function') { + fieldDetail.element.setAutofilled(true); + } } },