LCOV - code coverage report
Current view: top level - dom/html - nsGenericHTMLElement.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 277 1248 22.2 %
Date: 2017-07-14 16:53:18 Functions: 44 133 33.1 %
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/ArrayUtils.h"
       8             : #include "mozilla/DeclarationBlockInlines.h"
       9             : #include "mozilla/EventDispatcher.h"
      10             : #include "mozilla/EventListenerManager.h"
      11             : #include "mozilla/EventStateManager.h"
      12             : #include "mozilla/EventStates.h"
      13             : #include "mozilla/GenericSpecifiedValuesInlines.h"
      14             : #include "mozilla/Likely.h"
      15             : #include "mozilla/MouseEvents.h"
      16             : #include "mozilla/TextEditor.h"
      17             : 
      18             : #include "nscore.h"
      19             : #include "nsGenericHTMLElement.h"
      20             : #include "nsAttrValueInlines.h"
      21             : #include "nsCOMPtr.h"
      22             : #include "nsIAtom.h"
      23             : #include "nsQueryObject.h"
      24             : #include "nsIContentInlines.h"
      25             : #include "nsIContentViewer.h"
      26             : #include "mozilla/css/Declaration.h"
      27             : #include "nsIDocument.h"
      28             : #include "nsIDocumentEncoder.h"
      29             : #include "nsIDOMHTMLDocument.h"
      30             : #include "nsIDOMAttr.h"
      31             : #include "nsIDOMDocumentFragment.h"
      32             : #include "nsIDOMHTMLElement.h"
      33             : #include "nsIDOMHTMLMenuElement.h"
      34             : #include "nsIDOMWindow.h"
      35             : #include "nsIDOMDocument.h"
      36             : #include "nsMappedAttributes.h"
      37             : #include "nsHTMLStyleSheet.h"
      38             : #include "nsIHTMLDocument.h"
      39             : #include "nsPIDOMWindow.h"
      40             : #include "nsIURL.h"
      41             : #include "nsEscape.h"
      42             : #include "nsIFrameInlines.h"
      43             : #include "nsIScrollableFrame.h"
      44             : #include "nsView.h"
      45             : #include "nsViewManager.h"
      46             : #include "nsIWidget.h"
      47             : #include "nsRange.h"
      48             : #include "nsIPresShell.h"
      49             : #include "nsPresContext.h"
      50             : #include "nsIDocShell.h"
      51             : #include "nsNameSpaceManager.h"
      52             : #include "nsError.h"
      53             : #include "nsIPrincipal.h"
      54             : #include "nsContainerFrame.h"
      55             : #include "nsStyleUtil.h"
      56             : 
      57             : #include "nsPresState.h"
      58             : #include "nsILayoutHistoryState.h"
      59             : 
      60             : #include "nsHTMLParts.h"
      61             : #include "nsContentUtils.h"
      62             : #include "mozilla/dom/DirectionalityUtils.h"
      63             : #include "nsString.h"
      64             : #include "nsUnicharUtils.h"
      65             : #include "nsGkAtoms.h"
      66             : #include "nsIDOMEvent.h"
      67             : #include "nsDOMCSSDeclaration.h"
      68             : #include "nsITextControlFrame.h"
      69             : #include "nsIForm.h"
      70             : #include "nsIFormControl.h"
      71             : #include "nsIDOMHTMLFormElement.h"
      72             : #include "mozilla/dom/HTMLFormElement.h"
      73             : #include "nsFocusManager.h"
      74             : #include "nsAttrValueOrString.h"
      75             : 
      76             : #include "mozilla/InternalMutationEvent.h"
      77             : #include "nsDOMStringMap.h"
      78             : 
      79             : #include "nsIEditor.h"
      80             : #include "nsLayoutUtils.h"
      81             : #include "mozAutoDocUpdate.h"
      82             : #include "nsHtml5Module.h"
      83             : #include "nsITextControlElement.h"
      84             : #include "mozilla/dom/Element.h"
      85             : #include "HTMLFieldSetElement.h"
      86             : #include "nsTextNode.h"
      87             : #include "HTMLBRElement.h"
      88             : #include "HTMLMenuElement.h"
      89             : #include "nsDOMMutationObserver.h"
      90             : #include "mozilla/Preferences.h"
      91             : #include "mozilla/dom/FromParser.h"
      92             : #include "mozilla/dom/Link.h"
      93             : #include "mozilla/BloomFilter.h"
      94             : #include "mozilla/dom/ScriptLoader.h"
      95             : 
      96             : #include "nsVariant.h"
      97             : #include "nsDOMTokenList.h"
      98             : #include "nsThreadUtils.h"
      99             : #include "nsTextFragment.h"
     100             : #include "mozilla/dom/BindingUtils.h"
     101             : #include "mozilla/dom/TouchEvent.h"
     102             : #include "mozilla/ErrorResult.h"
     103             : #include "nsHTMLDocument.h"
     104             : #include "nsGlobalWindow.h"
     105             : #include "mozilla/dom/HTMLBodyElement.h"
     106             : #include "imgIContainer.h"
     107             : #include "nsComputedDOMStyle.h"
     108             : #include "mozilla/StyleSetHandle.h"
     109             : #include "mozilla/StyleSetHandleInlines.h"
     110             : #include "ReferrerPolicy.h"
     111             : #include "mozilla/dom/HTMLLabelElement.h"
     112             : 
     113             : using namespace mozilla;
     114             : using namespace mozilla::dom;
     115             : 
     116             : /**
     117             :  * nsAutoFocusEvent is used to dispatch a focus event when a
     118             :  * nsGenericHTMLFormElement is binded to the tree with the autofocus attribute
     119             :  * enabled.
     120             :  */
     121           0 : class nsAutoFocusEvent : public Runnable
     122             : {
     123             : public:
     124           0 :   explicit nsAutoFocusEvent(nsGenericHTMLFormElement* aElement)
     125           0 :     : mozilla::Runnable("nsAutoFocusEvent")
     126           0 :     , mElement(aElement)
     127             :   {
     128           0 :   }
     129             : 
     130           0 :   NS_IMETHOD Run() override {
     131           0 :     nsFocusManager* fm = nsFocusManager::GetFocusManager();
     132           0 :     if (!fm) {
     133           0 :       return NS_ERROR_NULL_POINTER;
     134             :     }
     135             : 
     136           0 :     nsIDocument* document = mElement->OwnerDoc();
     137             : 
     138           0 :     nsPIDOMWindowOuter* window = document->GetWindow();
     139           0 :     if (!window) {
     140           0 :       return NS_OK;
     141             :     }
     142             : 
     143             :     // Trying to found the top window (equivalent to window.top).
     144           0 :     if (nsCOMPtr<nsPIDOMWindowOuter> top = window->GetTop()) {
     145           0 :       window = top;
     146             :     }
     147             : 
     148           0 :     if (window->GetFocusedNode()) {
     149           0 :       return NS_OK;
     150             :     }
     151             : 
     152           0 :     nsCOMPtr<nsIDocument> topDoc = window->GetExtantDoc();
     153           0 :     if (topDoc && topDoc->GetReadyStateEnum() == nsIDocument::READYSTATE_COMPLETE) {
     154           0 :       return NS_OK;
     155             :     }
     156             : 
     157             :     // If something is focused in the same document, ignore autofocus.
     158           0 :     if (!fm->GetFocusedContent() ||
     159           0 :         fm->GetFocusedContent()->OwnerDoc() != document) {
     160           0 :       mozilla::ErrorResult rv;
     161           0 :       mElement->Focus(rv);
     162           0 :       return rv.StealNSResult();
     163             :     }
     164             : 
     165           0 :     return NS_OK;
     166             :   }
     167             : private:
     168             :   // NOTE: nsGenericHTMLFormElement is saved as a nsGenericHTMLElement
     169             :   // because AddRef/Release are ambiguous with nsGenericHTMLFormElement
     170             :   // and Focus() is declared (and defined) in nsGenericHTMLElement class.
     171             :   RefPtr<nsGenericHTMLElement> mElement;
     172             : };
     173             : 
     174        1088 : NS_IMPL_ADDREF_INHERITED(nsGenericHTMLElement, nsGenericHTMLElementBase)
     175         889 : NS_IMPL_RELEASE_INHERITED(nsGenericHTMLElement, nsGenericHTMLElementBase)
     176             : 
     177        1038 : NS_INTERFACE_MAP_BEGIN(nsGenericHTMLElement)
     178        1038 :   NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLElement)
     179        1026 :   NS_INTERFACE_MAP_ENTRY(nsIDOMElement)
     180        1007 :   NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
     181         985 : NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElementBase)
     182             : 
     183             : nsresult
     184           4 : nsGenericHTMLElement::CopyInnerTo(Element* aDst, bool aPreallocateChildren)
     185             : {
     186           4 :   MOZ_ASSERT(!aDst->GetUncomposedDoc(),
     187             :              "Should not CopyInnerTo an Element in a document");
     188             :   nsresult rv;
     189             : 
     190           4 :   bool reparse = (aDst->OwnerDoc() != OwnerDoc());
     191             : 
     192             :   rv = static_cast<nsGenericHTMLElement*>(aDst)->mAttrsAndChildren.
     193           4 :        EnsureCapacityToClone(mAttrsAndChildren, aPreallocateChildren);
     194           4 :   NS_ENSURE_SUCCESS(rv, rv);
     195             : 
     196           4 :   int32_t i, count = GetAttrCount();
     197          14 :   for (i = 0; i < count; ++i) {
     198          10 :     const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
     199          10 :     const nsAttrValue *value = mAttrsAndChildren.AttrAt(i);
     200             : 
     201          10 :     if (name->Equals(nsGkAtoms::style, kNameSpaceID_None) &&
     202           0 :         value->Type() == nsAttrValue::eCSSDeclaration) {
     203             :       // We still clone CSS attributes, even in the cross-document case.
     204             :       // https://github.com/w3c/webappsec-csp/issues/212
     205             : 
     206             :       // We can't just set this as a string, because that will fail
     207             :       // to reparse the string into style data until the node is
     208             :       // inserted into the document.  Clone the Rule instead.
     209           0 :       nsAttrValue valueCopy(*value);
     210           0 :       rv = aDst->SetParsedAttr(name->NamespaceID(), name->LocalName(),
     211           0 :                                name->GetPrefix(), valueCopy, false);
     212           0 :       NS_ENSURE_SUCCESS(rv, rv);
     213             : 
     214           0 :       DeclarationBlock* cssDeclaration = value->GetCSSDeclarationValue();
     215           0 :       cssDeclaration->SetImmutable();
     216          10 :     } else if (reparse) {
     217          20 :       nsAutoString valStr;
     218          10 :       value->ToString(valStr);
     219             : 
     220          10 :       rv = aDst->SetAttr(name->NamespaceID(), name->LocalName(),
     221          20 :                          name->GetPrefix(), valStr, false);
     222          10 :       NS_ENSURE_SUCCESS(rv, rv);
     223             :     } else {
     224           0 :       nsAttrValue valueCopy(*value);
     225           0 :       rv = aDst->SetParsedAttr(name->NamespaceID(), name->LocalName(),
     226           0 :                                name->GetPrefix(), valueCopy, false);
     227           0 :       NS_ENSURE_SUCCESS(rv, rv);
     228             :     }
     229             :   }
     230             : 
     231           4 :   return NS_OK;
     232             : }
     233             : 
     234             : NS_IMETHODIMP
     235           0 : nsGenericHTMLElement::GetDataset(nsISupports** aDataset)
     236             : {
     237           0 :   *aDataset = Dataset().take();
     238           0 :   return NS_OK;
     239             : }
     240             : 
     241             : static const nsAttrValue::EnumTable kDirTable[] = {
     242             :   { "ltr", eDir_LTR },
     243             :   { "rtl", eDir_RTL },
     244             :   { "auto", eDir_Auto },
     245             :   { nullptr, 0 }
     246             : };
     247             : 
     248             : void
     249           0 : nsGenericHTMLElement::GetAccessKeyLabel(nsString& aLabel)
     250             : {
     251           0 :   nsAutoString suffix;
     252           0 :   GetAccessKey(suffix);
     253           0 :   if (!suffix.IsEmpty()) {
     254           0 :     EventStateManager::GetAccessKeyLabelPrefix(this, aLabel);
     255           0 :     aLabel.Append(suffix);
     256             :   }
     257           0 : }
     258             : 
     259             : static bool
     260           0 : IS_TABLE_CELL(LayoutFrameType frameType)
     261             : {
     262           0 :   return LayoutFrameType::TableCell == frameType ||
     263           0 :          LayoutFrameType::BCTableCell == frameType;
     264             : }
     265             : 
     266             : static bool
     267           0 : IsOffsetParent(nsIFrame* aFrame)
     268             : {
     269           0 :   LayoutFrameType frameType = aFrame->Type();
     270             : 
     271           0 :   if (IS_TABLE_CELL(frameType) || frameType == LayoutFrameType::Table) {
     272             :     // Per the IDL for Element, only td, th, and table are acceptable offsetParents
     273             :     // apart from body or positioned elements; we need to check the content type as
     274             :     // well as the frame type so we ignore anonymous tables created by an element
     275             :     // with display: table-cell with no actual table
     276           0 :     nsIContent* content = aFrame->GetContent();
     277             : 
     278           0 :     return content->IsAnyOfHTMLElements(nsGkAtoms::table,
     279             :                                         nsGkAtoms::td,
     280           0 :                                         nsGkAtoms::th);
     281             :   }
     282           0 :   return false;
     283             : }
     284             : 
     285             : Element*
     286           0 : nsGenericHTMLElement::GetOffsetRect(CSSIntRect& aRect)
     287             : {
     288           0 :   aRect = CSSIntRect();
     289             : 
     290           0 :   nsIFrame* frame = GetStyledFrame();
     291           0 :   if (!frame) {
     292           0 :     return nullptr;
     293             :   }
     294             : 
     295           0 :   nsIFrame* parent = frame->GetParent();
     296           0 :   nsPoint origin(0, 0);
     297             : 
     298           0 :   if (parent && parent->IsTableWrapperFrame() && frame->IsTableFrame()) {
     299           0 :     origin = parent->GetPositionIgnoringScrolling();
     300           0 :     parent = parent->GetParent();
     301             :   }
     302             : 
     303           0 :   nsIContent* offsetParent = nullptr;
     304           0 :   Element* docElement = GetComposedDoc()->GetRootElement();
     305           0 :   nsIContent* content = frame->GetContent();
     306             : 
     307           0 :   if (content && (content->IsHTMLElement(nsGkAtoms::body) ||
     308             :                   content == docElement)) {
     309           0 :     parent = frame;
     310             :   }
     311             :   else {
     312           0 :     const bool isPositioned = frame->IsAbsPosContainingBlock();
     313           0 :     const bool isAbsolutelyPositioned = frame->IsAbsolutelyPositioned();
     314           0 :     origin += frame->GetPositionIgnoringScrolling();
     315             : 
     316           0 :     for ( ; parent ; parent = parent->GetParent()) {
     317           0 :       content = parent->GetContent();
     318             : 
     319             :       // Stop at the first ancestor that is positioned.
     320           0 :       if (parent->IsAbsPosContainingBlock()) {
     321           0 :         offsetParent = content;
     322           0 :         break;
     323             :       }
     324             : 
     325             :       // Add the parent's origin to our own to get to the
     326             :       // right coordinate system.
     327           0 :       const bool isOffsetParent = !isPositioned && IsOffsetParent(parent);
     328           0 :       if (!isAbsolutelyPositioned && !isOffsetParent) {
     329           0 :         origin += parent->GetPositionIgnoringScrolling();
     330             :       }
     331             : 
     332           0 :       if (content) {
     333             :         // If we've hit the document element, break here.
     334           0 :         if (content == docElement) {
     335           0 :           break;
     336             :         }
     337             : 
     338             :         // Break if the ancestor frame type makes it suitable as offset parent
     339             :         // and this element is *not* positioned or if we found the body element.
     340           0 :         if (isOffsetParent || content->IsHTMLElement(nsGkAtoms::body)) {
     341           0 :           offsetParent = content;
     342           0 :           break;
     343             :         }
     344             :       }
     345             :     }
     346             : 
     347           0 :     if (isAbsolutelyPositioned && !offsetParent) {
     348             :       // If this element is absolutely positioned, but we don't have
     349             :       // an offset parent it means this element is an absolutely
     350             :       // positioned child that's not nested inside another positioned
     351             :       // element, in this case the element's frame's parent is the
     352             :       // frame for the HTML element so we fail to find the body in the
     353             :       // parent chain. We want the offset parent in this case to be
     354             :       // the body, so we just get the body element from the document.
     355             : 
     356           0 :       nsCOMPtr<nsIDOMHTMLDocument> html_doc(do_QueryInterface(GetComposedDoc()));
     357             : 
     358           0 :       if (html_doc) {
     359           0 :         offsetParent = static_cast<nsHTMLDocument*>(html_doc.get())->GetBody();
     360             :       }
     361             :     }
     362             :   }
     363             : 
     364             :   // Subtract the parent border unless it uses border-box sizing.
     365           0 :   if (parent &&
     366           0 :       parent->StylePosition()->mBoxSizing != StyleBoxSizing::Border) {
     367           0 :     const nsStyleBorder* border = parent->StyleBorder();
     368           0 :     origin.x -= border->GetComputedBorderWidth(eSideLeft);
     369           0 :     origin.y -= border->GetComputedBorderWidth(eSideTop);
     370             :   }
     371             : 
     372             :   // XXX We should really consider subtracting out padding for
     373             :   // content-box sizing, but we should see what IE does....
     374             : 
     375             :   // Get the union of all rectangles in this and continuation frames.
     376             :   // It doesn't really matter what we use as aRelativeTo here, since
     377             :   // we only care about the size. We just have to use something non-null.
     378           0 :   nsRect rcFrame = nsLayoutUtils::GetAllInFlowRectsUnion(frame, frame);
     379           0 :   rcFrame.MoveTo(origin);
     380           0 :   aRect = CSSIntRect::FromAppUnitsRounded(rcFrame);
     381             : 
     382           0 :   return offsetParent ? offsetParent->AsElement() : nullptr;
     383             : }
     384             : 
     385             : NS_IMETHODIMP
     386           0 : nsGenericHTMLElement::InsertAdjacentHTML(const nsAString& aPosition,
     387             :                                          const nsAString& aText)
     388             : {
     389           0 :   ErrorResult rv;
     390           0 :   Element::InsertAdjacentHTML(aPosition, aText, rv);
     391           0 :   return rv.StealNSResult();
     392             : }
     393             : 
     394             : bool
     395           4 : nsGenericHTMLElement::Spellcheck()
     396             : {
     397             :   // Has the state has been explicitly set?
     398             :   nsIContent* node;
     399          52 :   for (node = this; node; node = node->GetParent()) {
     400          48 :     if (node->IsHTMLElement()) {
     401             :       static nsIContent::AttrValuesArray strings[] =
     402             :         {&nsGkAtoms::_true, &nsGkAtoms::_false, nullptr};
     403           4 :       switch (node->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::spellcheck,
     404           4 :                                     strings, eCaseMatters)) {
     405             :         case 0:                         // spellcheck = "true"
     406           0 :           return true;
     407             :         case 1:                         // spellcheck = "false"
     408           0 :           return false;
     409             :       }
     410             :     }
     411             :   }
     412             : 
     413             :   // contenteditable/designMode are spellchecked by default
     414           4 :   if (IsEditable()) {
     415           0 :     return true;
     416             :   }
     417             : 
     418             :   // Is this a chrome element?
     419           4 :   if (nsContentUtils::IsChromeDoc(OwnerDoc())) {
     420           4 :     return false;                       // Not spellchecked by default
     421             :   }
     422             : 
     423             :   // Anything else that's not a form control is not spellchecked by default
     424           0 :   nsCOMPtr<nsIFormControl> formControl = do_QueryObject(this);
     425           0 :   if (!formControl) {
     426           0 :     return false;                       // Not spellchecked by default
     427             :   }
     428             : 
     429             :   // Is this a multiline plaintext input?
     430           0 :   int32_t controlType = formControl->ControlType();
     431           0 :   if (controlType == NS_FORM_TEXTAREA) {
     432           0 :     return true;             // Spellchecked by default
     433             :   }
     434             : 
     435             :   // Is this anything other than an input text?
     436             :   // Other inputs are not spellchecked.
     437           0 :   if (controlType != NS_FORM_INPUT_TEXT) {
     438           0 :     return false;                       // Not spellchecked by default
     439             :   }
     440             : 
     441             :   // Does the user want input text spellchecked by default?
     442             :   // NOTE: Do not reflect a pref value of 0 back to the DOM getter.
     443             :   // The web page should not know if the user has disabled spellchecking.
     444             :   // We'll catch this in the editor itself.
     445           0 :   int32_t spellcheckLevel = Preferences::GetInt("layout.spellcheckDefault", 1);
     446           0 :   return spellcheckLevel == 2;           // "Spellcheck multi- and single-line"
     447             : }
     448             : 
     449             : bool
     450           0 : nsGenericHTMLElement::InNavQuirksMode(nsIDocument* aDoc)
     451             : {
     452           0 :   return aDoc && aDoc->GetCompatibilityMode() == eCompatibility_NavQuirks;
     453             : }
     454             : 
     455             : void
     456         130 : nsGenericHTMLElement::UpdateEditableState(bool aNotify)
     457             : {
     458             :   // XXX Should we do this only when in a document?
     459         130 :   ContentEditableTristate value = GetContentEditableValue();
     460         130 :   if (value != eInherit) {
     461           0 :     DoSetEditableFlag(!!value, aNotify);
     462           0 :     return;
     463             :   }
     464             : 
     465         130 :   nsStyledElement::UpdateEditableState(aNotify);
     466             : }
     467             : 
     468             : EventStates
     469         187 : nsGenericHTMLElement::IntrinsicState() const
     470             : {
     471         187 :   EventStates state = nsGenericHTMLElementBase::IntrinsicState();
     472             : 
     473         187 :   if (GetDirectionality() == eDir_RTL) {
     474           0 :     state |= NS_EVENT_STATE_RTL;
     475           0 :     state &= ~NS_EVENT_STATE_LTR;
     476             :   } else { // at least for HTML, directionality is exclusively LTR or RTL
     477         187 :     NS_ASSERTION(GetDirectionality() == eDir_LTR,
     478             :                  "HTML element's directionality must be either RTL or LTR");
     479         187 :     state |= NS_EVENT_STATE_LTR;
     480         187 :     state &= ~NS_EVENT_STATE_RTL;
     481             :   }
     482             : 
     483         187 :   return state;
     484             : }
     485             : 
     486             : uint32_t
     487         121 : nsGenericHTMLElement::EditableInclusiveDescendantCount()
     488             : {
     489         126 :   bool isEditable = IsInUncomposedDoc() && HasFlag(NODE_IS_EDITABLE) &&
     490         126 :     GetContentEditableValue() == eTrue;
     491         121 :   return EditableDescendantCount() + isEditable;
     492             : }
     493             : 
     494             : nsresult
     495         130 : nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
     496             :                                  nsIContent* aBindingParent,
     497             :                                  bool aCompileEventHandlers)
     498             : {
     499         130 :   nsresult rv = nsGenericHTMLElementBase::BindToTree(aDocument, aParent,
     500             :                                                      aBindingParent,
     501         130 :                                                      aCompileEventHandlers);
     502         130 :   NS_ENSURE_SUCCESS(rv, rv);
     503             : 
     504         130 :   if (aDocument) {
     505          97 :     RegAccessKey();
     506          97 :     if (HasName()) {
     507             :       aDocument->
     508           0 :         AddToNameTable(this, GetParsedAttr(nsGkAtoms::name)->GetAtomValue());
     509             :     }
     510             : 
     511          97 :     if (HasFlag(NODE_IS_EDITABLE) && GetContentEditableValue() == eTrue) {
     512           0 :       nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(aDocument);
     513           0 :       if (htmlDocument) {
     514           0 :         htmlDocument->ChangeContentEditableCount(this, +1);
     515             :       }
     516             :     }
     517             :   }
     518             : 
     519             :   // We need to consider a labels element is moved to another subtree
     520             :   // with different root, it needs to update labels list and its root
     521             :   // as well.
     522         130 :   nsDOMSlots* slots = GetExistingDOMSlots();
     523         130 :   if (slots && slots->mLabelsList) {
     524           0 :     slots->mLabelsList->MaybeResetRoot(SubtreeRoot());
     525             :   }
     526             : 
     527         130 :   return rv;
     528             : }
     529             : 
     530             : void
     531          10 : nsGenericHTMLElement::UnbindFromTree(bool aDeep, bool aNullParent)
     532             : {
     533          10 :   if (IsInUncomposedDoc()) {
     534           6 :     UnregAccessKey();
     535             :   }
     536             : 
     537          10 :   RemoveFromNameTable();
     538             : 
     539          10 :   if (GetContentEditableValue() == eTrue) {
     540             :     //XXXsmaug Fix this for Shadow DOM, bug 1066965.
     541           0 :     nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(GetUncomposedDoc());
     542           0 :     if (htmlDocument) {
     543           0 :       htmlDocument->ChangeContentEditableCount(this, -1);
     544             :     }
     545             :   }
     546             : 
     547             :   // We need to consider a labels element is removed from tree,
     548             :   // it needs to update labels list and its root as well.
     549          10 :   nsDOMSlots* slots = GetExistingDOMSlots();
     550          10 :   if (slots && slots->mLabelsList) {
     551           0 :     slots->mLabelsList->MaybeResetRoot(SubtreeRoot());
     552             :   }
     553             : 
     554          10 :   nsStyledElement::UnbindFromTree(aDeep, aNullParent);
     555          10 : }
     556             : 
     557             : HTMLFormElement*
     558          29 : nsGenericHTMLElement::FindAncestorForm(HTMLFormElement* aCurrentForm)
     559             : {
     560          29 :   NS_ASSERTION(!HasAttr(kNameSpaceID_None, nsGkAtoms::form) ||
     561             :                IsHTMLElement(nsGkAtoms::img),
     562             :                "FindAncestorForm should not be called if @form is set!");
     563             : 
     564             :   // Make sure we don't end up finding a form that's anonymous from
     565             :   // our point of view.
     566          29 :   nsIContent* bindingParent = GetBindingParent();
     567             : 
     568          29 :   nsIContent* content = this;
     569         291 :   while (content != bindingParent && content) {
     570             :     // If the current ancestor is a form, return it as our form
     571         131 :     if (content->IsHTMLElement(nsGkAtoms::form)) {
     572             : #ifdef DEBUG
     573           0 :       if (!nsContentUtils::IsInSameAnonymousTree(this, content)) {
     574             :         // It's possible that we started unbinding at |content| or
     575             :         // some ancestor of it, and |content| and |this| used to all be
     576             :         // anonymous.  Check for this the hard way.
     577           0 :         for (nsIContent* child = this; child != content;
     578           0 :              child = child->GetParent()) {
     579           0 :           NS_ASSERTION(child->GetParent()->IndexOf(child) != -1,
     580             :                        "Walked too far?");
     581             :         }
     582             :       }
     583             : #endif
     584           0 :       return static_cast<HTMLFormElement*>(content);
     585             :     }
     586             : 
     587         131 :     nsIContent *prevContent = content;
     588         131 :     content = prevContent->GetParent();
     589             : 
     590         131 :     if (!content && aCurrentForm) {
     591             :       // We got to the root of the subtree we're in, and we're being removed
     592             :       // from the DOM (the only time we get into this method with a non-null
     593             :       // aCurrentForm).  Check whether aCurrentForm is in the same subtree.  If
     594             :       // it is, we want to return aCurrentForm, since this case means that
     595             :       // we're one of those inputs-in-a-table that have a hacked mForm pointer
     596             :       // and a subtree containing both us and the form got removed from the
     597             :       // DOM.
     598           0 :       if (nsContentUtils::ContentIsDescendantOf(aCurrentForm, prevContent)) {
     599           0 :         return aCurrentForm;
     600             :       }
     601             :     }
     602             :   }
     603             : 
     604          29 :   return nullptr;
     605             : }
     606             : 
     607             : bool
     608           0 : nsGenericHTMLElement::CheckHandleEventForAnchorsPreconditions(
     609             :                         EventChainVisitor& aVisitor)
     610             : {
     611           0 :   NS_PRECONDITION(nsCOMPtr<Link>(do_QueryObject(this)),
     612             :                   "should be called only when |this| implements |Link|");
     613             : 
     614           0 :   if (!aVisitor.mPresContext) {
     615             :     // We need a pres context to do link stuff. Some events (e.g. mutation
     616             :     // events) don't have one.
     617             :     // XXX: ideally, shouldn't we be able to do what we need without one?
     618           0 :     return false;
     619             :   }
     620             : 
     621             :   //Need to check if we hit an imagemap area and if so see if we're handling
     622             :   //the event on that map or on a link farther up the tree.  If we're on a
     623             :   //link farther up, do nothing.
     624           0 :   nsCOMPtr<nsIContent> target = aVisitor.mPresContext->EventStateManager()->
     625           0 :     GetEventTargetContent(aVisitor.mEvent);
     626             : 
     627           0 :   return !target || !target->IsHTMLElement(nsGkAtoms::area) ||
     628           0 :          IsHTMLElement(nsGkAtoms::area);
     629             : }
     630             : 
     631             : nsresult
     632           0 : nsGenericHTMLElement::GetEventTargetParentForAnchors(EventChainPreVisitor& aVisitor)
     633             : {
     634           0 :   nsresult rv = nsGenericHTMLElementBase::GetEventTargetParent(aVisitor);
     635           0 :   NS_ENSURE_SUCCESS(rv, rv);
     636             : 
     637           0 :   if (!CheckHandleEventForAnchorsPreconditions(aVisitor)) {
     638           0 :     return NS_OK;
     639             :   }
     640             : 
     641           0 :   return GetEventTargetParentForLinks(aVisitor);
     642             : }
     643             : 
     644             : nsresult
     645           0 : nsGenericHTMLElement::PostHandleEventForAnchors(EventChainPostVisitor& aVisitor)
     646             : {
     647           0 :   if (!CheckHandleEventForAnchorsPreconditions(aVisitor)) {
     648           0 :     return NS_OK;
     649             :   }
     650             : 
     651           0 :   return PostHandleEventForLinks(aVisitor);
     652             : }
     653             : 
     654             : bool
     655           0 : nsGenericHTMLElement::IsHTMLLink(nsIURI** aURI) const
     656             : {
     657           0 :   NS_PRECONDITION(aURI, "Must provide aURI out param");
     658             : 
     659           0 :   *aURI = GetHrefURIForAnchors().take();
     660             :   // We promise out param is non-null if we return true, so base rv on it
     661           0 :   return *aURI != nullptr;
     662             : }
     663             : 
     664             : already_AddRefed<nsIURI>
     665           0 : nsGenericHTMLElement::GetHrefURIForAnchors() const
     666             : {
     667             :   // This is used by the three Link implementations and
     668             :   // nsHTMLStyleElement.
     669             : 
     670             :   // Get href= attribute (relative URI).
     671             : 
     672             :   // We use the nsAttrValue's copy of the URI string to avoid copying.
     673           0 :   nsCOMPtr<nsIURI> uri;
     674           0 :   GetURIAttr(nsGkAtoms::href, nullptr, getter_AddRefs(uri));
     675             : 
     676           0 :   return uri.forget();
     677             : }
     678             : 
     679             : nsresult
     680         139 : nsGenericHTMLElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
     681             :                                     const nsAttrValueOrString* aValue,
     682             :                                     bool aNotify)
     683             : {
     684         139 :   if (aNamespaceID == kNameSpaceID_None) {
     685         129 :     if (aName == nsGkAtoms::accesskey) {
     686             :       // Have to unregister before clearing flag. See UnregAccessKey
     687           0 :       UnregAccessKey();
     688           0 :       if (!aValue) {
     689           0 :         UnsetFlags(NODE_HAS_ACCESSKEY);
     690             :       }
     691         129 :     } else if (aName == nsGkAtoms::name) {
     692             :       // Have to do this before clearing flag. See RemoveFromNameTable
     693           0 :       RemoveFromNameTable();
     694           0 :       if (!aValue || aValue->IsEmpty()) {
     695           0 :         ClearHasName();
     696             :       }
     697         129 :     } else if (aName == nsGkAtoms::contenteditable) {
     698           0 :       if (aValue) {
     699             :         // Set this before the attribute is set so that any subclass code that
     700             :         // runs before the attribute is set won't think we're missing a
     701             :         // contenteditable attr when we actually have one.
     702           0 :         SetMayHaveContentEditableAttr();
     703             :       }
     704             :     }
     705         129 :     if (!aValue && IsEventAttributeName(aName)) {
     706           0 :       if (EventListenerManager* manager = GetExistingListenerManager()) {
     707           0 :         manager->RemoveEventHandler(aName, EmptyString());
     708             :       }
     709             :     }
     710             :   }
     711             : 
     712         139 :   return nsGenericHTMLElementBase::BeforeSetAttr(aNamespaceID, aName, aValue,
     713         139 :                                                  aNotify);
     714             : }
     715             : 
     716             : nsresult
     717         139 : nsGenericHTMLElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
     718             :                                    const nsAttrValue* aValue,
     719             :                                    const nsAttrValue* aOldValue, bool aNotify)
     720             : {
     721         139 :   if (aNamespaceID == kNameSpaceID_None) {
     722         129 :     if (IsEventAttributeName(aName) && aValue) {
     723           1 :       MOZ_ASSERT(aValue->Type() == nsAttrValue::eString,
     724             :                  "Expected string value for script body");
     725           1 :       nsresult rv = SetEventHandler(aName, aValue->GetStringValue());
     726           1 :       NS_ENSURE_SUCCESS(rv, rv);
     727             :     }
     728         128 :     else if (aNotify && aName == nsGkAtoms::spellcheck) {
     729           0 :       SyncEditorsOnSubtree(this);
     730             :     }
     731         128 :     else if (aName == nsGkAtoms::dir) {
     732           0 :       Directionality dir = eDir_LTR;
     733             :       // A boolean tracking whether we need to recompute our directionality.
     734             :       // This needs to happen after we update our internal "dir" attribute
     735             :       // state but before we call SetDirectionalityOnDescendants.
     736           0 :       bool recomputeDirectionality = false;
     737             :       // We don't want to have to keep getting the "dir" attribute in
     738             :       // IntrinsicState, so we manually recompute our dir-related event states
     739             :       // here and send the relevant update notifications.
     740           0 :       EventStates dirStates;
     741           0 :       if (aValue && aValue->Type() == nsAttrValue::eEnum) {
     742           0 :         SetHasValidDir();
     743           0 :         dirStates |= NS_EVENT_STATE_HAS_DIR_ATTR;
     744           0 :         Directionality dirValue = (Directionality)aValue->GetEnumValue();
     745           0 :         if (dirValue == eDir_Auto) {
     746           0 :           dirStates |= NS_EVENT_STATE_DIR_ATTR_LIKE_AUTO;
     747             :         } else {
     748           0 :           dir = dirValue;
     749           0 :           SetDirectionality(dir, aNotify);
     750           0 :           if (dirValue == eDir_LTR) {
     751           0 :             dirStates |= NS_EVENT_STATE_DIR_ATTR_LTR;
     752             :           } else {
     753           0 :             MOZ_ASSERT(dirValue == eDir_RTL);
     754           0 :             dirStates |= NS_EVENT_STATE_DIR_ATTR_RTL;
     755             :           }
     756             :         }
     757             :       } else {
     758           0 :         if (aValue) {
     759             :           // We have a value, just not a valid one.
     760           0 :           dirStates |= NS_EVENT_STATE_HAS_DIR_ATTR;
     761             :         }
     762           0 :         ClearHasValidDir();
     763           0 :         if (NodeInfo()->Equals(nsGkAtoms::bdi)) {
     764           0 :           dirStates |= NS_EVENT_STATE_DIR_ATTR_LIKE_AUTO;
     765             :         } else {
     766           0 :           recomputeDirectionality = true;
     767             :         }
     768             :       }
     769             :       // Now figure out what's changed about our dir states.
     770           0 :       EventStates oldDirStates = State() & DIR_ATTR_STATES;
     771           0 :       EventStates changedStates = dirStates ^ oldDirStates;
     772           0 :       ToggleStates(changedStates, aNotify);
     773           0 :       if (recomputeDirectionality) {
     774           0 :         dir = RecomputeDirectionality(this, aNotify);
     775             :       }
     776           0 :       SetDirectionalityOnDescendants(this, dir, aNotify);
     777         128 :     } else if (aName == nsGkAtoms::contenteditable) {
     778           0 :       int32_t editableCountDelta = 0;
     779           0 :       if (aOldValue &&
     780           0 :           (aOldValue->Equals(NS_LITERAL_STRING("true"), eIgnoreCase) ||
     781           0 :           aOldValue->Equals(EmptyString(), eIgnoreCase))) {
     782           0 :         editableCountDelta = -1;
     783             :       }
     784           0 :       if (aValue && (aValue->Equals(NS_LITERAL_STRING("true"), eIgnoreCase) ||
     785           0 :                      aValue->Equals(EmptyString(), eIgnoreCase))) {
     786           0 :         ++editableCountDelta;
     787             :       }
     788           0 :       ChangeEditableState(editableCountDelta);
     789         128 :     } else if (aName == nsGkAtoms::accesskey) {
     790           0 :       if (aValue && !aValue->Equals(EmptyString(), eIgnoreCase)) {
     791           0 :         SetFlags(NODE_HAS_ACCESSKEY);
     792           0 :         RegAccessKey();
     793             :       }
     794         128 :     } else if (aName == nsGkAtoms::name) {
     795           0 :       if (aValue && !aValue->Equals(EmptyString(), eIgnoreCase) &&
     796           0 :           CanHaveName(NodeInfo()->NameAtom())) {
     797             :         // This may not be quite right because we can have subclass code run
     798             :         // before here. But in practice subclasses don't care about this flag,
     799             :         // and in particular selector matching does not care.  Otherwise we'd
     800             :         // want to handle it like we handle id attributes (in PreIdMaybeChange
     801             :         // and PostIdMaybeChange).
     802           0 :         SetHasName();
     803           0 :         AddToNameTable(aValue->GetAtomValue());
     804             :       }
     805             :     }
     806             :   }
     807             : 
     808         139 :   return nsGenericHTMLElementBase::AfterSetAttr(aNamespaceID, aName,
     809         139 :                                                 aValue, aOldValue, aNotify);
     810             : }
     811             : 
     812             : EventListenerManager*
     813           1 : nsGenericHTMLElement::GetEventListenerManagerForAttr(nsIAtom* aAttrName,
     814             :                                                      bool* aDefer)
     815             : {
     816             :   // Attributes on the body and frameset tags get set on the global object
     817           3 :   if ((mNodeInfo->Equals(nsGkAtoms::body) ||
     818           1 :        mNodeInfo->Equals(nsGkAtoms::frameset)) &&
     819             :       // We only forward some event attributes from body/frameset to window
     820             :       (0
     821             : #define EVENT(name_, id_, type_, struct_) /* nothing */
     822             : #define FORWARDED_EVENT(name_, id_, type_, struct_) \
     823             :        || nsGkAtoms::on##name_ == aAttrName
     824             : #define WINDOW_EVENT FORWARDED_EVENT
     825             : #include "mozilla/EventNameList.h" // IWYU pragma: keep
     826             : #undef WINDOW_EVENT
     827             : #undef FORWARDED_EVENT
     828             : #undef EVENT
     829             :        )
     830             :       ) {
     831             :     nsPIDOMWindowInner *win;
     832             : 
     833             :     // If we have a document, and it has a window, add the event
     834             :     // listener on the window (the inner window). If not, proceed as
     835             :     // normal.
     836             :     // XXXbz sXBL/XBL2 issue: should we instead use GetComposedDoc() here,
     837             :     // override BindToTree for those classes and munge event listeners there?
     838           0 :     nsIDocument *document = OwnerDoc();
     839             : 
     840           0 :     *aDefer = false;
     841           0 :     if ((win = document->GetInnerWindow())) {
     842           0 :       nsCOMPtr<EventTarget> piTarget(do_QueryInterface(win));
     843             : 
     844           0 :       return piTarget->GetOrCreateListenerManager();
     845             :     }
     846             : 
     847           0 :     return nullptr;
     848             :   }
     849             : 
     850           1 :   return nsGenericHTMLElementBase::GetEventListenerManagerForAttr(aAttrName,
     851           1 :                                                                   aDefer);
     852             : }
     853             : 
     854             : #define EVENT(name_, id_, type_, struct_) /* nothing; handled by nsINode */
     855             : #define FORWARDED_EVENT(name_, id_, type_, struct_)                           \
     856             : EventHandlerNonNull*                                                          \
     857             : nsGenericHTMLElement::GetOn##name_()                                          \
     858             : {                                                                             \
     859             :   if (IsAnyOfHTMLElements(nsGkAtoms::body, nsGkAtoms::frameset)) {            \
     860             :     /* XXXbz note to self: add tests for this! */                             \
     861             :     if (nsPIDOMWindowInner* win = OwnerDoc()->GetInnerWindow()) {             \
     862             :       nsGlobalWindow* globalWin = nsGlobalWindow::Cast(win);                  \
     863             :       return globalWin->GetOn##name_();                                       \
     864             :     }                                                                         \
     865             :     return nullptr;                                                           \
     866             :   }                                                                           \
     867             :                                                                               \
     868             :   return nsINode::GetOn##name_();                                             \
     869             : }                                                                             \
     870             : void                                                                          \
     871             : nsGenericHTMLElement::SetOn##name_(EventHandlerNonNull* handler)              \
     872             : {                                                                             \
     873             :   if (IsAnyOfHTMLElements(nsGkAtoms::body, nsGkAtoms::frameset)) {            \
     874             :     nsPIDOMWindowInner* win = OwnerDoc()->GetInnerWindow();                   \
     875             :     if (!win) {                                                               \
     876             :       return;                                                                 \
     877             :     }                                                                         \
     878             :                                                                               \
     879             :     nsGlobalWindow* globalWin = nsGlobalWindow::Cast(win);                    \
     880             :     return globalWin->SetOn##name_(handler);                                  \
     881             :   }                                                                           \
     882             :                                                                               \
     883             :   return nsINode::SetOn##name_(handler);                                      \
     884             : }
     885             : #define ERROR_EVENT(name_, id_, type_, struct_)                               \
     886             : already_AddRefed<EventHandlerNonNull>                                         \
     887             : nsGenericHTMLElement::GetOn##name_()                                          \
     888             : {                                                                             \
     889             :   if (IsAnyOfHTMLElements(nsGkAtoms::body, nsGkAtoms::frameset)) {            \
     890             :     /* XXXbz note to self: add tests for this! */                             \
     891             :     if (nsPIDOMWindowInner* win = OwnerDoc()->GetInnerWindow()) {             \
     892             :       nsGlobalWindow* globalWin = nsGlobalWindow::Cast(win);                  \
     893             :       OnErrorEventHandlerNonNull* errorHandler = globalWin->GetOn##name_();   \
     894             :       if (errorHandler) {                                                     \
     895             :         RefPtr<EventHandlerNonNull> handler =                                 \
     896             :           new EventHandlerNonNull(errorHandler);                              \
     897             :         return handler.forget();                                              \
     898             :       }                                                                       \
     899             :     }                                                                         \
     900             :     return nullptr;                                                           \
     901             :   }                                                                           \
     902             :                                                                               \
     903             :   RefPtr<EventHandlerNonNull> handler = nsINode::GetOn##name_();              \
     904             :   return handler.forget();                                                    \
     905             : }                                                                             \
     906             : void                                                                          \
     907             : nsGenericHTMLElement::SetOn##name_(EventHandlerNonNull* handler)              \
     908             : {                                                                             \
     909             :   if (IsAnyOfHTMLElements(nsGkAtoms::body, nsGkAtoms::frameset)) {            \
     910             :     nsPIDOMWindowInner* win = OwnerDoc()->GetInnerWindow();                   \
     911             :     if (!win) {                                                               \
     912             :       return;                                                                 \
     913             :     }                                                                         \
     914             :                                                                               \
     915             :     nsGlobalWindow* globalWin = nsGlobalWindow::Cast(win);                    \
     916             :     RefPtr<OnErrorEventHandlerNonNull> errorHandler;                          \
     917             :     if (handler) {                                                            \
     918             :       errorHandler = new OnErrorEventHandlerNonNull(handler);                 \
     919             :     }                                                                         \
     920             :     return globalWin->SetOn##name_(errorHandler);                             \
     921             :   }                                                                           \
     922             :                                                                               \
     923             :   return nsINode::SetOn##name_(handler);                                      \
     924             : }
     925             : #include "mozilla/EventNameList.h" // IWYU pragma: keep
     926             : #undef ERROR_EVENT
     927             : #undef FORWARDED_EVENT
     928             : #undef EVENT
     929             : 
     930             : void
     931           0 : nsGenericHTMLElement::GetBaseTarget(nsAString& aBaseTarget) const
     932             : {
     933           0 :   OwnerDoc()->GetBaseTarget(aBaseTarget);
     934           0 : }
     935             : 
     936             : //----------------------------------------------------------------------
     937             : 
     938             : bool
     939          86 : nsGenericHTMLElement::ParseAttribute(int32_t aNamespaceID,
     940             :                                      nsIAtom* aAttribute,
     941             :                                      const nsAString& aValue,
     942             :                                      nsAttrValue& aResult)
     943             : {
     944          86 :   if (aNamespaceID == kNameSpaceID_None) {
     945          76 :     if (aAttribute == nsGkAtoms::dir) {
     946           0 :       return aResult.ParseEnumValue(aValue, kDirTable, false);
     947             :     }
     948             : 
     949          76 :     if (aAttribute == nsGkAtoms::tabindex) {
     950           0 :       return aResult.ParseIntValue(aValue);
     951             :     }
     952             : 
     953          76 :     if (aAttribute == nsGkAtoms::referrerpolicy) {
     954           0 :       return ParseReferrerAttribute(aValue, aResult);
     955             :     }
     956             : 
     957          76 :     if (aAttribute == nsGkAtoms::name) {
     958             :       // Store name as an atom.  name="" means that the element has no name,
     959             :       // not that it has an empty string as the name.
     960           0 :       if (aValue.IsEmpty()) {
     961           0 :         return false;
     962             :       }
     963           0 :       aResult.ParseAtom(aValue);
     964           0 :       return true;
     965             :     }
     966             : 
     967          76 :     if (aAttribute == nsGkAtoms::contenteditable) {
     968           0 :       aResult.ParseAtom(aValue);
     969           0 :       return true;
     970             :     }
     971             : 
     972          76 :     if (aAttribute == nsGkAtoms::rel) {
     973           0 :       aResult.ParseAtomArray(aValue);
     974           0 :       return true;
     975             :     }
     976             :   }
     977             : 
     978          86 :   return nsGenericHTMLElementBase::ParseAttribute(aNamespaceID, aAttribute,
     979          86 :                                                   aValue, aResult);
     980             : }
     981             : 
     982             : bool
     983           0 : nsGenericHTMLElement::ParseBackgroundAttribute(int32_t aNamespaceID,
     984             :                                                nsIAtom* aAttribute,
     985             :                                                const nsAString& aValue,
     986             :                                                nsAttrValue& aResult)
     987             : {
     988           0 :   if (aNamespaceID == kNameSpaceID_None &&
     989           0 :       aAttribute == nsGkAtoms::background &&
     990           0 :       !aValue.IsEmpty()) {
     991             :     // Resolve url to an absolute url
     992           0 :     nsIDocument* doc = OwnerDoc();
     993           0 :     nsCOMPtr<nsIURI> baseURI = GetBaseURI();
     994           0 :     nsCOMPtr<nsIURI> uri;
     995           0 :     nsresult rv = nsContentUtils::NewURIWithDocumentCharset(
     996           0 :         getter_AddRefs(uri), aValue, doc, baseURI);
     997           0 :     if (NS_FAILED(rv)) {
     998           0 :       return false;
     999             :     }
    1000             : 
    1001             :     mozilla::css::URLValue *url =
    1002           0 :       new mozilla::css::URLValue(uri, aValue, baseURI, doc->GetDocumentURI(),
    1003           0 :                                  NodePrincipal());
    1004           0 :     aResult.SetTo(url, &aValue);
    1005           0 :     return true;
    1006             :   }
    1007             : 
    1008           0 :   return false;
    1009             : }
    1010             : 
    1011             : bool
    1012          26 : nsGenericHTMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const
    1013             : {
    1014             :   static const MappedAttributeEntry* const map[] = {
    1015             :     sCommonAttributeMap
    1016             :   };
    1017             : 
    1018          26 :   return FindAttributeDependence(aAttribute, map);
    1019             : }
    1020             : 
    1021             : nsMapRuleToAttributesFunc
    1022           0 : nsGenericHTMLElement::GetAttributeMappingFunction() const
    1023             : {
    1024           0 :   return &MapCommonAttributesInto;
    1025             : }
    1026             : 
    1027             : nsIFormControlFrame*
    1028           0 : nsGenericHTMLElement::GetFormControlFrame(bool aFlushFrames)
    1029             : {
    1030           0 :   if (aFlushFrames && IsInComposedDoc()) {
    1031             :     // Cause a flush of the frames, so we get up-to-date frame information
    1032           0 :     GetComposedDoc()->FlushPendingNotifications(FlushType::Frames);
    1033             :   }
    1034           0 :   nsIFrame* frame = GetPrimaryFrame();
    1035           0 :   if (frame) {
    1036           0 :     nsIFormControlFrame* form_frame = do_QueryFrame(frame);
    1037           0 :     if (form_frame) {
    1038           0 :       return form_frame;
    1039             :     }
    1040             : 
    1041             :     // If we have generated content, the primary frame will be a
    1042             :     // wrapper frame..  out real frame will be in its child list.
    1043           0 :     for (frame = frame->PrincipalChildList().FirstChild();
    1044           0 :          frame;
    1045             :          frame = frame->GetNextSibling()) {
    1046           0 :       form_frame = do_QueryFrame(frame);
    1047           0 :       if (form_frame) {
    1048           0 :         return form_frame;
    1049             :       }
    1050             :     }
    1051             :   }
    1052             : 
    1053           0 :   return nullptr;
    1054             : }
    1055             : 
    1056             : nsPresContext*
    1057           0 : nsGenericHTMLElement::GetPresContext(PresContextFor aFor)
    1058             : {
    1059             :   // Get the document
    1060           0 :   nsIDocument* doc = (aFor == eForComposedDoc) ?
    1061           0 :     GetComposedDoc() : GetUncomposedDoc();
    1062           0 :   if (doc) {
    1063             :     // Get presentation shell.
    1064           0 :     nsIPresShell *presShell = doc->GetShell();
    1065           0 :     if (presShell) {
    1066           0 :       return presShell->GetPresContext();
    1067             :     }
    1068             :   }
    1069             : 
    1070           0 :   return nullptr;
    1071             : }
    1072             : 
    1073             : static const nsAttrValue::EnumTable kDivAlignTable[] = {
    1074             :   { "left", NS_STYLE_TEXT_ALIGN_MOZ_LEFT },
    1075             :   { "right", NS_STYLE_TEXT_ALIGN_MOZ_RIGHT },
    1076             :   { "center", NS_STYLE_TEXT_ALIGN_MOZ_CENTER },
    1077             :   { "middle", NS_STYLE_TEXT_ALIGN_MOZ_CENTER },
    1078             :   { "justify", NS_STYLE_TEXT_ALIGN_JUSTIFY },
    1079             :   { nullptr, 0 }
    1080             : };
    1081             : 
    1082             : static const nsAttrValue::EnumTable kFrameborderTable[] = {
    1083             :   { "yes", NS_STYLE_FRAME_YES },
    1084             :   { "no", NS_STYLE_FRAME_NO },
    1085             :   { "1", NS_STYLE_FRAME_1 },
    1086             :   { "0", NS_STYLE_FRAME_0 },
    1087             :   { nullptr, 0 }
    1088             : };
    1089             : 
    1090             : static const nsAttrValue::EnumTable kScrollingTable[] = {
    1091             :   { "yes", NS_STYLE_FRAME_YES },
    1092             :   { "no", NS_STYLE_FRAME_NO },
    1093             :   { "on", NS_STYLE_FRAME_ON },
    1094             :   { "off", NS_STYLE_FRAME_OFF },
    1095             :   { "scroll", NS_STYLE_FRAME_SCROLL },
    1096             :   { "noscroll", NS_STYLE_FRAME_NOSCROLL },
    1097             :   { "auto", NS_STYLE_FRAME_AUTO },
    1098             :   { nullptr, 0 }
    1099             : };
    1100             : 
    1101             : static const nsAttrValue::EnumTable kTableVAlignTable[] = {
    1102             :   { "top",     NS_STYLE_VERTICAL_ALIGN_TOP },
    1103             :   { "middle",  NS_STYLE_VERTICAL_ALIGN_MIDDLE },
    1104             :   { "bottom",  NS_STYLE_VERTICAL_ALIGN_BOTTOM },
    1105             :   { "baseline",NS_STYLE_VERTICAL_ALIGN_BASELINE },
    1106             :   { nullptr,   0 }
    1107             : };
    1108             : 
    1109             : bool
    1110           0 : nsGenericHTMLElement::ParseAlignValue(const nsAString& aString,
    1111             :                                       nsAttrValue& aResult)
    1112             : {
    1113             :   static const nsAttrValue::EnumTable kAlignTable[] = {
    1114             :     { "left",      NS_STYLE_TEXT_ALIGN_LEFT },
    1115             :     { "right",     NS_STYLE_TEXT_ALIGN_RIGHT },
    1116             : 
    1117             :     { "top",       NS_STYLE_VERTICAL_ALIGN_TOP },
    1118             :     { "middle",    NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE },
    1119             :     { "bottom",    NS_STYLE_VERTICAL_ALIGN_BASELINE },
    1120             : 
    1121             :     { "center",    NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE },
    1122             :     { "baseline",  NS_STYLE_VERTICAL_ALIGN_BASELINE },
    1123             : 
    1124             :     { "texttop",   NS_STYLE_VERTICAL_ALIGN_TEXT_TOP },
    1125             :     { "absmiddle", NS_STYLE_VERTICAL_ALIGN_MIDDLE },
    1126             :     { "abscenter", NS_STYLE_VERTICAL_ALIGN_MIDDLE },
    1127             :     { "absbottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM },
    1128             :     { nullptr,     0 }
    1129             :   };
    1130             : 
    1131           0 :   return aResult.ParseEnumValue(aString, kAlignTable, false);
    1132             : }
    1133             : 
    1134             : //----------------------------------------
    1135             : 
    1136             : static const nsAttrValue::EnumTable kTableHAlignTable[] = {
    1137             :   { "left",   NS_STYLE_TEXT_ALIGN_LEFT },
    1138             :   { "right",  NS_STYLE_TEXT_ALIGN_RIGHT },
    1139             :   { "center", NS_STYLE_TEXT_ALIGN_CENTER },
    1140             :   { "char",   NS_STYLE_TEXT_ALIGN_CHAR },
    1141             :   { "justify",NS_STYLE_TEXT_ALIGN_JUSTIFY },
    1142             :   { nullptr,  0 }
    1143             : };
    1144             : 
    1145             : bool
    1146           0 : nsGenericHTMLElement::ParseTableHAlignValue(const nsAString& aString,
    1147             :                                             nsAttrValue& aResult)
    1148             : {
    1149           0 :   return aResult.ParseEnumValue(aString, kTableHAlignTable, false);
    1150             : }
    1151             : 
    1152             : //----------------------------------------
    1153             : 
    1154             : // This table is used for td, th, tr, col, thead, tbody and tfoot.
    1155             : static const nsAttrValue::EnumTable kTableCellHAlignTable[] = {
    1156             :   { "left",   NS_STYLE_TEXT_ALIGN_MOZ_LEFT },
    1157             :   { "right",  NS_STYLE_TEXT_ALIGN_MOZ_RIGHT },
    1158             :   { "center", NS_STYLE_TEXT_ALIGN_MOZ_CENTER },
    1159             :   { "char",   NS_STYLE_TEXT_ALIGN_CHAR },
    1160             :   { "justify",NS_STYLE_TEXT_ALIGN_JUSTIFY },
    1161             :   { "middle", NS_STYLE_TEXT_ALIGN_MOZ_CENTER },
    1162             :   { "absmiddle", NS_STYLE_TEXT_ALIGN_CENTER },
    1163             :   { nullptr,  0 }
    1164             : };
    1165             : 
    1166             : bool
    1167           0 : nsGenericHTMLElement::ParseTableCellHAlignValue(const nsAString& aString,
    1168             :                                                 nsAttrValue& aResult)
    1169             : {
    1170           0 :   return aResult.ParseEnumValue(aString, kTableCellHAlignTable, false);
    1171             : }
    1172             : 
    1173             : //----------------------------------------
    1174             : 
    1175             : bool
    1176           0 : nsGenericHTMLElement::ParseTableVAlignValue(const nsAString& aString,
    1177             :                                             nsAttrValue& aResult)
    1178             : {
    1179           0 :   return aResult.ParseEnumValue(aString, kTableVAlignTable, false);
    1180             : }
    1181             : 
    1182             : bool
    1183           0 : nsGenericHTMLElement::ParseDivAlignValue(const nsAString& aString,
    1184             :                                          nsAttrValue& aResult)
    1185             : {
    1186           0 :   return aResult.ParseEnumValue(aString, kDivAlignTable, false);
    1187             : }
    1188             : 
    1189             : bool
    1190          20 : nsGenericHTMLElement::ParseImageAttribute(nsIAtom* aAttribute,
    1191             :                                           const nsAString& aString,
    1192             :                                           nsAttrValue& aResult)
    1193             : {
    1194          40 :   if ((aAttribute == nsGkAtoms::width) ||
    1195          20 :       (aAttribute == nsGkAtoms::height)) {
    1196           0 :     return aResult.ParseSpecialIntValue(aString);
    1197             :   }
    1198          40 :   if ((aAttribute == nsGkAtoms::hspace) ||
    1199          40 :       (aAttribute == nsGkAtoms::vspace) ||
    1200          20 :       (aAttribute == nsGkAtoms::border)) {
    1201           0 :     return aResult.ParseIntWithBounds(aString, 0);
    1202             :   }
    1203          20 :   return false;
    1204             : }
    1205             : 
    1206             : bool
    1207           0 : nsGenericHTMLElement::ParseReferrerAttribute(const nsAString& aString,
    1208             :                                              nsAttrValue& aResult)
    1209             : {
    1210             :   static const nsAttrValue::EnumTable kReferrerTable[] = {
    1211             :     { net::kRPS_No_Referrer, static_cast<int16_t>(net::RP_No_Referrer) },
    1212             :     { net::kRPS_Origin, static_cast<int16_t>(net::RP_Origin) },
    1213             :     { net::kRPS_Origin_When_Cross_Origin, static_cast<int16_t>(net::RP_Origin_When_Crossorigin) },
    1214             :     { net::kRPS_No_Referrer_When_Downgrade, static_cast<int16_t>(net::RP_No_Referrer_When_Downgrade) },
    1215             :     { net::kRPS_Unsafe_URL, static_cast<int16_t>(net::RP_Unsafe_URL) },
    1216             :     { net::kRPS_Strict_Origin, static_cast<int16_t>(net::RP_Strict_Origin) },
    1217             :     { net::kRPS_Same_Origin, static_cast<int16_t>(net::RP_Same_Origin) },
    1218             :     { net::kRPS_Strict_Origin_When_Cross_Origin, static_cast<int16_t>(net::RP_Strict_Origin_When_Cross_Origin) },
    1219             :     { nullptr, 0 }
    1220             :   };
    1221           0 :   return aResult.ParseEnumValue(aString, kReferrerTable, false);
    1222             : }
    1223             : 
    1224             : bool
    1225           0 : nsGenericHTMLElement::ParseFrameborderValue(const nsAString& aString,
    1226             :                                             nsAttrValue& aResult)
    1227             : {
    1228           0 :   return aResult.ParseEnumValue(aString, kFrameborderTable, false);
    1229             : }
    1230             : 
    1231             : bool
    1232           0 : nsGenericHTMLElement::ParseScrollingValue(const nsAString& aString,
    1233             :                                           nsAttrValue& aResult)
    1234             : {
    1235           0 :   return aResult.ParseEnumValue(aString, kScrollingTable, false);
    1236             : }
    1237             : 
    1238             : static inline void
    1239         172 : MapLangAttributeInto(const nsMappedAttributes* aAttributes, GenericSpecifiedValues* aData)
    1240             : {
    1241         172 :   if (!aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Font) |
    1242             :                                        NS_STYLE_INHERIT_BIT(Text))) {
    1243         160 :     return;
    1244             :   }
    1245             : 
    1246          12 :   const nsAttrValue* langValue = aAttributes->GetAttr(nsGkAtoms::lang);
    1247          12 :   if (!langValue) {
    1248          12 :     return;
    1249             :   }
    1250           0 :   MOZ_ASSERT(langValue->Type() == nsAttrValue::eAtom);
    1251           0 :   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Font))) {
    1252           0 :     aData->SetIdentAtomValueIfUnset(eCSSProperty__x_lang,
    1253           0 :                                     langValue->GetAtomValue());
    1254             :   }
    1255           0 :   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Text))) {
    1256           0 :     if (!aData->PropertyIsSet(eCSSProperty_text_emphasis_position)) {
    1257           0 :       const nsIAtom* lang = langValue->GetAtomValue();
    1258           0 :       if (nsStyleUtil::MatchesLanguagePrefix(lang, u"zh")) {
    1259             :         aData->SetKeywordValue(eCSSProperty_text_emphasis_position,
    1260           0 :                                NS_STYLE_TEXT_EMPHASIS_POSITION_DEFAULT_ZH);
    1261           0 :       } else if (nsStyleUtil::MatchesLanguagePrefix(lang, u"ja") ||
    1262           0 :                  nsStyleUtil::MatchesLanguagePrefix(lang, u"mn")) {
    1263             :         // This branch is currently no part of the spec.
    1264             :         // See bug 1040668 comment 69 and comment 75.
    1265             :         aData->SetKeywordValue(eCSSProperty_text_emphasis_position,
    1266           0 :                                NS_STYLE_TEXT_EMPHASIS_POSITION_DEFAULT);
    1267             :       }
    1268             :     }
    1269             :   }
    1270             : }
    1271             : 
    1272             : /**
    1273             :  * Handle attributes common to all html elements
    1274             :  */
    1275             : void
    1276         172 : nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden(const nsMappedAttributes* aAttributes,
    1277             :                                                           GenericSpecifiedValues* aData)
    1278             : {
    1279         172 :   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(UserInterface))) {
    1280          38 :     if (!aData->PropertyIsSet(eCSSProperty__moz_user_modify)) {
    1281             :       const nsAttrValue* value =
    1282          35 :         aAttributes->GetAttr(nsGkAtoms::contenteditable);
    1283          35 :       if (value) {
    1284           0 :         if (value->Equals(nsGkAtoms::_empty, eCaseMatters) ||
    1285           0 :             value->Equals(nsGkAtoms::_true, eIgnoreCase)) {
    1286             :           aData->SetKeywordValue(eCSSProperty__moz_user_modify,
    1287           0 :                                  StyleUserModify::ReadWrite);
    1288             :         }
    1289           0 :         else if (value->Equals(nsGkAtoms::_false, eIgnoreCase)) {
    1290             :             aData->SetKeywordValue(eCSSProperty__moz_user_modify,
    1291           0 :                                    StyleUserModify::ReadOnly);
    1292             :         }
    1293             :       }
    1294             :     }
    1295             :   }
    1296             : 
    1297         172 :   MapLangAttributeInto(aAttributes, aData);
    1298         172 : }
    1299             : 
    1300             : void
    1301         172 : nsGenericHTMLElement::MapCommonAttributesInto(const nsMappedAttributes* aAttributes,
    1302             :                                               GenericSpecifiedValues* aData)
    1303             : {
    1304         172 :   MapCommonAttributesIntoExceptHidden(aAttributes, aData);
    1305             : 
    1306         172 :   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Display))) {
    1307          33 :     if (!aData->PropertyIsSet(eCSSProperty_display)) {
    1308          33 :       if (aAttributes->IndexOfAttr(nsGkAtoms::hidden) >= 0) {
    1309          28 :         aData->SetKeywordValue(eCSSProperty_display, StyleDisplay::None);
    1310             :       }
    1311             :     }
    1312             :   }
    1313         172 : }
    1314             : 
    1315             : /* static */ const nsGenericHTMLElement::MappedAttributeEntry
    1316             : nsGenericHTMLElement::sCommonAttributeMap[] = {
    1317             :   { &nsGkAtoms::contenteditable },
    1318             :   { &nsGkAtoms::lang },
    1319             :   { &nsGkAtoms::hidden },
    1320             :   { nullptr }
    1321             : };
    1322             : 
    1323             : /* static */ const Element::MappedAttributeEntry
    1324             : nsGenericHTMLElement::sImageMarginSizeAttributeMap[] = {
    1325             :   { &nsGkAtoms::width },
    1326             :   { &nsGkAtoms::height },
    1327             :   { &nsGkAtoms::hspace },
    1328             :   { &nsGkAtoms::vspace },
    1329             :   { nullptr }
    1330             : };
    1331             : 
    1332             : /* static */ const Element::MappedAttributeEntry
    1333             : nsGenericHTMLElement::sImageAlignAttributeMap[] = {
    1334             :   { &nsGkAtoms::align },
    1335             :   { nullptr }
    1336             : };
    1337             : 
    1338             : /* static */ const Element::MappedAttributeEntry
    1339             : nsGenericHTMLElement::sDivAlignAttributeMap[] = {
    1340             :   { &nsGkAtoms::align },
    1341             :   { nullptr }
    1342             : };
    1343             : 
    1344             : /* static */ const Element::MappedAttributeEntry
    1345             : nsGenericHTMLElement::sImageBorderAttributeMap[] = {
    1346             :   { &nsGkAtoms::border },
    1347             :   { nullptr }
    1348             : };
    1349             : 
    1350             : /* static */ const Element::MappedAttributeEntry
    1351             : nsGenericHTMLElement::sBackgroundAttributeMap[] = {
    1352             :   { &nsGkAtoms::background },
    1353             :   { &nsGkAtoms::bgcolor },
    1354             :   { nullptr }
    1355             : };
    1356             : 
    1357             : /* static */ const Element::MappedAttributeEntry
    1358             : nsGenericHTMLElement::sBackgroundColorAttributeMap[] = {
    1359             :   { &nsGkAtoms::bgcolor },
    1360             :   { nullptr }
    1361             : };
    1362             : 
    1363             : void
    1364           0 : nsGenericHTMLElement::MapImageAlignAttributeInto(const nsMappedAttributes* aAttributes,
    1365             :                                                  GenericSpecifiedValues* aData)
    1366             : {
    1367           0 :   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Display))) {
    1368           0 :     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
    1369           0 :     if (value && value->Type() == nsAttrValue::eEnum) {
    1370           0 :       int32_t align = value->GetEnumValue();
    1371           0 :       if (!aData->PropertyIsSet(eCSSProperty_float_)) {
    1372           0 :         if (align == NS_STYLE_TEXT_ALIGN_LEFT) {
    1373           0 :           aData->SetKeywordValue(eCSSProperty_float_, StyleFloat::Left);
    1374           0 :         } else if (align == NS_STYLE_TEXT_ALIGN_RIGHT) {
    1375           0 :           aData->SetKeywordValue(eCSSProperty_float_, StyleFloat::Right);
    1376             :         }
    1377             :       }
    1378           0 :       if (!aData->PropertyIsSet(eCSSProperty_vertical_align)) {
    1379           0 :         switch (align) {
    1380             :         case NS_STYLE_TEXT_ALIGN_LEFT:
    1381             :         case NS_STYLE_TEXT_ALIGN_RIGHT:
    1382           0 :           break;
    1383             :         default:
    1384           0 :           aData->SetKeywordValue(eCSSProperty_vertical_align, align);
    1385           0 :           break;
    1386             :         }
    1387             :       }
    1388             :     }
    1389             :   }
    1390           0 : }
    1391             : 
    1392             : void
    1393          88 : nsGenericHTMLElement::MapDivAlignAttributeInto(const nsMappedAttributes* aAttributes,
    1394             :                                                GenericSpecifiedValues* aData)
    1395             : {
    1396          88 :   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Text))) {
    1397           0 :     if (!aData->PropertyIsSet(eCSSProperty_text_align)) {
    1398             :       // align: enum
    1399           0 :       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
    1400           0 :       if (value && value->Type() == nsAttrValue::eEnum)
    1401           0 :         aData->SetKeywordValue(eCSSProperty_text_align, value->GetEnumValue());
    1402             :     }
    1403             :   }
    1404          88 : }
    1405             : 
    1406             : void
    1407           0 : nsGenericHTMLElement::MapVAlignAttributeInto(const nsMappedAttributes* aAttributes,
    1408             :                                              GenericSpecifiedValues* aData)
    1409             : {
    1410           0 :   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Display))) {
    1411           0 :     if (!aData->PropertyIsSet(eCSSProperty_vertical_align)) {
    1412             :       // align: enum
    1413           0 :       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::valign);
    1414           0 :       if (value && value->Type() == nsAttrValue::eEnum)
    1415           0 :         aData->SetKeywordValue(eCSSProperty_vertical_align, value->GetEnumValue());
    1416             :     }
    1417             :   }
    1418           0 : }
    1419             : 
    1420             : void
    1421           0 : nsGenericHTMLElement::MapImageMarginAttributeInto(const nsMappedAttributes* aAttributes,
    1422             :                                                   GenericSpecifiedValues* aData)
    1423             : {
    1424           0 :   if (!aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Margin)))
    1425           0 :     return;
    1426             : 
    1427             :   const nsAttrValue* value;
    1428             : 
    1429             :   // hspace: value
    1430           0 :   value = aAttributes->GetAttr(nsGkAtoms::hspace);
    1431           0 :   if (value) {
    1432           0 :     if (value->Type() == nsAttrValue::eInteger) {
    1433           0 :       aData->SetPixelValueIfUnset(eCSSProperty_margin_left,
    1434           0 :                                   (float)value->GetIntegerValue());
    1435           0 :       aData->SetPixelValueIfUnset(eCSSProperty_margin_right,
    1436           0 :                                   (float)value->GetIntegerValue());
    1437           0 :     } else if (value->Type() == nsAttrValue::ePercent) {
    1438           0 :       aData->SetPercentValueIfUnset(eCSSProperty_margin_left,
    1439           0 :                                     value->GetPercentValue());
    1440           0 :       aData->SetPercentValueIfUnset(eCSSProperty_margin_right,
    1441           0 :                                     value->GetPercentValue());
    1442             :     }
    1443             :   }
    1444             : 
    1445             :   // vspace: value
    1446           0 :   value = aAttributes->GetAttr(nsGkAtoms::vspace);
    1447           0 :   if (value) {
    1448           0 :     if (value->Type() == nsAttrValue::eInteger) {
    1449           0 :       aData->SetPixelValueIfUnset(eCSSProperty_margin_top,
    1450           0 :                                   (float)value->GetIntegerValue());
    1451           0 :       aData->SetPixelValueIfUnset(eCSSProperty_margin_bottom,
    1452           0 :                                   (float)value->GetIntegerValue());
    1453           0 :     } else if (value->Type() == nsAttrValue::ePercent) {
    1454           0 :       aData->SetPercentValueIfUnset(eCSSProperty_margin_top,
    1455           0 :                                     value->GetPercentValue());
    1456           0 :       aData->SetPercentValueIfUnset(eCSSProperty_margin_bottom,
    1457           0 :                                     value->GetPercentValue());
    1458             :     }
    1459             :   }
    1460             : }
    1461             : 
    1462             : void
    1463           0 : nsGenericHTMLElement::MapWidthAttributeInto(const nsMappedAttributes* aAttributes,
    1464             :                                             GenericSpecifiedValues* aData)
    1465             : {
    1466           0 :   if (!aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Position))) {
    1467           0 :     return;
    1468             :   }
    1469             : 
    1470             :   // width: value
    1471           0 :   if (!aData->PropertyIsSet(eCSSProperty_width)) {
    1472           0 :     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
    1473           0 :     if (value && value->Type() == nsAttrValue::eInteger) {
    1474           0 :       aData->SetPixelValue(eCSSProperty_width,
    1475           0 :                            (float)value->GetIntegerValue());
    1476           0 :     } else if (value && value->Type() == nsAttrValue::ePercent) {
    1477           0 :       aData->SetPercentValue(eCSSProperty_width,
    1478           0 :                              value->GetPercentValue());
    1479             :     }
    1480             :   }
    1481             : }
    1482             : 
    1483             : void
    1484           0 : nsGenericHTMLElement::MapHeightAttributeInto(const nsMappedAttributes* aAttributes,
    1485             :                                              GenericSpecifiedValues* aData)
    1486             : {
    1487           0 :   if (!aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Position)))
    1488           0 :     return;
    1489             : 
    1490             :   // height: value
    1491           0 :   if (!aData->PropertyIsSet(eCSSProperty_height)) {
    1492           0 :     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
    1493           0 :     if (value && value->Type() == nsAttrValue::eInteger) {
    1494           0 :       aData->SetPixelValue(eCSSProperty_height,
    1495           0 :                            (float)value->GetIntegerValue());
    1496           0 :     } else if (value && value->Type() == nsAttrValue::ePercent) {
    1497           0 :       aData->SetPercentValue(eCSSProperty_height,
    1498           0 :                              value->GetPercentValue());
    1499             :     }
    1500             :   }
    1501             : }
    1502             : 
    1503             : void
    1504           0 : nsGenericHTMLElement::MapImageSizeAttributesInto(const nsMappedAttributes* aAttributes,
    1505             :                                                  GenericSpecifiedValues* aData)
    1506             : {
    1507           0 :   nsGenericHTMLElement::MapWidthAttributeInto(aAttributes, aData);
    1508           0 :   nsGenericHTMLElement::MapHeightAttributeInto(aAttributes, aData);
    1509           0 : }
    1510             : 
    1511             : void
    1512           0 : nsGenericHTMLElement::MapImageBorderAttributeInto(const nsMappedAttributes* aAttributes,
    1513             :                                                   GenericSpecifiedValues* aData)
    1514             : {
    1515           0 :   if (!(aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Border))))
    1516           0 :     return;
    1517             : 
    1518             :   // border: pixels
    1519           0 :   const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::border);
    1520           0 :   if (!value)
    1521           0 :     return;
    1522             : 
    1523           0 :   nscoord val = 0;
    1524           0 :   if (value->Type() == nsAttrValue::eInteger)
    1525           0 :     val = value->GetIntegerValue();
    1526             : 
    1527           0 :   aData->SetPixelValueIfUnset(eCSSProperty_border_top_width, (float)val);
    1528           0 :   aData->SetPixelValueIfUnset(eCSSProperty_border_right_width, (float)val);
    1529           0 :   aData->SetPixelValueIfUnset(eCSSProperty_border_bottom_width, (float)val);
    1530           0 :   aData->SetPixelValueIfUnset(eCSSProperty_border_left_width, (float)val);
    1531             : 
    1532             :   aData->SetKeywordValueIfUnset(eCSSProperty_border_top_style,
    1533           0 :                                 NS_STYLE_BORDER_STYLE_SOLID);
    1534             :   aData->SetKeywordValueIfUnset(eCSSProperty_border_right_style,
    1535           0 :                                 NS_STYLE_BORDER_STYLE_SOLID);
    1536             :   aData->SetKeywordValueIfUnset(eCSSProperty_border_bottom_style,
    1537           0 :                                 NS_STYLE_BORDER_STYLE_SOLID);
    1538             :   aData->SetKeywordValueIfUnset(eCSSProperty_border_left_style,
    1539           0 :                                 NS_STYLE_BORDER_STYLE_SOLID);
    1540             : 
    1541           0 :   aData->SetCurrentColorIfUnset(eCSSProperty_border_top_color);
    1542           0 :   aData->SetCurrentColorIfUnset(eCSSProperty_border_right_color);
    1543           0 :   aData->SetCurrentColorIfUnset(eCSSProperty_border_bottom_color);
    1544           0 :   aData->SetCurrentColorIfUnset(eCSSProperty_border_left_color);
    1545             : }
    1546             : 
    1547             : void
    1548          51 : nsGenericHTMLElement::MapBackgroundInto(const nsMappedAttributes* aAttributes,
    1549             :                                         GenericSpecifiedValues* aData)
    1550             : {
    1551             : 
    1552          51 :   if (!aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Background)))
    1553          48 :     return;
    1554             : 
    1555           6 :   if (!aData->PropertyIsSet(eCSSProperty_background_image) &&
    1556           3 :       aData->PresContext()->UseDocumentColors()) {
    1557             :     // background
    1558             :     nsAttrValue* value =
    1559           3 :       const_cast<nsAttrValue*>(aAttributes->GetAttr(nsGkAtoms::background));
    1560           3 :     if (value) {
    1561           0 :       aData->SetBackgroundImage(*value);
    1562             :     }
    1563             :   }
    1564             : }
    1565             : 
    1566             : void
    1567          51 : nsGenericHTMLElement::MapBGColorInto(const nsMappedAttributes* aAttributes,
    1568             :                                      GenericSpecifiedValues* aData)
    1569             : {
    1570          51 :   if (!aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Background)))
    1571          48 :     return;
    1572             : 
    1573           6 :   if (!aData->PropertyIsSet(eCSSProperty_background_color) &&
    1574           3 :       aData->PresContext()->UseDocumentColors()) {
    1575           3 :     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::bgcolor);
    1576             :     nscolor color;
    1577           3 :     if (value && value->GetColorValue(color)) {
    1578           0 :       aData->SetColorValue(eCSSProperty_background_color, color);
    1579             :     }
    1580             :   }
    1581             : }
    1582             : 
    1583             : void
    1584          51 : nsGenericHTMLElement::MapBackgroundAttributesInto(const nsMappedAttributes* aAttributes,
    1585             :                                                   GenericSpecifiedValues* aData)
    1586             : {
    1587          51 :   MapBackgroundInto(aAttributes, aData);
    1588          51 :   MapBGColorInto(aAttributes, aData);
    1589          51 : }
    1590             : 
    1591             : //----------------------------------------------------------------------
    1592             : 
    1593             : nsresult
    1594           0 : nsGenericHTMLElement::SetAttrHelper(nsIAtom* aAttr, const nsAString& aValue)
    1595             : {
    1596           0 :   return SetAttr(kNameSpaceID_None, aAttr, aValue, true);
    1597             : }
    1598             : 
    1599             : int32_t
    1600           0 : nsGenericHTMLElement::GetIntAttr(nsIAtom* aAttr, int32_t aDefault) const
    1601             : {
    1602           0 :   const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(aAttr);
    1603           0 :   if (attrVal && attrVal->Type() == nsAttrValue::eInteger) {
    1604           0 :     return attrVal->GetIntegerValue();
    1605             :   }
    1606           0 :   return aDefault;
    1607             : }
    1608             : 
    1609             : nsresult
    1610           0 : nsGenericHTMLElement::SetIntAttr(nsIAtom* aAttr, int32_t aValue)
    1611             : {
    1612           0 :   nsAutoString value;
    1613           0 :   value.AppendInt(aValue);
    1614             : 
    1615           0 :   return SetAttr(kNameSpaceID_None, aAttr, value, true);
    1616             : }
    1617             : 
    1618             : uint32_t
    1619           0 : nsGenericHTMLElement::GetUnsignedIntAttr(nsIAtom* aAttr,
    1620             :                                          uint32_t aDefault) const
    1621             : {
    1622           0 :   const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(aAttr);
    1623           0 :   if (!attrVal || attrVal->Type() != nsAttrValue::eInteger) {
    1624           0 :     return aDefault;
    1625             :   }
    1626             : 
    1627           0 :   return attrVal->GetIntegerValue();
    1628             : }
    1629             : 
    1630             : void
    1631           0 : nsGenericHTMLElement::GetURIAttr(nsIAtom* aAttr, nsIAtom* aBaseAttr,
    1632             :                                  nsAString& aResult) const
    1633             : {
    1634           0 :   nsCOMPtr<nsIURI> uri;
    1635           0 :   bool hadAttr = GetURIAttr(aAttr, aBaseAttr, getter_AddRefs(uri));
    1636           0 :   if (!hadAttr) {
    1637           0 :     aResult.Truncate();
    1638           0 :     return;
    1639             :   }
    1640             : 
    1641           0 :   if (!uri) {
    1642             :     // Just return the attr value
    1643           0 :     GetAttr(kNameSpaceID_None, aAttr, aResult);
    1644           0 :     return;
    1645             :   }
    1646             : 
    1647           0 :   nsAutoCString spec;
    1648           0 :   uri->GetSpec(spec);
    1649           0 :   CopyUTF8toUTF16(spec, aResult);
    1650             : }
    1651             : 
    1652             : bool
    1653           0 : nsGenericHTMLElement::GetURIAttr(nsIAtom* aAttr, nsIAtom* aBaseAttr, nsIURI** aURI) const
    1654             : {
    1655           0 :   *aURI = nullptr;
    1656             : 
    1657           0 :   const nsAttrValue* attr = mAttrsAndChildren.GetAttr(aAttr);
    1658           0 :   if (!attr) {
    1659           0 :     return false;
    1660             :   }
    1661             : 
    1662           0 :   nsCOMPtr<nsIURI> baseURI = GetBaseURI();
    1663             : 
    1664           0 :   if (aBaseAttr) {
    1665           0 :     nsAutoString baseAttrValue;
    1666           0 :     if (GetAttr(kNameSpaceID_None, aBaseAttr, baseAttrValue)) {
    1667           0 :       nsCOMPtr<nsIURI> baseAttrURI;
    1668             :       nsresult rv =
    1669           0 :         nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(baseAttrURI),
    1670             :                                                   baseAttrValue, OwnerDoc(),
    1671           0 :                                                   baseURI);
    1672           0 :       if (NS_FAILED(rv)) {
    1673           0 :         return true;
    1674             :       }
    1675           0 :       baseURI.swap(baseAttrURI);
    1676             :     }
    1677             :   }
    1678             : 
    1679             :   // Don't care about return value.  If it fails, we still want to
    1680             :   // return true, and *aURI will be null.
    1681           0 :   nsContentUtils::NewURIWithDocumentCharset(aURI,
    1682           0 :                                             attr->GetStringValue(),
    1683           0 :                                             OwnerDoc(), baseURI);
    1684           0 :   return true;
    1685             : }
    1686             : 
    1687             : HTMLMenuElement*
    1688           0 : nsGenericHTMLElement::GetContextMenu() const
    1689             : {
    1690           0 :   nsAutoString value;
    1691           0 :   GetHTMLAttr(nsGkAtoms::contextmenu, value);
    1692           0 :   if (!value.IsEmpty()) {
    1693             :     //XXXsmaug How should this work in Shadow DOM?
    1694           0 :     nsIDocument* doc = GetUncomposedDoc();
    1695           0 :     if (doc) {
    1696           0 :       return HTMLMenuElement::FromContentOrNull(doc->GetElementById(value));
    1697             :     }
    1698             :   }
    1699           0 :   return nullptr;
    1700             : }
    1701             : 
    1702             : NS_IMETHODIMP
    1703           0 : nsGenericHTMLElement::GetContextMenu(nsIDOMHTMLMenuElement** aContextMenu)
    1704             : {
    1705           0 :   NS_IF_ADDREF(*aContextMenu = GetContextMenu());
    1706           0 :   return NS_OK;
    1707             : }
    1708             : 
    1709             : bool
    1710           0 : nsGenericHTMLElement::IsLabelable() const
    1711             : {
    1712           0 :   return IsAnyOfHTMLElements(nsGkAtoms::progress, nsGkAtoms::meter);
    1713             : }
    1714             : 
    1715             : /* static */ bool
    1716           0 : nsGenericHTMLElement::MatchLabelsElement(Element* aElement, int32_t aNamespaceID,
    1717             :                                          nsIAtom* aAtom, void* aData)
    1718             : {
    1719           0 :   HTMLLabelElement* element = HTMLLabelElement::FromContent(aElement);
    1720           0 :   return element && element->GetControl() == aData;
    1721             : }
    1722             : 
    1723             : already_AddRefed<nsINodeList>
    1724           0 : nsGenericHTMLElement::Labels()
    1725             : {
    1726           0 :   MOZ_ASSERT(IsLabelable(),
    1727             :              "Labels() only allow labelable elements to use it.");
    1728           0 :   nsDOMSlots* slots = DOMSlots();
    1729             : 
    1730           0 :   if (!slots->mLabelsList) {
    1731           0 :     slots->mLabelsList = new nsLabelsNodeList(SubtreeRoot(), MatchLabelsElement,
    1732           0 :                                               nullptr, this);
    1733             :   }
    1734             : 
    1735           0 :   RefPtr<nsLabelsNodeList> labels = slots->mLabelsList;
    1736           0 :   return labels.forget();
    1737             : }
    1738             : 
    1739             : bool
    1740           0 : nsGenericHTMLElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
    1741             : {
    1742           0 :   return IsAnyOfHTMLElements(nsGkAtoms::details, nsGkAtoms::embed,
    1743           0 :                              nsGkAtoms::keygen) ||
    1744           0 :          (!aIgnoreTabindex && HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex));
    1745             : }
    1746             : 
    1747             : // static
    1748             : bool
    1749          24 : nsGenericHTMLElement::TouchEventsEnabled(JSContext* aCx, JSObject* aGlobal)
    1750             : {
    1751          24 :   return TouchEvent::PrefEnabled(aCx, aGlobal);
    1752             : }
    1753             : 
    1754             : //----------------------------------------------------------------------
    1755             : 
    1756           9 : nsGenericHTMLFormElement::nsGenericHTMLFormElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
    1757           9 :                                                    uint8_t aType)
    1758             :   : nsGenericHTMLElement(aNodeInfo)
    1759             :   , nsIFormControl(aType)
    1760             :   , mForm(nullptr)
    1761           9 :   , mFieldSet(nullptr)
    1762             : {
    1763             :   // We should add the NS_EVENT_STATE_ENABLED bit here as needed, but
    1764             :   // that depends on our type, which is not initialized yet.  So we
    1765             :   // have to do this in subclasses.
    1766           9 : }
    1767             : 
    1768           0 : nsGenericHTMLFormElement::~nsGenericHTMLFormElement()
    1769             : {
    1770           0 :   if (mFieldSet) {
    1771           0 :     mFieldSet->RemoveElement(this);
    1772             :   }
    1773             : 
    1774             :   // Check that this element doesn't know anything about its form at this point.
    1775           0 :   NS_ASSERTION(!mForm, "mForm should be null at this point!");
    1776           0 : }
    1777             : 
    1778         161 : NS_IMPL_ISUPPORTS_INHERITED(nsGenericHTMLFormElement,
    1779             :                             nsGenericHTMLElement,
    1780             :                             nsIFormControl)
    1781             : 
    1782             : nsINode*
    1783           0 : nsGenericHTMLFormElement::GetScopeChainParent() const
    1784             : {
    1785           0 :   return mForm ? mForm : nsGenericHTMLElement::GetScopeChainParent();
    1786             : }
    1787             : 
    1788             : bool
    1789        1044 : nsGenericHTMLFormElement::IsNodeOfType(uint32_t aFlags) const
    1790             : {
    1791        1044 :   return !(aFlags & ~(eCONTENT | eHTML_FORM_CONTROL));
    1792             : }
    1793             : 
    1794             : void
    1795           0 : nsGenericHTMLFormElement::SaveSubtreeState()
    1796             : {
    1797           0 :   SaveState();
    1798             : 
    1799           0 :   nsGenericHTMLElement::SaveSubtreeState();
    1800           0 : }
    1801             : 
    1802             : void
    1803           0 : nsGenericHTMLFormElement::SetForm(nsIDOMHTMLFormElement* aForm)
    1804             : {
    1805           0 :   NS_PRECONDITION(aForm, "Don't pass null here");
    1806           0 :   NS_ASSERTION(!mForm,
    1807             :                "We don't support switching from one non-null form to another.");
    1808             : 
    1809           0 :   SetForm(static_cast<HTMLFormElement*>(aForm), false);
    1810           0 : }
    1811             : 
    1812          25 : void nsGenericHTMLFormElement::SetForm(HTMLFormElement* aForm, bool aBindToTree)
    1813             : {
    1814          25 :   if (aForm) {
    1815           0 :     BeforeSetForm(aBindToTree);
    1816             :   }
    1817             : 
    1818             :   // keep a *weak* ref to the form here
    1819          25 :   mForm = aForm;
    1820          25 : }
    1821             : 
    1822             : void
    1823           0 : nsGenericHTMLFormElement::ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete)
    1824             : {
    1825           0 :   NS_ASSERTION((mForm != nullptr) == HasFlag(ADDED_TO_FORM),
    1826             :                "Form control should have had flag set correctly");
    1827             : 
    1828           0 :   if (!mForm) {
    1829           0 :     return;
    1830             :   }
    1831             : 
    1832           0 :   if (aRemoveFromForm) {
    1833           0 :     nsAutoString nameVal, idVal;
    1834           0 :     GetAttr(kNameSpaceID_None, nsGkAtoms::name, nameVal);
    1835           0 :     GetAttr(kNameSpaceID_None, nsGkAtoms::id, idVal);
    1836             : 
    1837           0 :     mForm->RemoveElement(this, true);
    1838             : 
    1839           0 :     if (!nameVal.IsEmpty()) {
    1840           0 :       mForm->RemoveElementFromTable(this, nameVal);
    1841             :     }
    1842             : 
    1843           0 :     if (!idVal.IsEmpty()) {
    1844           0 :       mForm->RemoveElementFromTable(this, idVal);
    1845             :     }
    1846             :   }
    1847             : 
    1848           0 :   UnsetFlags(ADDED_TO_FORM);
    1849           0 :   mForm = nullptr;
    1850             : 
    1851           0 :   AfterClearForm(aUnbindOrDelete);
    1852             : }
    1853             : 
    1854             : Element*
    1855           0 : nsGenericHTMLFormElement::GetFormElement()
    1856             : {
    1857           0 :   return mForm;
    1858             : }
    1859             : 
    1860             : HTMLFieldSetElement*
    1861           0 : nsGenericHTMLFormElement::GetFieldSet()
    1862             : {
    1863           0 :   return mFieldSet;
    1864             : }
    1865             : 
    1866             : nsresult
    1867           0 : nsGenericHTMLFormElement::GetForm(nsIDOMHTMLFormElement** aForm)
    1868             : {
    1869           0 :   NS_ENSURE_ARG_POINTER(aForm);
    1870           0 :   NS_IF_ADDREF(*aForm = mForm);
    1871           0 :   return NS_OK;
    1872             : }
    1873             : 
    1874             : nsIContent::IMEState
    1875           0 : nsGenericHTMLFormElement::GetDesiredIMEState()
    1876             : {
    1877           0 :   TextEditor* textEditor = GetTextEditorInternal();
    1878           0 :   if (!textEditor) {
    1879           0 :     return nsGenericHTMLElement::GetDesiredIMEState();
    1880             :   }
    1881           0 :   IMEState state;
    1882           0 :   nsresult rv = textEditor->GetPreferredIMEState(&state);
    1883           0 :   if (NS_FAILED(rv)) {
    1884           0 :     return nsGenericHTMLElement::GetDesiredIMEState();
    1885             :   }
    1886           0 :   return state;
    1887             : }
    1888             : 
    1889             : nsresult
    1890          25 : nsGenericHTMLFormElement::BindToTree(nsIDocument* aDocument,
    1891             :                                      nsIContent* aParent,
    1892             :                                      nsIContent* aBindingParent,
    1893             :                                      bool aCompileEventHandlers)
    1894             : {
    1895          25 :   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
    1896             :                                                  aBindingParent,
    1897          25 :                                                  aCompileEventHandlers);
    1898          25 :   NS_ENSURE_SUCCESS(rv, rv);
    1899             : 
    1900             :   // An autofocus event has to be launched if the autofocus attribute is
    1901             :   // specified and the element accept the autofocus attribute. In addition,
    1902             :   // the document should not be already loaded and the "browser.autofocus"
    1903             :   // preference should be 'true'.
    1904          25 :   if (IsAutofocusable() && HasAttr(kNameSpaceID_None, nsGkAtoms::autofocus) &&
    1905           0 :       nsContentUtils::AutoFocusEnabled()) {
    1906           0 :     nsCOMPtr<nsIRunnable> event = new nsAutoFocusEvent(this);
    1907           0 :     rv = NS_DispatchToCurrentThread(event);
    1908           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1909             :   }
    1910             : 
    1911             :   // If @form is set, the element *has* to be in a document, otherwise it
    1912             :   // wouldn't be possible to find an element with the corresponding id.
    1913             :   // If @form isn't set, the element *has* to have a parent, otherwise it
    1914             :   // wouldn't be possible to find a form ancestor.
    1915             :   // We should not call UpdateFormOwner if none of these conditions are
    1916             :   // fulfilled.
    1917          25 :   if (HasAttr(kNameSpaceID_None, nsGkAtoms::form) ? !!GetUncomposedDoc()
    1918             :                                                   : !!aParent) {
    1919          25 :     UpdateFormOwner(true, nullptr);
    1920             :   }
    1921             : 
    1922             :   // Set parent fieldset which should be used for the disabled state.
    1923          25 :   UpdateFieldSet(false);
    1924             : 
    1925          25 :   return NS_OK;
    1926             : }
    1927             : 
    1928             : void
    1929           2 : nsGenericHTMLFormElement::UnbindFromTree(bool aDeep, bool aNullParent)
    1930             : {
    1931             :   // Save state before doing anything
    1932           2 :   SaveState();
    1933             : 
    1934           2 :   if (mForm) {
    1935             :     // Might need to unset mForm
    1936           0 :     if (aNullParent) {
    1937             :       // No more parent means no more form
    1938           0 :       ClearForm(true, true);
    1939             :     } else {
    1940             :       // Recheck whether we should still have an mForm.
    1941           0 :       if (HasAttr(kNameSpaceID_None, nsGkAtoms::form) ||
    1942           0 :           !FindAncestorForm(mForm)) {
    1943           0 :         ClearForm(true, true);
    1944             :       } else {
    1945           0 :         UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
    1946             :       }
    1947             :     }
    1948             : 
    1949           0 :     if (!mForm) {
    1950             :       // Our novalidate state might have changed
    1951           0 :       UpdateState(false);
    1952             :     }
    1953             :   }
    1954             : 
    1955             :   // We have to remove the form id observer if there was one.
    1956             :   // We will re-add one later if needed (during bind to tree).
    1957           2 :   if (nsContentUtils::HasNonEmptyAttr(this, kNameSpaceID_None,
    1958             :                                       nsGkAtoms::form)) {
    1959           0 :     RemoveFormIdObserver();
    1960             :   }
    1961             : 
    1962           2 :   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
    1963             : 
    1964             :   // The element might not have a fieldset anymore.
    1965           2 :   UpdateFieldSet(false);
    1966           2 : }
    1967             : 
    1968             : nsresult
    1969          37 : nsGenericHTMLFormElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
    1970             :                                         const nsAttrValueOrString* aValue,
    1971             :                                         bool aNotify)
    1972             : {
    1973          37 :   if (aNameSpaceID == kNameSpaceID_None) {
    1974          58 :     nsAutoString tmp;
    1975             : 
    1976             :     // remove the control from the hashtable as needed
    1977             : 
    1978          29 :     if (mForm && (aName == nsGkAtoms::name || aName == nsGkAtoms::id)) {
    1979           0 :       GetAttr(kNameSpaceID_None, aName, tmp);
    1980             : 
    1981           0 :       if (!tmp.IsEmpty()) {
    1982           0 :         mForm->RemoveElementFromTable(this, tmp);
    1983             :       }
    1984             :     }
    1985             : 
    1986          29 :     if (mForm && aName == nsGkAtoms::type) {
    1987           0 :       GetAttr(kNameSpaceID_None, nsGkAtoms::name, tmp);
    1988             : 
    1989           0 :       if (!tmp.IsEmpty()) {
    1990           0 :         mForm->RemoveElementFromTable(this, tmp);
    1991             :       }
    1992             : 
    1993           0 :       GetAttr(kNameSpaceID_None, nsGkAtoms::id, tmp);
    1994             : 
    1995           0 :       if (!tmp.IsEmpty()) {
    1996           0 :         mForm->RemoveElementFromTable(this, tmp);
    1997             :       }
    1998             : 
    1999           0 :       mForm->RemoveElement(this, false);
    2000             :     }
    2001             : 
    2002          29 :     if (aName == nsGkAtoms::form) {
    2003             :       // If @form isn't set or set to the empty string, there were no observer
    2004             :       // so we don't have to remove it.
    2005           0 :       if (nsContentUtils::HasNonEmptyAttr(this, kNameSpaceID_None,
    2006             :                                           nsGkAtoms::form)) {
    2007             :         // The current form id observer is no longer needed.
    2008             :         // A new one may be added in AfterSetAttr.
    2009           0 :         RemoveFormIdObserver();
    2010             :       }
    2011             :     }
    2012             :   }
    2013             : 
    2014          37 :   return nsGenericHTMLElement::BeforeSetAttr(aNameSpaceID, aName,
    2015          37 :                                              aValue, aNotify);
    2016             : }
    2017             : 
    2018             : nsresult
    2019          37 : nsGenericHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
    2020             :                                        const nsAttrValue* aValue,
    2021             :                                        const nsAttrValue* aOldValue, bool aNotify)
    2022             : {
    2023          37 :   if (aNameSpaceID == kNameSpaceID_None) {
    2024             :     // add the control to the hashtable as needed
    2025             : 
    2026          58 :     if (mForm && (aName == nsGkAtoms::name || aName == nsGkAtoms::id) &&
    2027          29 :         aValue && !aValue->IsEmptyString()) {
    2028           0 :       MOZ_ASSERT(aValue->Type() == nsAttrValue::eAtom,
    2029             :                  "Expected atom value for name/id");
    2030           0 :       mForm->AddElementToTable(this,
    2031           0 :         nsDependentAtomString(aValue->GetAtomValue()));
    2032             :     }
    2033             : 
    2034          29 :     if (mForm && aName == nsGkAtoms::type) {
    2035           0 :       nsAutoString tmp;
    2036             : 
    2037           0 :       GetAttr(kNameSpaceID_None, nsGkAtoms::name, tmp);
    2038             : 
    2039           0 :       if (!tmp.IsEmpty()) {
    2040           0 :         mForm->AddElementToTable(this, tmp);
    2041             :       }
    2042             : 
    2043           0 :       GetAttr(kNameSpaceID_None, nsGkAtoms::id, tmp);
    2044             : 
    2045           0 :       if (!tmp.IsEmpty()) {
    2046           0 :         mForm->AddElementToTable(this, tmp);
    2047             :       }
    2048             : 
    2049           0 :       mForm->AddElement(this, false, aNotify);
    2050             :     }
    2051             : 
    2052          29 :     if (aName == nsGkAtoms::form) {
    2053             :       // We need a new form id observer.
    2054             :       //XXXsmaug How should this work in Shadow DOM?
    2055           0 :       nsIDocument* doc = GetUncomposedDoc();
    2056           0 :       if (doc) {
    2057           0 :         Element* formIdElement = nullptr;
    2058           0 :         if (aValue && !aValue->IsEmptyString()) {
    2059           0 :           formIdElement = AddFormIdObserver();
    2060             :         }
    2061             : 
    2062             :         // Because we have a new @form value (or no more @form), we have to
    2063             :         // update our form owner.
    2064           0 :         UpdateFormOwner(false, formIdElement);
    2065             :       }
    2066             :     }
    2067             :   }
    2068             : 
    2069          37 :   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
    2070          37 :                                             aValue, aOldValue, aNotify);
    2071             : }
    2072             : 
    2073             : nsresult
    2074           4 : nsGenericHTMLFormElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
    2075             : {
    2076           8 :   if (aVisitor.mEvent->IsTrusted() && (aVisitor.mEvent->mMessage == eFocus ||
    2077           4 :                                        aVisitor.mEvent->mMessage == eBlur)) {
    2078             :     // We have to handle focus/blur event to change focus states in
    2079             :     // PreHandleEvent to prevent it breaks event target chain creation.
    2080           0 :     aVisitor.mWantsPreHandleEvent = true;
    2081             :   }
    2082           4 :   return nsGenericHTMLElement::GetEventTargetParent(aVisitor);
    2083             : }
    2084             : 
    2085             : nsresult
    2086           0 : nsGenericHTMLFormElement::PreHandleEvent(EventChainVisitor& aVisitor)
    2087             : {
    2088           0 :   if (aVisitor.mEvent->IsTrusted()) {
    2089           0 :     switch (aVisitor.mEvent->mMessage) {
    2090             :       case eFocus: {
    2091             :         // Check to see if focus has bubbled up from a form control's
    2092             :         // child textfield or button.  If that's the case, don't focus
    2093             :         // this parent file control -- leave focus on the child.
    2094           0 :         nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
    2095           0 :         if (formControlFrame &&
    2096           0 :             aVisitor.mEvent->mOriginalTarget == static_cast<nsINode*>(this))
    2097           0 :           formControlFrame->SetFocus(true, true);
    2098           0 :         break;
    2099             :       }
    2100             :       case eBlur: {
    2101           0 :         nsIFormControlFrame* formControlFrame = GetFormControlFrame(true);
    2102           0 :         if (formControlFrame)
    2103           0 :           formControlFrame->SetFocus(false, false);
    2104           0 :         break;
    2105             :       }
    2106             :       default:
    2107           0 :         break;
    2108             :     }
    2109             :   }
    2110           0 :   return nsGenericHTMLElement::PreHandleEvent(aVisitor);
    2111             : }
    2112             : 
    2113             : /* virtual */
    2114             : bool
    2115         100 : nsGenericHTMLFormElement::IsDisabled() const
    2116             : {
    2117         200 :   return HasAttr(kNameSpaceID_None, nsGkAtoms::disabled) ||
    2118         200 :          (mFieldSet && mFieldSet->IsDisabled());
    2119             : }
    2120             : 
    2121             : void
    2122           0 : nsGenericHTMLFormElement::ForgetFieldSet(nsIContent* aFieldset)
    2123             : {
    2124           0 :   if (mFieldSet == aFieldset) {
    2125           0 :     mFieldSet = nullptr;
    2126             :   }
    2127           0 : }
    2128             : 
    2129             : bool
    2130          69 : nsGenericHTMLFormElement::CanBeDisabled() const
    2131             : {
    2132          69 :   int32_t type = ControlType();
    2133             :   // It's easier to test the types that _cannot_ be disabled
    2134             :   return
    2135          69 :     type != NS_FORM_OBJECT &&
    2136          69 :     type != NS_FORM_OUTPUT;
    2137             : }
    2138             : 
    2139             : bool
    2140           0 : nsGenericHTMLFormElement::IsHTMLFocusable(bool aWithMouse,
    2141             :                                           bool* aIsFocusable,
    2142             :                                           int32_t* aTabIndex)
    2143             : {
    2144           0 :   if (nsGenericHTMLElement::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex)) {
    2145           0 :     return true;
    2146             :   }
    2147             : 
    2148             : #ifdef XP_MACOSX
    2149             :   *aIsFocusable =
    2150             :     (!aWithMouse || nsFocusManager::sMouseFocusesFormControl) && *aIsFocusable;
    2151             : #endif
    2152           0 :   return false;
    2153             : }
    2154             : 
    2155             : EventStates
    2156          69 : nsGenericHTMLFormElement::IntrinsicState() const
    2157             : {
    2158             :   // If you add attribute-dependent states here, you need to add them them to
    2159             :   // AfterSetAttr too.  And add them to AfterSetAttr for all subclasses that
    2160             :   // implement IntrinsicState() and are affected by that attribute.
    2161          69 :   EventStates state = nsGenericHTMLElement::IntrinsicState();
    2162             : 
    2163          69 :   if (CanBeDisabled()) {
    2164             :     // :enabled/:disabled
    2165          69 :     if (IsDisabled()) {
    2166           0 :       state |= NS_EVENT_STATE_DISABLED;
    2167           0 :       state &= ~NS_EVENT_STATE_ENABLED;
    2168             :     } else {
    2169          69 :       state &= ~NS_EVENT_STATE_DISABLED;
    2170          69 :       state |= NS_EVENT_STATE_ENABLED;
    2171             :     }
    2172             :   }
    2173             : 
    2174          69 :   if (mForm && mForm->IsDefaultSubmitElement(this)) {
    2175           0 :       NS_ASSERTION(IsSubmitControl(),
    2176             :                    "Default submit element that isn't a submit control.");
    2177             :       // We are the default submit element (:default)
    2178           0 :       state |= NS_EVENT_STATE_DEFAULT;
    2179             :   }
    2180             : 
    2181             :   // Make the text controls read-write
    2182         138 :   if (!state.HasState(NS_EVENT_STATE_MOZ_READWRITE) &&
    2183          69 :       IsTextOrNumberControl(/*aExcludePassword*/ false)) {
    2184          66 :     bool roState = GetBoolAttr(nsGkAtoms::readonly);
    2185             : 
    2186          66 :     if (!roState) {
    2187          66 :       state |= NS_EVENT_STATE_MOZ_READWRITE;
    2188          66 :       state &= ~NS_EVENT_STATE_MOZ_READONLY;
    2189             :     }
    2190             :   }
    2191             : 
    2192          69 :   return state;
    2193             : }
    2194             : 
    2195             : nsGenericHTMLFormElement::FocusTristate
    2196           0 : nsGenericHTMLFormElement::FocusState()
    2197             : {
    2198             :   // We can't be focused if we aren't in a (composed) document
    2199           0 :   nsIDocument* doc = GetComposedDoc();
    2200           0 :   if (!doc)
    2201           0 :     return eUnfocusable;
    2202             : 
    2203             :   // first see if we are disabled or not. If disabled then do nothing.
    2204           0 :   if (IsDisabled()) {
    2205           0 :     return eUnfocusable;
    2206             :   }
    2207             : 
    2208             :   // If the window is not active, do not allow the focus to bring the
    2209             :   // window to the front.  We update the focus controller, but do
    2210             :   // nothing else.
    2211           0 :   if (nsPIDOMWindowOuter* win = doc->GetWindow()) {
    2212           0 :     nsCOMPtr<nsPIDOMWindowOuter> rootWindow = win->GetPrivateRoot();
    2213             : 
    2214           0 :     nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
    2215           0 :     if (fm && rootWindow) {
    2216           0 :       nsCOMPtr<mozIDOMWindowProxy> activeWindow;
    2217           0 :       fm->GetActiveWindow(getter_AddRefs(activeWindow));
    2218           0 :       if (activeWindow == rootWindow) {
    2219           0 :         return eActiveWindow;
    2220             :       }
    2221             :     }
    2222             :   }
    2223             : 
    2224           0 :   return eInactiveWindow;
    2225             : }
    2226             : 
    2227             : Element*
    2228           0 : nsGenericHTMLFormElement::AddFormIdObserver()
    2229             : {
    2230           0 :   NS_ASSERTION(GetUncomposedDoc(), "When adding a form id observer, "
    2231             :                                    "we should be in a document!");
    2232             : 
    2233           0 :   nsAutoString formId;
    2234           0 :   nsIDocument* doc = OwnerDoc();
    2235           0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::form, formId);
    2236           0 :   NS_ASSERTION(!formId.IsEmpty(),
    2237             :                "@form value should not be the empty string!");
    2238           0 :   nsCOMPtr<nsIAtom> atom = NS_Atomize(formId);
    2239             : 
    2240           0 :   return doc->AddIDTargetObserver(atom, FormIdUpdated, this, false);
    2241             : }
    2242             : 
    2243             : void
    2244           0 : nsGenericHTMLFormElement::RemoveFormIdObserver()
    2245             : {
    2246             :   /**
    2247             :    * We are using OwnerDoc() because we don't really care about having the
    2248             :    * element actually being in the tree. If it is not and @form value changes,
    2249             :    * this method will be called for nothing but removing an observer which does
    2250             :    * not exist doesn't cost so much (no entry in the hash table) so having a
    2251             :    * boolean for GetUncomposedDoc()/GetOwnerDoc() would make everything look
    2252             :    * more complex for nothing.
    2253             :    */
    2254             : 
    2255           0 :   nsIDocument* doc = OwnerDoc();
    2256             : 
    2257             :   // At this point, we may not have a document anymore. In that case, we can't
    2258             :   // remove the observer. The document did that for us.
    2259           0 :   if (!doc) {
    2260           0 :     return;
    2261             :   }
    2262             : 
    2263           0 :   nsAutoString formId;
    2264           0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::form, formId);
    2265           0 :   NS_ASSERTION(!formId.IsEmpty(),
    2266             :                "@form value should not be the empty string!");
    2267           0 :   nsCOMPtr<nsIAtom> atom = NS_Atomize(formId);
    2268             : 
    2269           0 :   doc->RemoveIDTargetObserver(atom, FormIdUpdated, this, false);
    2270             : }
    2271             : 
    2272             : 
    2273             : /* static */
    2274             : bool
    2275           0 : nsGenericHTMLFormElement::FormIdUpdated(Element* aOldElement,
    2276             :                                         Element* aNewElement,
    2277             :                                         void* aData)
    2278             : {
    2279             :   nsGenericHTMLFormElement* element =
    2280           0 :     static_cast<nsGenericHTMLFormElement*>(aData);
    2281             : 
    2282           0 :   NS_ASSERTION(element->IsHTMLElement(), "aData should be an HTML element");
    2283             : 
    2284           0 :   element->UpdateFormOwner(false, aNewElement);
    2285             : 
    2286           0 :   return true;
    2287             : }
    2288             : 
    2289             : bool
    2290           4 : nsGenericHTMLFormElement::IsElementDisabledForEvents(EventMessage aMessage,
    2291             :                                                      nsIFrame* aFrame)
    2292             : {
    2293           4 :   switch (aMessage) {
    2294             :     case eMouseMove:
    2295             :     case eMouseOver:
    2296             :     case eMouseOut:
    2297             :     case eMouseEnter:
    2298             :     case eMouseLeave:
    2299             :     case ePointerMove:
    2300             :     case ePointerOver:
    2301             :     case ePointerOut:
    2302             :     case ePointerEnter:
    2303             :     case ePointerLeave:
    2304             :     case eWheel:
    2305             :     case eLegacyMouseLineOrPageScroll:
    2306             :     case eLegacyMousePixelScroll:
    2307           0 :       return false;
    2308             :     default:
    2309           4 :       break;
    2310             :   }
    2311             : 
    2312           4 :   bool disabled = IsDisabled();
    2313           4 :   if (!disabled && aFrame) {
    2314           4 :     const nsStyleUserInterface* uiStyle = aFrame->StyleUserInterface();
    2315           8 :     disabled = uiStyle->mUserInput == StyleUserInput::None ||
    2316           4 :                uiStyle->mUserInput == StyleUserInput::Disabled;
    2317             : 
    2318             :   }
    2319           4 :   return disabled;
    2320             : }
    2321             : 
    2322             : void
    2323          25 : nsGenericHTMLFormElement::UpdateFormOwner(bool aBindToTree,
    2324             :                                           Element* aFormIdElement)
    2325             : {
    2326          25 :   NS_PRECONDITION(!aBindToTree || !aFormIdElement,
    2327             :                   "aFormIdElement shouldn't be set if aBindToTree is true!");
    2328             : 
    2329          25 :   bool needStateUpdate = false;
    2330          25 :   if (!aBindToTree) {
    2331           0 :     needStateUpdate = mForm && mForm->IsDefaultSubmitElement(this);
    2332           0 :     ClearForm(true, false);
    2333             :   }
    2334             : 
    2335          25 :   HTMLFormElement *oldForm = mForm;
    2336             : 
    2337          25 :   if (!mForm) {
    2338             :     // If @form is set, we have to use that to find the form.
    2339          50 :     nsAutoString formId;
    2340          25 :     if (GetAttr(kNameSpaceID_None, nsGkAtoms::form, formId)) {
    2341           0 :       if (!formId.IsEmpty()) {
    2342           0 :         Element* element = nullptr;
    2343             : 
    2344           0 :         if (aBindToTree) {
    2345           0 :           element = AddFormIdObserver();
    2346             :         } else {
    2347           0 :           element = aFormIdElement;
    2348             :         }
    2349             : 
    2350           0 :         NS_ASSERTION(GetUncomposedDoc(), "The element should be in a document "
    2351             :                                          "when UpdateFormOwner is called!");
    2352           0 :         NS_ASSERTION(!GetUncomposedDoc() ||
    2353             :                      element == GetUncomposedDoc()->GetElementById(formId),
    2354             :                      "element should be equals to the current element "
    2355             :                      "associated with the id in @form!");
    2356             : 
    2357           0 :         if (element && element->IsHTMLElement(nsGkAtoms::form)) {
    2358           0 :           SetForm(static_cast<HTMLFormElement*>(element), aBindToTree);
    2359             :         }
    2360             :       }
    2361             :      } else {
    2362             :       // We now have a parent, so we may have picked up an ancestor form.  Search
    2363             :       // for it.  Note that if mForm is already set we don't want to do this,
    2364             :       // because that means someone (probably the content sink) has already set
    2365             :       // it to the right value.  Also note that even if being bound here didn't
    2366             :       // change our parent, we still need to search, since our parent chain
    2367             :       // probably changed _somewhere_.
    2368          25 :       SetForm(FindAncestorForm(), aBindToTree);
    2369             :     }
    2370             :   }
    2371             : 
    2372          25 :   if (mForm && !HasFlag(ADDED_TO_FORM)) {
    2373             :     // Now we need to add ourselves to the form
    2374           0 :     nsAutoString nameVal, idVal;
    2375           0 :     GetAttr(kNameSpaceID_None, nsGkAtoms::name, nameVal);
    2376           0 :     GetAttr(kNameSpaceID_None, nsGkAtoms::id, idVal);
    2377             : 
    2378           0 :     SetFlags(ADDED_TO_FORM);
    2379             : 
    2380             :     // Notify only if we just found this mForm.
    2381           0 :     mForm->AddElement(this, true, oldForm == nullptr);
    2382             : 
    2383           0 :     if (!nameVal.IsEmpty()) {
    2384           0 :       mForm->AddElementToTable(this, nameVal);
    2385             :     }
    2386             : 
    2387           0 :     if (!idVal.IsEmpty()) {
    2388           0 :       mForm->AddElementToTable(this, idVal);
    2389             :     }
    2390             :   }
    2391             : 
    2392          25 :   if (mForm != oldForm || needStateUpdate) {
    2393           0 :     UpdateState(true);
    2394             :   }
    2395          25 : }
    2396             : 
    2397             : void
    2398          27 : nsGenericHTMLFormElement::UpdateFieldSet(bool aNotify)
    2399             : {
    2400          27 :   nsIContent* parent = nullptr;
    2401          27 :   nsIContent* prev = nullptr;
    2402             : 
    2403         113 :   for (parent = GetParent(); parent;
    2404          86 :        prev = parent, parent = parent->GetParent()) {
    2405             :     HTMLFieldSetElement* fieldset =
    2406          86 :       HTMLFieldSetElement::FromContent(parent);
    2407          86 :     if (fieldset &&
    2408           0 :         (!prev || fieldset->GetFirstLegend() != prev)) {
    2409           0 :       if (mFieldSet == fieldset) {
    2410             :         // We already have the right fieldset;
    2411           0 :         return;
    2412             :       }
    2413             : 
    2414           0 :       if (mFieldSet) {
    2415           0 :         mFieldSet->RemoveElement(this);
    2416             :       }
    2417           0 :       mFieldSet = fieldset;
    2418           0 :       fieldset->AddElement(this);
    2419             : 
    2420             :       // The disabled state may have changed
    2421           0 :       FieldSetDisabledChanged(aNotify);
    2422           0 :       return;
    2423             :     }
    2424             :   }
    2425             : 
    2426             :   // No fieldset found.
    2427          27 :   if (mFieldSet) {
    2428           0 :     mFieldSet->RemoveElement(this);
    2429           0 :     mFieldSet = nullptr;
    2430             :     // The disabled state may have changed
    2431           0 :     FieldSetDisabledChanged(aNotify);
    2432             :   }
    2433             : }
    2434             : 
    2435             : void
    2436           0 : nsGenericHTMLFormElement::FieldSetDisabledChanged(bool aNotify)
    2437             : {
    2438           0 :   UpdateState(aNotify);
    2439           0 : }
    2440             : 
    2441             : bool
    2442           0 : nsGenericHTMLFormElement::IsLabelable() const
    2443             : {
    2444             :   // TODO: keygen should be in that list, see bug 101019.
    2445           0 :   uint32_t type = ControlType();
    2446           0 :   return (type & NS_FORM_INPUT_ELEMENT && type != NS_FORM_INPUT_HIDDEN) ||
    2447           0 :          type & NS_FORM_BUTTON_ELEMENT ||
    2448             :          // type == NS_FORM_KEYGEN ||
    2449           0 :          type == NS_FORM_OUTPUT ||
    2450           0 :          type == NS_FORM_SELECT ||
    2451           0 :          type == NS_FORM_TEXTAREA;
    2452             : }
    2453             : 
    2454             : //----------------------------------------------------------------------
    2455             : 
    2456             : void
    2457           0 : nsGenericHTMLElement::Click(CallerType aCallerType)
    2458             : {
    2459           0 :   if (HandlingClick())
    2460           0 :     return;
    2461             : 
    2462             :   // Strong in case the event kills it
    2463           0 :   nsCOMPtr<nsIDocument> doc = GetComposedDoc();
    2464             : 
    2465           0 :   nsCOMPtr<nsIPresShell> shell;
    2466           0 :   RefPtr<nsPresContext> context;
    2467           0 :   if (doc) {
    2468           0 :     shell = doc->GetShell();
    2469           0 :     if (shell) {
    2470           0 :       context = shell->GetPresContext();
    2471             :     }
    2472             :   }
    2473             : 
    2474           0 :   SetHandlingClick();
    2475             : 
    2476             :   // Mark this event trusted if Click() is called from system code.
    2477             :   WidgetMouseEvent event(aCallerType == CallerType::System,
    2478           0 :                          eMouseClick, nullptr, WidgetMouseEvent::eReal);
    2479           0 :   event.mFlags.mIsPositionless = true;
    2480           0 :   event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
    2481             : 
    2482           0 :   EventDispatcher::Dispatch(static_cast<nsIContent*>(this), context, &event);
    2483             : 
    2484           0 :   ClearHandlingClick();
    2485             : }
    2486             : 
    2487             : bool
    2488           0 : nsGenericHTMLElement::IsHTMLFocusable(bool aWithMouse,
    2489             :                                       bool *aIsFocusable,
    2490             :                                       int32_t *aTabIndex)
    2491             : {
    2492           0 :   nsIDocument* doc = GetComposedDoc();
    2493           0 :   if (!doc || doc->HasFlag(NODE_IS_EDITABLE)) {
    2494             :     // In designMode documents we only allow focusing the document.
    2495           0 :     if (aTabIndex) {
    2496           0 :       *aTabIndex = -1;
    2497             :     }
    2498             : 
    2499           0 :     *aIsFocusable = false;
    2500             : 
    2501           0 :     return true;
    2502             :   }
    2503             : 
    2504           0 :   int32_t tabIndex = TabIndex();
    2505           0 :   bool disabled = false;
    2506           0 :   bool disallowOverridingFocusability = true;
    2507             : 
    2508           0 :   if (IsEditableRoot()) {
    2509             :     // Editable roots should always be focusable.
    2510           0 :     disallowOverridingFocusability = true;
    2511             : 
    2512             :     // Ignore the disabled attribute in editable contentEditable/designMode
    2513             :     // roots.
    2514           0 :     if (!HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
    2515             :       // The default value for tabindex should be 0 for editable
    2516             :       // contentEditable roots.
    2517           0 :       tabIndex = 0;
    2518             :     }
    2519             :   }
    2520             :   else {
    2521           0 :     disallowOverridingFocusability = false;
    2522             : 
    2523             :     // Just check for disabled attribute on form controls
    2524           0 :     disabled = IsDisabled();
    2525           0 :     if (disabled) {
    2526           0 :       tabIndex = -1;
    2527             :     }
    2528             :   }
    2529             : 
    2530           0 :   if (aTabIndex) {
    2531           0 :     *aTabIndex = tabIndex;
    2532             :   }
    2533             : 
    2534             :   // If a tabindex is specified at all, or the default tabindex is 0, we're focusable
    2535           0 :   *aIsFocusable =
    2536           0 :     (tabIndex >= 0 || (!disabled && HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)));
    2537             : 
    2538           0 :   return disallowOverridingFocusability;
    2539             : }
    2540             : 
    2541             : void
    2542           0 : nsGenericHTMLElement::RegUnRegAccessKey(bool aDoReg)
    2543             : {
    2544             :   // first check to see if we have an access key
    2545           0 :   nsAutoString accessKey;
    2546           0 :   GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, accessKey);
    2547           0 :   if (accessKey.IsEmpty()) {
    2548           0 :     return;
    2549             :   }
    2550             : 
    2551             :   // We have an access key, so get the ESM from the pres context.
    2552           0 :   nsPresContext* presContext = GetPresContext(eForUncomposedDoc);
    2553             : 
    2554           0 :   if (presContext) {
    2555           0 :     EventStateManager* esm = presContext->EventStateManager();
    2556             : 
    2557             :     // Register or unregister as appropriate.
    2558           0 :     if (aDoReg) {
    2559           0 :       esm->RegisterAccessKey(this, (uint32_t)accessKey.First());
    2560             :     } else {
    2561           0 :       esm->UnregisterAccessKey(this, (uint32_t)accessKey.First());
    2562             :     }
    2563             :   }
    2564             : }
    2565             : 
    2566             : bool
    2567           0 : nsGenericHTMLElement::PerformAccesskey(bool aKeyCausesActivation,
    2568             :                                        bool aIsTrustedEvent)
    2569             : {
    2570           0 :   nsPresContext* presContext = GetPresContext(eForUncomposedDoc);
    2571           0 :   if (!presContext) {
    2572           0 :     return false;
    2573             :   }
    2574             : 
    2575             :   // It's hard to say what HTML4 wants us to do in all cases.
    2576           0 :   bool focused = true;
    2577           0 :   nsFocusManager* fm = nsFocusManager::GetFocusManager();
    2578           0 :   if (fm) {
    2579           0 :     fm->SetFocus(this, nsIFocusManager::FLAG_BYKEY);
    2580             : 
    2581             :     // Return true if the element became the current focus within its window.
    2582           0 :     nsPIDOMWindowOuter* window = OwnerDoc()->GetWindow();
    2583           0 :     focused = (window && window->GetFocusedNode());
    2584             :   }
    2585             : 
    2586           0 :   if (aKeyCausesActivation) {
    2587             :     // Click on it if the users prefs indicate to do so.
    2588             :     nsAutoPopupStatePusher popupStatePusher(aIsTrustedEvent ?
    2589           0 :                                             openAllowed : openAbused);
    2590           0 :     DispatchSimulatedClick(this, aIsTrustedEvent, presContext);
    2591             :   }
    2592             : 
    2593           0 :   return focused;
    2594             : }
    2595             : 
    2596             : nsresult
    2597           0 : nsGenericHTMLElement::DispatchSimulatedClick(nsGenericHTMLElement* aElement,
    2598             :                                              bool aIsTrusted,
    2599             :                                              nsPresContext* aPresContext)
    2600             : {
    2601             :   WidgetMouseEvent event(aIsTrusted, eMouseClick, nullptr,
    2602           0 :                          WidgetMouseEvent::eReal);
    2603           0 :   event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD;
    2604           0 :   event.mFlags.mIsPositionless = true;
    2605           0 :   return EventDispatcher::Dispatch(ToSupports(aElement), aPresContext, &event);
    2606             : }
    2607             : 
    2608             : already_AddRefed<nsIEditor>
    2609           0 : nsGenericHTMLElement::GetAssociatedEditor()
    2610             : {
    2611             :   // If contenteditable is ever implemented, it might need to do something different here?
    2612             : 
    2613           0 :   RefPtr<TextEditor> textEditor = GetTextEditorInternal();
    2614           0 :   return textEditor.forget();
    2615             : }
    2616             : 
    2617             : bool
    2618           0 : nsGenericHTMLElement::IsCurrentBodyElement()
    2619             : {
    2620             :   // TODO Bug 698498: Should this handle the case where GetBody returns a
    2621             :   //                  frameset?
    2622           0 :   if (!IsHTMLElement(nsGkAtoms::body)) {
    2623           0 :     return false;
    2624             :   }
    2625             : 
    2626             :   nsCOMPtr<nsIDOMHTMLDocument> htmlDocument =
    2627           0 :     do_QueryInterface(GetUncomposedDoc());
    2628           0 :   if (!htmlDocument) {
    2629           0 :     return false;
    2630             :   }
    2631             : 
    2632           0 :   nsCOMPtr<nsIDOMHTMLElement> htmlElement;
    2633           0 :   htmlDocument->GetBody(getter_AddRefs(htmlElement));
    2634           0 :   return htmlElement == static_cast<HTMLBodyElement*>(this);
    2635             : }
    2636             : 
    2637             : // static
    2638             : void
    2639           0 : nsGenericHTMLElement::SyncEditorsOnSubtree(nsIContent* content)
    2640             : {
    2641             :   /* Sync this node */
    2642           0 :   nsGenericHTMLElement* element = FromContent(content);
    2643           0 :   if (element) {
    2644           0 :     nsCOMPtr<nsIEditor> editor = element->GetAssociatedEditor();
    2645           0 :     if (editor) {
    2646           0 :       editor->SyncRealTimeSpell();
    2647             :     }
    2648             :   }
    2649             : 
    2650             :   /* Sync all children */
    2651           0 :   for (nsIContent* child = content->GetFirstChild();
    2652           0 :        child;
    2653           0 :        child = child->GetNextSibling()) {
    2654           0 :     SyncEditorsOnSubtree(child);
    2655             :   }
    2656           0 : }
    2657             : 
    2658             : void
    2659           0 : nsGenericHTMLElement::RecompileScriptEventListeners()
    2660             : {
    2661           0 :     int32_t i, count = mAttrsAndChildren.AttrCount();
    2662           0 :     for (i = 0; i < count; ++i) {
    2663           0 :         const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
    2664             : 
    2665             :         // Eventlistenener-attributes are always in the null namespace
    2666           0 :         if (!name->IsAtom()) {
    2667           0 :             continue;
    2668             :         }
    2669             : 
    2670           0 :         nsIAtom *attr = name->Atom();
    2671           0 :         if (!IsEventAttributeName(attr)) {
    2672           0 :             continue;
    2673             :         }
    2674             : 
    2675           0 :         nsAutoString value;
    2676           0 :         GetAttr(kNameSpaceID_None, attr, value);
    2677           0 :         SetEventHandler(attr, value, true);
    2678             :     }
    2679           0 : }
    2680             : 
    2681             : bool
    2682           0 : nsGenericHTMLElement::IsEditableRoot() const
    2683             : {
    2684           0 :   nsIDocument *document = GetComposedDoc();
    2685           0 :   if (!document) {
    2686           0 :     return false;
    2687             :   }
    2688             : 
    2689           0 :   if (document->HasFlag(NODE_IS_EDITABLE)) {
    2690           0 :     return false;
    2691             :   }
    2692             : 
    2693           0 :   if (GetContentEditableValue() != eTrue) {
    2694           0 :     return false;
    2695             :   }
    2696             : 
    2697           0 :   nsIContent *parent = GetParent();
    2698             : 
    2699           0 :   return !parent || !parent->HasFlag(NODE_IS_EDITABLE);
    2700             : }
    2701             : 
    2702             : static void
    2703           0 : MakeContentDescendantsEditable(nsIContent *aContent, nsIDocument *aDocument)
    2704             : {
    2705             :   // If aContent is not an element, we just need to update its
    2706             :   // internal editable state and don't need to notify anyone about
    2707             :   // that.  For elements, we need to send a ContentStateChanged
    2708             :   // notification.
    2709           0 :   if (!aContent->IsElement()) {
    2710           0 :     aContent->UpdateEditableState(false);
    2711           0 :     return;
    2712             :   }
    2713             : 
    2714           0 :   Element *element = aContent->AsElement();
    2715             : 
    2716           0 :   element->UpdateEditableState(true);
    2717             : 
    2718           0 :   for (nsIContent *child = aContent->GetFirstChild();
    2719           0 :        child;
    2720           0 :        child = child->GetNextSibling()) {
    2721           0 :     if (!child->HasAttr(kNameSpaceID_None, nsGkAtoms::contenteditable)) {
    2722           0 :       MakeContentDescendantsEditable(child, aDocument);
    2723             :     }
    2724             :   }
    2725             : }
    2726             : 
    2727             : void
    2728           0 : nsGenericHTMLElement::ChangeEditableState(int32_t aChange)
    2729             : {
    2730             :   //XXXsmaug Fix this for Shadow DOM, bug 1066965.
    2731           0 :   nsIDocument* document = GetUncomposedDoc();
    2732           0 :   if (!document) {
    2733           0 :     return;
    2734             :   }
    2735             : 
    2736           0 :   if (aChange != 0) {
    2737             :     nsCOMPtr<nsIHTMLDocument> htmlDocument =
    2738           0 :       do_QueryInterface(document);
    2739           0 :     if (htmlDocument) {
    2740           0 :       htmlDocument->ChangeContentEditableCount(this, aChange);
    2741             :     }
    2742             : 
    2743           0 :     nsIContent* parent = GetParent();
    2744           0 :     while (parent) {
    2745           0 :       parent->ChangeEditableDescendantCount(aChange);
    2746           0 :       parent = parent->GetParent();
    2747             :     }
    2748             :   }
    2749             : 
    2750           0 :   if (document->HasFlag(NODE_IS_EDITABLE)) {
    2751           0 :     document = nullptr;
    2752             :   }
    2753             : 
    2754             :   // MakeContentDescendantsEditable is going to call ContentStateChanged for
    2755             :   // this element and all descendants if editable state has changed.
    2756             :   // We might as well wrap it all in one script blocker.
    2757           0 :   nsAutoScriptBlocker scriptBlocker;
    2758           0 :   MakeContentDescendantsEditable(this, document);
    2759             : }
    2760             : 
    2761             : 
    2762             : //----------------------------------------------------------------------
    2763             : 
    2764           9 : nsGenericHTMLFormElementWithState::nsGenericHTMLFormElementWithState(
    2765             :     already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo, uint8_t aType
    2766           9 :   )
    2767           9 :   : nsGenericHTMLFormElement(aNodeInfo, aType)
    2768             : {
    2769           9 :   mStateKey.SetIsVoid(true);
    2770           9 : }
    2771             : 
    2772             : nsresult
    2773           2 : nsGenericHTMLFormElementWithState::GenerateStateKey()
    2774             : {
    2775             :   // Keep the key if already computed
    2776           2 :   if (!mStateKey.IsVoid()) {
    2777           0 :     return NS_OK;
    2778             :   }
    2779             : 
    2780           2 :   nsIDocument* doc = GetUncomposedDoc();
    2781           2 :   if (!doc) {
    2782           2 :     return NS_OK;
    2783             :   }
    2784             : 
    2785             :   // Generate the state key
    2786           0 :   nsresult rv = nsContentUtils::GenerateStateKey(this, doc, mStateKey);
    2787             : 
    2788           0 :   if (NS_FAILED(rv)) {
    2789           0 :     mStateKey.SetIsVoid(true);
    2790           0 :     return rv;
    2791             :   }
    2792             : 
    2793             :   // If the state key is blank, this is anonymous content or for whatever
    2794             :   // reason we are not supposed to save/restore state: keep it as such.
    2795           0 :   if (!mStateKey.IsEmpty()) {
    2796             :     // Add something unique to content so layout doesn't muck us up.
    2797           0 :     mStateKey += "-C";
    2798             :   }
    2799           0 :   return NS_OK;
    2800             : }
    2801             : 
    2802             : nsPresState*
    2803           0 : nsGenericHTMLFormElementWithState::GetPrimaryPresState()
    2804             : {
    2805           0 :   if (mStateKey.IsEmpty()) {
    2806           0 :     return nullptr;
    2807             :   }
    2808             : 
    2809           0 :   nsCOMPtr<nsILayoutHistoryState> history = GetLayoutHistory(false);
    2810             : 
    2811           0 :   if (!history) {
    2812           0 :     return nullptr;
    2813             :   }
    2814             : 
    2815             :   // Get the pres state for this key, if it doesn't exist, create one.
    2816           0 :   nsPresState* result = history->GetState(mStateKey);
    2817           0 :   if (!result) {
    2818           0 :     result = new nsPresState();
    2819           0 :     history->AddState(mStateKey, result);
    2820             :   }
    2821             : 
    2822           0 :   return result;
    2823             : }
    2824             : 
    2825             : already_AddRefed<nsILayoutHistoryState>
    2826           0 : nsGenericHTMLFormElementWithState::GetLayoutHistory(bool aRead)
    2827             : {
    2828           0 :   nsCOMPtr<nsIDocument> doc = GetUncomposedDoc();
    2829           0 :   if (!doc) {
    2830           0 :     return nullptr;
    2831             :   }
    2832             : 
    2833             :   //
    2834             :   // Get the history
    2835             :   //
    2836           0 :   nsCOMPtr<nsILayoutHistoryState> history = doc->GetLayoutHistoryState();
    2837           0 :   if (!history) {
    2838           0 :     return nullptr;
    2839             :   }
    2840             : 
    2841           0 :   if (aRead && !history->HasStates()) {
    2842           0 :     return nullptr;
    2843             :   }
    2844             : 
    2845           0 :   return history.forget();
    2846             : }
    2847             : 
    2848             : bool
    2849           2 : nsGenericHTMLFormElementWithState::RestoreFormControlState()
    2850             : {
    2851           2 :   if (mStateKey.IsEmpty()) {
    2852           2 :     return false;
    2853             :   }
    2854             : 
    2855             :   nsCOMPtr<nsILayoutHistoryState> history =
    2856           0 :     GetLayoutHistory(true);
    2857           0 :   if (!history) {
    2858           0 :     return false;
    2859             :   }
    2860             : 
    2861             :   nsPresState *state;
    2862             :   // Get the pres state for this key
    2863           0 :   state = history->GetState(mStateKey);
    2864           0 :   if (state) {
    2865           0 :     bool result = RestoreState(state);
    2866           0 :     history->RemoveState(mStateKey);
    2867           0 :     return result;
    2868             :   }
    2869             : 
    2870           0 :   return false;
    2871             : }
    2872             : 
    2873             : void
    2874           0 : nsGenericHTMLFormElementWithState::NodeInfoChanged(nsIDocument* aOldDoc)
    2875             : {
    2876           0 :   nsGenericHTMLElement::NodeInfoChanged(aOldDoc);
    2877           0 :   mStateKey.SetIsVoid(true);
    2878           0 : }
    2879             : 
    2880             : nsSize
    2881           0 : nsGenericHTMLElement::GetWidthHeightForImage(RefPtr<imgRequestProxy>& aImageRequest)
    2882             : {
    2883           0 :   nsSize size(0,0);
    2884             : 
    2885           0 :   nsIFrame* frame = GetPrimaryFrame(FlushType::Layout);
    2886             : 
    2887           0 :   if (frame) {
    2888           0 :     size = frame->GetContentRect().Size();
    2889             : 
    2890           0 :     size.width = nsPresContext::AppUnitsToIntCSSPixels(size.width);
    2891           0 :     size.height = nsPresContext::AppUnitsToIntCSSPixels(size.height);
    2892             :   } else {
    2893             :     const nsAttrValue* value;
    2894           0 :     nsCOMPtr<imgIContainer> image;
    2895           0 :     if (aImageRequest) {
    2896           0 :       aImageRequest->GetImage(getter_AddRefs(image));
    2897             :     }
    2898             : 
    2899           0 :     if ((value = GetParsedAttr(nsGkAtoms::width)) &&
    2900           0 :         value->Type() == nsAttrValue::eInteger) {
    2901           0 :       size.width = value->GetIntegerValue();
    2902           0 :     } else if (image) {
    2903           0 :       image->GetWidth(&size.width);
    2904             :     }
    2905             : 
    2906           0 :     if ((value = GetParsedAttr(nsGkAtoms::height)) &&
    2907           0 :         value->Type() == nsAttrValue::eInteger) {
    2908           0 :       size.height = value->GetIntegerValue();
    2909           0 :     } else if (image) {
    2910           0 :       image->GetHeight(&size.height);
    2911             :     }
    2912             :   }
    2913             : 
    2914           0 :   NS_ASSERTION(size.width >= 0, "negative width");
    2915           0 :   NS_ASSERTION(size.height >= 0, "negative height");
    2916           0 :   return size;
    2917             : }
    2918             : 
    2919             : bool
    2920           1 : nsGenericHTMLElement::IsEventAttributeNameInternal(nsIAtom *aName)
    2921             : {
    2922           1 :   return nsContentUtils::IsEventAttributeName(aName, EventNameType_HTML);
    2923             : }
    2924             : 
    2925             : /**
    2926             :  * Construct a URI from a string, as an element.src attribute
    2927             :  * would be set to. Helper for the media elements.
    2928             :  */
    2929             : nsresult
    2930           0 : nsGenericHTMLElement::NewURIFromString(const nsAString& aURISpec,
    2931             :                                        nsIURI** aURI)
    2932             : {
    2933           0 :   NS_ENSURE_ARG_POINTER(aURI);
    2934             : 
    2935           0 :   *aURI = nullptr;
    2936             : 
    2937           0 :   nsCOMPtr<nsIDocument> doc = OwnerDoc();
    2938             : 
    2939           0 :   nsCOMPtr<nsIURI> baseURI = GetBaseURI();
    2940           0 :   nsresult rv = nsContentUtils::NewURIWithDocumentCharset(aURI, aURISpec,
    2941           0 :                                                           doc, baseURI);
    2942           0 :   NS_ENSURE_SUCCESS(rv, rv);
    2943             : 
    2944             :   bool equal;
    2945           0 :   if (aURISpec.IsEmpty() &&
    2946           0 :       doc->GetDocumentURI() &&
    2947           0 :       NS_SUCCEEDED(doc->GetDocumentURI()->Equals(*aURI, &equal)) &&
    2948             :       equal) {
    2949             :     // Assume an element can't point to a fragment of its embedding
    2950             :     // document. Fail here instead of returning the recursive URI
    2951             :     // and waiting for the subsequent load to fail.
    2952           0 :     NS_RELEASE(*aURI);
    2953           0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
    2954             :   }
    2955             : 
    2956           0 :   return NS_OK;
    2957             : }
    2958             : 
    2959             : static bool
    2960           0 : IsOrHasAncestorWithDisplayNone(Element* aElement, nsIPresShell* aPresShell)
    2961             : {
    2962           0 :   nsTArray<Element*> elementsToCheck;
    2963           0 :   for (Element* e = aElement; e; e = e->GetParentElement()) {
    2964           0 :     if (e->GetPrimaryFrame()) {
    2965             :       // e definitely isn't display:none and doesn't have a display:none
    2966             :       // ancestor.
    2967           0 :       break;
    2968             :     }
    2969           0 :     elementsToCheck.AppendElement(e);
    2970             :   }
    2971             : 
    2972           0 :   if (elementsToCheck.IsEmpty()) {
    2973           0 :     return false;
    2974             :   }
    2975             : 
    2976             :   // XXXbholley: This could be done more directly with Servo's style system.
    2977           0 :   StyleSetHandle styleSet = aPresShell->StyleSet();
    2978           0 :   RefPtr<nsStyleContext> sc;
    2979           0 :   for (int32_t i = elementsToCheck.Length() - 1; i >= 0; --i) {
    2980           0 :     if (sc) {
    2981           0 :       sc = styleSet->ResolveStyleFor(elementsToCheck[i], sc, LazyComputeBehavior::Assert);
    2982             :     } else {
    2983           0 :       sc = nsComputedDOMStyle::GetStyleContextNoFlush(elementsToCheck[i],
    2984           0 :                                                       nullptr, aPresShell);
    2985             :     }
    2986           0 :     if (sc->StyleDisplay()->mDisplay == StyleDisplay::None) {
    2987           0 :       return true;
    2988             :     }
    2989             :   }
    2990             : 
    2991           0 :   return false;
    2992             : }
    2993             : 
    2994             : void
    2995           0 : nsGenericHTMLElement::GetInnerText(mozilla::dom::DOMString& aValue,
    2996             :                                    mozilla::ErrorResult& aError)
    2997             : {
    2998           0 :   if (!GetPrimaryFrame(FlushType::Layout)) {
    2999           0 :     nsIPresShell* presShell = nsComputedDOMStyle::GetPresShellForContent(this);
    3000           0 :     if (!presShell || IsOrHasAncestorWithDisplayNone(this, presShell)) {
    3001           0 :       GetTextContentInternal(aValue, aError);
    3002           0 :       return;
    3003             :     }
    3004             :   }
    3005             : 
    3006           0 :   nsRange::GetInnerTextNoFlush(aValue, aError, this, 0, this, GetChildCount());
    3007             : }
    3008             : 
    3009             : void
    3010           0 : nsGenericHTMLElement::SetInnerText(const nsAString& aValue)
    3011             : {
    3012             :   // Batch possible DOMSubtreeModified events.
    3013           0 :   mozAutoSubtreeModified subtree(OwnerDoc(), nullptr);
    3014           0 :   FireNodeRemovedForChildren();
    3015             : 
    3016             :   // Might as well stick a batch around this since we're performing several
    3017             :   // mutations.
    3018             :   mozAutoDocUpdate updateBatch(GetComposedDoc(),
    3019           0 :     UPDATE_CONTENT_MODEL, true);
    3020           0 :   nsAutoMutationBatch mb;
    3021             : 
    3022           0 :   uint32_t childCount = GetChildCount();
    3023             : 
    3024           0 :   mb.Init(this, true, false);
    3025           0 :   for (uint32_t i = 0; i < childCount; ++i) {
    3026           0 :     RemoveChildAt(0, true);
    3027             :   }
    3028           0 :   mb.RemovalDone();
    3029             : 
    3030           0 :   nsString str;
    3031           0 :   const char16_t* s = aValue.BeginReading();
    3032           0 :   const char16_t* end = aValue.EndReading();
    3033             :   while (true) {
    3034           0 :     if (s != end && *s == '\r' && s + 1 != end && s[1] == '\n') {
    3035             :       // a \r\n pair should only generate one <br>, so just skip the \r
    3036           0 :       ++s;
    3037             :     }
    3038           0 :     if (s == end || *s == '\r' || *s == '\n') {
    3039           0 :       if (!str.IsEmpty()) {
    3040             :         RefPtr<nsTextNode> textContent =
    3041           0 :           new nsTextNode(NodeInfo()->NodeInfoManager());
    3042           0 :         textContent->SetText(str, true);
    3043           0 :         AppendChildTo(textContent, true);
    3044             :       }
    3045           0 :       if (s == end) {
    3046           0 :         break;
    3047             :       }
    3048           0 :       str.Truncate();
    3049             :       already_AddRefed<mozilla::dom::NodeInfo> ni =
    3050             :         NodeInfo()->NodeInfoManager()->GetNodeInfo(nsGkAtoms::br,
    3051           0 :           nullptr, kNameSpaceID_XHTML, nsIDOMNode::ELEMENT_NODE);
    3052           0 :       RefPtr<HTMLBRElement> br = new HTMLBRElement(ni);
    3053           0 :       AppendChildTo(br, true);
    3054             :     } else {
    3055           0 :       str.Append(*s);
    3056             :     }
    3057           0 :     ++s;
    3058           0 :   }
    3059             : 
    3060           0 :   mb.NodesAdded();
    3061           0 : }

Generated by: LCOV version 1.13