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 "mozilla/dom/HTMLTextAreaElement.h"
8 
9 #include "mozAutoDocUpdate.h"
10 #include "mozilla/AsyncEventDispatcher.h"
11 #include "mozilla/Attributes.h"
12 #include "mozilla/dom/FormData.h"
13 #include "mozilla/dom/HTMLTextAreaElementBinding.h"
14 #include "mozilla/dom/MutationEventBinding.h"
15 #include "mozilla/EventDispatcher.h"
16 #include "mozilla/EventStates.h"
17 #include "mozilla/MappedDeclarations.h"
18 #include "mozilla/MouseEvents.h"
19 #include "mozilla/PresState.h"
20 #include "mozilla/TextControlState.h"
21 #include "nsAttrValueInlines.h"
22 #include "nsBaseCommandController.h"
23 #include "nsContentCID.h"
24 #include "nsContentCreatorFunctions.h"
25 #include "nsError.h"
26 #include "nsFocusManager.h"
27 #include "nsIConstraintValidation.h"
28 #include "nsIControllers.h"
29 #include "mozilla/dom/Document.h"
30 #include "nsIFormControlFrame.h"
31 #include "nsIFormControl.h"
32 #include "nsIFrame.h"
33 #include "nsITextControlFrame.h"
34 #include "nsLayoutUtils.h"
35 #include "nsLinebreakConverter.h"
36 #include "nsMappedAttributes.h"
37 #include "nsPIDOMWindow.h"
38 #include "nsPresContext.h"
39 #include "nsReadableUtils.h"
40 #include "nsStyleConsts.h"
41 #include "nsTextControlFrame.h"
42 #include "nsXULControllers.h"
43 
44 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(TextArea)
45 
46 namespace mozilla::dom {
47 
HTMLTextAreaElement(already_AddRefed<mozilla::dom::NodeInfo> && aNodeInfo,FromParser aFromParser)48 HTMLTextAreaElement::HTMLTextAreaElement(
49     already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
50     FromParser aFromParser)
51     : TextControlElement(std::move(aNodeInfo), aFromParser,
52                          FormControlType::Textarea),
53       mValueChanged(false),
54       mLastValueChangeWasInteractive(false),
55       mHandlingSelect(false),
56       mDoneAddingChildren(!aFromParser),
57       mInhibitStateRestoration(!!(aFromParser & FROM_PARSER_FRAGMENT)),
58       mDisabledChanged(false),
59       mCanShowInvalidUI(true),
60       mCanShowValidUI(true),
61       mIsPreviewEnabled(false),
62       mAutocompleteAttrState(nsContentUtils::eAutocompleteAttrState_Unknown),
63       mState(TextControlState::Construct(this)) {
64   AddMutationObserver(this);
65 
66   // Set up our default state.  By default we're enabled (since we're
67   // a control type that can be disabled but not actually disabled
68   // right now), optional, and valid.  We are NOT readwrite by default
69   // until someone calls UpdateEditableState on us, apparently!  Also
70   // by default we don't have to show validity UI and so forth.
71   AddStatesSilently(NS_EVENT_STATE_ENABLED | NS_EVENT_STATE_OPTIONAL |
72                     NS_EVENT_STATE_VALID);
73 }
74 
~HTMLTextAreaElement()75 HTMLTextAreaElement::~HTMLTextAreaElement() {
76   mState->Destroy();
77   mState = nullptr;
78 }
79 
80 NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLTextAreaElement)
81 
82 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLTextAreaElement,
83                                                   TextControlElement)
84   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
85   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControllers)
86   if (tmp->mState) {
87     tmp->mState->Traverse(cb);
88   }
89 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
90 
91 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLTextAreaElement,
92                                                 TextControlElement)
93   NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
94   NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)
95   if (tmp->mState) {
96     tmp->mState->Unlink();
97   }
98 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
99 
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLTextAreaElement,TextControlElement,nsIMutationObserver,nsIConstraintValidation)100 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLTextAreaElement,
101                                              TextControlElement,
102                                              nsIMutationObserver,
103                                              nsIConstraintValidation)
104 
105 // nsIDOMHTMLTextAreaElement
106 
107 nsresult HTMLTextAreaElement::Clone(dom::NodeInfo* aNodeInfo,
108                                     nsINode** aResult) const {
109   *aResult = nullptr;
110   RefPtr<HTMLTextAreaElement> it = new (aNodeInfo->NodeInfoManager())
111       HTMLTextAreaElement(do_AddRef(aNodeInfo));
112 
113   nsresult rv = const_cast<HTMLTextAreaElement*>(this)->CopyInnerTo(it);
114   NS_ENSURE_SUCCESS(rv, rv);
115 
116   if (mValueChanged) {
117     // Set our value on the clone.
118     nsAutoString value;
119     GetValueInternal(value, true);
120 
121     // SetValueInternal handles setting mValueChanged for us
122     if (NS_WARN_IF(
123             NS_FAILED(rv = it->SetValueInternal(
124                           value, {ValueSetterOption::SetValueChanged})))) {
125       return rv;
126     }
127   }
128 
129   it->SetLastValueChangeWasInteractive(mLastValueChangeWasInteractive);
130   it.forget(aResult);
131   return NS_OK;
132 }
133 
134 // nsIContent
135 
Select()136 void HTMLTextAreaElement::Select() {
137   if (FocusState() != FocusTristate::eUnfocusable) {
138     if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
139       fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
140     }
141   }
142 
143   SetSelectionRange(0, UINT32_MAX, mozilla::dom::Optional<nsAString>(),
144                     IgnoreErrors());
145 }
146 
147 NS_IMETHODIMP
SelectAll(nsPresContext * aPresContext)148 HTMLTextAreaElement::SelectAll(nsPresContext* aPresContext) {
149   nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
150 
151   if (formControlFrame) {
152     formControlFrame->SetFormProperty(nsGkAtoms::select, u""_ns);
153   }
154 
155   return NS_OK;
156 }
157 
IsHTMLFocusable(bool aWithMouse,bool * aIsFocusable,int32_t * aTabIndex)158 bool HTMLTextAreaElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
159                                           int32_t* aTabIndex) {
160   if (nsGenericHTMLFormControlElementWithState::IsHTMLFocusable(
161           aWithMouse, aIsFocusable, aTabIndex)) {
162     return true;
163   }
164 
165   // disabled textareas are not focusable
166   *aIsFocusable = !IsDisabled();
167   return false;
168 }
169 
TabIndexDefault()170 int32_t HTMLTextAreaElement::TabIndexDefault() { return 0; }
171 
GetType(nsAString & aType)172 void HTMLTextAreaElement::GetType(nsAString& aType) {
173   aType.AssignLiteral("textarea");
174 }
175 
GetValue(nsAString & aValue)176 void HTMLTextAreaElement::GetValue(nsAString& aValue) {
177   GetValueInternal(aValue, true);
178   MOZ_ASSERT(aValue.FindChar(static_cast<char16_t>('\r')) == -1);
179 }
180 
GetValueInternal(nsAString & aValue,bool aIgnoreWrap) const181 void HTMLTextAreaElement::GetValueInternal(nsAString& aValue,
182                                            bool aIgnoreWrap) const {
183   MOZ_ASSERT(mState);
184   mState->GetValue(aValue, aIgnoreWrap);
185 }
186 
ValueEquals(const nsAString & aValue) const187 bool HTMLTextAreaElement::ValueEquals(const nsAString& aValue) const {
188   MOZ_ASSERT(mState);
189   return mState->ValueEquals(aValue);
190 }
191 
GetEditorForBindings()192 nsIEditor* HTMLTextAreaElement::GetEditorForBindings() {
193   if (!GetPrimaryFrame()) {
194     GetPrimaryFrame(FlushType::Frames);
195   }
196   return GetTextEditor();
197 }
198 
GetTextEditor()199 TextEditor* HTMLTextAreaElement::GetTextEditor() {
200   MOZ_ASSERT(mState);
201   return mState->GetTextEditor();
202 }
203 
GetTextEditorWithoutCreation()204 TextEditor* HTMLTextAreaElement::GetTextEditorWithoutCreation() {
205   MOZ_ASSERT(mState);
206   return mState->GetTextEditorWithoutCreation();
207 }
208 
GetSelectionController()209 nsISelectionController* HTMLTextAreaElement::GetSelectionController() {
210   MOZ_ASSERT(mState);
211   return mState->GetSelectionController();
212 }
213 
GetConstFrameSelection()214 nsFrameSelection* HTMLTextAreaElement::GetConstFrameSelection() {
215   MOZ_ASSERT(mState);
216   return mState->GetConstFrameSelection();
217 }
218 
BindToFrame(nsTextControlFrame * aFrame)219 nsresult HTMLTextAreaElement::BindToFrame(nsTextControlFrame* aFrame) {
220   MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript());
221   MOZ_ASSERT(mState);
222   return mState->BindToFrame(aFrame);
223 }
224 
UnbindFromFrame(nsTextControlFrame * aFrame)225 void HTMLTextAreaElement::UnbindFromFrame(nsTextControlFrame* aFrame) {
226   MOZ_ASSERT(mState);
227   if (aFrame) {
228     mState->UnbindFromFrame(aFrame);
229   }
230 }
231 
CreateEditor()232 nsresult HTMLTextAreaElement::CreateEditor() {
233   MOZ_ASSERT(mState);
234   return mState->PrepareEditor();
235 }
236 
SetPreviewValue(const nsAString & aValue)237 void HTMLTextAreaElement::SetPreviewValue(const nsAString& aValue) {
238   MOZ_ASSERT(mState);
239   mState->SetPreviewText(aValue, true);
240 }
241 
GetPreviewValue(nsAString & aValue)242 void HTMLTextAreaElement::GetPreviewValue(nsAString& aValue) {
243   MOZ_ASSERT(mState);
244   mState->GetPreviewText(aValue);
245 }
246 
EnablePreview()247 void HTMLTextAreaElement::EnablePreview() {
248   if (mIsPreviewEnabled) {
249     return;
250   }
251 
252   mIsPreviewEnabled = true;
253   // Reconstruct the frame to append an anonymous preview node
254   nsLayoutUtils::PostRestyleEvent(this, RestyleHint{0},
255                                   nsChangeHint_ReconstructFrame);
256 }
257 
IsPreviewEnabled()258 bool HTMLTextAreaElement::IsPreviewEnabled() { return mIsPreviewEnabled; }
259 
SetValueInternal(const nsAString & aValue,const ValueSetterOptions & aOptions)260 nsresult HTMLTextAreaElement::SetValueInternal(
261     const nsAString& aValue, const ValueSetterOptions& aOptions) {
262   MOZ_ASSERT(mState);
263 
264   // Need to set the value changed flag here if our value has in fact changed
265   // (i.e. if ValueSetterOption::SetValueChanged is in aOptions), so that
266   // retrieves the correct value if needed.
267   if (aOptions.contains(ValueSetterOption::SetValueChanged)) {
268     SetValueChanged(true);
269   }
270 
271   if (!mState->SetValue(aValue, aOptions)) {
272     return NS_ERROR_OUT_OF_MEMORY;
273   }
274 
275   return NS_OK;
276 }
277 
SetValue(const nsAString & aValue,ErrorResult & aError)278 void HTMLTextAreaElement::SetValue(const nsAString& aValue,
279                                    ErrorResult& aError) {
280   // If the value has been set by a script, we basically want to keep the
281   // current change event state. If the element is ready to fire a change
282   // event, we should keep it that way. Otherwise, we should make sure the
283   // element will not fire any event because of the script interaction.
284   //
285   // NOTE: this is currently quite expensive work (too much string
286   // manipulation). We should probably optimize that.
287   nsAutoString currentValue;
288   GetValueInternal(currentValue, true);
289 
290   nsresult rv = SetValueInternal(
291       aValue,
292       {ValueSetterOption::ByContentAPI, ValueSetterOption::SetValueChanged,
293        ValueSetterOption::MoveCursorToEndIfValueChanged});
294   if (NS_WARN_IF(NS_FAILED(rv))) {
295     aError.Throw(rv);
296     return;
297   }
298 
299   if (mFocusedValue.Equals(currentValue)) {
300     GetValueInternal(mFocusedValue, true);
301   }
302 }
303 
SetUserInput(const nsAString & aValue,nsIPrincipal & aSubjectPrincipal)304 void HTMLTextAreaElement::SetUserInput(const nsAString& aValue,
305                                        nsIPrincipal& aSubjectPrincipal) {
306   SetValueInternal(aValue, {ValueSetterOption::BySetUserInputAPI,
307                             ValueSetterOption::SetValueChanged,
308                             ValueSetterOption::MoveCursorToEndIfValueChanged});
309 }
310 
SetValueChanged(bool aValueChanged)311 nsresult HTMLTextAreaElement::SetValueChanged(bool aValueChanged) {
312   MOZ_ASSERT(mState);
313 
314   bool previousValue = mValueChanged;
315 
316   mValueChanged = aValueChanged;
317   if (!aValueChanged && !mState->IsEmpty()) {
318     mState->EmptyValue();
319   }
320 
321   if (mValueChanged != previousValue) {
322     UpdateTooLongValidityState();
323     UpdateTooShortValidityState();
324     // We need to do this unconditionally because the validity ui bits depend on
325     // this.
326     UpdateState(true);
327   }
328 
329   return NS_OK;
330 }
331 
SetLastValueChangeWasInteractive(bool aWasInteractive)332 void HTMLTextAreaElement::SetLastValueChangeWasInteractive(
333     bool aWasInteractive) {
334   if (aWasInteractive == mLastValueChangeWasInteractive) {
335     return;
336   }
337   mLastValueChangeWasInteractive = aWasInteractive;
338   const bool wasValid = IsValid();
339   UpdateTooLongValidityState();
340   UpdateTooShortValidityState();
341   if (wasValid != IsValid()) {
342     UpdateState(true);
343   }
344 }
345 
GetDefaultValue(nsAString & aDefaultValue,ErrorResult & aError)346 void HTMLTextAreaElement::GetDefaultValue(nsAString& aDefaultValue,
347                                           ErrorResult& aError) {
348   if (!nsContentUtils::GetNodeTextContent(this, false, aDefaultValue,
349                                           fallible)) {
350     aError.Throw(NS_ERROR_OUT_OF_MEMORY);
351   }
352 }
353 
SetDefaultValue(const nsAString & aDefaultValue,ErrorResult & aError)354 void HTMLTextAreaElement::SetDefaultValue(const nsAString& aDefaultValue,
355                                           ErrorResult& aError) {
356   nsresult rv = nsContentUtils::SetNodeTextContent(this, aDefaultValue, true);
357   if (NS_SUCCEEDED(rv) && !mValueChanged) {
358     Reset();
359   }
360   if (NS_FAILED(rv)) {
361     aError.Throw(rv);
362   }
363 }
364 
ParseAttribute(int32_t aNamespaceID,nsAtom * aAttribute,const nsAString & aValue,nsIPrincipal * aMaybeScriptedPrincipal,nsAttrValue & aResult)365 bool HTMLTextAreaElement::ParseAttribute(int32_t aNamespaceID,
366                                          nsAtom* aAttribute,
367                                          const nsAString& aValue,
368                                          nsIPrincipal* aMaybeScriptedPrincipal,
369                                          nsAttrValue& aResult) {
370   if (aNamespaceID == kNameSpaceID_None) {
371     if (aAttribute == nsGkAtoms::maxlength ||
372         aAttribute == nsGkAtoms::minlength) {
373       return aResult.ParseNonNegativeIntValue(aValue);
374     } else if (aAttribute == nsGkAtoms::cols) {
375       aResult.ParseIntWithFallback(aValue, DEFAULT_COLS);
376       return true;
377     } else if (aAttribute == nsGkAtoms::rows) {
378       aResult.ParseIntWithFallback(aValue, DEFAULT_ROWS_TEXTAREA);
379       return true;
380     } else if (aAttribute == nsGkAtoms::autocomplete) {
381       aResult.ParseAtomArray(aValue);
382       return true;
383     }
384   }
385   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
386                                               aMaybeScriptedPrincipal, aResult);
387 }
388 
MapAttributesIntoRule(const nsMappedAttributes * aAttributes,MappedDeclarations & aDecls)389 void HTMLTextAreaElement::MapAttributesIntoRule(
390     const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls) {
391   // wrap=off
392   if (!aDecls.PropertyIsSet(eCSSProperty_white_space)) {
393     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::wrap);
394     if (value && value->Type() == nsAttrValue::eString &&
395         value->Equals(nsGkAtoms::OFF, eIgnoreCase)) {
396       aDecls.SetKeywordValue(eCSSProperty_white_space, StyleWhiteSpace::Pre);
397     }
398   }
399 
400   nsGenericHTMLFormControlElementWithState::MapDivAlignAttributeInto(
401       aAttributes, aDecls);
402   nsGenericHTMLFormControlElementWithState::MapCommonAttributesInto(aAttributes,
403                                                                     aDecls);
404 }
405 
GetAttributeChangeHint(const nsAtom * aAttribute,int32_t aModType) const406 nsChangeHint HTMLTextAreaElement::GetAttributeChangeHint(
407     const nsAtom* aAttribute, int32_t aModType) const {
408   nsChangeHint retval =
409       nsGenericHTMLFormControlElementWithState::GetAttributeChangeHint(
410           aAttribute, aModType);
411 
412   const bool isAdditionOrRemoval =
413       aModType == MutationEvent_Binding::ADDITION ||
414       aModType == MutationEvent_Binding::REMOVAL;
415 
416   if (aAttribute == nsGkAtoms::rows || aAttribute == nsGkAtoms::cols) {
417     retval |= NS_STYLE_HINT_REFLOW;
418   } else if (aAttribute == nsGkAtoms::wrap) {
419     retval |= nsChangeHint_ReconstructFrame;
420   } else if (aAttribute == nsGkAtoms::placeholder && isAdditionOrRemoval) {
421     retval |= nsChangeHint_ReconstructFrame;
422   }
423   return retval;
424 }
425 
NS_IMETHODIMP_(bool)426 NS_IMETHODIMP_(bool)
427 HTMLTextAreaElement::IsAttributeMapped(const nsAtom* aAttribute) const {
428   static const MappedAttributeEntry attributes[] = {{nsGkAtoms::wrap},
429                                                     {nullptr}};
430 
431   static const MappedAttributeEntry* const map[] = {
432       attributes,
433       sDivAlignAttributeMap,
434       sCommonAttributeMap,
435   };
436 
437   return FindAttributeDependence(aAttribute, map);
438 }
439 
GetAttributeMappingFunction() const440 nsMapRuleToAttributesFunc HTMLTextAreaElement::GetAttributeMappingFunction()
441     const {
442   return &MapAttributesIntoRule;
443 }
444 
IsDisabledForEvents(WidgetEvent * aEvent)445 bool HTMLTextAreaElement::IsDisabledForEvents(WidgetEvent* aEvent) {
446   nsIFormControlFrame* formControlFrame = GetFormControlFrame(false);
447   nsIFrame* formFrame = do_QueryFrame(formControlFrame);
448   return IsElementDisabledForEvents(aEvent, formFrame);
449 }
450 
GetEventTargetParent(EventChainPreVisitor & aVisitor)451 void HTMLTextAreaElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
452   aVisitor.mCanHandle = false;
453   if (IsDisabledForEvents(aVisitor.mEvent)) {
454     return;
455   }
456 
457   // Don't dispatch a second select event if we are already handling
458   // one.
459   if (aVisitor.mEvent->mMessage == eFormSelect) {
460     if (mHandlingSelect) {
461       return;
462     }
463     mHandlingSelect = true;
464   }
465 
466   if (aVisitor.mEvent->mMessage == eBlur) {
467     // Set mWantsPreHandleEvent and fire change event in PreHandleEvent to
468     // prevent it breaks event target chain creation.
469     aVisitor.mWantsPreHandleEvent = true;
470   }
471 
472   nsGenericHTMLFormControlElementWithState::GetEventTargetParent(aVisitor);
473 }
474 
PreHandleEvent(EventChainVisitor & aVisitor)475 nsresult HTMLTextAreaElement::PreHandleEvent(EventChainVisitor& aVisitor) {
476   if (aVisitor.mEvent->mMessage == eBlur) {
477     // Fire onchange (if necessary), before we do the blur, bug 370521.
478     FireChangeEventIfNeeded();
479   }
480   return nsGenericHTMLFormControlElementWithState::PreHandleEvent(aVisitor);
481 }
482 
FireChangeEventIfNeeded()483 void HTMLTextAreaElement::FireChangeEventIfNeeded() {
484   nsString value;
485   GetValueInternal(value, true);
486 
487   if (mFocusedValue.Equals(value)) {
488     return;
489   }
490 
491   // Dispatch the change event.
492   mFocusedValue = value;
493   nsContentUtils::DispatchTrustedEvent(
494       OwnerDoc(), static_cast<nsIContent*>(this), u"change"_ns, CanBubble::eYes,
495       Cancelable::eNo);
496 }
497 
PostHandleEvent(EventChainPostVisitor & aVisitor)498 nsresult HTMLTextAreaElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
499   if (aVisitor.mEvent->mMessage == eFormSelect) {
500     mHandlingSelect = false;
501   }
502 
503   if (aVisitor.mEvent->mMessage == eFocus ||
504       aVisitor.mEvent->mMessage == eBlur) {
505     if (aVisitor.mEvent->mMessage == eFocus) {
506       // If the invalid UI is shown, we should show it while focusing (and
507       // update). Otherwise, we should not.
508       GetValueInternal(mFocusedValue, true);
509       mCanShowInvalidUI = !IsValid() && ShouldShowValidityUI();
510 
511       // If neither invalid UI nor valid UI is shown, we shouldn't show the
512       // valid UI while typing.
513       mCanShowValidUI = ShouldShowValidityUI();
514     } else {  // eBlur
515       mCanShowInvalidUI = true;
516       mCanShowValidUI = true;
517     }
518 
519     UpdateState(true);
520   }
521 
522   return NS_OK;
523 }
524 
DoneAddingChildren(bool aHaveNotified)525 void HTMLTextAreaElement::DoneAddingChildren(bool aHaveNotified) {
526   if (!mValueChanged) {
527     if (!mDoneAddingChildren) {
528       // Reset now that we're done adding children if the content sink tried to
529       // sneak some text in without calling AppendChildTo.
530       Reset();
531     }
532 
533     if (!mInhibitStateRestoration) {
534       GenerateStateKey();
535       RestoreFormControlState();
536     }
537   }
538 
539   mDoneAddingChildren = true;
540 }
541 
IsDoneAddingChildren()542 bool HTMLTextAreaElement::IsDoneAddingChildren() { return mDoneAddingChildren; }
543 
544 // Controllers Methods
545 
GetControllers(ErrorResult & aError)546 nsIControllers* HTMLTextAreaElement::GetControllers(ErrorResult& aError) {
547   if (!mControllers) {
548     mControllers = new nsXULControllers();
549     if (!mControllers) {
550       aError.Throw(NS_ERROR_FAILURE);
551       return nullptr;
552     }
553 
554     RefPtr<nsBaseCommandController> commandController =
555         nsBaseCommandController::CreateEditorController();
556     if (!commandController) {
557       aError.Throw(NS_ERROR_FAILURE);
558       return nullptr;
559     }
560 
561     mControllers->AppendController(commandController);
562 
563     commandController = nsBaseCommandController::CreateEditingController();
564     if (!commandController) {
565       aError.Throw(NS_ERROR_FAILURE);
566       return nullptr;
567     }
568 
569     mControllers->AppendController(commandController);
570   }
571 
572   return mControllers;
573 }
574 
GetControllers(nsIControllers ** aResult)575 nsresult HTMLTextAreaElement::GetControllers(nsIControllers** aResult) {
576   NS_ENSURE_ARG_POINTER(aResult);
577 
578   ErrorResult error;
579   *aResult = GetControllers(error);
580   NS_IF_ADDREF(*aResult);
581 
582   return error.StealNSResult();
583 }
584 
GetTextLength()585 uint32_t HTMLTextAreaElement::GetTextLength() {
586   nsAutoString val;
587   GetValue(val);
588   return val.Length();
589 }
590 
GetSelectionStart(ErrorResult & aError)591 Nullable<uint32_t> HTMLTextAreaElement::GetSelectionStart(ErrorResult& aError) {
592   uint32_t selStart, selEnd;
593   GetSelectionRange(&selStart, &selEnd, aError);
594   return Nullable<uint32_t>(selStart);
595 }
596 
SetSelectionStart(const Nullable<uint32_t> & aSelectionStart,ErrorResult & aError)597 void HTMLTextAreaElement::SetSelectionStart(
598     const Nullable<uint32_t>& aSelectionStart, ErrorResult& aError) {
599   MOZ_ASSERT(mState);
600   mState->SetSelectionStart(aSelectionStart, aError);
601 }
602 
GetSelectionEnd(ErrorResult & aError)603 Nullable<uint32_t> HTMLTextAreaElement::GetSelectionEnd(ErrorResult& aError) {
604   uint32_t selStart, selEnd;
605   GetSelectionRange(&selStart, &selEnd, aError);
606   return Nullable<uint32_t>(selEnd);
607 }
608 
SetSelectionEnd(const Nullable<uint32_t> & aSelectionEnd,ErrorResult & aError)609 void HTMLTextAreaElement::SetSelectionEnd(
610     const Nullable<uint32_t>& aSelectionEnd, ErrorResult& aError) {
611   MOZ_ASSERT(mState);
612   mState->SetSelectionEnd(aSelectionEnd, aError);
613 }
614 
GetSelectionRange(uint32_t * aSelectionStart,uint32_t * aSelectionEnd,ErrorResult & aRv)615 void HTMLTextAreaElement::GetSelectionRange(uint32_t* aSelectionStart,
616                                             uint32_t* aSelectionEnd,
617                                             ErrorResult& aRv) {
618   MOZ_ASSERT(mState);
619   return mState->GetSelectionRange(aSelectionStart, aSelectionEnd, aRv);
620 }
621 
GetSelectionDirection(nsAString & aDirection,ErrorResult & aError)622 void HTMLTextAreaElement::GetSelectionDirection(nsAString& aDirection,
623                                                 ErrorResult& aError) {
624   MOZ_ASSERT(mState);
625   mState->GetSelectionDirectionString(aDirection, aError);
626 }
627 
SetSelectionDirection(const nsAString & aDirection,ErrorResult & aError)628 void HTMLTextAreaElement::SetSelectionDirection(const nsAString& aDirection,
629                                                 ErrorResult& aError) {
630   MOZ_ASSERT(mState);
631   mState->SetSelectionDirection(aDirection, aError);
632 }
633 
SetSelectionRange(uint32_t aSelectionStart,uint32_t aSelectionEnd,const Optional<nsAString> & aDirection,ErrorResult & aError)634 void HTMLTextAreaElement::SetSelectionRange(
635     uint32_t aSelectionStart, uint32_t aSelectionEnd,
636     const Optional<nsAString>& aDirection, ErrorResult& aError) {
637   MOZ_ASSERT(mState);
638   mState->SetSelectionRange(aSelectionStart, aSelectionEnd, aDirection, aError);
639 }
640 
SetRangeText(const nsAString & aReplacement,ErrorResult & aRv)641 void HTMLTextAreaElement::SetRangeText(const nsAString& aReplacement,
642                                        ErrorResult& aRv) {
643   MOZ_ASSERT(mState);
644   mState->SetRangeText(aReplacement, aRv);
645 }
646 
SetRangeText(const nsAString & aReplacement,uint32_t aStart,uint32_t aEnd,SelectionMode aSelectMode,ErrorResult & aRv)647 void HTMLTextAreaElement::SetRangeText(const nsAString& aReplacement,
648                                        uint32_t aStart, uint32_t aEnd,
649                                        SelectionMode aSelectMode,
650                                        ErrorResult& aRv) {
651   MOZ_ASSERT(mState);
652   mState->SetRangeText(aReplacement, aStart, aEnd, aSelectMode, aRv);
653 }
654 
GetValueFromSetRangeText(nsAString & aValue)655 void HTMLTextAreaElement::GetValueFromSetRangeText(nsAString& aValue) {
656   GetValueInternal(aValue, false);
657 }
658 
SetValueFromSetRangeText(const nsAString & aValue)659 nsresult HTMLTextAreaElement::SetValueFromSetRangeText(
660     const nsAString& aValue) {
661   return SetValueInternal(aValue, {ValueSetterOption::ByContentAPI,
662                                    ValueSetterOption::BySetRangeTextAPI,
663                                    ValueSetterOption::SetValueChanged});
664 }
665 
Reset()666 nsresult HTMLTextAreaElement::Reset() {
667   nsAutoString resetVal;
668   GetDefaultValue(resetVal, IgnoreErrors());
669   SetValueChanged(false);
670 
671   nsresult rv = SetValueInternal(resetVal, ValueSetterOption::ByInternalAPI);
672   NS_ENSURE_SUCCESS(rv, rv);
673 
674   return NS_OK;
675 }
676 
677 NS_IMETHODIMP
SubmitNamesValues(FormData * aFormData)678 HTMLTextAreaElement::SubmitNamesValues(FormData* aFormData) {
679   //
680   // Get the name (if no name, no submit)
681   //
682   nsAutoString name;
683   GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
684   if (name.IsEmpty()) {
685     return NS_OK;
686   }
687 
688   //
689   // Get the value
690   //
691   nsAutoString value;
692   GetValueInternal(value, false);
693 
694   //
695   // Submit
696   //
697   return aFormData->AddNameValuePair(name, value);
698 }
699 
SaveState()700 void HTMLTextAreaElement::SaveState() {
701   // Only save if value != defaultValue (bug 62713)
702   PresState* state = nullptr;
703   if (mValueChanged) {
704     state = GetPrimaryPresState();
705     if (state) {
706       nsAutoString value;
707       GetValueInternal(value, true);
708 
709       if (NS_FAILED(nsLinebreakConverter::ConvertStringLineBreaks(
710               value, nsLinebreakConverter::eLinebreakPlatform,
711               nsLinebreakConverter::eLinebreakContent))) {
712         NS_ERROR("Converting linebreaks failed!");
713         return;
714       }
715 
716       state->contentData() =
717           TextContentData(value, mLastValueChangeWasInteractive);
718     }
719   }
720 
721   if (mDisabledChanged) {
722     if (!state) {
723       state = GetPrimaryPresState();
724     }
725     if (state) {
726       // We do not want to save the real disabled state but the disabled
727       // attribute.
728       state->disabled() = HasAttr(kNameSpaceID_None, nsGkAtoms::disabled);
729       state->disabledSet() = true;
730     }
731   }
732 }
733 
RestoreState(PresState * aState)734 bool HTMLTextAreaElement::RestoreState(PresState* aState) {
735   const PresContentData& state = aState->contentData();
736 
737   if (state.type() == PresContentData::TTextContentData) {
738     ErrorResult rv;
739     SetValue(state.get_TextContentData().value(), rv);
740     ENSURE_SUCCESS(rv, false);
741     if (state.get_TextContentData().lastValueChangeWasInteractive()) {
742       SetLastValueChangeWasInteractive(true);
743     }
744   }
745   if (aState->disabledSet() && !aState->disabled()) {
746     SetDisabled(false, IgnoreErrors());
747   }
748 
749   return false;
750 }
751 
IntrinsicState() const752 EventStates HTMLTextAreaElement::IntrinsicState() const {
753   EventStates state =
754       nsGenericHTMLFormControlElementWithState::IntrinsicState();
755 
756   if (IsCandidateForConstraintValidation()) {
757     if (IsValid()) {
758       state |= NS_EVENT_STATE_VALID;
759     } else {
760       state |= NS_EVENT_STATE_INVALID;
761       // :-moz-ui-invalid always apply if the element suffers from a custom
762       // error.
763       if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR) ||
764           (mCanShowInvalidUI && ShouldShowValidityUI())) {
765         state |= NS_EVENT_STATE_MOZ_UI_INVALID;
766       }
767     }
768 
769     // :-moz-ui-valid applies if all the following are true:
770     // 1. The element is not focused, or had either :-moz-ui-valid or
771     //    :-moz-ui-invalid applying before it was focused ;
772     // 2. The element is either valid or isn't allowed to have
773     //    :-moz-ui-invalid applying ;
774     // 3. The element has already been modified or the user tried to submit the
775     //    form owner while invalid.
776     if (mCanShowValidUI && ShouldShowValidityUI() &&
777         (IsValid() || (state.HasState(NS_EVENT_STATE_MOZ_UI_INVALID) &&
778                        !mCanShowInvalidUI))) {
779       state |= NS_EVENT_STATE_MOZ_UI_VALID;
780     }
781   }
782 
783   if (HasAttr(nsGkAtoms::placeholder) && IsValueEmpty()) {
784     state |= NS_EVENT_STATE_PLACEHOLDERSHOWN;
785   }
786 
787   return state;
788 }
789 
BindToTree(BindContext & aContext,nsINode & aParent)790 nsresult HTMLTextAreaElement::BindToTree(BindContext& aContext,
791                                          nsINode& aParent) {
792   nsresult rv =
793       nsGenericHTMLFormControlElementWithState::BindToTree(aContext, aParent);
794   NS_ENSURE_SUCCESS(rv, rv);
795 
796   // If there is a disabled fieldset in the parent chain, the element is now
797   // barred from constraint validation and can't suffer from value missing.
798   UpdateValueMissingValidityState();
799   UpdateBarredFromConstraintValidation();
800 
801   // And now make sure our state is up to date
802   UpdateState(false);
803 
804   return rv;
805 }
806 
UnbindFromTree(bool aNullParent)807 void HTMLTextAreaElement::UnbindFromTree(bool aNullParent) {
808   nsGenericHTMLFormControlElementWithState::UnbindFromTree(aNullParent);
809 
810   // We might be no longer disabled because of parent chain changed.
811   UpdateValueMissingValidityState();
812   UpdateBarredFromConstraintValidation();
813 
814   // And now make sure our state is up to date
815   UpdateState(false);
816 }
817 
BeforeSetAttr(int32_t aNameSpaceID,nsAtom * aName,const nsAttrValueOrString * aValue,bool aNotify)818 nsresult HTMLTextAreaElement::BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName,
819                                             const nsAttrValueOrString* aValue,
820                                             bool aNotify) {
821   if (aNotify && aName == nsGkAtoms::disabled &&
822       aNameSpaceID == kNameSpaceID_None) {
823     mDisabledChanged = true;
824   }
825 
826   return nsGenericHTMLFormControlElementWithState::BeforeSetAttr(
827       aNameSpaceID, aName, aValue, aNotify);
828 }
829 
CharacterDataChanged(nsIContent * aContent,const CharacterDataChangeInfo &)830 void HTMLTextAreaElement::CharacterDataChanged(nsIContent* aContent,
831                                                const CharacterDataChangeInfo&) {
832   ContentChanged(aContent);
833 }
834 
ContentAppended(nsIContent * aFirstNewContent)835 void HTMLTextAreaElement::ContentAppended(nsIContent* aFirstNewContent) {
836   ContentChanged(aFirstNewContent);
837 }
838 
ContentInserted(nsIContent * aChild)839 void HTMLTextAreaElement::ContentInserted(nsIContent* aChild) {
840   ContentChanged(aChild);
841 }
842 
ContentRemoved(nsIContent * aChild,nsIContent * aPreviousSibling)843 void HTMLTextAreaElement::ContentRemoved(nsIContent* aChild,
844                                          nsIContent* aPreviousSibling) {
845   ContentChanged(aChild);
846 }
847 
ContentChanged(nsIContent * aContent)848 void HTMLTextAreaElement::ContentChanged(nsIContent* aContent) {
849   if (!mValueChanged && mDoneAddingChildren &&
850       nsContentUtils::IsInSameAnonymousTree(this, aContent)) {
851     // Hard to say what the reset can trigger, so be safe pending
852     // further auditing.
853     nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
854     Reset();
855   }
856 }
857 
AfterSetAttr(int32_t aNameSpaceID,nsAtom * aName,const nsAttrValue * aValue,const nsAttrValue * aOldValue,nsIPrincipal * aSubjectPrincipal,bool aNotify)858 nsresult HTMLTextAreaElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
859                                            const nsAttrValue* aValue,
860                                            const nsAttrValue* aOldValue,
861                                            nsIPrincipal* aSubjectPrincipal,
862                                            bool aNotify) {
863   if (aNameSpaceID == kNameSpaceID_None) {
864     if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
865         aName == nsGkAtoms::readonly) {
866       if (aName == nsGkAtoms::disabled) {
867         // This *has* to be called *before* validity state check because
868         // UpdateBarredFromConstraintValidation and
869         // UpdateValueMissingValidityState depend on our disabled state.
870         UpdateDisabledState(aNotify);
871       }
872 
873       if (aName == nsGkAtoms::required) {
874         // This *has* to be called *before* UpdateValueMissingValidityState
875         // because UpdateValueMissingValidityState depends on our required
876         // state.
877         UpdateRequiredState(!!aValue, aNotify);
878       }
879 
880       UpdateValueMissingValidityState();
881 
882       // This *has* to be called *after* validity has changed.
883       if (aName == nsGkAtoms::readonly || aName == nsGkAtoms::disabled) {
884         UpdateBarredFromConstraintValidation();
885       }
886     } else if (aName == nsGkAtoms::autocomplete) {
887       // Clear the cached @autocomplete attribute state.
888       mAutocompleteAttrState = nsContentUtils::eAutocompleteAttrState_Unknown;
889     } else if (aName == nsGkAtoms::maxlength) {
890       UpdateTooLongValidityState();
891     } else if (aName == nsGkAtoms::minlength) {
892       UpdateTooShortValidityState();
893     } else if (aName == nsGkAtoms::placeholder) {
894       if (nsTextControlFrame* f = do_QueryFrame(GetPrimaryFrame())) {
895         f->PlaceholderChanged(aOldValue, aValue);
896       }
897     }
898   }
899 
900   return nsGenericHTMLFormControlElementWithState::AfterSetAttr(
901       aNameSpaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify);
902 }
903 
CopyInnerTo(Element * aDest)904 nsresult HTMLTextAreaElement::CopyInnerTo(Element* aDest) {
905   nsresult rv = nsGenericHTMLFormControlElementWithState::CopyInnerTo(aDest);
906   NS_ENSURE_SUCCESS(rv, rv);
907 
908   if (aDest->OwnerDoc()->IsStaticDocument()) {
909     nsAutoString value;
910     GetValueInternal(value, true);
911     ErrorResult ret;
912     static_cast<HTMLTextAreaElement*>(aDest)->SetValue(value, ret);
913     return ret.StealNSResult();
914   }
915   return NS_OK;
916 }
917 
IsMutable() const918 bool HTMLTextAreaElement::IsMutable() const {
919   return (!HasAttr(kNameSpaceID_None, nsGkAtoms::readonly) && !IsDisabled());
920 }
921 
IsValueEmpty() const922 bool HTMLTextAreaElement::IsValueEmpty() const {
923   nsAutoString value;
924   GetValueInternal(value, true);
925 
926   return value.IsEmpty();
927 }
928 
SetCustomValidity(const nsAString & aError)929 void HTMLTextAreaElement::SetCustomValidity(const nsAString& aError) {
930   ConstraintValidation::SetCustomValidity(aError);
931 
932   UpdateState(true);
933 }
934 
IsTooLong()935 bool HTMLTextAreaElement::IsTooLong() {
936   if (!mValueChanged || !mLastValueChangeWasInteractive ||
937       !HasAttr(nsGkAtoms::maxlength)) {
938     return false;
939   }
940 
941   int32_t maxLength = MaxLength();
942 
943   // Maxlength of -1 means parsing error.
944   if (maxLength == -1) {
945     return false;
946   }
947 
948   int32_t textLength = GetTextLength();
949 
950   return textLength > maxLength;
951 }
952 
IsTooShort()953 bool HTMLTextAreaElement::IsTooShort() {
954   if (!mValueChanged || !mLastValueChangeWasInteractive ||
955       !HasAttr(nsGkAtoms::minlength)) {
956     return false;
957   }
958 
959   int32_t minLength = MinLength();
960 
961   // Minlength of -1 means parsing error.
962   if (minLength == -1) {
963     return false;
964   }
965 
966   int32_t textLength = GetTextLength();
967 
968   return textLength && textLength < minLength;
969 }
970 
IsValueMissing() const971 bool HTMLTextAreaElement::IsValueMissing() const {
972   if (!Required() || !IsMutable()) {
973     return false;
974   }
975 
976   return IsValueEmpty();
977 }
978 
UpdateTooLongValidityState()979 void HTMLTextAreaElement::UpdateTooLongValidityState() {
980   SetValidityState(VALIDITY_STATE_TOO_LONG, IsTooLong());
981 }
982 
UpdateTooShortValidityState()983 void HTMLTextAreaElement::UpdateTooShortValidityState() {
984   SetValidityState(VALIDITY_STATE_TOO_SHORT, IsTooShort());
985 }
986 
UpdateValueMissingValidityState()987 void HTMLTextAreaElement::UpdateValueMissingValidityState() {
988   SetValidityState(VALIDITY_STATE_VALUE_MISSING, IsValueMissing());
989 }
990 
UpdateBarredFromConstraintValidation()991 void HTMLTextAreaElement::UpdateBarredFromConstraintValidation() {
992   SetBarredFromConstraintValidation(
993       HasAttr(kNameSpaceID_None, nsGkAtoms::readonly) ||
994       HasFlag(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR) || IsDisabled());
995 }
996 
GetValidationMessage(nsAString & aValidationMessage,ValidityStateType aType)997 nsresult HTMLTextAreaElement::GetValidationMessage(
998     nsAString& aValidationMessage, ValidityStateType aType) {
999   nsresult rv = NS_OK;
1000 
1001   switch (aType) {
1002     case VALIDITY_STATE_TOO_LONG: {
1003       nsAutoString message;
1004       int32_t maxLength = MaxLength();
1005       int32_t textLength = GetTextLength();
1006       nsAutoString strMaxLength;
1007       nsAutoString strTextLength;
1008 
1009       strMaxLength.AppendInt(maxLength);
1010       strTextLength.AppendInt(textLength);
1011 
1012       rv = nsContentUtils::FormatMaybeLocalizedString(
1013           message, nsContentUtils::eDOM_PROPERTIES, "FormValidationTextTooLong",
1014           OwnerDoc(), strMaxLength, strTextLength);
1015       aValidationMessage = message;
1016     } break;
1017     case VALIDITY_STATE_TOO_SHORT: {
1018       nsAutoString message;
1019       int32_t minLength = MinLength();
1020       int32_t textLength = GetTextLength();
1021       nsAutoString strMinLength;
1022       nsAutoString strTextLength;
1023 
1024       strMinLength.AppendInt(minLength);
1025       strTextLength.AppendInt(textLength);
1026 
1027       rv = nsContentUtils::FormatMaybeLocalizedString(
1028           message, nsContentUtils::eDOM_PROPERTIES,
1029           "FormValidationTextTooShort", OwnerDoc(), strMinLength,
1030           strTextLength);
1031       aValidationMessage = message;
1032     } break;
1033     case VALIDITY_STATE_VALUE_MISSING: {
1034       nsAutoString message;
1035       rv = nsContentUtils::GetMaybeLocalizedString(
1036           nsContentUtils::eDOM_PROPERTIES, "FormValidationValueMissing",
1037           OwnerDoc(), message);
1038       aValidationMessage = message;
1039     } break;
1040     default:
1041       rv =
1042           ConstraintValidation::GetValidationMessage(aValidationMessage, aType);
1043   }
1044 
1045   return rv;
1046 }
1047 
IsSingleLineTextControl() const1048 bool HTMLTextAreaElement::IsSingleLineTextControl() const { return false; }
1049 
IsTextArea() const1050 bool HTMLTextAreaElement::IsTextArea() const { return true; }
1051 
IsPasswordTextControl() const1052 bool HTMLTextAreaElement::IsPasswordTextControl() const { return false; }
1053 
GetCols()1054 int32_t HTMLTextAreaElement::GetCols() { return Cols(); }
1055 
GetWrapCols()1056 int32_t HTMLTextAreaElement::GetWrapCols() {
1057   nsHTMLTextWrap wrapProp;
1058   TextControlElement::GetWrapPropertyEnum(this, wrapProp);
1059   if (wrapProp == TextControlElement::eHTMLTextWrap_Off) {
1060     // do not wrap when wrap=off
1061     return 0;
1062   }
1063 
1064   // Otherwise we just wrap at the given number of columns
1065   return GetCols();
1066 }
1067 
GetRows()1068 int32_t HTMLTextAreaElement::GetRows() {
1069   const nsAttrValue* attr = GetParsedAttr(nsGkAtoms::rows);
1070   if (attr && attr->Type() == nsAttrValue::eInteger) {
1071     int32_t rows = attr->GetIntegerValue();
1072     return (rows <= 0) ? DEFAULT_ROWS_TEXTAREA : rows;
1073   }
1074 
1075   return DEFAULT_ROWS_TEXTAREA;
1076 }
1077 
GetDefaultValueFromContent(nsAString & aValue)1078 void HTMLTextAreaElement::GetDefaultValueFromContent(nsAString& aValue) {
1079   GetDefaultValue(aValue, IgnoreErrors());
1080 }
1081 
ValueChanged() const1082 bool HTMLTextAreaElement::ValueChanged() const { return mValueChanged; }
1083 
GetTextEditorValue(nsAString & aValue,bool aIgnoreWrap) const1084 void HTMLTextAreaElement::GetTextEditorValue(nsAString& aValue,
1085                                              bool aIgnoreWrap) const {
1086   MOZ_ASSERT(mState);
1087   mState->GetValue(aValue, aIgnoreWrap);
1088 }
1089 
InitializeKeyboardEventListeners()1090 void HTMLTextAreaElement::InitializeKeyboardEventListeners() {
1091   MOZ_ASSERT(mState);
1092   mState->InitializeKeyboardEventListeners();
1093 }
1094 
OnValueChanged(ValueChangeKind aKind)1095 void HTMLTextAreaElement::OnValueChanged(ValueChangeKind aKind) {
1096   if (aKind != ValueChangeKind::Internal) {
1097     mLastValueChangeWasInteractive = aKind == ValueChangeKind::UserInteraction;
1098   }
1099 
1100   // Update the validity state
1101   bool validBefore = IsValid();
1102   UpdateTooLongValidityState();
1103   UpdateTooShortValidityState();
1104   UpdateValueMissingValidityState();
1105 
1106   if (validBefore != IsValid() || HasAttr(nsGkAtoms::placeholder)) {
1107     UpdateState(true);
1108   }
1109 }
1110 
HasCachedSelection()1111 bool HTMLTextAreaElement::HasCachedSelection() {
1112   MOZ_ASSERT(mState);
1113   return mState->IsSelectionCached();
1114 }
1115 
FieldSetDisabledChanged(bool aNotify)1116 void HTMLTextAreaElement::FieldSetDisabledChanged(bool aNotify) {
1117   // This *has* to be called before UpdateBarredFromConstraintValidation and
1118   // UpdateValueMissingValidityState because these two functions depend on our
1119   // disabled state.
1120   nsGenericHTMLFormControlElementWithState::FieldSetDisabledChanged(aNotify);
1121 
1122   UpdateValueMissingValidityState();
1123   UpdateBarredFromConstraintValidation();
1124   UpdateState(aNotify);
1125 }
1126 
WrapNode(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)1127 JSObject* HTMLTextAreaElement::WrapNode(JSContext* aCx,
1128                                         JS::Handle<JSObject*> aGivenProto) {
1129   return HTMLTextAreaElement_Binding::Wrap(aCx, this, aGivenProto);
1130 }
1131 
GetAutocomplete(DOMString & aValue)1132 void HTMLTextAreaElement::GetAutocomplete(DOMString& aValue) {
1133   const nsAttrValue* attributeVal = GetParsedAttr(nsGkAtoms::autocomplete);
1134 
1135   mAutocompleteAttrState = nsContentUtils::SerializeAutocompleteAttribute(
1136       attributeVal, aValue, mAutocompleteAttrState);
1137 }
1138 
1139 }  // namespace mozilla::dom
1140