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