LCOV - code coverage report
Current view: top level - dom/html - HTMLTextAreaElement.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 69 610 11.3 %
Date: 2017-07-14 16:53:18 Functions: 14 136 10.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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/HTMLFormSubmission.h"
      13             : #include "mozilla/dom/HTMLTextAreaElementBinding.h"
      14             : #include "mozilla/EventDispatcher.h"
      15             : #include "mozilla/EventStates.h"
      16             : #include "mozilla/GenericSpecifiedValuesInlines.h"
      17             : #include "mozilla/MouseEvents.h"
      18             : #include "nsAttrValueInlines.h"
      19             : #include "nsContentCID.h"
      20             : #include "nsContentCreatorFunctions.h"
      21             : #include "nsError.h"
      22             : #include "nsFocusManager.h"
      23             : #include "nsIComponentManager.h"
      24             : #include "nsIConstraintValidation.h"
      25             : #include "nsIControllers.h"
      26             : #include "nsIDocument.h"
      27             : #include "nsIDOMHTMLFormElement.h"
      28             : #include "nsIFormControlFrame.h"
      29             : #include "nsIFormControl.h"
      30             : #include "nsIForm.h"
      31             : #include "nsIFrame.h"
      32             : #include "nsISupportsPrimitives.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 "nsPresState.h"
      40             : #include "nsReadableUtils.h"
      41             : #include "nsStyleConsts.h"
      42             : #include "nsTextEditorState.h"
      43             : #include "nsIController.h"
      44             : 
      45             : static NS_DEFINE_CID(kXULControllersCID,  NS_XULCONTROLLERS_CID);
      46             : 
      47             : #define NS_NO_CONTENT_DISPATCH (1 << 0)
      48             : 
      49           2 : NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(TextArea)
      50             : 
      51             : namespace mozilla {
      52             : namespace dom {
      53             : 
      54           1 : HTMLTextAreaElement::HTMLTextAreaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
      55           1 :                                          FromParser aFromParser)
      56             :   : nsGenericHTMLFormElementWithState(aNodeInfo, NS_FORM_TEXTAREA),
      57             :     mValueChanged(false),
      58             :     mLastValueChangeWasInteractive(false),
      59             :     mHandlingSelect(false),
      60           1 :     mDoneAddingChildren(!aFromParser),
      61           1 :     mInhibitStateRestoration(!!(aFromParser & FROM_PARSER_FRAGMENT)),
      62             :     mDisabledChanged(false),
      63             :     mCanShowInvalidUI(true),
      64             :     mCanShowValidUI(true),
      65             :     mIsPreviewEnabled(false),
      66           3 :     mState(this)
      67             : {
      68           1 :   AddMutationObserver(this);
      69             : 
      70             :   // Set up our default state.  By default we're enabled (since we're
      71             :   // a control type that can be disabled but not actually disabled
      72             :   // right now), optional, and valid.  We are NOT readwrite by default
      73             :   // until someone calls UpdateEditableState on us, apparently!  Also
      74             :   // by default we don't have to show validity UI and so forth.
      75           2 :   AddStatesSilently(NS_EVENT_STATE_ENABLED |
      76           2 :                     NS_EVENT_STATE_OPTIONAL |
      77           3 :                     NS_EVENT_STATE_VALID);
      78           1 : }
      79             : 
      80             : 
      81           0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLTextAreaElement,
      82             :                                    nsGenericHTMLFormElementWithState,
      83             :                                    mValidity,
      84             :                                    mControllers,
      85             :                                    mState)
      86             : 
      87           7 : NS_IMPL_ADDREF_INHERITED(HTMLTextAreaElement, Element)
      88           5 : NS_IMPL_RELEASE_INHERITED(HTMLTextAreaElement, Element)
      89             : 
      90             : 
      91             : // QueryInterface implementation for HTMLTextAreaElement
      92           4 : NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLTextAreaElement)
      93           3 :   NS_INTERFACE_TABLE_INHERITED(HTMLTextAreaElement,
      94             :                                nsIDOMHTMLTextAreaElement,
      95             :                                nsITextControlElement,
      96             :                                nsIDOMNSEditableElement,
      97             :                                nsIMutationObserver,
      98             :                                nsIConstraintValidation)
      99           3 : NS_INTERFACE_TABLE_TAIL_INHERITING(nsGenericHTMLFormElementWithState)
     100             : 
     101             : 
     102             : // nsIDOMHTMLTextAreaElement
     103             : 
     104             : nsresult
     105           0 : HTMLTextAreaElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
     106             :                            bool aPreallocateChildren) const
     107             : {
     108           0 :   *aResult = nullptr;
     109             :   already_AddRefed<mozilla::dom::NodeInfo> ni =
     110           0 :     RefPtr<mozilla::dom::NodeInfo>(aNodeInfo).forget();
     111           0 :   RefPtr<HTMLTextAreaElement> it = new HTMLTextAreaElement(ni);
     112             : 
     113           0 :   nsresult rv = const_cast<HTMLTextAreaElement*>(this)->CopyInnerTo(it, aPreallocateChildren);
     114           0 :   NS_ENSURE_SUCCESS(rv, rv);
     115             : 
     116           0 :   if (mValueChanged) {
     117             :     // Set our value on the clone.
     118           0 :     nsAutoString value;
     119           0 :     GetValueInternal(value, true);
     120             : 
     121             :     // SetValueInternal handles setting mValueChanged for us
     122           0 :     rv = it->SetValueInternal(value, nsTextEditorState::eSetValue_Notify);
     123           0 :     NS_ENSURE_SUCCESS(rv, rv);
     124             :   }
     125             : 
     126           0 :   it->mLastValueChangeWasInteractive = mLastValueChangeWasInteractive;
     127           0 :   it.forget(aResult);
     128           0 :   return NS_OK;
     129             : }
     130             : 
     131             : // nsIConstraintValidation
     132           0 : NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(HTMLTextAreaElement)
     133             : 
     134             : 
     135             : NS_IMETHODIMP
     136           0 : HTMLTextAreaElement::GetForm(nsIDOMHTMLFormElement** aForm)
     137             : {
     138           0 :   return nsGenericHTMLFormElementWithState::GetForm(aForm);
     139             : }
     140             : 
     141             : 
     142             : // nsIContent
     143             : 
     144             : NS_IMETHODIMP
     145           0 : HTMLTextAreaElement::Select()
     146             : {
     147             :   // XXX Bug?  We have to give the input focus before contents can be
     148             :   // selected
     149             : 
     150           0 :   FocusTristate state = FocusState();
     151           0 :   if (state == eUnfocusable) {
     152           0 :     return NS_OK;
     153             :   }
     154             : 
     155           0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
     156             : 
     157           0 :   RefPtr<nsPresContext> presContext = GetPresContext(eForComposedDoc);
     158           0 :   if (state == eInactiveWindow) {
     159           0 :     if (fm)
     160           0 :       fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
     161           0 :     SelectAll(presContext);
     162           0 :     return NS_OK;
     163             :   }
     164             : 
     165           0 :   nsEventStatus status = nsEventStatus_eIgnore;
     166           0 :   WidgetGUIEvent event(true, eFormSelect, nullptr);
     167             :   // XXXbz HTMLInputElement guards against this reentering; shouldn't we?
     168           0 :   EventDispatcher::Dispatch(static_cast<nsIContent*>(this), presContext,
     169           0 :                             &event, nullptr, &status);
     170             : 
     171             :   // If the DOM event was not canceled (e.g. by a JS event handler
     172             :   // returning false)
     173           0 :   if (status == nsEventStatus_eIgnore) {
     174           0 :     if (fm) {
     175           0 :       fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
     176             : 
     177             :       // ensure that the element is actually focused
     178           0 :       nsCOMPtr<nsIDOMElement> focusedElement;
     179           0 :       fm->GetFocusedElement(getter_AddRefs(focusedElement));
     180           0 :       if (SameCOMIdentity(static_cast<nsIDOMNode*>(this), focusedElement)) {
     181             :         // Now Select all the text!
     182           0 :         SelectAll(presContext);
     183             :       }
     184             :     }
     185             :   }
     186             : 
     187           0 :   return NS_OK;
     188             : }
     189             : 
     190             : NS_IMETHODIMP
     191           0 : HTMLTextAreaElement::SelectAll(nsPresContext* aPresContext)
     192             : {
     193           0 :   nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
     194             : 
     195           0 :   if (formControlFrame) {
     196           0 :     formControlFrame->SetFormProperty(nsGkAtoms::select, EmptyString());
     197             :   }
     198             : 
     199           0 :   return NS_OK;
     200             : }
     201             : 
     202             : bool
     203           0 : HTMLTextAreaElement::IsHTMLFocusable(bool aWithMouse,
     204             :                                      bool *aIsFocusable, int32_t *aTabIndex)
     205             : {
     206           0 :   if (nsGenericHTMLFormElementWithState::IsHTMLFocusable(aWithMouse, aIsFocusable,
     207             :                                                          aTabIndex))
     208             :   {
     209           0 :     return true;
     210             :   }
     211             : 
     212             :   // disabled textareas are not focusable
     213           0 :   *aIsFocusable = !IsDisabled();
     214           0 :   return false;
     215             : }
     216             : 
     217           0 : NS_IMPL_BOOL_ATTR(HTMLTextAreaElement, Autofocus, autofocus)
     218           0 : NS_IMPL_UINT_ATTR_NON_ZERO_DEFAULT_VALUE(HTMLTextAreaElement, Cols, cols, DEFAULT_COLS)
     219           0 : NS_IMPL_BOOL_ATTR(HTMLTextAreaElement, Disabled, disabled)
     220           0 : NS_IMPL_NON_NEGATIVE_INT_ATTR(HTMLTextAreaElement, MaxLength, maxlength)
     221           0 : NS_IMPL_NON_NEGATIVE_INT_ATTR(HTMLTextAreaElement, MinLength, minlength)
     222           0 : NS_IMPL_STRING_ATTR(HTMLTextAreaElement, Name, name)
     223           0 : NS_IMPL_BOOL_ATTR(HTMLTextAreaElement, ReadOnly, readonly)
     224           0 : NS_IMPL_BOOL_ATTR(HTMLTextAreaElement, Required, required)
     225           0 : NS_IMPL_UINT_ATTR_NON_ZERO_DEFAULT_VALUE(HTMLTextAreaElement, Rows, rows, DEFAULT_ROWS_TEXTAREA)
     226           0 : NS_IMPL_STRING_ATTR(HTMLTextAreaElement, Wrap, wrap)
     227           0 : NS_IMPL_STRING_ATTR(HTMLTextAreaElement, Placeholder, placeholder)
     228             : 
     229             : int32_t
     230           0 : HTMLTextAreaElement::TabIndexDefault()
     231             : {
     232           0 :   return 0;
     233             : }
     234             : 
     235             : NS_IMETHODIMP
     236           0 : HTMLTextAreaElement::GetType(nsAString& aType)
     237             : {
     238           0 :   aType.AssignLiteral("textarea");
     239             : 
     240           0 :   return NS_OK;
     241             : }
     242             : 
     243             : NS_IMETHODIMP
     244           0 : HTMLTextAreaElement::GetValue(nsAString& aValue)
     245             : {
     246           0 :   nsAutoString value;
     247           0 :   GetValueInternal(value, true);
     248             : 
     249             :   // Normalize CRLF and CR to LF
     250           0 :   nsContentUtils::PlatformToDOMLineBreaks(value);
     251             : 
     252           0 :   aValue = value;
     253           0 :   return NS_OK;
     254             : }
     255             : 
     256             : void
     257           0 : HTMLTextAreaElement::GetValueInternal(nsAString& aValue, bool aIgnoreWrap) const
     258             : {
     259           0 :   mState.GetValue(aValue, aIgnoreWrap);
     260           0 : }
     261             : 
     262             : NS_IMETHODIMP_(TextEditor*)
     263           0 : HTMLTextAreaElement::GetTextEditor()
     264             : {
     265           0 :   return mState.GetTextEditor();
     266             : }
     267             : 
     268             : NS_IMETHODIMP_(nsISelectionController*)
     269           0 : HTMLTextAreaElement::GetSelectionController()
     270             : {
     271           0 :   return mState.GetSelectionController();
     272             : }
     273             : 
     274             : NS_IMETHODIMP_(nsFrameSelection*)
     275           0 : HTMLTextAreaElement::GetConstFrameSelection()
     276             : {
     277           0 :   return mState.GetConstFrameSelection();
     278             : }
     279             : 
     280             : NS_IMETHODIMP
     281           0 : HTMLTextAreaElement::BindToFrame(nsTextControlFrame* aFrame)
     282             : {
     283           0 :   return mState.BindToFrame(aFrame);
     284             : }
     285             : 
     286             : NS_IMETHODIMP_(void)
     287           0 : HTMLTextAreaElement::UnbindFromFrame(nsTextControlFrame* aFrame)
     288             : {
     289           0 :   if (aFrame) {
     290           0 :     mState.UnbindFromFrame(aFrame);
     291             :   }
     292           0 : }
     293             : 
     294             : NS_IMETHODIMP
     295           0 : HTMLTextAreaElement::CreateEditor()
     296             : {
     297           0 :   return mState.PrepareEditor();
     298             : }
     299             : 
     300             : NS_IMETHODIMP_(Element*)
     301           0 : HTMLTextAreaElement::GetRootEditorNode()
     302             : {
     303           0 :   return mState.GetRootNode();
     304             : }
     305             : 
     306             : NS_IMETHODIMP_(Element*)
     307           0 : HTMLTextAreaElement::CreatePlaceholderNode()
     308             : {
     309           0 :   NS_ENSURE_SUCCESS(mState.CreatePlaceholderNode(), nullptr);
     310           0 :   return mState.GetPlaceholderNode();
     311             : }
     312             : 
     313             : NS_IMETHODIMP_(Element*)
     314           0 : HTMLTextAreaElement::GetPlaceholderNode()
     315             : {
     316           0 :   return mState.GetPlaceholderNode();
     317             : }
     318             : 
     319             : NS_IMETHODIMP_(void)
     320           0 : HTMLTextAreaElement::UpdateOverlayTextVisibility(bool aNotify)
     321             : {
     322           0 :   mState.UpdateOverlayTextVisibility(aNotify);
     323           0 : }
     324             : 
     325             : NS_IMETHODIMP_(bool)
     326           0 : HTMLTextAreaElement::GetPlaceholderVisibility()
     327             : {
     328           0 :   return mState.GetPlaceholderVisibility();
     329             : }
     330             : 
     331             : NS_IMETHODIMP_(Element*)
     332           0 : HTMLTextAreaElement::CreatePreviewNode()
     333             : {
     334           0 :   NS_ENSURE_SUCCESS(mState.CreatePreviewNode(), nullptr);
     335           0 :   return mState.GetPreviewNode();
     336             : }
     337             : 
     338             : NS_IMETHODIMP_(Element*)
     339           0 : HTMLTextAreaElement::GetPreviewNode()
     340             : {
     341           0 :   return mState.GetPreviewNode();
     342             : }
     343             : 
     344             : NS_IMETHODIMP_(void)
     345           0 : HTMLTextAreaElement::SetPreviewValue(const nsAString& aValue)
     346             : {
     347           0 :   mState.SetPreviewText(aValue, true);
     348           0 : }
     349             : 
     350             : NS_IMETHODIMP_(void)
     351           0 : HTMLTextAreaElement::GetPreviewValue(nsAString& aValue)
     352             : {
     353           0 :   mState.GetPreviewText(aValue);
     354           0 : }
     355             : 
     356             : NS_IMETHODIMP_(void)
     357           0 : HTMLTextAreaElement::EnablePreview()
     358             : {
     359           0 :   if (mIsPreviewEnabled) {
     360           0 :     return;
     361             :   }
     362             : 
     363           0 :   mIsPreviewEnabled = true;
     364             :   // Reconstruct the frame to append an anonymous preview node
     365           0 :   nsLayoutUtils::PostRestyleEvent(this, nsRestyleHint(0), nsChangeHint_ReconstructFrame);
     366             : }
     367             : 
     368             : NS_IMETHODIMP_(bool)
     369           0 : HTMLTextAreaElement::IsPreviewEnabled()
     370             : {
     371           0 :   return mIsPreviewEnabled;
     372             : }
     373             : 
     374             : NS_IMETHODIMP_(bool)
     375           0 : HTMLTextAreaElement::GetPreviewVisibility()
     376             : {
     377           0 :   return mState.GetPreviewVisibility();
     378             : }
     379             : 
     380             : nsresult
     381           0 : HTMLTextAreaElement::SetValueInternal(const nsAString& aValue,
     382             :                                       uint32_t aFlags)
     383             : {
     384             :   // Need to set the value changed flag here if our value has in fact changed
     385             :   // (i.e. if eSetValue_Notify is in aFlags), so that
     386             :   // nsTextControlFrame::UpdateValueDisplay retrieves the correct value if
     387             :   // needed.
     388           0 :   if (aFlags & nsTextEditorState::eSetValue_Notify) {
     389           0 :     SetValueChanged(true);
     390             :   }
     391             : 
     392           0 :   if (!mState.SetValue(aValue, aFlags)) {
     393           0 :     return NS_ERROR_OUT_OF_MEMORY;
     394             :   }
     395             : 
     396           0 :   return NS_OK;
     397             : }
     398             : 
     399             : NS_IMETHODIMP
     400           0 : HTMLTextAreaElement::SetValue(const nsAString& aValue)
     401             : {
     402             :   // If the value has been set by a script, we basically want to keep the
     403             :   // current change event state. If the element is ready to fire a change
     404             :   // event, we should keep it that way. Otherwise, we should make sure the
     405             :   // element will not fire any event because of the script interaction.
     406             :   //
     407             :   // NOTE: this is currently quite expensive work (too much string
     408             :   // manipulation). We should probably optimize that.
     409           0 :   nsAutoString currentValue;
     410           0 :   GetValueInternal(currentValue, true);
     411             : 
     412             :   nsresult rv =
     413             :     SetValueInternal(aValue,
     414             :       nsTextEditorState::eSetValue_ByContent |
     415             :       nsTextEditorState::eSetValue_Notify |
     416           0 :       nsTextEditorState::eSetValue_MoveCursorToEndIfValueChanged);
     417           0 :   NS_ENSURE_SUCCESS(rv, rv);
     418             : 
     419           0 :   if (mFocusedValue.Equals(currentValue)) {
     420           0 :     GetValueInternal(mFocusedValue, true);
     421             :   }
     422             : 
     423           0 :   return NS_OK;
     424             : }
     425             : 
     426             : NS_IMETHODIMP
     427           0 : HTMLTextAreaElement::SetUserInput(const nsAString& aValue)
     428             : {
     429             :   return SetValueInternal(aValue,
     430             :     nsTextEditorState::eSetValue_BySetUserInput |
     431             :     nsTextEditorState::eSetValue_Notify|
     432           0 :     nsTextEditorState::eSetValue_MoveCursorToEndIfValueChanged);
     433             : }
     434             : 
     435             : NS_IMETHODIMP
     436           0 : HTMLTextAreaElement::SetValueChanged(bool aValueChanged)
     437             : {
     438           0 :   bool previousValue = mValueChanged;
     439             : 
     440           0 :   mValueChanged = aValueChanged;
     441           0 :   if (!aValueChanged && !mState.IsEmpty()) {
     442           0 :     mState.EmptyValue();
     443             :   }
     444             : 
     445           0 :   if (mValueChanged != previousValue) {
     446           0 :     UpdateState(true);
     447             :   }
     448             : 
     449           0 :   return NS_OK;
     450             : }
     451             : 
     452             : NS_IMETHODIMP
     453           0 : HTMLTextAreaElement::GetDefaultValue(nsAString& aDefaultValue)
     454             : {
     455           0 :   if (!nsContentUtils::GetNodeTextContent(this, false, aDefaultValue, fallible)) {
     456           0 :     return NS_ERROR_OUT_OF_MEMORY;
     457             :   }
     458           0 :   return NS_OK;
     459             : }
     460             : 
     461             : NS_IMETHODIMP
     462           0 : HTMLTextAreaElement::SetDefaultValue(const nsAString& aDefaultValue)
     463             : {
     464           0 :   ErrorResult error;
     465           0 :   SetDefaultValue(aDefaultValue, error);
     466           0 :   return error.StealNSResult();
     467             : }
     468             : 
     469             : void
     470           0 : HTMLTextAreaElement::SetDefaultValue(const nsAString& aDefaultValue, ErrorResult& aError)
     471             : {
     472           0 :   nsresult rv = nsContentUtils::SetNodeTextContent(this, aDefaultValue, true);
     473           0 :   if (NS_SUCCEEDED(rv) && !mValueChanged) {
     474           0 :     Reset();
     475             :   }
     476           0 :   if (NS_FAILED(rv)) {
     477           0 :     aError.Throw(rv);
     478             :   }
     479           0 : }
     480             : 
     481             : bool
     482           2 : HTMLTextAreaElement::ParseAttribute(int32_t aNamespaceID,
     483             :                                     nsIAtom* aAttribute,
     484             :                                     const nsAString& aValue,
     485             :                                     nsAttrValue& aResult)
     486             : {
     487           2 :   if (aNamespaceID == kNameSpaceID_None) {
     488           2 :     if (aAttribute == nsGkAtoms::maxlength ||
     489           1 :         aAttribute == nsGkAtoms::minlength) {
     490           0 :       return aResult.ParseNonNegativeIntValue(aValue);
     491           1 :     } else if (aAttribute == nsGkAtoms::cols) {
     492           0 :       aResult.ParseIntWithFallback(aValue, DEFAULT_COLS);
     493           0 :       return true;
     494           1 :     } else if (aAttribute == nsGkAtoms::rows) {
     495           0 :       aResult.ParseIntWithFallback(aValue, DEFAULT_ROWS_TEXTAREA);
     496           0 :       return true;
     497             :     }
     498             :   }
     499           2 :   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
     500           2 :                                               aResult);
     501             : }
     502             : 
     503             : void
     504           0 : HTMLTextAreaElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
     505             :                                            GenericSpecifiedValues* aData)
     506             : {
     507           0 :   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Text))) {
     508             :     // wrap=off
     509           0 :     if (!aData->PropertyIsSet(eCSSProperty_white_space)) {
     510           0 :       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::wrap);
     511           0 :       if (value && value->Type() == nsAttrValue::eString &&
     512           0 :           value->Equals(nsGkAtoms::OFF, eIgnoreCase)) {
     513           0 :         aData->SetKeywordValue(eCSSProperty_white_space, StyleWhiteSpace::Pre);
     514             :       }
     515             :     }
     516             :   }
     517             : 
     518           0 :   nsGenericHTMLFormElementWithState::MapDivAlignAttributeInto(aAttributes, aData);
     519           0 :   nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aData);
     520           0 : }
     521             : 
     522             : nsChangeHint
     523           0 : HTMLTextAreaElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
     524             :                                             int32_t aModType) const
     525             : {
     526             :   nsChangeHint retval =
     527           0 :       nsGenericHTMLFormElementWithState::GetAttributeChangeHint(aAttribute, aModType);
     528           0 :   if (aAttribute == nsGkAtoms::rows ||
     529           0 :       aAttribute == nsGkAtoms::cols) {
     530           0 :     retval |= NS_STYLE_HINT_REFLOW;
     531           0 :   } else if (aAttribute == nsGkAtoms::wrap) {
     532           0 :     retval |= nsChangeHint_ReconstructFrame;
     533           0 :   } else if (aAttribute == nsGkAtoms::placeholder) {
     534           0 :     retval |= nsChangeHint_ReconstructFrame;
     535             :   }
     536           0 :   return retval;
     537             : }
     538             : 
     539             : NS_IMETHODIMP_(bool)
     540           2 : HTMLTextAreaElement::IsAttributeMapped(const nsIAtom* aAttribute) const
     541             : {
     542             :   static const MappedAttributeEntry attributes[] = {
     543             :     { &nsGkAtoms::wrap },
     544             :     { nullptr }
     545             :   };
     546             : 
     547             :   static const MappedAttributeEntry* const map[] = {
     548             :     attributes,
     549             :     sDivAlignAttributeMap,
     550             :     sCommonAttributeMap,
     551             :   };
     552             : 
     553           2 :   return FindAttributeDependence(aAttribute, map);
     554             : }
     555             : 
     556             : nsMapRuleToAttributesFunc
     557           0 : HTMLTextAreaElement::GetAttributeMappingFunction() const
     558             : {
     559           0 :   return &MapAttributesIntoRule;
     560             : }
     561             : 
     562             : bool
     563           0 : HTMLTextAreaElement::IsDisabledForEvents(EventMessage aMessage)
     564             : {
     565           0 :   nsIFormControlFrame* formControlFrame = GetFormControlFrame(false);
     566           0 :   nsIFrame* formFrame = do_QueryFrame(formControlFrame);
     567           0 :   return IsElementDisabledForEvents(aMessage, formFrame);
     568             : }
     569             : 
     570             : nsresult
     571           0 : HTMLTextAreaElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
     572             : {
     573           0 :   aVisitor.mCanHandle = false;
     574           0 :   if (IsDisabledForEvents(aVisitor.mEvent->mMessage)) {
     575           0 :     return NS_OK;
     576             :   }
     577             : 
     578             :   // Don't dispatch a second select event if we are already handling
     579             :   // one.
     580           0 :   if (aVisitor.mEvent->mMessage == eFormSelect) {
     581           0 :     if (mHandlingSelect) {
     582           0 :       return NS_OK;
     583             :     }
     584           0 :     mHandlingSelect = true;
     585             :   }
     586             : 
     587             :   // If noContentDispatch is true we will not allow content to handle
     588             :   // this event.  But to allow middle mouse button paste to work we must allow
     589             :   // middle clicks to go to text fields anyway.
     590           0 :   if (aVisitor.mEvent->mFlags.mNoContentDispatch) {
     591           0 :     aVisitor.mItemFlags |= NS_NO_CONTENT_DISPATCH;
     592             :   }
     593           0 :   if (aVisitor.mEvent->mMessage == eMouseClick &&
     594           0 :       aVisitor.mEvent->AsMouseEvent()->button ==
     595             :         WidgetMouseEvent::eMiddleButton) {
     596           0 :     aVisitor.mEvent->mFlags.mNoContentDispatch = false;
     597             :   }
     598             : 
     599           0 :   if (aVisitor.mEvent->mMessage == eBlur) {
     600             :     // Set mWantsPreHandleEvent and fire change event in PreHandleEvent to
     601             :     // prevent it breaks event target chain creation.
     602           0 :     aVisitor.mWantsPreHandleEvent = true;
     603             :   }
     604             : 
     605           0 :   return nsGenericHTMLFormElementWithState::GetEventTargetParent(aVisitor);
     606             : }
     607             : 
     608             : nsresult
     609           0 : HTMLTextAreaElement::PreHandleEvent(EventChainVisitor& aVisitor)
     610             : {
     611           0 :   if (aVisitor.mEvent->mMessage == eBlur) {
     612             :     // Fire onchange (if necessary), before we do the blur, bug 370521.
     613           0 :     FireChangeEventIfNeeded();
     614             :   }
     615           0 :   return nsGenericHTMLFormElementWithState::PreHandleEvent(aVisitor);
     616             : }
     617             : 
     618             : void
     619           0 : HTMLTextAreaElement::FireChangeEventIfNeeded()
     620             : {
     621           0 :   nsString value;
     622           0 :   GetValueInternal(value, true);
     623             : 
     624           0 :   if (mFocusedValue.Equals(value)) {
     625           0 :     return;
     626             :   }
     627             : 
     628             :   // Dispatch the change event.
     629           0 :   mFocusedValue = value;
     630           0 :   nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
     631             :                                        static_cast<nsIContent*>(this),
     632           0 :                                        NS_LITERAL_STRING("change"), true,
     633           0 :                                        false);
     634             : }
     635             : 
     636             : nsresult
     637           0 : HTMLTextAreaElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
     638             : {
     639           0 :   if (aVisitor.mEvent->mMessage == eFormSelect) {
     640           0 :     mHandlingSelect = false;
     641             :   }
     642             : 
     643           0 :   if (aVisitor.mEvent->mMessage == eFocus ||
     644           0 :       aVisitor.mEvent->mMessage == eBlur) {
     645           0 :     if (aVisitor.mEvent->mMessage == eFocus) {
     646             :       // If the invalid UI is shown, we should show it while focusing (and
     647             :       // update). Otherwise, we should not.
     648           0 :       GetValueInternal(mFocusedValue, true);
     649           0 :       mCanShowInvalidUI = !IsValid() && ShouldShowValidityUI();
     650             : 
     651             :       // If neither invalid UI nor valid UI is shown, we shouldn't show the valid
     652             :       // UI while typing.
     653           0 :       mCanShowValidUI = ShouldShowValidityUI();
     654             :     } else { // eBlur
     655           0 :       mCanShowInvalidUI = true;
     656           0 :       mCanShowValidUI = true;
     657             :     }
     658             : 
     659           0 :     UpdateState(true);
     660             :   }
     661             : 
     662             :   // Reset the flag for other content besides this text field
     663           0 :   aVisitor.mEvent->mFlags.mNoContentDispatch =
     664           0 :     ((aVisitor.mItemFlags & NS_NO_CONTENT_DISPATCH) != 0);
     665             : 
     666           0 :   return NS_OK;
     667             : }
     668             : 
     669             : void
     670           0 : HTMLTextAreaElement::DoneAddingChildren(bool aHaveNotified)
     671             : {
     672           0 :   if (!mValueChanged) {
     673           0 :     if (!mDoneAddingChildren) {
     674             :       // Reset now that we're done adding children if the content sink tried to
     675             :       // sneak some text in without calling AppendChildTo.
     676           0 :       Reset();
     677             :     }
     678             : 
     679           0 :     if (!mInhibitStateRestoration) {
     680           0 :       nsresult rv = GenerateStateKey();
     681           0 :       if (NS_SUCCEEDED(rv)) {
     682           0 :         RestoreFormControlState();
     683             :       }
     684             :     }
     685             :   }
     686             : 
     687           0 :   mDoneAddingChildren = true;
     688           0 : }
     689             : 
     690             : bool
     691           0 : HTMLTextAreaElement::IsDoneAddingChildren()
     692             : {
     693           0 :   return mDoneAddingChildren;
     694             : }
     695             : 
     696             : // Controllers Methods
     697             : 
     698             : nsIControllers*
     699           0 : HTMLTextAreaElement::GetControllers(ErrorResult& aError)
     700             : {
     701           0 :   if (!mControllers)
     702             :   {
     703             :     nsresult rv;
     704           0 :     mControllers = do_CreateInstance(kXULControllersCID, &rv);
     705           0 :     if (NS_FAILED(rv)) {
     706           0 :       aError.Throw(rv);
     707           0 :       return nullptr;
     708             :     }
     709             : 
     710           0 :     nsCOMPtr<nsIController> controller = do_CreateInstance("@mozilla.org/editor/editorcontroller;1", &rv);
     711           0 :     if (NS_FAILED(rv)) {
     712           0 :       aError.Throw(rv);
     713           0 :       return nullptr;
     714             :     }
     715             : 
     716           0 :     mControllers->AppendController(controller);
     717             : 
     718           0 :     controller = do_CreateInstance("@mozilla.org/editor/editingcontroller;1", &rv);
     719           0 :     if (NS_FAILED(rv)) {
     720           0 :       aError.Throw(rv);
     721           0 :       return nullptr;
     722             :     }
     723             : 
     724           0 :     mControllers->AppendController(controller);
     725             :   }
     726             : 
     727           0 :   return mControllers;
     728             : }
     729             : 
     730             : NS_IMETHODIMP
     731           0 : HTMLTextAreaElement::GetControllers(nsIControllers** aResult)
     732             : {
     733           0 :   NS_ENSURE_ARG_POINTER(aResult);
     734             : 
     735           0 :   ErrorResult error;
     736           0 :   *aResult = GetControllers(error);
     737           0 :   NS_IF_ADDREF(*aResult);
     738             : 
     739           0 :   return error.StealNSResult();
     740             : }
     741             : 
     742             : uint32_t
     743           0 : HTMLTextAreaElement::GetTextLength()
     744             : {
     745           0 :   nsAutoString val;
     746           0 :   GetValue(val);
     747           0 :   return val.Length();
     748             : }
     749             : 
     750             : NS_IMETHODIMP
     751           0 : HTMLTextAreaElement::GetTextLength(int32_t *aTextLength)
     752             : {
     753           0 :   NS_ENSURE_ARG_POINTER(aTextLength);
     754           0 :   *aTextLength = GetTextLength();
     755             : 
     756           0 :   return NS_OK;
     757             : }
     758             : 
     759             : Nullable<uint32_t>
     760           0 : HTMLTextAreaElement::GetSelectionStart(ErrorResult& aError)
     761             : {
     762             :   uint32_t selStart, selEnd;
     763           0 :   GetSelectionRange(&selStart, &selEnd, aError);
     764           0 :   return Nullable<uint32_t>(selStart);
     765             : }
     766             : 
     767             : void
     768           0 : HTMLTextAreaElement::SetSelectionStart(const Nullable<uint32_t>& aSelectionStart,
     769             :                                        ErrorResult& aError)
     770             : {
     771           0 :   mState.SetSelectionStart(aSelectionStart, aError);
     772           0 : }
     773             : 
     774             : Nullable<uint32_t>
     775           0 : HTMLTextAreaElement::GetSelectionEnd(ErrorResult& aError)
     776             : {
     777             :   uint32_t selStart, selEnd;
     778           0 :   GetSelectionRange(&selStart, &selEnd, aError);
     779           0 :   return Nullable<uint32_t>(selEnd);
     780             : }
     781             : 
     782             : void
     783           0 : HTMLTextAreaElement::SetSelectionEnd(const Nullable<uint32_t>& aSelectionEnd,
     784             :                                      ErrorResult& aError)
     785             : {
     786           0 :   mState.SetSelectionEnd(aSelectionEnd, aError);
     787           0 : }
     788             : 
     789             : void
     790           0 : HTMLTextAreaElement::GetSelectionRange(uint32_t* aSelectionStart,
     791             :                                        uint32_t* aSelectionEnd,
     792             :                                        ErrorResult& aRv)
     793             : {
     794           0 :   return mState.GetSelectionRange(aSelectionStart, aSelectionEnd, aRv);
     795             : }
     796             : 
     797             : void
     798           0 : HTMLTextAreaElement::GetSelectionDirection(nsAString& aDirection, ErrorResult& aError)
     799             : {
     800           0 :   mState.GetSelectionDirectionString(aDirection, aError);
     801           0 : }
     802             : 
     803             : void
     804           0 : HTMLTextAreaElement::SetSelectionDirection(const nsAString& aDirection,
     805             :                                            ErrorResult& aError)
     806             : {
     807           0 :   mState.SetSelectionDirection(aDirection, aError);
     808           0 : }
     809             : 
     810             : void
     811           0 : HTMLTextAreaElement::SetSelectionRange(uint32_t aSelectionStart,
     812             :                                        uint32_t aSelectionEnd,
     813             :                                        const Optional<nsAString>& aDirection,
     814             :                                        ErrorResult& aError)
     815             : {
     816           0 :   mState.SetSelectionRange(aSelectionStart, aSelectionEnd,
     817           0 :                            aDirection, aError);
     818           0 : }
     819             : 
     820             : void
     821           0 : HTMLTextAreaElement::SetRangeText(const nsAString& aReplacement,
     822             :                                   ErrorResult& aRv)
     823             : {
     824           0 :   mState.SetRangeText(aReplacement, aRv);
     825           0 : }
     826             : 
     827             : void
     828           0 : HTMLTextAreaElement::SetRangeText(const nsAString& aReplacement,
     829             :                                   uint32_t aStart, uint32_t aEnd,
     830             :                                   SelectionMode aSelectMode,
     831             :                                   ErrorResult& aRv)
     832             : {
     833           0 :   mState.SetRangeText(aReplacement, aStart, aEnd, aSelectMode, aRv);
     834           0 : }
     835             : 
     836             : void
     837           0 : HTMLTextAreaElement::GetValueFromSetRangeText(nsAString& aValue)
     838             : {
     839           0 :   GetValueInternal(aValue, false);
     840           0 : }
     841             : 
     842             : nsresult
     843           0 : HTMLTextAreaElement::SetValueFromSetRangeText(const nsAString& aValue)
     844             : {
     845             :   return SetValueInternal(aValue,
     846             :                           nsTextEditorState::eSetValue_ByContent |
     847           0 :                           nsTextEditorState::eSetValue_Notify);
     848             : }
     849             : 
     850             : nsresult
     851           0 : HTMLTextAreaElement::Reset()
     852             : {
     853           0 :   nsAutoString resetVal;
     854           0 :   GetDefaultValue(resetVal);
     855           0 :   SetValueChanged(false);
     856             : 
     857             :   nsresult rv = SetValueInternal(resetVal,
     858           0 :                                  nsTextEditorState::eSetValue_Internal);
     859           0 :   NS_ENSURE_SUCCESS(rv, rv);
     860             : 
     861           0 :   return NS_OK;
     862             : }
     863             : 
     864             : NS_IMETHODIMP
     865           0 : HTMLTextAreaElement::SubmitNamesValues(HTMLFormSubmission* aFormSubmission)
     866             : {
     867             :   // Disabled elements don't submit
     868           0 :   if (IsDisabled()) {
     869           0 :     return NS_OK;
     870             :   }
     871             : 
     872             :   //
     873             :   // Get the name (if no name, no submit)
     874             :   //
     875           0 :   nsAutoString name;
     876           0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
     877           0 :   if (name.IsEmpty()) {
     878           0 :     return NS_OK;
     879             :   }
     880             : 
     881             :   //
     882             :   // Get the value
     883             :   //
     884           0 :   nsAutoString value;
     885           0 :   GetValueInternal(value, false);
     886             : 
     887             :   //
     888             :   // Submit
     889             :   //
     890           0 :   return aFormSubmission->AddNameValuePair(name, value);
     891             : }
     892             : 
     893             : NS_IMETHODIMP
     894           0 : HTMLTextAreaElement::SaveState()
     895             : {
     896           0 :   nsresult rv = NS_OK;
     897             : 
     898             :   // Only save if value != defaultValue (bug 62713)
     899           0 :   nsPresState *state = nullptr;
     900           0 :   if (mValueChanged) {
     901           0 :     state = GetPrimaryPresState();
     902           0 :     if (state) {
     903           0 :       nsAutoString value;
     904           0 :       GetValueInternal(value, true);
     905             : 
     906             :       rv = nsLinebreakConverter::ConvertStringLineBreaks(
     907             :                value,
     908             :                nsLinebreakConverter::eLinebreakPlatform,
     909           0 :                nsLinebreakConverter::eLinebreakContent);
     910             : 
     911           0 :       if (NS_FAILED(rv)) {
     912           0 :         NS_ERROR("Converting linebreaks failed!");
     913           0 :         return rv;
     914             :       }
     915             : 
     916             :       nsCOMPtr<nsISupportsString> pState =
     917           0 :         do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
     918           0 :       if (!pState) {
     919           0 :         return NS_ERROR_OUT_OF_MEMORY;
     920             :       }
     921           0 :       pState->SetData(value);
     922           0 :       state->SetStateProperty(pState);
     923             :     }
     924             :   }
     925             : 
     926           0 :   if (mDisabledChanged) {
     927           0 :     if (!state) {
     928           0 :       state = GetPrimaryPresState();
     929           0 :       rv = NS_OK;
     930             :     }
     931           0 :     if (state) {
     932             :       // We do not want to save the real disabled state but the disabled
     933             :       // attribute.
     934           0 :       state->SetDisabled(HasAttr(kNameSpaceID_None, nsGkAtoms::disabled));
     935             :     }
     936             :   }
     937           0 :   return rv;
     938             : }
     939             : 
     940             : bool
     941           0 : HTMLTextAreaElement::RestoreState(nsPresState* aState)
     942             : {
     943             :   nsCOMPtr<nsISupportsString> state
     944           0 :     (do_QueryInterface(aState->GetStateProperty()));
     945             : 
     946           0 :   if (state) {
     947           0 :     nsAutoString data;
     948           0 :     state->GetData(data);
     949           0 :     nsresult rv = SetValue(data);
     950           0 :     NS_ENSURE_SUCCESS(rv, false);
     951             :   }
     952             : 
     953           0 :   if (aState->IsDisabledSet() && !aState->GetDisabled()) {
     954           0 :     SetDisabled(false);
     955             :   }
     956             : 
     957           0 :   return false;
     958             : }
     959             : 
     960             : EventStates
     961           6 : HTMLTextAreaElement::IntrinsicState() const
     962             : {
     963           6 :   EventStates state = nsGenericHTMLFormElementWithState::IntrinsicState();
     964             : 
     965           6 :   if (HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
     966           0 :     state |= NS_EVENT_STATE_REQUIRED;
     967             :   } else {
     968           6 :     state |= NS_EVENT_STATE_OPTIONAL;
     969             :   }
     970             : 
     971           6 :   if (IsCandidateForConstraintValidation()) {
     972           6 :     if (IsValid()) {
     973           6 :       state |= NS_EVENT_STATE_VALID;
     974             :     } else {
     975           0 :       state |= NS_EVENT_STATE_INVALID;
     976             :       // :-moz-ui-invalid always apply if the element suffers from a custom
     977             :       // error and never applies if novalidate is set on the form owner.
     978           0 :       if ((!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) &&
     979           0 :           (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR) ||
     980           0 :            (mCanShowInvalidUI && ShouldShowValidityUI()))) {
     981           0 :         state |= NS_EVENT_STATE_MOZ_UI_INVALID;
     982             :       }
     983             :     }
     984             : 
     985             :     // :-moz-ui-valid applies if all the following are true:
     986             :     // 1. The element is not focused, or had either :-moz-ui-valid or
     987             :     //    :-moz-ui-invalid applying before it was focused ;
     988             :     // 2. The element is either valid or isn't allowed to have
     989             :     //    :-moz-ui-invalid applying ;
     990             :     // 3. The element has no form owner or its form owner doesn't have the
     991             :     //    novalidate attribute set ;
     992             :     // 4. The element has already been modified or the user tried to submit the
     993             :     //    form owner while invalid.
     994          24 :     if ((!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) &&
     995          12 :         (mCanShowValidUI && ShouldShowValidityUI() &&
     996           6 :          (IsValid() || (state.HasState(NS_EVENT_STATE_MOZ_UI_INVALID) &&
     997           0 :                         !mCanShowInvalidUI)))) {
     998           0 :       state |= NS_EVENT_STATE_MOZ_UI_VALID;
     999             :     }
    1000             :   }
    1001             : 
    1002           6 :   if (HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder) &&
    1003           0 :       IsValueEmpty()) {
    1004           0 :     state |= NS_EVENT_STATE_PLACEHOLDERSHOWN;
    1005             :   }
    1006             : 
    1007           6 :   return state;
    1008             : }
    1009             : 
    1010             : nsresult
    1011           3 : HTMLTextAreaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
    1012             :                                 nsIContent* aBindingParent,
    1013             :                                 bool aCompileEventHandlers)
    1014             : {
    1015           3 :   nsresult rv = nsGenericHTMLFormElementWithState::BindToTree(aDocument, aParent,
    1016             :                                                               aBindingParent,
    1017           3 :                                                               aCompileEventHandlers);
    1018           3 :   NS_ENSURE_SUCCESS(rv, rv);
    1019             : 
    1020             :   // If there is a disabled fieldset in the parent chain, the element is now
    1021             :   // barred from constraint validation and can't suffer from value missing.
    1022           3 :   UpdateValueMissingValidityState();
    1023           3 :   UpdateBarredFromConstraintValidation();
    1024             : 
    1025             :   // And now make sure our state is up to date
    1026           3 :   UpdateState(false);
    1027             : 
    1028           3 :   return rv;
    1029             : }
    1030             : 
    1031             : void
    1032           0 : HTMLTextAreaElement::UnbindFromTree(bool aDeep, bool aNullParent)
    1033             : {
    1034           0 :   nsGenericHTMLFormElementWithState::UnbindFromTree(aDeep, aNullParent);
    1035             : 
    1036             :   // We might be no longer disabled because of parent chain changed.
    1037           0 :   UpdateValueMissingValidityState();
    1038           0 :   UpdateBarredFromConstraintValidation();
    1039             : 
    1040             :   // And now make sure our state is up to date
    1041           0 :   UpdateState(false);
    1042           0 : }
    1043             : 
    1044             : nsresult
    1045           3 : HTMLTextAreaElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
    1046             :                                    const nsAttrValueOrString* aValue,
    1047             :                                    bool aNotify)
    1048             : {
    1049           3 :   if (aNotify && aName == nsGkAtoms::disabled &&
    1050             :       aNameSpaceID == kNameSpaceID_None) {
    1051           0 :     mDisabledChanged = true;
    1052             :   }
    1053             : 
    1054           3 :   return nsGenericHTMLFormElementWithState::BeforeSetAttr(aNameSpaceID, aName,
    1055           3 :                                                  aValue, aNotify);
    1056             : }
    1057             : 
    1058             : void
    1059           0 : HTMLTextAreaElement::CharacterDataChanged(nsIDocument* aDocument,
    1060             :                                           nsIContent* aContent,
    1061             :                                           CharacterDataChangeInfo* aInfo)
    1062             : {
    1063           0 :   ContentChanged(aContent);
    1064           0 : }
    1065             : 
    1066             : void
    1067           0 : HTMLTextAreaElement::ContentAppended(nsIDocument* aDocument,
    1068             :                                      nsIContent* aContainer,
    1069             :                                      nsIContent* aFirstNewContent,
    1070             :                                      int32_t /* unused */)
    1071             : {
    1072           0 :   ContentChanged(aFirstNewContent);
    1073           0 : }
    1074             : 
    1075             : void
    1076           0 : HTMLTextAreaElement::ContentInserted(nsIDocument* aDocument,
    1077             :                                      nsIContent* aContainer,
    1078             :                                      nsIContent* aChild,
    1079             :                                      int32_t /* unused */)
    1080             : {
    1081           0 :   ContentChanged(aChild);
    1082           0 : }
    1083             : 
    1084             : void
    1085           0 : HTMLTextAreaElement::ContentRemoved(nsIDocument* aDocument,
    1086             :                                     nsIContent* aContainer,
    1087             :                                     nsIContent* aChild,
    1088             :                                     int32_t aIndexInContainer,
    1089             :                                     nsIContent* aPreviousSibling)
    1090             : {
    1091           0 :   ContentChanged(aChild);
    1092           0 : }
    1093             : 
    1094             : void
    1095           0 : HTMLTextAreaElement::ContentChanged(nsIContent* aContent)
    1096             : {
    1097           0 :   if (!mValueChanged && mDoneAddingChildren &&
    1098           0 :       nsContentUtils::IsInSameAnonymousTree(this, aContent)) {
    1099             :     // Hard to say what the reset can trigger, so be safe pending
    1100             :     // further auditing.
    1101           0 :     nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
    1102           0 :     Reset();
    1103             :   }
    1104           0 : }
    1105             : 
    1106             : nsresult
    1107           3 : HTMLTextAreaElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
    1108             :                                   const nsAttrValue* aValue,
    1109             :                                   const nsAttrValue* aOldValue, bool aNotify)
    1110             : {
    1111           3 :   if (aNameSpaceID == kNameSpaceID_None) {
    1112           4 :     if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
    1113           2 :         aName == nsGkAtoms::readonly) {
    1114           0 :       UpdateValueMissingValidityState();
    1115             : 
    1116             :       // This *has* to be called *after* validity has changed.
    1117           0 :       if (aName == nsGkAtoms::readonly || aName == nsGkAtoms::disabled) {
    1118           0 :         UpdateBarredFromConstraintValidation();
    1119             :       }
    1120           2 :     } else if (aName == nsGkAtoms::maxlength) {
    1121           0 :       UpdateTooLongValidityState();
    1122           2 :     } else if (aName == nsGkAtoms::minlength) {
    1123           0 :       UpdateTooShortValidityState();
    1124             :     }
    1125             :   }
    1126             : 
    1127           3 :   return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, aValue,
    1128           3 :                                                          aOldValue, aNotify);
    1129             :   }
    1130             : 
    1131             : nsresult
    1132           0 : HTMLTextAreaElement::CopyInnerTo(Element* aDest, bool aPreallocateChildren)
    1133             : {
    1134           0 :   nsresult rv = nsGenericHTMLFormElementWithState::CopyInnerTo(aDest,
    1135           0 :                                                                aPreallocateChildren);
    1136           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1137             : 
    1138           0 :   if (aDest->OwnerDoc()->IsStaticDocument()) {
    1139           0 :     nsAutoString value;
    1140           0 :     GetValueInternal(value, true);
    1141           0 :     return static_cast<HTMLTextAreaElement*>(aDest)->SetValue(value);
    1142             :   }
    1143           0 :   return NS_OK;
    1144             : }
    1145             : 
    1146             : bool
    1147           0 : HTMLTextAreaElement::IsMutable() const
    1148             : {
    1149           0 :   return (!HasAttr(kNameSpaceID_None, nsGkAtoms::readonly) && !IsDisabled());
    1150             : }
    1151             : 
    1152             : bool
    1153           0 : HTMLTextAreaElement::IsValueEmpty() const
    1154             : {
    1155           0 :   nsAutoString value;
    1156           0 :   GetValueInternal(value, true);
    1157             : 
    1158           0 :   return value.IsEmpty();
    1159             : }
    1160             : 
    1161             : // nsIConstraintValidation
    1162             : 
    1163             : NS_IMETHODIMP
    1164           0 : HTMLTextAreaElement::SetCustomValidity(const nsAString& aError)
    1165             : {
    1166           0 :   nsIConstraintValidation::SetCustomValidity(aError);
    1167             : 
    1168           0 :   UpdateState(true);
    1169             : 
    1170           0 :   return NS_OK;
    1171             : }
    1172             : 
    1173             : bool
    1174           0 : HTMLTextAreaElement::IsTooLong()
    1175             : {
    1176           0 :   if (!mValueChanged ||
    1177           0 :       !mLastValueChangeWasInteractive ||
    1178           0 :       !HasAttr(kNameSpaceID_None, nsGkAtoms::maxlength)) {
    1179           0 :     return false;
    1180             :   }
    1181             : 
    1182           0 :   int32_t maxLength = -1;
    1183           0 :   GetMaxLength(&maxLength);
    1184             : 
    1185             :   // Maxlength of -1 means parsing error.
    1186           0 :   if (maxLength == -1) {
    1187           0 :     return false;
    1188             :   }
    1189             : 
    1190           0 :   int32_t textLength = -1;
    1191           0 :   GetTextLength(&textLength);
    1192             : 
    1193           0 :   return textLength > maxLength;
    1194             : }
    1195             : 
    1196             : bool
    1197           0 : HTMLTextAreaElement::IsTooShort()
    1198             : {
    1199           0 :   if (!mValueChanged ||
    1200           0 :       !mLastValueChangeWasInteractive ||
    1201           0 :       !HasAttr(kNameSpaceID_None, nsGkAtoms::minlength)) {
    1202           0 :     return false;
    1203             :   }
    1204             : 
    1205           0 :   int32_t minLength = -1;
    1206           0 :   GetMinLength(&minLength);
    1207             : 
    1208             :   // Minlength of -1 means parsing error.
    1209           0 :   if (minLength == -1) {
    1210           0 :     return false;
    1211             :   }
    1212             : 
    1213           0 :   int32_t textLength = -1;
    1214           0 :   GetTextLength(&textLength);
    1215             : 
    1216           0 :   return textLength && textLength < minLength;
    1217             : }
    1218             : 
    1219             : bool
    1220           3 : HTMLTextAreaElement::IsValueMissing() const
    1221             : {
    1222           3 :   if (!HasAttr(kNameSpaceID_None, nsGkAtoms::required) || !IsMutable()) {
    1223           3 :     return false;
    1224             :   }
    1225             : 
    1226           0 :   return IsValueEmpty();
    1227             : }
    1228             : 
    1229             : void
    1230           0 : HTMLTextAreaElement::UpdateTooLongValidityState()
    1231             : {
    1232           0 :   SetValidityState(VALIDITY_STATE_TOO_LONG, IsTooLong());
    1233           0 : }
    1234             : 
    1235             : void
    1236           0 : HTMLTextAreaElement::UpdateTooShortValidityState()
    1237             : {
    1238           0 :   SetValidityState(VALIDITY_STATE_TOO_SHORT, IsTooShort());
    1239           0 : }
    1240             : 
    1241             : void
    1242           3 : HTMLTextAreaElement::UpdateValueMissingValidityState()
    1243             : {
    1244           3 :   SetValidityState(VALIDITY_STATE_VALUE_MISSING, IsValueMissing());
    1245           3 : }
    1246             : 
    1247             : void
    1248           3 : HTMLTextAreaElement::UpdateBarredFromConstraintValidation()
    1249             : {
    1250           6 :   SetBarredFromConstraintValidation(HasAttr(kNameSpaceID_None,
    1251           6 :                                             nsGkAtoms::readonly) ||
    1252           6 :                                     IsDisabled());
    1253           3 : }
    1254             : 
    1255             : nsresult
    1256           0 : HTMLTextAreaElement::GetValidationMessage(nsAString& aValidationMessage,
    1257             :                                           ValidityStateType aType)
    1258             : {
    1259           0 :   nsresult rv = NS_OK;
    1260             : 
    1261           0 :   switch (aType)
    1262             :   {
    1263             :     case VALIDITY_STATE_TOO_LONG:
    1264             :       {
    1265           0 :         nsXPIDLString message;
    1266           0 :         int32_t maxLength = -1;
    1267           0 :         int32_t textLength = -1;
    1268           0 :         nsAutoString strMaxLength;
    1269           0 :         nsAutoString strTextLength;
    1270             : 
    1271           0 :         GetMaxLength(&maxLength);
    1272           0 :         GetTextLength(&textLength);
    1273             : 
    1274           0 :         strMaxLength.AppendInt(maxLength);
    1275           0 :         strTextLength.AppendInt(textLength);
    1276             : 
    1277           0 :         const char16_t* params[] = { strMaxLength.get(), strTextLength.get() };
    1278             :         rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
    1279             :                                                    "FormValidationTextTooLong",
    1280           0 :                                                    params, message);
    1281           0 :         aValidationMessage = message;
    1282             :       }
    1283           0 :       break;
    1284             :     case VALIDITY_STATE_TOO_SHORT:
    1285             :       {
    1286           0 :         nsXPIDLString message;
    1287           0 :         int32_t minLength = -1;
    1288           0 :         int32_t textLength = -1;
    1289           0 :         nsAutoString strMinLength;
    1290           0 :         nsAutoString strTextLength;
    1291             : 
    1292           0 :         GetMinLength(&minLength);
    1293           0 :         GetTextLength(&textLength);
    1294             : 
    1295           0 :         strMinLength.AppendInt(minLength);
    1296           0 :         strTextLength.AppendInt(textLength);
    1297             : 
    1298           0 :         const char16_t* params[] = { strMinLength.get(), strTextLength.get() };
    1299             :         rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
    1300             :                                                    "FormValidationTextTooShort",
    1301           0 :                                                    params, message);
    1302           0 :         aValidationMessage = message;
    1303             :       }
    1304           0 :       break;
    1305             :     case VALIDITY_STATE_VALUE_MISSING:
    1306             :       {
    1307           0 :         nsXPIDLString message;
    1308             :         rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
    1309             :                                                 "FormValidationValueMissing",
    1310           0 :                                                 message);
    1311           0 :         aValidationMessage = message;
    1312             :       }
    1313           0 :       break;
    1314             :     default:
    1315           0 :       rv = nsIConstraintValidation::GetValidationMessage(aValidationMessage, aType);
    1316             :   }
    1317             : 
    1318           0 :   return rv;
    1319             : }
    1320             : 
    1321             : NS_IMETHODIMP_(bool)
    1322           0 : HTMLTextAreaElement::IsSingleLineTextControl() const
    1323             : {
    1324           0 :   return false;
    1325             : }
    1326             : 
    1327             : NS_IMETHODIMP_(bool)
    1328           0 : HTMLTextAreaElement::IsTextArea() const
    1329             : {
    1330           0 :   return true;
    1331             : }
    1332             : 
    1333             : NS_IMETHODIMP_(bool)
    1334           0 : HTMLTextAreaElement::IsPlainTextControl() const
    1335             : {
    1336             :   // need to check our HTML attribute and/or CSS.
    1337           0 :   return true;
    1338             : }
    1339             : 
    1340             : NS_IMETHODIMP_(bool)
    1341           0 : HTMLTextAreaElement::IsPasswordTextControl() const
    1342             : {
    1343           0 :   return false;
    1344             : }
    1345             : 
    1346             : NS_IMETHODIMP_(int32_t)
    1347           0 : HTMLTextAreaElement::GetCols()
    1348             : {
    1349           0 :   return Cols();
    1350             : }
    1351             : 
    1352             : NS_IMETHODIMP_(int32_t)
    1353           0 : HTMLTextAreaElement::GetWrapCols()
    1354             : {
    1355             :   // wrap=off means -1 for wrap width no matter what cols is
    1356             :   nsHTMLTextWrap wrapProp;
    1357           0 :   nsITextControlElement::GetWrapPropertyEnum(this, wrapProp);
    1358           0 :   if (wrapProp == nsITextControlElement::eHTMLTextWrap_Off) {
    1359             :     // do not wrap when wrap=off
    1360           0 :     return 0;
    1361             :   }
    1362             : 
    1363             :   // Otherwise we just wrap at the given number of columns
    1364           0 :   return GetCols();
    1365             : }
    1366             : 
    1367             : 
    1368             : NS_IMETHODIMP_(int32_t)
    1369           0 : HTMLTextAreaElement::GetRows()
    1370             : {
    1371           0 :   const nsAttrValue* attr = GetParsedAttr(nsGkAtoms::rows);
    1372           0 :   if (attr && attr->Type() == nsAttrValue::eInteger) {
    1373           0 :     int32_t rows = attr->GetIntegerValue();
    1374           0 :     return (rows <= 0) ? DEFAULT_ROWS_TEXTAREA : rows;
    1375             :   }
    1376             : 
    1377           0 :   return DEFAULT_ROWS_TEXTAREA;
    1378             : }
    1379             : 
    1380             : NS_IMETHODIMP_(void)
    1381           0 : HTMLTextAreaElement::GetDefaultValueFromContent(nsAString& aValue)
    1382             : {
    1383           0 :   GetDefaultValue(aValue);
    1384           0 : }
    1385             : 
    1386             : NS_IMETHODIMP_(bool)
    1387           0 : HTMLTextAreaElement::ValueChanged() const
    1388             : {
    1389           0 :   return mValueChanged;
    1390             : }
    1391             : 
    1392             : NS_IMETHODIMP_(void)
    1393           0 : HTMLTextAreaElement::GetTextEditorValue(nsAString& aValue,
    1394             :                                         bool aIgnoreWrap) const
    1395             : {
    1396           0 :   mState.GetValue(aValue, aIgnoreWrap);
    1397           0 : }
    1398             : 
    1399             : NS_IMETHODIMP_(void)
    1400           0 : HTMLTextAreaElement::InitializeKeyboardEventListeners()
    1401             : {
    1402           0 :   mState.InitializeKeyboardEventListeners();
    1403           0 : }
    1404             : 
    1405             : NS_IMETHODIMP_(void)
    1406           0 : HTMLTextAreaElement::OnValueChanged(bool aNotify, bool aWasInteractiveUserChange)
    1407             : {
    1408           0 :   mLastValueChangeWasInteractive = aWasInteractiveUserChange;
    1409             : 
    1410             :   // Update the validity state
    1411           0 :   bool validBefore = IsValid();
    1412           0 :   UpdateTooLongValidityState();
    1413           0 :   UpdateTooShortValidityState();
    1414           0 :   UpdateValueMissingValidityState();
    1415             : 
    1416           0 :   if (validBefore != IsValid() ||
    1417           0 :       HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
    1418           0 :     UpdateState(aNotify);
    1419             :   }
    1420           0 : }
    1421             : 
    1422             : NS_IMETHODIMP_(bool)
    1423           0 : HTMLTextAreaElement::HasCachedSelection()
    1424             : {
    1425           0 :   return mState.IsSelectionCached();
    1426             : }
    1427             : 
    1428             : void
    1429           0 : HTMLTextAreaElement::FieldSetDisabledChanged(bool aNotify)
    1430             : {
    1431           0 :   UpdateValueMissingValidityState();
    1432           0 :   UpdateBarredFromConstraintValidation();
    1433             : 
    1434           0 :   nsGenericHTMLFormElementWithState::FieldSetDisabledChanged(aNotify);
    1435           0 : }
    1436             : 
    1437             : JSObject*
    1438           0 : HTMLTextAreaElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
    1439             : {
    1440           0 :   return HTMLTextAreaElementBinding::Wrap(aCx, this, aGivenProto);
    1441             : }
    1442             : 
    1443             : } // namespace dom
    1444             : } // namespace mozilla

Generated by: LCOV version 1.13