nsIConstraintValidation.cpp (4463B)
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/. */ 6 7 #include "nsIConstraintValidation.h" 8 9 #include "mozilla/dom/CustomEvent.h" 10 #include "mozilla/dom/HTMLFieldSetElement.h" 11 #include "mozilla/dom/HTMLFormElement.h" 12 #include "mozilla/dom/HTMLInputElement.h" 13 #include "mozilla/dom/ValidityState.h" 14 #include "nsContentUtils.h" 15 #include "nsGenericHTMLElement.h" 16 #include "nsIFormControl.h" 17 #include "nsISimpleEnumerator.h" 18 19 const uint16_t nsIConstraintValidation::sContentSpecifiedMaxLengthMessage = 256; 20 21 using namespace mozilla; 22 using namespace mozilla::dom; 23 24 nsIConstraintValidation::nsIConstraintValidation() 25 : mValidityBitField(0) 26 // By default, all elements are subjects to constraint validation. 27 , 28 mBarredFromConstraintValidation(false) {} 29 30 nsIConstraintValidation::~nsIConstraintValidation() = default; 31 32 mozilla::dom::ValidityState* nsIConstraintValidation::Validity() { 33 if (!mValidity) { 34 mValidity = new mozilla::dom::ValidityState(this); 35 } 36 37 return mValidity; 38 } 39 40 bool nsIConstraintValidation::CheckValidity(nsIContent& aEventTarget, 41 bool* aEventDefaultAction) const { 42 if (!IsCandidateForConstraintValidation() || IsValid()) { 43 return true; 44 } 45 46 nsContentUtils::DispatchTrustedEvent( 47 aEventTarget.OwnerDoc(), &aEventTarget, u"invalid"_ns, CanBubble::eNo, 48 Cancelable::eYes, Composed::eDefault, aEventDefaultAction); 49 return false; 50 } 51 52 bool nsIConstraintValidation::ReportValidity() { 53 nsCOMPtr<Element> element = do_QueryInterface(this); 54 MOZ_ASSERT(element, "This class should be inherited by HTML elements only!"); 55 56 bool defaultAction = true; 57 if (CheckValidity(*element, &defaultAction)) { 58 return true; 59 } 60 61 if (!defaultAction) { 62 return false; 63 } 64 65 AutoTArray<RefPtr<Element>, 1> invalidElements; 66 invalidElements.AppendElement(element); 67 68 AutoJSAPI jsapi; 69 if (!jsapi.Init(element->GetOwnerGlobal())) { 70 return false; 71 } 72 JS::Rooted<JS::Value> detail(jsapi.cx()); 73 if (!ToJSValue(jsapi.cx(), invalidElements, &detail)) { 74 return false; 75 } 76 77 RefPtr<CustomEvent> event = 78 NS_NewDOMCustomEvent(element->OwnerDoc(), nullptr, nullptr); 79 event->InitCustomEvent(jsapi.cx(), u"MozInvalidForm"_ns, 80 /* CanBubble */ true, 81 /* Cancelable */ true, detail); 82 event->SetTrusted(true); 83 event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true; 84 85 element->DispatchEvent(*event); 86 return false; 87 } 88 89 void nsIConstraintValidation::SetValidityState(ValidityStateType aState, 90 bool aValue) { 91 bool previousValidity = IsValid(); 92 93 if (aValue) { 94 mValidityBitField |= aState; 95 } else { 96 mValidityBitField &= ~aState; 97 } 98 99 // Inform the form and fieldset elements if our validity has changed. 100 if (previousValidity != IsValid() && IsCandidateForConstraintValidation()) { 101 nsCOMPtr<nsIFormControl> formCtrl = do_QueryInterface(this); 102 NS_ASSERTION(formCtrl, "This interface should be used by form elements!"); 103 104 if (HTMLFormElement* form = formCtrl->GetForm()) { 105 form->UpdateValidity(IsValid()); 106 } 107 if (HTMLFieldSetElement* fieldSet = formCtrl->GetFieldSet()) { 108 fieldSet->UpdateValidity(IsValid()); 109 } 110 } 111 } 112 113 void nsIConstraintValidation::SetBarredFromConstraintValidation(bool aBarred) { 114 bool previousBarred = mBarredFromConstraintValidation; 115 116 mBarredFromConstraintValidation = aBarred; 117 118 // Inform the form and fieldset elements if our status regarding constraint 119 // validation is going to change. 120 if (!IsValid() && previousBarred != mBarredFromConstraintValidation) { 121 nsCOMPtr<nsIFormControl> formCtrl = do_QueryInterface(this); 122 NS_ASSERTION(formCtrl, "This interface should be used by form elements!"); 123 124 // If the element is going to be barred from constraint validation, we can 125 // inform the form and fieldset that we are now valid. Otherwise, we are now 126 // invalid. 127 if (HTMLFormElement* form = formCtrl->GetForm()) { 128 form->UpdateValidity(aBarred); 129 } 130 HTMLFieldSetElement* fieldSet = formCtrl->GetFieldSet(); 131 if (fieldSet) { 132 fieldSet->UpdateValidity(aBarred); 133 } 134 } 135 }