1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsIConstraintValidation.h"
9 #include "nsGenericHTMLElement.h"
10 #include "mozilla/dom/CustomEvent.h"
11 #include "mozilla/dom/HTMLFormElement.h"
12 #include "mozilla/dom/HTMLFieldSetElement.h"
13 #include "mozilla/dom/HTMLInputElement.h"
14 #include "mozilla/dom/ValidityState.h"
15 #include "nsIFormControl.h"
16 #include "nsISimpleEnumerator.h"
17 #include "nsContentUtils.h"
19 const uint16_t nsIConstraintValidation::sContentSpecifiedMaxLengthMessage
= 256;
21 using namespace mozilla
;
22 using namespace mozilla::dom
;
24 nsIConstraintValidation::nsIConstraintValidation()
25 : mValidityBitField(0)
26 // By default, all elements are subjects to constraint validation.
28 mBarredFromConstraintValidation(false) {}
30 nsIConstraintValidation::~nsIConstraintValidation() = default;
32 mozilla::dom::ValidityState
* nsIConstraintValidation::Validity() {
34 mValidity
= new mozilla::dom::ValidityState(this);
40 bool nsIConstraintValidation::CheckValidity(nsIContent
& aEventTarget
,
41 bool* aEventDefaultAction
) const {
42 if (!IsCandidateForConstraintValidation() || IsValid()) {
46 nsContentUtils::DispatchTrustedEvent(
47 aEventTarget
.OwnerDoc(), &aEventTarget
, u
"invalid"_ns
, CanBubble::eNo
,
48 Cancelable::eYes
, Composed::eDefault
, aEventDefaultAction
);
52 bool nsIConstraintValidation::ReportValidity() {
53 nsCOMPtr
<Element
> element
= do_QueryInterface(this);
54 MOZ_ASSERT(element
, "This class should be inherited by HTML elements only!");
56 bool defaultAction
= true;
57 if (CheckValidity(*element
, &defaultAction
)) {
65 AutoTArray
<RefPtr
<Element
>, 1> invalidElements
;
66 invalidElements
.AppendElement(element
);
69 if (!jsapi
.Init(element
->GetOwnerGlobal())) {
72 JS::Rooted
<JS::Value
> detail(jsapi
.cx());
73 if (!ToJSValue(jsapi
.cx(), invalidElements
, &detail
)) {
77 RefPtr
<CustomEvent
> event
=
78 NS_NewDOMCustomEvent(element
->OwnerDoc(), nullptr, nullptr);
79 event
->InitCustomEvent(jsapi
.cx(), u
"MozInvalidForm"_ns
,
81 /* Cancelable */ true, detail
);
82 event
->SetTrusted(true);
83 event
->WidgetEventPtr()->mFlags
.mOnlyChromeDispatch
= true;
85 element
->DispatchEvent(*event
);
87 auto* inputElement
= HTMLInputElement::FromNode(element
);
88 if (inputElement
&& inputElement
->State().HasState(ElementState::FOCUS
)) {
89 inputElement
->UpdateValidityUIBits(true);
92 element
->UpdateState(true);
96 void nsIConstraintValidation::SetValidityState(ValidityStateType aState
,
98 bool previousValidity
= IsValid();
101 mValidityBitField
|= aState
;
103 mValidityBitField
&= ~aState
;
106 // Inform the form and fieldset elements if our validity has changed.
107 if (previousValidity
!= IsValid() && IsCandidateForConstraintValidation()) {
108 nsCOMPtr
<nsIFormControl
> formCtrl
= do_QueryInterface(this);
109 NS_ASSERTION(formCtrl
, "This interface should be used by form elements!");
111 if (HTMLFormElement
* form
= formCtrl
->GetForm()) {
112 form
->UpdateValidity(IsValid());
114 HTMLFieldSetElement
* fieldSet
= formCtrl
->GetFieldSet();
116 fieldSet
->UpdateValidity(IsValid());
121 void nsIConstraintValidation::SetBarredFromConstraintValidation(bool aBarred
) {
122 bool previousBarred
= mBarredFromConstraintValidation
;
124 mBarredFromConstraintValidation
= aBarred
;
126 // Inform the form and fieldset elements if our status regarding constraint
127 // validation is going to change.
128 if (!IsValid() && previousBarred
!= mBarredFromConstraintValidation
) {
129 nsCOMPtr
<nsIFormControl
> formCtrl
= do_QueryInterface(this);
130 NS_ASSERTION(formCtrl
, "This interface should be used by form elements!");
132 // If the element is going to be barred from constraint validation, we can
133 // inform the form and fieldset that we are now valid. Otherwise, we are now
135 if (HTMLFormElement
* form
= formCtrl
->GetForm()) {
136 form
->UpdateValidity(aBarred
);
138 HTMLFieldSetElement
* fieldSet
= formCtrl
->GetFieldSet();
140 fieldSet
->UpdateValidity(aBarred
);