Bug 502258 - Add a Show Password button to <input type=password> controls. r=Gijs

It's controlled by the pref:
layout.forms.input-type-show-password-button.enabled

Differential Revision: https://phabricator.services.mozilla.com/D130407
This commit is contained in:
Emilio Cobos Álvarez
2021-11-25 20:12:05 +00:00
parent 6e137d35c5
commit 54e796f48d
36 changed files with 499 additions and 69 deletions

View File

@@ -3990,16 +3990,35 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
case eMouseClick: {
if (!aVisitor.mEvent->DefaultPrevented() &&
aVisitor.mEvent->IsTrusted() &&
mType == FormControlType::InputSearch &&
aVisitor.mEvent->AsMouseEvent()->mButton ==
MouseButton::ePrimary) {
if (nsSearchControlFrame* searchControlFrame =
do_QueryFrame(GetPrimaryFrame())) {
Element* clearButton = searchControlFrame->GetAnonClearButton();
if (clearButton &&
aVisitor.mEvent->mOriginalTarget == clearButton) {
SetUserInput(EmptyString(),
*nsContentUtils::GetSystemPrincipal());
// TODO(emilio): Handling this should ideally not move focus.
if (mType == FormControlType::InputSearch) {
if (nsSearchControlFrame* searchControlFrame =
do_QueryFrame(GetPrimaryFrame())) {
Element* clearButton = searchControlFrame->GetAnonClearButton();
if (clearButton &&
aVisitor.mEvent->mOriginalTarget == clearButton) {
SetUserInput(EmptyString(),
*nsContentUtils::GetSystemPrincipal());
// TODO(emilio): This should focus the input, but calling
// SetFocus(this, FLAG_NOSCROLL) for some reason gets us into
// an inconsistent state where we're focused but don't match
// :focus-visible / :focus.
}
}
} else if (mType == FormControlType::InputPassword) {
if (nsTextControlFrame* textControlFrame =
do_QueryFrame(GetPrimaryFrame())) {
auto* showPassword = textControlFrame->GetShowPasswordButton();
if (showPassword &&
aVisitor.mEvent->mOriginalTarget == showPassword) {
SetShowPassword(!ShowPassword());
// TODO(emilio): This should focus the input, but calling
// SetFocus(this, FLAG_NOSCROLL) for some reason gets us into
// an inconsistent state where we're focused but don't match
// :focus-visible / :focus.
}
}
}
}
@@ -5946,19 +5965,16 @@ EventStates HTMLInputElement::IntrinsicState() const {
}
}
if (PlaceholderApplies() && HasAttr(nsGkAtoms::placeholder) &&
ShouldShowPlaceholder()) {
state |= NS_EVENT_STATE_PLACEHOLDERSHOWN;
if (mType != FormControlType::InputFile && IsValueEmpty()) {
state |= NS_EVENT_STATE_VALUE_EMPTY;
if (PlaceholderApplies() && HasAttr(nsGkAtoms::placeholder)) {
state |= NS_EVENT_STATE_PLACEHOLDERSHOWN;
}
}
return state;
}
bool HTMLInputElement::ShouldShowPlaceholder() const {
MOZ_ASSERT(PlaceholderApplies());
return IsValueEmpty();
}
static nsTArray<OwningFileOrDirectory> RestoreFileContentData(
nsPIDOMWindowInner* aWindow, const nsTArray<FileContentData>& aData) {
nsTArray<OwningFileOrDirectory> res(aData.Length());
@@ -6666,19 +6682,9 @@ void HTMLInputElement::OnValueChanged(ValueChangeKind aKind) {
SetDirectionFromValue(true);
}
// :placeholder-shown pseudo-class may change when the value changes.
// However, we don't want to waste cycles if the state doesn't apply.
if (PlaceholderApplies() && HasAttr(nsGkAtoms::placeholder)) {
UpdateState(true);
}
// Update clear button state on search inputs
if (mType == FormControlType::InputSearch) {
if (nsSearchControlFrame* searchControlFrame =
do_QueryFrame(GetPrimaryFrame())) {
searchControlFrame->UpdateClearButtonState();
}
}
// :placeholder-shown and value-empty pseudo-class may change when the value
// changes.
UpdateState(true);
}
bool HTMLInputElement::HasCachedSelection() {
@@ -6691,6 +6697,24 @@ bool HTMLInputElement::HasCachedSelection() {
state->GetSelectionProperties().GetEnd();
}
void HTMLInputElement::SetShowPassword(bool aValue) {
if (NS_WARN_IF(mType != FormControlType::InputPassword)) {
return;
}
if (aValue) {
AddStates(NS_EVENT_STATE_REVEALED);
} else {
RemoveStates(NS_EVENT_STATE_REVEALED);
}
}
bool HTMLInputElement::ShowPassword() const {
if (NS_WARN_IF(mType != FormControlType::InputPassword)) {
return false;
}
return State().HasState(NS_EVENT_STATE_REVEALED);
}
void HTMLInputElement::FieldSetDisabledChanged(bool aNotify) {
// This *has* to be called *before* UpdateBarredFromConstraintValidation and
// UpdateValueMissingValidityState because these two functions depend on our