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 #ifndef mozilla_dom_HTMLTextAreaElement_h 8 #define mozilla_dom_HTMLTextAreaElement_h 9 10 #include "mozilla/Attributes.h" 11 #include "mozilla/TextControlElement.h" 12 #include "mozilla/TextControlState.h" 13 #include "mozilla/TextEditor.h" 14 #include "mozilla/dom/ConstraintValidation.h" 15 #include "mozilla/dom/HTMLFormElement.h" 16 #include "mozilla/dom/HTMLInputElementBinding.h" 17 #include "nsIControllers.h" 18 #include "nsCOMPtr.h" 19 #include "nsGenericHTMLElement.h" 20 #include "nsStubMutationObserver.h" 21 #include "nsGkAtoms.h" 22 23 class nsIControllers; 24 class nsPresContext; 25 26 namespace mozilla { 27 28 class EventChainPostVisitor; 29 class EventChainPreVisitor; 30 class EventStates; 31 class PresState; 32 33 namespace dom { 34 35 class FormData; 36 37 class HTMLTextAreaElement final : public TextControlElement, 38 public nsStubMutationObserver, 39 public ConstraintValidation { 40 public: 41 using ConstraintValidation::GetValidationMessage; 42 using ValueSetterOption = TextControlState::ValueSetterOption; 43 using ValueSetterOptions = TextControlState::ValueSetterOptions; 44 45 explicit HTMLTextAreaElement( 46 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, 47 FromParser aFromParser = NOT_FROM_PARSER); 48 49 // nsISupports 50 NS_DECL_ISUPPORTS_INHERITED 51 52 NS_IMPL_FROMNODE_HTML_WITH_TAG(HTMLTextAreaElement, textarea) 53 54 virtual int32_t TabIndexDefault() override; 55 56 // Element IsInteractiveHTMLContent()57 virtual bool IsInteractiveHTMLContent() const override { return true; } 58 59 // nsGenericHTMLElement 60 virtual bool IsDisabledForEvents(WidgetEvent* aEvent) override; 61 62 // nsGenericHTMLFormElement 63 void SaveState() override; 64 bool RestoreState(PresState* aState) override; 65 66 // nsIFormControl 67 MOZ_CAN_RUN_SCRIPT_BOUNDARY 68 NS_IMETHOD Reset() override; 69 NS_IMETHOD SubmitNamesValues(FormData* aFormData) override; 70 71 virtual void FieldSetDisabledChanged(bool aNotify) override; 72 73 virtual EventStates IntrinsicState() const override; 74 75 void SetLastValueChangeWasInteractive(bool); 76 77 // TextControlElement 78 virtual nsresult SetValueChanged(bool aValueChanged) override; 79 virtual bool IsSingleLineTextControl() const override; 80 virtual bool IsTextArea() const override; 81 virtual bool IsPasswordTextControl() const override; 82 virtual int32_t GetCols() override; 83 virtual int32_t GetWrapCols() override; 84 virtual int32_t GetRows() override; 85 virtual void GetDefaultValueFromContent(nsAString& aValue) override; 86 virtual bool ValueChanged() const override; 87 virtual void GetTextEditorValue(nsAString& aValue, 88 bool aIgnoreWrap) const override; 89 MOZ_CAN_RUN_SCRIPT virtual TextEditor* GetTextEditor() override; 90 virtual TextEditor* GetTextEditorWithoutCreation() override; 91 virtual nsISelectionController* GetSelectionController() override; 92 virtual nsFrameSelection* GetConstFrameSelection() override; GetTextControlState()93 virtual TextControlState* GetTextControlState() const override { 94 return mState; 95 } 96 virtual nsresult BindToFrame(nsTextControlFrame* aFrame) override; 97 MOZ_CAN_RUN_SCRIPT virtual void UnbindFromFrame( 98 nsTextControlFrame* aFrame) override; 99 MOZ_CAN_RUN_SCRIPT virtual nsresult CreateEditor() override; 100 virtual void SetPreviewValue(const nsAString& aValue) override; 101 virtual void GetPreviewValue(nsAString& aValue) override; 102 virtual void EnablePreview() override; 103 virtual bool IsPreviewEnabled() override; 104 virtual void InitializeKeyboardEventListeners() override; 105 virtual void OnValueChanged(ValueChangeKind) override; 106 virtual void GetValueFromSetRangeText(nsAString& aValue) override; 107 MOZ_CAN_RUN_SCRIPT virtual nsresult SetValueFromSetRangeText( 108 const nsAString& aValue) override; 109 virtual bool HasCachedSelection() override; 110 111 // nsIContent 112 virtual nsresult BindToTree(BindContext&, nsINode& aParent) override; 113 virtual void UnbindFromTree(bool aNullParent = true) override; 114 virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, 115 const nsAString& aValue, 116 nsIPrincipal* aMaybeScriptedPrincipal, 117 nsAttrValue& aResult) override; 118 virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() 119 const override; 120 virtual nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute, 121 int32_t aModType) const override; 122 NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override; 123 124 void GetEventTargetParent(EventChainPreVisitor& aVisitor) override; 125 virtual nsresult PreHandleEvent(EventChainVisitor& aVisitor) override; 126 virtual nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override; 127 128 virtual bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, 129 int32_t* aTabIndex) override; 130 131 virtual void DoneAddingChildren(bool aHaveNotified) override; 132 virtual bool IsDoneAddingChildren() override; 133 134 MOZ_CAN_RUN_SCRIPT_BOUNDARY 135 virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override; 136 137 nsresult CopyInnerTo(Element* aDest); 138 139 /** 140 * Called when an attribute is about to be changed 141 */ 142 virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName, 143 const nsAttrValueOrString* aValue, 144 bool aNotify) override; 145 146 // nsIMutationObserver 147 NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED 148 NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED 149 NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED 150 NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED 151 152 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLTextAreaElement, 153 TextControlElement) 154 155 // nsIConstraintValidation 156 bool IsTooLong(); 157 bool IsTooShort(); 158 bool IsValueMissing() const; 159 void UpdateTooLongValidityState(); 160 void UpdateTooShortValidityState(); 161 void UpdateValueMissingValidityState(); 162 void UpdateBarredFromConstraintValidation(); 163 164 // ConstraintValidation 165 nsresult GetValidationMessage(nsAString& aValidationMessage, 166 ValidityStateType aType) override; 167 168 // Web IDL binding methods 169 void GetAutocomplete(DOMString& aValue); SetAutocomplete(const nsAString & aValue,ErrorResult & aRv)170 void SetAutocomplete(const nsAString& aValue, ErrorResult& aRv) { 171 SetHTMLAttr(nsGkAtoms::autocomplete, aValue, aRv); 172 } Autofocus()173 bool Autofocus() { return GetBoolAttr(nsGkAtoms::autofocus); } SetAutofocus(bool aAutoFocus,ErrorResult & aError)174 void SetAutofocus(bool aAutoFocus, ErrorResult& aError) { 175 SetHTMLBoolAttr(nsGkAtoms::autofocus, aAutoFocus, aError); 176 } Cols()177 uint32_t Cols() { return GetUnsignedIntAttr(nsGkAtoms::cols, DEFAULT_COLS); } SetCols(uint32_t aCols,ErrorResult & aError)178 void SetCols(uint32_t aCols, ErrorResult& aError) { 179 uint32_t cols = aCols ? aCols : DEFAULT_COLS; 180 SetUnsignedIntAttr(nsGkAtoms::cols, cols, DEFAULT_COLS, aError); 181 } Disabled()182 bool Disabled() { return GetBoolAttr(nsGkAtoms::disabled); } SetDisabled(bool aDisabled,ErrorResult & aError)183 void SetDisabled(bool aDisabled, ErrorResult& aError) { 184 SetHTMLBoolAttr(nsGkAtoms::disabled, aDisabled, aError); 185 } 186 // nsGenericHTMLFormControlElementWithState::GetForm is fine 187 using nsGenericHTMLFormControlElementWithState::GetForm; MaxLength()188 int32_t MaxLength() const { return GetIntAttr(nsGkAtoms::maxlength, -1); } UsedMaxLength()189 int32_t UsedMaxLength() const final { return MaxLength(); } SetMaxLength(int32_t aMaxLength,ErrorResult & aError)190 void SetMaxLength(int32_t aMaxLength, ErrorResult& aError) { 191 int32_t minLength = MinLength(); 192 if (aMaxLength < 0 || (minLength >= 0 && aMaxLength < minLength)) { 193 aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); 194 } else { 195 SetHTMLIntAttr(nsGkAtoms::maxlength, aMaxLength, aError); 196 } 197 } MinLength()198 int32_t MinLength() const { return GetIntAttr(nsGkAtoms::minlength, -1); } SetMinLength(int32_t aMinLength,ErrorResult & aError)199 void SetMinLength(int32_t aMinLength, ErrorResult& aError) { 200 int32_t maxLength = MaxLength(); 201 if (aMinLength < 0 || (maxLength >= 0 && aMinLength > maxLength)) { 202 aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); 203 } else { 204 SetHTMLIntAttr(nsGkAtoms::minlength, aMinLength, aError); 205 } 206 } GetName(nsAString & aName)207 void GetName(nsAString& aName) { GetHTMLAttr(nsGkAtoms::name, aName); } SetName(const nsAString & aName,ErrorResult & aError)208 void SetName(const nsAString& aName, ErrorResult& aError) { 209 SetHTMLAttr(nsGkAtoms::name, aName, aError); 210 } GetPlaceholder(nsAString & aPlaceholder)211 void GetPlaceholder(nsAString& aPlaceholder) { 212 GetHTMLAttr(nsGkAtoms::placeholder, aPlaceholder); 213 } SetPlaceholder(const nsAString & aPlaceholder,ErrorResult & aError)214 void SetPlaceholder(const nsAString& aPlaceholder, ErrorResult& aError) { 215 SetHTMLAttr(nsGkAtoms::placeholder, aPlaceholder, aError); 216 } ReadOnly()217 bool ReadOnly() { return GetBoolAttr(nsGkAtoms::readonly); } SetReadOnly(bool aReadOnly,ErrorResult & aError)218 void SetReadOnly(bool aReadOnly, ErrorResult& aError) { 219 SetHTMLBoolAttr(nsGkAtoms::readonly, aReadOnly, aError); 220 } Required()221 bool Required() const { return State().HasState(NS_EVENT_STATE_REQUIRED); } 222 223 MOZ_CAN_RUN_SCRIPT void SetRangeText(const nsAString& aReplacement, 224 ErrorResult& aRv); 225 226 MOZ_CAN_RUN_SCRIPT void SetRangeText(const nsAString& aReplacement, 227 uint32_t aStart, uint32_t aEnd, 228 SelectionMode aSelectMode, 229 ErrorResult& aRv); 230 SetRequired(bool aRequired,ErrorResult & aError)231 void SetRequired(bool aRequired, ErrorResult& aError) { 232 SetHTMLBoolAttr(nsGkAtoms::required, aRequired, aError); 233 } Rows()234 uint32_t Rows() { 235 return GetUnsignedIntAttr(nsGkAtoms::rows, DEFAULT_ROWS_TEXTAREA); 236 } SetRows(uint32_t aRows,ErrorResult & aError)237 void SetRows(uint32_t aRows, ErrorResult& aError) { 238 uint32_t rows = aRows ? aRows : DEFAULT_ROWS_TEXTAREA; 239 SetUnsignedIntAttr(nsGkAtoms::rows, rows, DEFAULT_ROWS_TEXTAREA, aError); 240 } GetWrap(nsAString & aWrap)241 void GetWrap(nsAString& aWrap) { GetHTMLAttr(nsGkAtoms::wrap, aWrap); } SetWrap(const nsAString & aWrap,ErrorResult & aError)242 void SetWrap(const nsAString& aWrap, ErrorResult& aError) { 243 SetHTMLAttr(nsGkAtoms::wrap, aWrap, aError); 244 } 245 void GetType(nsAString& aType); 246 void GetDefaultValue(nsAString& aDefaultValue, ErrorResult& aError); 247 void SetDefaultValue(const nsAString& aDefaultValue, ErrorResult& aError); 248 void GetValue(nsAString& aValue); 249 /** 250 * ValueEquals() is designed for internal use so that aValue shouldn't 251 * include \r character. It should be handled before calling this with 252 * nsContentUtils::PlatformToDOMLineBreaks(). 253 */ 254 bool ValueEquals(const nsAString& aValue) const; 255 MOZ_CAN_RUN_SCRIPT_BOUNDARY void SetValue(const nsAString& aValue, 256 ErrorResult& aError); 257 258 uint32_t GetTextLength(); 259 260 // Override SetCustomValidity so we update our state properly when it's called 261 // via bindings. 262 void SetCustomValidity(const nsAString& aError); 263 264 MOZ_CAN_RUN_SCRIPT void Select(); 265 Nullable<uint32_t> GetSelectionStart(ErrorResult& aError); 266 MOZ_CAN_RUN_SCRIPT void SetSelectionStart( 267 const Nullable<uint32_t>& aSelectionStart, ErrorResult& aError); 268 Nullable<uint32_t> GetSelectionEnd(ErrorResult& aError); 269 MOZ_CAN_RUN_SCRIPT void SetSelectionEnd( 270 const Nullable<uint32_t>& aSelectionEnd, ErrorResult& aError); 271 void GetSelectionDirection(nsAString& aDirection, ErrorResult& aError); 272 MOZ_CAN_RUN_SCRIPT void SetSelectionDirection(const nsAString& aDirection, 273 ErrorResult& aError); 274 MOZ_CAN_RUN_SCRIPT void SetSelectionRange( 275 uint32_t aSelectionStart, uint32_t aSelectionEnd, 276 const Optional<nsAString>& aDirecton, ErrorResult& aError); 277 nsIControllers* GetControllers(ErrorResult& aError); 278 // XPCOM adapter function widely used throughout code, leaving it as is. 279 nsresult GetControllers(nsIControllers** aResult); 280 281 MOZ_CAN_RUN_SCRIPT nsIEditor* GetEditorForBindings(); HasEditor()282 bool HasEditor() { 283 MOZ_ASSERT(mState); 284 return !!mState->GetTextEditorWithoutCreation(); 285 } 286 IsInputEventTarget()287 bool IsInputEventTarget() const { return true; } 288 289 MOZ_CAN_RUN_SCRIPT_BOUNDARY void SetUserInput( 290 const nsAString& aValue, nsIPrincipal& aSubjectPrincipal); 291 292 protected: 293 MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual ~HTMLTextAreaElement(); 294 295 // get rid of the compiler warning 296 using nsGenericHTMLFormControlElementWithState::IsSingleLineTextControl; 297 298 virtual JSObject* WrapNode(JSContext* aCx, 299 JS::Handle<JSObject*> aGivenProto) override; 300 301 nsCOMPtr<nsIControllers> mControllers; 302 /** Whether or not the value has changed since its default value was given. */ 303 bool mValueChanged; 304 /** Whether or not the last change to the value was made interactively by the 305 * user. */ 306 bool mLastValueChangeWasInteractive; 307 /** Whether or not we are already handling select event. */ 308 bool mHandlingSelect; 309 /** Whether or not we are done adding children (always true if not 310 created by a parser */ 311 bool mDoneAddingChildren; 312 /** Whether state restoration should be inhibited in DoneAddingChildren. */ 313 bool mInhibitStateRestoration; 314 /** Whether our disabled state has changed from the default **/ 315 bool mDisabledChanged; 316 /** Whether we should make :-moz-ui-invalid apply on the element. **/ 317 bool mCanShowInvalidUI; 318 /** Whether we should make :-moz-ui-valid apply on the element. **/ 319 bool mCanShowValidUI; 320 bool mIsPreviewEnabled; 321 322 nsContentUtils::AutocompleteAttrState mAutocompleteAttrState; 323 324 void FireChangeEventIfNeeded(); 325 326 nsString mFocusedValue; 327 328 /** The state of the text editor (selection controller and the editor) **/ 329 TextControlState* mState; 330 331 NS_IMETHOD SelectAll(nsPresContext* aPresContext); 332 /** 333 * Get the value, whether it is from the content or the frame. 334 * @param aValue the value [out] 335 * @param aIgnoreWrap whether to ignore the wrap attribute when getting the 336 * value. If this is true, linebreaks will not be inserted even if 337 * wrap=hard. 338 */ 339 void GetValueInternal(nsAString& aValue, bool aIgnoreWrap) const; 340 341 /** 342 * Setting the value. 343 * 344 * @param aValue String to set. 345 * @param aOptions See TextControlState::ValueSetterOption. 346 */ 347 MOZ_CAN_RUN_SCRIPT nsresult 348 SetValueInternal(const nsAString& aValue, const ValueSetterOptions& aOptions); 349 350 /** 351 * Common method to call from the various mutation observer methods. 352 * aContent is a content node that's either the one that changed or its 353 * parent; we should only respond to the change if aContent is non-anonymous. 354 */ 355 void ContentChanged(nsIContent* aContent); 356 357 virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName, 358 const nsAttrValue* aValue, 359 const nsAttrValue* aOldValue, 360 nsIPrincipal* aSubjectPrincipal, 361 bool aNotify) override; 362 363 /** 364 * Return if an element should have a specific validity UI 365 * (with :-moz-ui-invalid and :-moz-ui-valid pseudo-classes). 366 * 367 * @return Whether the element should have a validity UI. 368 */ ShouldShowValidityUI()369 bool ShouldShowValidityUI() const { 370 /** 371 * Always show the validity UI if the form has already tried to be submitted 372 * but was invalid. 373 * 374 * Otherwise, show the validity UI if the element's value has been changed. 375 */ 376 377 if (mForm && mForm->HasEverTriedInvalidSubmit()) { 378 return true; 379 } 380 381 return mValueChanged; 382 } 383 384 /** 385 * Get the mutable state of the element. 386 */ 387 bool IsMutable() const; 388 389 /** 390 * Returns whether the current value is the empty string. 391 * 392 * @return whether the current value is the empty string. 393 */ 394 bool IsValueEmpty() const; 395 396 /** 397 * A helper to get the current selection range. Will throw on the ErrorResult 398 * if we have no editor state. 399 */ 400 void GetSelectionRange(uint32_t* aSelectionStart, uint32_t* aSelectionEnd, 401 ErrorResult& aRv); 402 403 private: 404 static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes, 405 MappedDeclarations&); 406 }; 407 408 } // namespace dom 409 } // namespace mozilla 410 411 #endif 412