1 : /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is Mozilla Foundation
18 : * Portions created by the Initial Developer are Copyright (C) 2010
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Mounir Lamouri <mounir.lamouri@mozilla.com> (original author)
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #include "nsIConstraintValidation.h"
39 :
40 : #include "nsAString.h"
41 : #include "nsGenericHTMLElement.h"
42 : #include "nsHTMLFormElement.h"
43 : #include "nsDOMValidityState.h"
44 : #include "nsIFormControl.h"
45 : #include "nsHTMLFormElement.h"
46 : #include "nsContentUtils.h"
47 :
48 : const PRUint16 nsIConstraintValidation::sContentSpecifiedMaxLengthMessage = 256;
49 :
50 1 : nsIConstraintValidation::nsIConstraintValidation()
51 : : mValidityBitField(0)
52 : , mValidity(nsnull)
53 : // By default, all elements are subjects to constraint validation.
54 1 : , mBarredFromConstraintValidation(false)
55 : {
56 1 : }
57 :
58 2 : nsIConstraintValidation::~nsIConstraintValidation()
59 : {
60 1 : if (mValidity) {
61 0 : mValidity->Disconnect();
62 : }
63 2 : }
64 :
65 : nsresult
66 0 : nsIConstraintValidation::GetValidity(nsIDOMValidityState** aValidity)
67 : {
68 0 : if (!mValidity) {
69 0 : mValidity = new nsDOMValidityState(this);
70 : }
71 :
72 0 : NS_ADDREF(*aValidity = mValidity);
73 :
74 0 : return NS_OK;
75 : }
76 :
77 : NS_IMETHODIMP
78 0 : nsIConstraintValidation::GetValidationMessage(nsAString& aValidationMessage)
79 : {
80 0 : aValidationMessage.Truncate();
81 :
82 0 : if (IsCandidateForConstraintValidation() && !IsValid()) {
83 0 : nsCOMPtr<nsIContent> content = do_QueryInterface(this);
84 0 : NS_ASSERTION(content, "This class should be inherited by HTML elements only!");
85 :
86 0 : nsAutoString authorMessage;
87 0 : content->GetAttr(kNameSpaceID_None, nsGkAtoms::x_moz_errormessage,
88 0 : authorMessage);
89 :
90 0 : if (!authorMessage.IsEmpty()) {
91 0 : aValidationMessage.Assign(authorMessage);
92 0 : if (aValidationMessage.Length() > sContentSpecifiedMaxLengthMessage) {
93 0 : aValidationMessage.Truncate(sContentSpecifiedMaxLengthMessage);
94 : }
95 0 : } else if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR)) {
96 0 : aValidationMessage.Assign(mCustomValidity);
97 0 : if (aValidationMessage.Length() > sContentSpecifiedMaxLengthMessage) {
98 0 : aValidationMessage.Truncate(sContentSpecifiedMaxLengthMessage);
99 : }
100 0 : } else if (GetValidityState(VALIDITY_STATE_TOO_LONG)) {
101 0 : GetValidationMessage(aValidationMessage, VALIDITY_STATE_TOO_LONG);
102 0 : } else if (GetValidityState(VALIDITY_STATE_VALUE_MISSING)) {
103 0 : GetValidationMessage(aValidationMessage, VALIDITY_STATE_VALUE_MISSING);
104 0 : } else if (GetValidityState(VALIDITY_STATE_TYPE_MISMATCH)) {
105 0 : GetValidationMessage(aValidationMessage, VALIDITY_STATE_TYPE_MISMATCH);
106 0 : } else if (GetValidityState(VALIDITY_STATE_PATTERN_MISMATCH)) {
107 0 : GetValidationMessage(aValidationMessage, VALIDITY_STATE_PATTERN_MISMATCH);
108 : } else {
109 : // TODO: The other messages have not been written
110 : // because related constraint validation are not implemented yet.
111 : // We should not be here.
112 0 : return NS_ERROR_UNEXPECTED;
113 : }
114 : } else {
115 0 : aValidationMessage.Truncate();
116 : }
117 :
118 0 : return NS_OK;
119 : }
120 :
121 : nsresult
122 0 : nsIConstraintValidation::CheckValidity(bool* aValidity)
123 : {
124 0 : if (!IsCandidateForConstraintValidation() || IsValid()) {
125 0 : *aValidity = true;
126 0 : return NS_OK;
127 : }
128 :
129 0 : *aValidity = false;
130 :
131 0 : nsCOMPtr<nsIContent> content = do_QueryInterface(this);
132 0 : NS_ASSERTION(content, "This class should be inherited by HTML elements only!");
133 :
134 0 : return nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content,
135 0 : NS_LITERAL_STRING("invalid"),
136 0 : false, true);
137 : }
138 :
139 : void
140 7 : nsIConstraintValidation::SetValidityState(ValidityStateType aState,
141 : bool aValue)
142 : {
143 7 : bool previousValidity = IsValid();
144 :
145 7 : if (aValue) {
146 0 : mValidityBitField |= aState;
147 : } else {
148 7 : mValidityBitField &= ~aState;
149 : }
150 :
151 : // Inform the form element if our validity has changed.
152 7 : if (previousValidity != IsValid() && IsCandidateForConstraintValidation()) {
153 0 : nsCOMPtr<nsIFormControl> formCtrl = do_QueryInterface(this);
154 0 : NS_ASSERTION(formCtrl, "This interface should be used by form elements!");
155 :
156 : nsHTMLFormElement* form =
157 0 : static_cast<nsHTMLFormElement*>(formCtrl->GetFormElement());
158 0 : if (form) {
159 0 : form->UpdateValidity(IsValid());
160 : }
161 : }
162 7 : }
163 :
164 : void
165 0 : nsIConstraintValidation::SetCustomValidity(const nsAString& aError)
166 : {
167 0 : mCustomValidity.Assign(aError);
168 0 : SetValidityState(VALIDITY_STATE_CUSTOM_ERROR, !mCustomValidity.IsEmpty());
169 0 : }
170 :
171 : void
172 4 : nsIConstraintValidation::SetBarredFromConstraintValidation(bool aBarred)
173 : {
174 4 : bool previousBarred = mBarredFromConstraintValidation;
175 :
176 4 : mBarredFromConstraintValidation = aBarred;
177 :
178 : // Inform the form element if our status regarding constraint validation
179 : // is going to change.
180 4 : if (!IsValid() && previousBarred != mBarredFromConstraintValidation) {
181 0 : nsCOMPtr<nsIFormControl> formCtrl = do_QueryInterface(this);
182 0 : NS_ASSERTION(formCtrl, "This interface should be used by form elements!");
183 :
184 : nsHTMLFormElement* form =
185 0 : static_cast<nsHTMLFormElement*>(formCtrl->GetFormElement());
186 0 : if (form) {
187 : // If the element is going to be barred from constraint validation,
188 : // we can inform the form that we are now valid.
189 : // Otherwise, we are now invalid.
190 0 : form->UpdateValidity(aBarred);
191 : }
192 : }
193 4 : }
194 :
|