LCOV - code coverage report
Current view: top level - parser/html - nsHtml5TreeOperation.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 190 524 36.3 %
Date: 2017-07-14 16:53:18 Functions: 14 28 50.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=2 sw=2 et tw=78: */
       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 "nsHtml5TreeOperation.h"
       8             : #include "nsContentUtils.h"
       9             : #include "nsDocElementCreatedNotificationRunner.h"
      10             : #include "nsNodeUtils.h"
      11             : #include "nsAttrName.h"
      12             : #include "nsHtml5TreeBuilder.h"
      13             : #include "nsIDOMMutationEvent.h"
      14             : #include "mozAutoDocUpdate.h"
      15             : #include "nsBindingManager.h"
      16             : #include "nsXBLBinding.h"
      17             : #include "nsHtml5DocumentMode.h"
      18             : #include "nsHtml5HtmlAttributes.h"
      19             : #include "nsContentCreatorFunctions.h"
      20             : #include "nsIScriptElement.h"
      21             : #include "nsIDTD.h"
      22             : #include "nsISupportsImpl.h"
      23             : #include "nsIDOMHTMLFormElement.h"
      24             : #include "nsIFormControl.h"
      25             : #include "nsIStyleSheetLinkingElement.h"
      26             : #include "nsIDOMDocumentType.h"
      27             : #include "nsIObserverService.h"
      28             : #include "mozilla/Services.h"
      29             : #include "nsIMutationObserver.h"
      30             : #include "nsIFormProcessor.h"
      31             : #include "nsIServiceManager.h"
      32             : #include "nsEscape.h"
      33             : #include "mozilla/dom/Comment.h"
      34             : #include "mozilla/dom/Element.h"
      35             : #include "mozilla/dom/HTMLImageElement.h"
      36             : #include "mozilla/dom/HTMLTemplateElement.h"
      37             : #include "nsHtml5SVGLoadDispatcher.h"
      38             : #include "nsIURI.h"
      39             : #include "nsIProtocolHandler.h"
      40             : #include "nsNetUtil.h"
      41             : #include "nsIHTMLDocument.h"
      42             : #include "mozilla/Likely.h"
      43             : #include "nsTextNode.h"
      44             : 
      45             : using namespace mozilla;
      46             : 
      47             : static NS_DEFINE_CID(kFormProcessorCID, NS_FORMPROCESSOR_CID);
      48             : 
      49             : /**
      50             :  * Helper class that opens a notification batch if the current doc
      51             :  * is different from the executor doc.
      52             :  */
      53             : class MOZ_STACK_CLASS nsHtml5OtherDocUpdate {
      54             :   public:
      55          27 :     nsHtml5OtherDocUpdate(nsIDocument* aCurrentDoc, nsIDocument* aExecutorDoc)
      56          27 :     {
      57          27 :       NS_PRECONDITION(aCurrentDoc, "Node has no doc?");
      58          27 :       NS_PRECONDITION(aExecutorDoc, "Executor has no doc?");
      59          27 :       if (MOZ_LIKELY(aCurrentDoc == aExecutorDoc)) {
      60          27 :         mDocument = nullptr;
      61             :       } else {
      62           0 :         mDocument = aCurrentDoc;
      63           0 :         aCurrentDoc->BeginUpdate(UPDATE_CONTENT_MODEL);        
      64             :       }
      65          27 :     }
      66             : 
      67          27 :     ~nsHtml5OtherDocUpdate()
      68          27 :     {
      69          27 :       if (MOZ_UNLIKELY(mDocument)) {
      70           0 :         mDocument->EndUpdate(UPDATE_CONTENT_MODEL);
      71             :       }
      72          27 :     }
      73             :   private:
      74             :     nsCOMPtr<nsIDocument> mDocument;
      75             : };
      76             : 
      77          67 : nsHtml5TreeOperation::nsHtml5TreeOperation()
      78          67 :  : mOpCode(eTreeOpUninitialized)
      79             : {
      80          67 :   MOZ_COUNT_CTOR(nsHtml5TreeOperation);
      81          67 : }
      82             : 
      83         134 : nsHtml5TreeOperation::~nsHtml5TreeOperation()
      84             : {
      85          67 :   MOZ_COUNT_DTOR(nsHtml5TreeOperation);
      86          67 :   NS_ASSERTION(mOpCode != eTreeOpUninitialized, "Uninitialized tree op.");
      87          67 :   switch(mOpCode) {
      88             :     case eTreeOpAddAttributes:
      89           0 :       delete mTwo.attributes;
      90           0 :       break;
      91             :     case eTreeOpCreateElementNetwork:
      92             :     case eTreeOpCreateElementNotNetwork:
      93          14 :       delete mThree.attributes;
      94          14 :       break;
      95             :     case eTreeOpAppendDoctypeToDocument:
      96           1 :       delete mTwo.stringPair;
      97           1 :       break;
      98             :     case eTreeOpFosterParentText:
      99             :     case eTreeOpAppendText:
     100             :     case eTreeOpAppendComment:
     101             :     case eTreeOpAppendCommentToDocument:
     102             :     case eTreeOpAddViewSourceHref:
     103             :     case eTreeOpAddViewSourceBase:
     104          17 :       delete[] mTwo.unicharPtr;
     105          17 :       break;
     106             :     case eTreeOpSetDocumentCharset:
     107             :     case eTreeOpNeedsCharsetSwitchTo:
     108           0 :       break;
     109             :     case eTreeOpProcessOfflineManifest:
     110           0 :       free(mOne.unicharPtr);
     111           0 :       break;
     112             :     default: // keep the compiler happy
     113          35 :       break;
     114             :   }
     115          67 : }
     116             : 
     117             : nsresult
     118           1 : nsHtml5TreeOperation::AppendTextToTextNode(const char16_t* aBuffer,
     119             :                                            uint32_t aLength,
     120             :                                            nsIContent* aTextNode,
     121             :                                            nsHtml5DocumentBuilder* aBuilder)
     122             : {
     123           1 :   NS_PRECONDITION(aTextNode, "Got null text node.");
     124           1 :   MOZ_ASSERT(aBuilder);
     125           1 :   MOZ_ASSERT(aBuilder->IsInDocUpdate());
     126           1 :   uint32_t oldLength = aTextNode->TextLength();
     127             :   CharacterDataChangeInfo info = {
     128             :     true,
     129             :     oldLength,
     130             :     oldLength,
     131             :     aLength
     132           1 :   };
     133           1 :   nsNodeUtils::CharacterDataWillChange(aTextNode, &info);
     134             : 
     135           1 :   nsresult rv = aTextNode->AppendText(aBuffer, aLength, false);
     136           1 :   NS_ENSURE_SUCCESS(rv, rv);
     137             : 
     138           1 :   nsNodeUtils::CharacterDataChanged(aTextNode, &info);
     139           1 :   return rv;
     140             : }
     141             : 
     142             : 
     143             : nsresult
     144          12 : nsHtml5TreeOperation::AppendText(const char16_t* aBuffer,
     145             :                                  uint32_t aLength,
     146             :                                  nsIContent* aParent,
     147             :                                  nsHtml5DocumentBuilder* aBuilder)
     148             : {
     149          12 :   nsresult rv = NS_OK;
     150          12 :   nsIContent* lastChild = aParent->GetLastChild();
     151          12 :   if (lastChild && lastChild->IsNodeOfType(nsINode::eTEXT)) {
     152             :     nsHtml5OtherDocUpdate update(aParent->OwnerDoc(),
     153           2 :                                  aBuilder->GetDocument());
     154             :     return AppendTextToTextNode(aBuffer, 
     155             :                                 aLength, 
     156             :                                 lastChild, 
     157           1 :                                 aBuilder);
     158             :   }
     159             : 
     160          11 :   nsNodeInfoManager* nodeInfoManager = aParent->OwnerDoc()->NodeInfoManager();
     161          22 :   RefPtr<nsTextNode> text = new nsTextNode(nodeInfoManager);
     162          11 :   NS_ASSERTION(text, "Infallible malloc failed?");
     163          11 :   rv = text->SetText(aBuffer, aLength, false);
     164          11 :   NS_ENSURE_SUCCESS(rv, rv);
     165             : 
     166          11 :   return Append(text, aParent, aBuilder);
     167             : }
     168             : 
     169             : nsresult
     170          26 : nsHtml5TreeOperation::Append(nsIContent* aNode,
     171             :                              nsIContent* aParent,
     172             :                              nsHtml5DocumentBuilder* aBuilder)
     173             : {
     174          26 :   MOZ_ASSERT(aBuilder);
     175          26 :   MOZ_ASSERT(aBuilder->IsInDocUpdate());
     176          26 :   nsresult rv = NS_OK;
     177             :   nsHtml5OtherDocUpdate update(aParent->OwnerDoc(),
     178          52 :                                aBuilder->GetDocument());
     179          26 :   uint32_t childCount = aParent->GetChildCount();
     180          26 :   rv = aParent->AppendChildTo(aNode, false);
     181          26 :   if (NS_SUCCEEDED(rv)) {
     182          26 :     aNode->SetParserHasNotified();
     183          26 :     nsNodeUtils::ContentAppended(aParent, aNode, childCount);
     184             :   }
     185          52 :   return rv;
     186             : }
     187             : 
     188             : nsresult
     189           5 : nsHtml5TreeOperation::AppendToDocument(nsIContent* aNode,
     190             :                                        nsHtml5DocumentBuilder* aBuilder)
     191             : {
     192           5 :   MOZ_ASSERT(aBuilder);
     193           5 :   MOZ_ASSERT(aBuilder->GetDocument() == aNode->OwnerDoc());
     194           5 :   MOZ_ASSERT(aBuilder->IsInDocUpdate());
     195           5 :   nsresult rv = NS_OK;
     196             : 
     197           5 :   nsIDocument* doc = aBuilder->GetDocument();
     198           5 :   uint32_t childCount = doc->GetChildCount();
     199           5 :   rv = doc->AppendChildTo(aNode, false);
     200           5 :   if (rv == NS_ERROR_DOM_HIERARCHY_REQUEST_ERR) {
     201           0 :     aNode->SetParserHasNotified();
     202           0 :     return NS_OK;
     203             :   }
     204           5 :   NS_ENSURE_SUCCESS(rv, rv);
     205           5 :   aNode->SetParserHasNotified();
     206           5 :   nsNodeUtils::ContentInserted(doc, aNode, childCount);
     207             : 
     208           5 :   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
     209             :                "Someone forgot to block scripts");
     210           5 :   if (aNode->IsElement()) {
     211             :     nsContentUtils::AddScriptRunner(
     212           2 :         new nsDocElementCreatedNotificationRunner(doc));
     213             :   }
     214           5 :   return rv;
     215             : }
     216             : 
     217             : static bool
     218           0 : IsElementOrTemplateContent(nsINode* aNode) {
     219           0 :   if (aNode) {
     220           0 :     if (aNode->IsElement()) {
     221           0 :       return true;
     222           0 :     } else if (aNode->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
     223             :       // Check if the node is a template content.
     224             :       mozilla::dom::DocumentFragment* frag =
     225           0 :         static_cast<mozilla::dom::DocumentFragment*>(aNode);
     226           0 :       nsIContent* fragHost = frag->GetHost();
     227           0 :       if (fragHost && nsNodeUtils::IsTemplateElement(fragHost)) {
     228           0 :         return true;
     229             :       }
     230             :     }
     231             :   }
     232           0 :   return false;
     233             : }
     234             : 
     235             : void
     236           0 : nsHtml5TreeOperation::Detach(nsIContent* aNode, nsHtml5DocumentBuilder* aBuilder)
     237             : {
     238           0 :   MOZ_ASSERT(aBuilder);
     239           0 :   MOZ_ASSERT(aBuilder->IsInDocUpdate());
     240           0 :   nsCOMPtr<nsINode> parent = aNode->GetParentNode();
     241           0 :   if (parent) {
     242             :     nsHtml5OtherDocUpdate update(parent->OwnerDoc(),
     243           0 :         aBuilder->GetDocument());
     244           0 :     int32_t pos = parent->IndexOf(aNode);
     245           0 :     NS_ASSERTION((pos >= 0), "Element not found as child of its parent");
     246           0 :     parent->RemoveChildAt(pos, true);
     247             :   }
     248           0 : }
     249             : 
     250             : nsresult
     251           0 : nsHtml5TreeOperation::AppendChildrenToNewParent(nsIContent* aNode,
     252             :                                                 nsIContent* aParent,
     253             :                                                 nsHtml5DocumentBuilder* aBuilder)
     254             : {
     255           0 :   MOZ_ASSERT(aBuilder);
     256           0 :   MOZ_ASSERT(aBuilder->IsInDocUpdate());
     257             :   nsHtml5OtherDocUpdate update(aParent->OwnerDoc(),
     258           0 :                                aBuilder->GetDocument());
     259             : 
     260           0 :   uint32_t childCount = aParent->GetChildCount();
     261           0 :   bool didAppend = false;
     262           0 :   while (aNode->HasChildren()) {
     263           0 :     nsCOMPtr<nsIContent> child = aNode->GetFirstChild();
     264           0 :     aNode->RemoveChildAt(0, true);
     265           0 :     nsresult rv = aParent->AppendChildTo(child, false);
     266           0 :     NS_ENSURE_SUCCESS(rv, rv);
     267           0 :     didAppend = true;
     268             :   }
     269           0 :   if (didAppend) {
     270           0 :     nsNodeUtils::ContentAppended(aParent, aParent->GetChildAt(childCount),
     271           0 :                                  childCount);
     272             :   }
     273           0 :   return NS_OK;
     274             : }
     275             : 
     276             : nsresult
     277           0 : nsHtml5TreeOperation::FosterParent(nsIContent* aNode,
     278             :                                    nsIContent* aParent,
     279             :                                    nsIContent* aTable,
     280             :                                    nsHtml5DocumentBuilder* aBuilder)
     281             : {
     282           0 :   MOZ_ASSERT(aBuilder);
     283           0 :   MOZ_ASSERT(aBuilder->IsInDocUpdate());
     284           0 :   nsIContent* foster = aTable->GetParent();
     285             : 
     286           0 :   if (IsElementOrTemplateContent(foster)) {
     287             : 
     288             :     nsHtml5OtherDocUpdate update(foster->OwnerDoc(),
     289           0 :                                  aBuilder->GetDocument());
     290             : 
     291           0 :     uint32_t pos = foster->IndexOf(aTable);
     292           0 :     nsresult rv = foster->InsertChildAt(aNode, pos, false);
     293           0 :     NS_ENSURE_SUCCESS(rv, rv);
     294           0 :     nsNodeUtils::ContentInserted(foster, aNode, pos);
     295           0 :     return rv;
     296             :   }
     297             : 
     298           0 :   return Append(aNode, aParent, aBuilder);
     299             : }
     300             : 
     301             : nsresult
     302           0 : nsHtml5TreeOperation::AddAttributes(nsIContent* aNode,
     303             :                                     nsHtml5HtmlAttributes* aAttributes,
     304             :                                     nsHtml5DocumentBuilder* aBuilder)
     305             : {
     306           0 :   dom::Element* node = aNode->AsElement();
     307             :   nsHtml5OtherDocUpdate update(node->OwnerDoc(),
     308           0 :                                aBuilder->GetDocument());
     309             : 
     310           0 :   int32_t len = aAttributes->getLength();
     311           0 :   for (int32_t i = len; i > 0;) {
     312           0 :     --i;
     313             :     // prefix doesn't need regetting. it is always null or a static atom
     314             :     // local name is never null
     315             :     nsCOMPtr<nsIAtom> localName =
     316           0 :       Reget(aAttributes->getLocalNameNoBoundsCheck(i));
     317           0 :     int32_t nsuri = aAttributes->getURINoBoundsCheck(i);
     318           0 :     if (!node->HasAttr(nsuri, localName)) {
     319             :       // prefix doesn't need regetting. it is always null or a static atom
     320             :       // local name is never null
     321           0 :       nsString value; // Not Auto, because using it to hold nsStringBuffer*
     322           0 :       aAttributes->getValueNoBoundsCheck(i).ToString(value);
     323           0 :       node->SetAttr(
     324           0 :         nsuri, localName, aAttributes->getPrefixNoBoundsCheck(i), value, true);
     325             :       // XXX what to do with nsresult?
     326             :     }
     327             :   }
     328           0 :   return NS_OK;
     329             : }
     330             : 
     331             : 
     332             : nsIContent*
     333          14 : nsHtml5TreeOperation::CreateElement(int32_t aNs,
     334             :                                     nsIAtom* aName,
     335             :                                     nsHtml5HtmlAttributes* aAttributes,
     336             :                                     mozilla::dom::FromParser aFromParser,
     337             :                                     nsNodeInfoManager* aNodeInfoManager,
     338             :                                     nsHtml5DocumentBuilder* aBuilder)
     339             : {
     340          14 :   bool isKeygen = (aName == nsGkAtoms::keygen && aNs == kNameSpaceID_XHTML);
     341          14 :   if (MOZ_UNLIKELY(isKeygen)) {
     342           0 :     aName = nsGkAtoms::select;
     343             :   }
     344             : 
     345          28 :   nsCOMPtr<dom::Element> newElement;
     346             :   RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->
     347          28 :     GetNodeInfo(aName, nullptr, aNs, nsIDOMNode::ELEMENT_NODE);
     348          14 :   NS_ASSERTION(nodeInfo, "Got null nodeinfo.");
     349          28 :   NS_NewElement(getter_AddRefs(newElement),
     350          28 :                 nodeInfo.forget(),
     351          14 :                 aFromParser);
     352          14 :   NS_ASSERTION(newElement, "Element creation created null pointer.");
     353             : 
     354          14 :   dom::Element* newContent = newElement;
     355          14 :   aBuilder->HoldElement(newElement.forget());
     356             : 
     357          14 :   if (MOZ_UNLIKELY(aName == nsGkAtoms::style || aName == nsGkAtoms::link)) {
     358           0 :     nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(newContent));
     359           0 :     if (ssle) {
     360           0 :       ssle->InitStyleLinkElement(false);
     361           0 :       ssle->SetEnableUpdates(false);
     362           0 :     }
     363          14 :   } else if (MOZ_UNLIKELY(isKeygen)) {
     364             :     // Adapted from CNavDTD
     365             :     nsresult rv;
     366             :     nsCOMPtr<nsIFormProcessor> theFormProcessor =
     367           0 :       do_GetService(kFormProcessorCID, &rv);
     368           0 :     if (NS_FAILED(rv)) {
     369           0 :       return newContent;
     370             :     }
     371             : 
     372           0 :     nsTArray<nsString> theContent;
     373           0 :     nsAutoString theAttribute;
     374             : 
     375           0 :     (void) theFormProcessor->ProvideContent(NS_LITERAL_STRING("select"),
     376             :                                             theContent,
     377           0 :                                             theAttribute);
     378             : 
     379             :     newContent->SetAttr(kNameSpaceID_None,
     380             :                         nsGkAtoms::moztype,
     381             :                         nullptr,
     382             :                         theAttribute,
     383           0 :                         false);
     384             : 
     385           0 :     RefPtr<dom::NodeInfo> optionNodeInfo = aNodeInfoManager->GetNodeInfo(
     386           0 :       nsGkAtoms::option, nullptr, kNameSpaceID_XHTML, nsIDOMNode::ELEMENT_NODE);
     387             : 
     388           0 :     for (uint32_t i = 0; i < theContent.Length(); ++i) {
     389           0 :       nsCOMPtr<dom::Element> optionElt;
     390           0 :       RefPtr<dom::NodeInfo> ni = optionNodeInfo;
     391           0 :       NS_NewElement(getter_AddRefs(optionElt),
     392           0 :                     ni.forget(),
     393           0 :                     aFromParser);
     394           0 :       RefPtr<nsTextNode> optionText = new nsTextNode(aNodeInfoManager);
     395           0 :       (void) optionText->SetText(theContent[i], false);
     396           0 :       optionElt->AppendChildTo(optionText, false);
     397           0 :       newContent->AppendChildTo(optionElt, false);
     398             :       // XXXsmaug Shouldn't we call this after adding all the child nodes.
     399           0 :       newContent->DoneAddingChildren(false);
     400             :     }
     401             :   }
     402             : 
     403          14 :   if (!aAttributes) {
     404           7 :     return newContent;
     405             :   }
     406             : 
     407           7 :   int32_t len = aAttributes->getLength();
     408          23 :   for (int32_t i = 0; i < len; i++) {
     409             :     // prefix doesn't need regetting. it is always null or a static atom
     410             :     // local name is never null
     411             :     nsCOMPtr<nsIAtom> localName =
     412          32 :       Reget(aAttributes->getLocalNameNoBoundsCheck(i));
     413          32 :     nsCOMPtr<nsIAtom> prefix = aAttributes->getPrefixNoBoundsCheck(i);
     414          16 :     int32_t nsuri = aAttributes->getURINoBoundsCheck(i);
     415             : 
     416          32 :     nsString value; // Not Auto, because using it to hold nsStringBuffer*
     417          16 :     aAttributes->getValueNoBoundsCheck(i).ToString(value);
     418          16 :     if (aNs == kNameSpaceID_XHTML && nsGkAtoms::a == aName &&
     419           0 :         nsGkAtoms::name == localName) {
     420             :       // This is an HTML5-incompliant Geckoism.
     421             :       // Remove when fixing bug 582361
     422           0 :       NS_ConvertUTF16toUTF8 cname(value);
     423           0 :       NS_ConvertUTF8toUTF16 uv(nsUnescape(cname.BeginWriting()));
     424           0 :       newContent->SetAttr(nsuri,
     425             :                           localName,
     426             :                           prefix,
     427             :                           uv,
     428           0 :                           false);
     429             :     } else {
     430          16 :       newContent->SetAttr(nsuri,
     431             :                           localName,
     432             :                           prefix,
     433             :                           value,
     434          32 :                           false);
     435             : 
     436             :       // Custom element setup may be needed if there is an "is" attribute.
     437          16 :       if (kNameSpaceID_None == nsuri && !prefix && nsGkAtoms::is == localName) {
     438           0 :         nsContentUtils::SetupCustomElement(newContent, &value);
     439             :       }
     440             :     }
     441             :   }
     442           7 :   return newContent;
     443             : }
     444             : 
     445             : void
     446           0 : nsHtml5TreeOperation::SetFormElement(nsIContent* aNode, nsIContent* aParent)
     447             : {
     448           0 :   nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(aNode));
     449           0 :   nsCOMPtr<nsIDOMHTMLImageElement> domImageElement = do_QueryInterface(aNode);
     450             :   // NS_ASSERTION(formControl, "Form-associated element did not implement nsIFormControl.");
     451             :   // TODO: uncomment the above line when <keygen> (bug 101019) is supported by Gecko
     452           0 :   nsCOMPtr<nsIDOMHTMLFormElement> formElement(do_QueryInterface(aParent));
     453           0 :   NS_ASSERTION(formElement, "The form element doesn't implement nsIDOMHTMLFormElement.");
     454             :   // avoid crashing on <keygen>
     455           0 :   if (formControl &&
     456           0 :       !aNode->HasAttr(kNameSpaceID_None, nsGkAtoms::form)) {
     457           0 :     formControl->SetForm(formElement);
     458           0 :   } else if (domImageElement) {
     459             :     RefPtr<dom::HTMLImageElement> imageElement =
     460           0 :       static_cast<dom::HTMLImageElement*>(domImageElement.get());
     461           0 :     MOZ_ASSERT(imageElement);
     462           0 :     imageElement->SetForm(formElement);
     463             :   }
     464           0 : }
     465             : 
     466             : nsresult
     467           0 : nsHtml5TreeOperation::AppendIsindexPrompt(nsIContent* parent, nsHtml5DocumentBuilder* aBuilder)
     468             : {
     469           0 :   nsXPIDLString prompt;
     470             :   nsresult rv =
     471             :       nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
     472           0 :                                          "IsIndexPromptWithSpace", prompt);
     473           0 :   uint32_t len = prompt.Length();
     474           0 :   if (NS_FAILED(rv)) {
     475           0 :     return rv;
     476             :   }
     477           0 :   if (!len) {
     478             :     // Don't bother appending a zero-length text node.
     479           0 :     return NS_OK;
     480             :   }
     481           0 :   return AppendText(prompt.BeginReading(), len, parent, aBuilder);
     482             : }
     483             : 
     484             : nsresult
     485           0 : nsHtml5TreeOperation::FosterParentText(nsIContent* aStackParent,
     486             :                                        char16_t* aBuffer,
     487             :                                        uint32_t aLength,
     488             :                                        nsIContent* aTable,
     489             :                                        nsHtml5DocumentBuilder* aBuilder)
     490             : {
     491           0 :   MOZ_ASSERT(aBuilder);
     492           0 :   MOZ_ASSERT(aBuilder->IsInDocUpdate());
     493           0 :   nsresult rv = NS_OK;
     494           0 :   nsIContent* foster = aTable->GetParent();
     495             : 
     496           0 :   if (IsElementOrTemplateContent(foster)) {
     497             :     nsHtml5OtherDocUpdate update(foster->OwnerDoc(),
     498           0 :                                  aBuilder->GetDocument());
     499             : 
     500           0 :     uint32_t pos = foster->IndexOf(aTable);
     501             : 
     502           0 :     nsIContent* previousSibling = aTable->GetPreviousSibling();
     503           0 :     if (previousSibling && previousSibling->IsNodeOfType(nsINode::eTEXT)) {
     504             :       return AppendTextToTextNode(aBuffer,
     505             :                                   aLength,
     506             :                                   previousSibling,
     507           0 :                                   aBuilder);
     508             :     }
     509             : 
     510           0 :     nsNodeInfoManager* nodeInfoManager = aStackParent->OwnerDoc()->NodeInfoManager();
     511           0 :     RefPtr<nsTextNode> text = new nsTextNode(nodeInfoManager);
     512           0 :     NS_ASSERTION(text, "Infallible malloc failed?");
     513           0 :     rv = text->SetText(aBuffer, aLength, false);
     514           0 :     NS_ENSURE_SUCCESS(rv, rv);
     515             : 
     516           0 :     rv = foster->InsertChildAt(text, pos, false);
     517           0 :     NS_ENSURE_SUCCESS(rv, rv);
     518           0 :     nsNodeUtils::ContentInserted(foster, text, pos);
     519           0 :     return rv;
     520             :   }
     521             : 
     522           0 :   return AppendText(aBuffer, aLength, aStackParent, aBuilder);
     523             : }
     524             : 
     525             : nsresult
     526           3 : nsHtml5TreeOperation::AppendComment(nsIContent* aParent,
     527             :                                     char16_t* aBuffer,
     528             :                                     int32_t aLength,
     529             :                                     nsHtml5DocumentBuilder* aBuilder)
     530             : {
     531           3 :   nsNodeInfoManager* nodeInfoManager = aParent->OwnerDoc()->NodeInfoManager();
     532           6 :   RefPtr<dom::Comment> comment = new dom::Comment(nodeInfoManager);
     533           3 :   NS_ASSERTION(comment, "Infallible malloc failed?");
     534           3 :   nsresult rv = comment->SetText(aBuffer, aLength, false);
     535           3 :   NS_ENSURE_SUCCESS(rv, rv);
     536             : 
     537           3 :   return Append(comment, aParent, aBuilder);
     538             : }
     539             : 
     540             : nsresult
     541           2 : nsHtml5TreeOperation::AppendCommentToDocument(char16_t* aBuffer,
     542             :                                               int32_t aLength,
     543             :                                               nsHtml5DocumentBuilder* aBuilder)
     544             : {
     545             :   RefPtr<dom::Comment> comment =
     546           6 :     new dom::Comment(aBuilder->GetNodeInfoManager());
     547           2 :   NS_ASSERTION(comment, "Infallible malloc failed?");
     548           2 :   nsresult rv = comment->SetText(aBuffer, aLength, false);
     549           2 :   NS_ENSURE_SUCCESS(rv, rv);
     550             : 
     551           2 :   return AppendToDocument(comment, aBuilder);
     552             : }
     553             : 
     554             : nsresult
     555           1 : nsHtml5TreeOperation::AppendDoctypeToDocument(nsIAtom* aName,
     556             :                                               const nsAString& aPublicId,
     557             :                                               const nsAString& aSystemId,
     558             :                                               nsHtml5DocumentBuilder* aBuilder)
     559             : {
     560             :   // Adapted from nsXMLContentSink
     561             :   // Create a new doctype node
     562           2 :   nsCOMPtr<nsIDOMDocumentType> docType;
     563           2 :   NS_NewDOMDocumentType(getter_AddRefs(docType),
     564             :                         aBuilder->GetNodeInfoManager(),
     565             :                         aName,
     566             :                         aPublicId,
     567             :                         aSystemId,
     568           2 :                         NullString());
     569           1 :   NS_ASSERTION(docType, "Doctype creation failed.");
     570           2 :   nsCOMPtr<nsIContent> asContent = do_QueryInterface(docType);
     571           2 :   return AppendToDocument(asContent, aBuilder);
     572             : }
     573             : 
     574             : nsIContent*
     575           0 : nsHtml5TreeOperation::GetDocumentFragmentForTemplate(nsIContent* aNode)
     576             : {
     577             :   dom::HTMLTemplateElement* tempElem =
     578           0 :     static_cast<dom::HTMLTemplateElement*>(aNode);
     579           0 :   RefPtr<dom::DocumentFragment> frag = tempElem->Content();
     580           0 :   return frag;
     581             : }
     582             : 
     583             : nsIContent*
     584           0 : nsHtml5TreeOperation::GetFosterParent(nsIContent* aTable, nsIContent* aStackParent)
     585             : {
     586           0 :   nsIContent* tableParent = aTable->GetParent();
     587           0 :   return IsElementOrTemplateContent(tableParent) ? tableParent : aStackParent;
     588             : }
     589             : 
     590             : void
     591           0 : nsHtml5TreeOperation::PreventScriptExecution(nsIContent* aNode)
     592             : {
     593           0 :   nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aNode);
     594           0 :   if (sele) {
     595           0 :     sele->PreventExecution();
     596             :   } else {
     597           0 :     MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled, "Node didn't QI to script, but SVG wasn't disabled.");
     598             :   }
     599           0 : }
     600             : 
     601             : void
     602           0 : nsHtml5TreeOperation::DoneAddingChildren(nsIContent* aNode)
     603             : {
     604           0 :   aNode->DoneAddingChildren(aNode->HasParserNotified());
     605           0 : }
     606             : 
     607             : void
     608           0 : nsHtml5TreeOperation::DoneCreatingElement(nsIContent* aNode)
     609             : {
     610           0 :   aNode->DoneCreatingElement();
     611           0 : }
     612             : 
     613             : void
     614           0 : nsHtml5TreeOperation::SvgLoad(nsIContent* aNode)
     615             : {
     616           0 :   nsCOMPtr<nsIRunnable> event = new nsHtml5SVGLoadDispatcher(aNode);
     617           0 :   if (NS_FAILED(aNode->OwnerDoc()->Dispatch(
     618             :         "nsHtml5SVGLoadDispatcher", TaskCategory::Network, event.forget()))) {
     619           0 :     NS_WARNING("failed to dispatch svg load dispatcher");
     620             :   }
     621           0 : }
     622             : 
     623             : void
     624           4 : nsHtml5TreeOperation::MarkMalformedIfScript(nsIContent* aNode)
     625             : {
     626           8 :   nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aNode);
     627           4 :   if (sele) {
     628             :     // Make sure to serialize this script correctly, for nice round tripping.
     629           0 :     sele->SetIsMalformed();
     630             :   }
     631           4 : }
     632             : 
     633             : nsresult
     634          67 : nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder,
     635             :                               nsIContent** aScriptElement,
     636             :                               bool* aInterrupted)
     637             : {
     638          67 :   switch(mOpCode) {
     639             :     case eTreeOpUninitialized: {
     640           0 :       MOZ_CRASH("eTreeOpUninitialized");
     641             :     }
     642             :     case eTreeOpAppend: {
     643          12 :       nsIContent* node = *(mOne.node);
     644          12 :       nsIContent* parent = *(mTwo.node);
     645          12 :       return Append(node, parent, aBuilder);
     646             :     }
     647             :     case eTreeOpDetach: {
     648           0 :       nsIContent* node = *(mOne.node);
     649           0 :       Detach(node, aBuilder);
     650           0 :       return NS_OK;
     651             :     }
     652             :     case eTreeOpAppendChildrenToNewParent: {
     653           0 :       nsCOMPtr<nsIContent> node = *(mOne.node);
     654           0 :       nsIContent* parent = *(mTwo.node);
     655           0 :       return AppendChildrenToNewParent(node, parent, aBuilder);
     656             :     }
     657             :     case eTreeOpFosterParent: {
     658           0 :       nsIContent* node = *(mOne.node);
     659           0 :       nsIContent* parent = *(mTwo.node);
     660           0 :       nsIContent* table = *(mThree.node);
     661           0 :       return FosterParent(node, parent, table, aBuilder);
     662             :     }
     663             :     case eTreeOpAppendToDocument: {
     664           2 :       nsIContent* node = *(mOne.node);
     665           2 :       nsresult rv = AppendToDocument(node, aBuilder);
     666             : 
     667           2 :       aBuilder->PauseDocUpdate(aInterrupted);
     668           2 :       return rv;
     669             :     }
     670             :     case eTreeOpAddAttributes: {
     671           0 :       nsIContent* node = *(mOne.node);
     672           0 :       nsHtml5HtmlAttributes* attributes = mTwo.attributes;
     673           0 :       return AddAttributes(node, attributes, aBuilder);
     674             :     }
     675             :     case eTreeOpDocumentMode: {
     676           0 :       aBuilder->SetDocumentMode(mOne.mode);
     677           0 :       return NS_OK;
     678             :     }
     679             :     case eTreeOpCreateElementNetwork:
     680             :     case eTreeOpCreateElementNotNetwork: {
     681          14 :       nsIContent** target = mOne.node;
     682          14 :       int32_t ns = mFour.integer;
     683          28 :       nsCOMPtr<nsIAtom> name = Reget(mTwo.atom);
     684          14 :       nsHtml5HtmlAttributes* attributes = mThree.attributes;
     685          14 :       nsIContent* intendedParent = mFive.node ? *(mFive.node) : nullptr;
     686             : 
     687             :       // intendedParent == nullptr is a special case where the
     688             :       // intended parent is the document.
     689          28 :       nsNodeInfoManager* nodeInfoManager = intendedParent ?
     690          12 :          intendedParent->OwnerDoc()->NodeInfoManager() :
     691          16 :          aBuilder->GetNodeInfoManager();
     692             : 
     693          14 :       *target = CreateElement(ns,
     694             :                               name,
     695             :                               attributes,
     696          14 :                               mOpCode == eTreeOpCreateElementNetwork ?
     697             :                                 dom::FROM_PARSER_NETWORK :
     698             :                                 dom::FROM_PARSER_DOCUMENT_WRITE,
     699             :                               nodeInfoManager,
     700             :                               aBuilder);
     701          14 :       return NS_OK;
     702             :     }
     703             :     case eTreeOpSetFormElement: {
     704           0 :       nsIContent* node = *(mOne.node);
     705           0 :       nsIContent* parent = *(mTwo.node);
     706           0 :       SetFormElement(node, parent);
     707           0 :       return NS_OK;
     708             :     }
     709             :     case eTreeOpAppendText: {
     710          12 :       nsIContent* parent = *mOne.node;
     711          12 :       char16_t* buffer = mTwo.unicharPtr;
     712          12 :       uint32_t length = mFour.integer;
     713          12 :       return AppendText(buffer, length, parent, aBuilder);
     714             :     }
     715             :     case eTreeOpAppendIsindexPrompt: {
     716           0 :       nsIContent* parent = *mOne.node;
     717           0 :       return AppendIsindexPrompt(parent, aBuilder);
     718             :     }
     719             :     case eTreeOpFosterParentText: {
     720           0 :       nsIContent* stackParent = *mOne.node;
     721           0 :       char16_t* buffer = mTwo.unicharPtr;
     722           0 :       uint32_t length = mFour.integer;
     723           0 :       nsIContent* table = *mThree.node;
     724           0 :       return FosterParentText(stackParent, buffer, length, table, aBuilder);
     725             :     }
     726             :     case eTreeOpAppendComment: {
     727           3 :       nsIContent* parent = *mOne.node;
     728           3 :       char16_t* buffer = mTwo.unicharPtr;
     729           3 :       int32_t length = mFour.integer;
     730           3 :       return AppendComment(parent, buffer, length, aBuilder);
     731             :     }
     732             :     case eTreeOpAppendCommentToDocument: {
     733           2 :       char16_t* buffer = mTwo.unicharPtr;
     734           2 :       int32_t length = mFour.integer;
     735           2 :       return AppendCommentToDocument(buffer, length, aBuilder);
     736             :     }
     737             :     case eTreeOpAppendDoctypeToDocument: {
     738           2 :       nsCOMPtr<nsIAtom> name = Reget(mOne.atom);
     739           1 :       nsHtml5TreeOperationStringPair* pair = mTwo.stringPair;
     740           2 :       nsString publicId;
     741           2 :       nsString systemId;
     742           1 :       pair->Get(publicId, systemId);
     743           1 :       return AppendDoctypeToDocument(name, publicId, systemId, aBuilder);
     744             :     }
     745             :     case eTreeOpGetDocumentFragmentForTemplate: {
     746           0 :       nsIContent* node = *(mOne.node);
     747           0 :       *mTwo.node = GetDocumentFragmentForTemplate(node);
     748           0 :       return NS_OK;
     749             :     }
     750             :     case eTreeOpGetFosterParent: {
     751           0 :       nsIContent* table = *(mOne.node);
     752           0 :       nsIContent* stackParent = *(mTwo.node);
     753           0 :       nsIContent* fosterParent = GetFosterParent(table, stackParent);
     754           0 :       *mThree.node = fosterParent;
     755           0 :       return NS_OK;
     756             :     }
     757             :     case eTreeOpMarkAsBroken: {
     758           0 :       return mOne.result;
     759             :     }
     760             :     case eTreeOpRunScript: {
     761           5 :       nsIContent* node = *(mOne.node);
     762           5 :       nsAHtml5TreeBuilderState* snapshot = mTwo.state;
     763           5 :       if (snapshot) {
     764           5 :         aBuilder->InitializeDocWriteParserState(snapshot, mFour.integer);
     765             :       }
     766           5 :       *aScriptElement = node;
     767           5 :       return NS_OK;
     768             :     }
     769             :     case eTreeOpRunScriptAsyncDefer: {
     770           0 :       nsIContent* node = *(mOne.node);
     771           0 :       aBuilder->RunScript(node);
     772           0 :       return NS_OK;
     773             :     }
     774             :     case eTreeOpPreventScriptExecution: {
     775           0 :       nsIContent* node = *(mOne.node);
     776           0 :       PreventScriptExecution(node);
     777           0 :       return NS_OK;
     778             :     }
     779             :     case eTreeOpDoneAddingChildren: {
     780           1 :       nsIContent* node = *(mOne.node);
     781           1 :       node->DoneAddingChildren(node->HasParserNotified());
     782           1 :       return NS_OK;
     783             :     }
     784             :     case eTreeOpDoneCreatingElement: {
     785           0 :       nsIContent* node = *(mOne.node);
     786           0 :       DoneCreatingElement(node);
     787           0 :       return NS_OK;
     788             :     }
     789             :     case eTreeOpSetDocumentCharset: {
     790           0 :       auto encoding = WrapNotNull(mOne.encoding);
     791           0 :       int32_t charsetSource = mFour.integer;
     792           0 :       aBuilder->SetDocumentCharsetAndSource(encoding, charsetSource);
     793           0 :       return NS_OK;
     794             :     }
     795             :     case eTreeOpNeedsCharsetSwitchTo: {
     796           0 :       auto encoding = WrapNotNull(mOne.encoding);
     797           0 :       int32_t charsetSource = mFour.integer;
     798           0 :       int32_t lineNumber = mTwo.integer;
     799           0 :       aBuilder->NeedsCharsetSwitchTo(encoding, charsetSource, (uint32_t)lineNumber);
     800           0 :       return NS_OK;
     801             :     }
     802             :     case eTreeOpUpdateStyleSheet: {
     803           0 :       nsIContent* node = *(mOne.node);
     804           0 :       aBuilder->UpdateStyleSheet(node);
     805           0 :       return NS_OK;
     806             :     }
     807             :     case eTreeOpProcessMeta: {
     808           2 :       nsIContent* node = *(mOne.node);
     809           2 :       return aBuilder->ProcessMETATag(node);
     810             :     }
     811             :     case eTreeOpProcessOfflineManifest: {
     812           0 :       char16_t* str = mOne.unicharPtr;
     813           0 :       nsDependentString dependentString(str);
     814           0 :       aBuilder->ProcessOfflineManifest(dependentString);
     815           0 :       return NS_OK;
     816             :     }
     817             :     case eTreeOpMarkMalformedIfScript: {
     818           4 :       nsIContent* node = *(mOne.node);
     819           4 :       MarkMalformedIfScript(node);
     820           4 :       return NS_OK;
     821             :     }
     822             :     case eTreeOpStreamEnded: {
     823           2 :       aBuilder->DidBuildModel(false); // this causes a notifications flush anyway
     824           2 :       return NS_OK;
     825             :     }
     826             :     case eTreeOpSetStyleLineNumber: {
     827           0 :       nsIContent* node = *(mOne.node);
     828           0 :       nsCOMPtr<nsIStyleSheetLinkingElement> ssle = do_QueryInterface(node);
     829           0 :       if (ssle) {
     830           0 :         ssle->SetLineNumber(mFour.integer);
     831             :       } else {
     832           0 :         MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled, "Node didn't QI to style, but SVG wasn't disabled.");
     833             :       }
     834           0 :       return NS_OK;
     835             :     }
     836             :     case eTreeOpSetScriptLineNumberAndFreeze: {
     837           5 :       nsIContent* node = *(mOne.node);
     838          10 :       nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node);
     839           5 :       if (sele) {
     840           5 :         sele->SetScriptLineNumber(mFour.integer);
     841           5 :         sele->FreezeUriAsyncDefer();
     842             :       } else {
     843           0 :         MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled, "Node didn't QI to script, but SVG wasn't disabled.");
     844             :       }
     845           5 :       return NS_OK;
     846             :     }
     847             :     case eTreeOpSvgLoad: {
     848           0 :       nsIContent* node = *(mOne.node);
     849           0 :       SvgLoad(node);
     850           0 :       return NS_OK;
     851             :     }
     852             :     case eTreeOpMaybeComplainAboutCharset: {
     853           0 :       char* msgId = mOne.charPtr;
     854           0 :       bool error = mTwo.integer;
     855           0 :       int32_t lineNumber = mThree.integer;
     856           0 :       aBuilder->MaybeComplainAboutCharset(msgId, error, (uint32_t)lineNumber);
     857           0 :       return NS_OK;
     858             :     }
     859             :     case eTreeOpAddClass: {
     860           0 :       nsIContent* node = *(mOne.node);
     861           0 :       char16_t* str = mTwo.unicharPtr;
     862           0 :       nsDependentString depStr(str);
     863             :       // See viewsource.css for the possible classes
     864           0 :       nsAutoString klass;
     865           0 :       node->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass);
     866           0 :       if (!klass.IsEmpty()) {
     867           0 :         klass.Append(' ');
     868           0 :         klass.Append(depStr);
     869           0 :         node->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass, true);
     870             :       } else {
     871           0 :         node->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, depStr, true);
     872             :       }
     873           0 :       return NS_OK;
     874             :     }
     875             :     case eTreeOpAddViewSourceHref: {
     876           0 :       nsIContent* node = *mOne.node;
     877           0 :       char16_t* buffer = mTwo.unicharPtr;
     878           0 :       int32_t length = mFour.integer;
     879             : 
     880           0 :       nsDependentString relative(buffer, length);
     881             : 
     882           0 :       nsIDocument* doc = aBuilder->GetDocument();
     883             : 
     884           0 :       auto encoding = doc->GetDocumentCharacterSet();
     885           0 :       nsCOMPtr<nsIURI> uri;
     886           0 :       nsresult rv = NS_NewURI(getter_AddRefs(uri),
     887             :                               relative,
     888             :                               encoding,
     889           0 :                               aBuilder->GetViewSourceBaseURI());
     890           0 :       NS_ENSURE_SUCCESS(rv, NS_OK);
     891             : 
     892             :       // Reuse the fix for bug 467852
     893             :       // URLs that execute script (e.g. "javascript:" URLs) should just be
     894             :       // ignored.  There's nothing reasonable we can do with them, and allowing
     895             :       // them to execute in the context of the view-source window presents a
     896             :       // security risk.  Just return the empty string in this case.
     897           0 :       bool openingExecutesScript = false;
     898           0 :       rv = NS_URIChainHasFlags(uri,
     899             :                                nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT,
     900           0 :                                &openingExecutesScript);
     901           0 :       if (NS_FAILED(rv) || openingExecutesScript) {
     902           0 :         return NS_OK;
     903             :       }
     904             : 
     905           0 :       nsAutoCString viewSourceUrl;
     906             : 
     907             :       // URLs that return data (e.g. "http:" URLs) should be prefixed with
     908             :       // "view-source:".  URLs that don't return data should just be returned
     909             :       // undecorated.
     910           0 :       bool doesNotReturnData = false;
     911           0 :       rv = NS_URIChainHasFlags(uri,
     912             :                                nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA,
     913           0 :                                &doesNotReturnData);
     914           0 :       NS_ENSURE_SUCCESS(rv, NS_OK);
     915           0 :       if (!doesNotReturnData) {
     916           0 :         viewSourceUrl.AssignLiteral("view-source:");
     917             :       }
     918             : 
     919           0 :       nsAutoCString spec;
     920           0 :       rv = uri->GetSpec(spec);
     921           0 :       NS_ENSURE_SUCCESS(rv, rv);
     922             : 
     923           0 :       viewSourceUrl.Append(spec);
     924             : 
     925           0 :       nsAutoString utf16;
     926           0 :       CopyUTF8toUTF16(viewSourceUrl, utf16);
     927             : 
     928           0 :       node->SetAttr(kNameSpaceID_None, nsGkAtoms::href, utf16, true);
     929           0 :       return NS_OK;
     930             :     }
     931             :     case eTreeOpAddViewSourceBase: {
     932           0 :       char16_t* buffer = mTwo.unicharPtr;
     933           0 :       int32_t length = mFour.integer;
     934           0 :       nsDependentString baseUrl(buffer, length);
     935           0 :       aBuilder->AddBase(baseUrl);
     936           0 :       return NS_OK;
     937             :     }
     938             :     case eTreeOpAddError: {
     939           0 :       nsIContent* node = *(mOne.node);
     940           0 :       char* msgId = mTwo.charPtr;
     941           0 :       nsCOMPtr<nsIAtom> atom = Reget(mThree.atom);
     942           0 :       nsCOMPtr<nsIAtom> otherAtom = Reget(mFour.atom);
     943             :       // See viewsource.css for the possible classes in addition to "error".
     944           0 :       nsAutoString klass;
     945           0 :       node->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass);
     946           0 :       if (!klass.IsEmpty()) {
     947           0 :         klass.AppendLiteral(" error");
     948           0 :         node->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass, true);
     949             :       } else {
     950           0 :         node->SetAttr(kNameSpaceID_None,
     951             :                       nsGkAtoms::_class,
     952           0 :                       NS_LITERAL_STRING("error"),
     953           0 :                       true);
     954             :       }
     955             : 
     956             :       nsresult rv;
     957           0 :       nsXPIDLString message;
     958           0 :       if (otherAtom) {
     959           0 :         const char16_t* params[] = { atom->GetUTF16String(),
     960           0 :                                       otherAtom->GetUTF16String() };
     961             :         rv = nsContentUtils::FormatLocalizedString(
     962           0 :           nsContentUtils::eHTMLPARSER_PROPERTIES, msgId, params, message);
     963           0 :         NS_ENSURE_SUCCESS(rv, NS_OK);
     964           0 :       } else if (atom) {
     965           0 :         const char16_t* params[] = { atom->GetUTF16String() };
     966             :         rv = nsContentUtils::FormatLocalizedString(
     967           0 :           nsContentUtils::eHTMLPARSER_PROPERTIES, msgId, params, message);
     968           0 :         NS_ENSURE_SUCCESS(rv, NS_OK);
     969             :       } else {
     970             :         rv = nsContentUtils::GetLocalizedString(
     971           0 :           nsContentUtils::eHTMLPARSER_PROPERTIES, msgId, message);
     972           0 :         NS_ENSURE_SUCCESS(rv, NS_OK);
     973             :       }
     974             : 
     975           0 :       nsAutoString title;
     976           0 :       node->GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
     977           0 :       if (!title.IsEmpty()) {
     978           0 :         title.Append('\n');
     979           0 :         title.Append(message);
     980           0 :         node->SetAttr(kNameSpaceID_None, nsGkAtoms::title, title, true);
     981             :       } else {
     982           0 :         node->SetAttr(kNameSpaceID_None, nsGkAtoms::title, message, true);
     983             :       }
     984           0 :       return rv;
     985             :     }
     986             :     case eTreeOpAddLineNumberId: {
     987           0 :       nsIContent* node = *(mOne.node);
     988           0 :       int32_t lineNumber = mFour.integer;
     989           0 :       nsAutoString val(NS_LITERAL_STRING("line"));
     990           0 :       val.AppendInt(lineNumber);
     991           0 :       node->SetAttr(kNameSpaceID_None, nsGkAtoms::id, val, true);
     992           0 :       return NS_OK;
     993             :     }
     994             :     case eTreeOpStartLayout: {
     995           2 :       aBuilder->StartLayout(aInterrupted); // this causes a notification flush anyway
     996           2 :       return NS_OK;
     997             :     }
     998             :     default: {
     999           0 :       MOZ_CRASH("Bogus tree op");
    1000             :     }
    1001             :   }
    1002             :   return NS_OK; // keep compiler happy
    1003             : }

Generated by: LCOV version 1.13