LCOV - code coverage report
Current view: directory - parser/html - nsHtml5TreeOperation.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 428 109 25.5 %
Date: 2012-06-02 Functions: 9 9 100.0 %

       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                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Mozilla Communicator client code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      25                 :  *   Henri Sivonen <hsivonen@iki.fi>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #include "nsHtml5TreeOperation.h"
      42                 : #include "nsContentUtils.h"
      43                 : #include "nsNodeUtils.h"
      44                 : #include "nsAttrName.h"
      45                 : #include "nsHtml5TreeBuilder.h"
      46                 : #include "nsIDOMMutationEvent.h"
      47                 : #include "mozAutoDocUpdate.h"
      48                 : #include "nsBindingManager.h"
      49                 : #include "nsXBLBinding.h"
      50                 : #include "nsHtml5DocumentMode.h"
      51                 : #include "nsHtml5HtmlAttributes.h"
      52                 : #include "nsContentCreatorFunctions.h"
      53                 : #include "nsIScriptElement.h"
      54                 : #include "nsIDTD.h"
      55                 : #include "nsTraceRefcnt.h"
      56                 : #include "nsIDOMHTMLFormElement.h"
      57                 : #include "nsIFormControl.h"
      58                 : #include "nsIStyleSheetLinkingElement.h"
      59                 : #include "nsIDOMDocumentType.h"
      60                 : #include "nsIObserverService.h"
      61                 : #include "mozilla/Services.h"
      62                 : #include "nsIMutationObserver.h"
      63                 : #include "nsIFormProcessor.h"
      64                 : #include "nsIServiceManager.h"
      65                 : #include "nsEscape.h"
      66                 : #include "mozilla/dom/Element.h"
      67                 : #include "nsHtml5SVGLoadDispatcher.h"
      68                 : #include "nsIURI.h"
      69                 : #include "nsIProtocolHandler.h"
      70                 : #include "nsNetUtil.h"
      71                 : 
      72                 : namespace dom = mozilla::dom;
      73                 : 
      74                 : static NS_DEFINE_CID(kFormProcessorCID, NS_FORMPROCESSOR_CID);
      75                 : 
      76                 : /**
      77                 :  * Helper class that opens a notification batch if the current doc
      78                 :  * is different from the executor doc.
      79                 :  */
      80                 : class NS_STACK_CLASS nsHtml5OtherDocUpdate {
      81                 :   public:
      82               1 :     nsHtml5OtherDocUpdate(nsIDocument* aCurrentDoc, nsIDocument* aExecutorDoc)
      83                 :     {
      84               1 :       NS_PRECONDITION(aCurrentDoc, "Node has no doc?");
      85               1 :       NS_PRECONDITION(aExecutorDoc, "Executor has no doc?");
      86               1 :       if (NS_LIKELY(aCurrentDoc == aExecutorDoc)) {
      87               1 :         mDocument = nsnull;
      88                 :       } else {
      89               0 :         mDocument = aCurrentDoc;
      90               0 :         aCurrentDoc->BeginUpdate(UPDATE_CONTENT_MODEL);        
      91                 :       }
      92               1 :     }
      93                 : 
      94               1 :     ~nsHtml5OtherDocUpdate()
      95                 :     {
      96               1 :       if (NS_UNLIKELY(mDocument)) {
      97               0 :         mDocument->EndUpdate(UPDATE_CONTENT_MODEL);
      98                 :       }
      99               1 :     }
     100                 :   private:
     101                 :     nsIDocument* mDocument;
     102                 : };
     103                 : 
     104            3251 : nsHtml5TreeOperation::nsHtml5TreeOperation()
     105                 : #ifdef DEBUG
     106            3251 :  : mOpCode(eTreeOpUninitialized)
     107                 : #endif
     108                 : {
     109            3251 :   MOZ_COUNT_CTOR(nsHtml5TreeOperation);
     110            3251 : }
     111                 : 
     112            3251 : nsHtml5TreeOperation::~nsHtml5TreeOperation()
     113                 : {
     114            3251 :   MOZ_COUNT_DTOR(nsHtml5TreeOperation);
     115            3251 :   NS_ASSERTION(mOpCode != eTreeOpUninitialized, "Uninitialized tree op.");
     116            3251 :   switch(mOpCode) {
     117                 :     case eTreeOpAddAttributes:
     118               0 :       delete mTwo.attributes;
     119               0 :       break;
     120                 :     case eTreeOpCreateElementNetwork:
     121                 :     case eTreeOpCreateElementNotNetwork:
     122             780 :       delete mThree.attributes;
     123             780 :       break;
     124                 :     case eTreeOpAppendDoctypeToDocument:
     125               0 :       delete mTwo.stringPair;
     126               0 :       break;
     127                 :     case eTreeOpFosterParentText:
     128                 :     case eTreeOpAppendText:
     129                 :     case eTreeOpAppendComment:
     130                 :     case eTreeOpAppendCommentToDocument:
     131                 :     case eTreeOpAddViewSourceHref:
     132             287 :       delete[] mTwo.unicharPtr;
     133             287 :       break;
     134                 :     case eTreeOpSetDocumentCharset:
     135                 :     case eTreeOpNeedsCharsetSwitchTo:
     136               0 :       delete[] mOne.charPtr;
     137               0 :       break;
     138                 :     case eTreeOpProcessOfflineManifest:
     139             234 :       nsMemory::Free(mOne.unicharPtr);
     140             234 :       break;
     141                 :     default: // keep the compiler happy
     142            1950 :       break;
     143                 :   }
     144            3251 : }
     145                 : 
     146                 : nsresult
     147               1 : nsHtml5TreeOperation::AppendTextToTextNode(const PRUnichar* aBuffer,
     148                 :                                            PRUint32 aLength,
     149                 :                                            nsIContent* aTextNode,
     150                 :                                            nsHtml5TreeOpExecutor* aBuilder)
     151                 : {
     152               1 :   NS_PRECONDITION(aTextNode, "Got null text node.");
     153                 : 
     154               1 :   if (aBuilder->HaveNotified(aTextNode)) {
     155                 :     // This text node has already been notified on, so it's necessary to
     156                 :     // notify on the append
     157               0 :     nsresult rv = NS_OK;
     158               0 :     PRUint32 oldLength = aTextNode->TextLength();
     159                 :     CharacterDataChangeInfo info = {
     160                 :       true,
     161                 :       oldLength,
     162                 :       oldLength,
     163                 :       aLength
     164               0 :     };
     165               0 :     nsNodeUtils::CharacterDataWillChange(aTextNode, &info);
     166                 : 
     167               0 :     rv = aTextNode->AppendText(aBuffer, aLength, false);
     168               0 :     NS_ENSURE_SUCCESS(rv, rv);
     169                 : 
     170               0 :     nsNodeUtils::CharacterDataChanged(aTextNode, &info);
     171               0 :     return rv;
     172                 :   }
     173                 : 
     174               1 :   return aTextNode->AppendText(aBuffer, aLength, false);
     175                 : }
     176                 : 
     177                 : 
     178                 : nsresult
     179             287 : nsHtml5TreeOperation::AppendText(const PRUnichar* aBuffer,
     180                 :                                  PRUint32 aLength,
     181                 :                                  nsIContent* aParent,
     182                 :                                  nsHtml5TreeOpExecutor* aBuilder)
     183                 : {
     184             287 :   nsresult rv = NS_OK;
     185             287 :   nsIContent* lastChild = aParent->GetLastChild();
     186             287 :   if (lastChild && lastChild->IsNodeOfType(nsINode::eTEXT)) {
     187                 :     nsHtml5OtherDocUpdate update(aParent->OwnerDoc(),
     188               2 :                                  aBuilder->GetDocument());
     189                 :     return AppendTextToTextNode(aBuffer, 
     190                 :                                 aLength, 
     191                 :                                 lastChild, 
     192               1 :                                 aBuilder);
     193                 :   }
     194                 : 
     195             572 :   nsCOMPtr<nsIContent> text;
     196             286 :   NS_NewTextNode(getter_AddRefs(text), aBuilder->GetNodeInfoManager());
     197             286 :   NS_ASSERTION(text, "Infallible malloc failed?");
     198             286 :   rv = text->SetText(aBuffer, aLength, false);
     199             286 :   NS_ENSURE_SUCCESS(rv, rv);
     200                 : 
     201             286 :   return Append(text, aParent, aBuilder);
     202                 : }
     203                 : 
     204                 : nsresult
     205             832 : nsHtml5TreeOperation::Append(nsIContent* aNode,
     206                 :                              nsIContent* aParent,
     207                 :                              nsHtml5TreeOpExecutor* aBuilder)
     208                 : {
     209             832 :   nsresult rv = NS_OK;
     210             832 :   nsIDocument* executorDoc = aBuilder->GetDocument();
     211             832 :   NS_ASSERTION(executorDoc, "Null doc on executor");
     212             832 :   nsIDocument* parentDoc = aParent->OwnerDoc();
     213             832 :   NS_ASSERTION(parentDoc, "Null owner doc on old node.");
     214                 : 
     215             832 :   if (NS_LIKELY(executorDoc == parentDoc)) {
     216                 :     // the usual case. the parent is in the parser's doc
     217             832 :     rv = aParent->AppendChildTo(aNode, false);
     218             832 :     if (NS_SUCCEEDED(rv)) {
     219             832 :       aBuilder->PostPendingAppendNotification(aParent, aNode);
     220                 :     }
     221             832 :     return rv;
     222                 :   }
     223                 : 
     224                 :   // The parent has been moved to another doc
     225               0 :   parentDoc->BeginUpdate(UPDATE_CONTENT_MODEL);
     226                 : 
     227               0 :   PRUint32 childCount = aParent->GetChildCount();
     228               0 :   rv = aParent->AppendChildTo(aNode, false);
     229               0 :   if (NS_SUCCEEDED(rv)) {
     230               0 :     nsNodeUtils::ContentAppended(aParent, aNode, childCount);
     231                 :   }
     232               0 :   parentDoc->EndUpdate(UPDATE_CONTENT_MODEL);
     233               0 :   return rv;
     234                 : }
     235                 : 
     236                 : nsresult
     237             234 : nsHtml5TreeOperation::AppendToDocument(nsIContent* aNode,
     238                 :                                        nsHtml5TreeOpExecutor* aBuilder)
     239                 : {
     240             234 :   nsresult rv = NS_OK;
     241             234 :   aBuilder->FlushPendingAppendNotifications();
     242             234 :   nsIDocument* doc = aBuilder->GetDocument();
     243             234 :   PRUint32 childCount = doc->GetChildCount();
     244             234 :   rv = doc->AppendChildTo(aNode, false);
     245             234 :   NS_ENSURE_SUCCESS(rv, rv);
     246             234 :   nsNodeUtils::ContentInserted(doc, aNode, childCount);
     247                 : 
     248             234 :   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
     249                 :                "Someone forgot to block scripts");
     250             234 :   if (aNode->IsElement()) {
     251                 :     nsContentUtils::AddScriptRunner(
     252             234 :         new nsDocElementCreatedNotificationRunner(doc));
     253                 :   }
     254             234 :   return rv;
     255                 : }
     256                 : 
     257                 : nsresult
     258            3251 : nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder,
     259                 :                               nsIContent** aScriptElement)
     260                 : {
     261            3251 :   nsresult rv = NS_OK;
     262            3251 :   switch(mOpCode) {
     263                 :     case eTreeOpAppend: {
     264             546 :       nsIContent* node = *(mOne.node);
     265             546 :       nsIContent* parent = *(mTwo.node);
     266             546 :       return Append(node, parent, aBuilder);
     267                 :     }
     268                 :     case eTreeOpDetach: {
     269               0 :       nsIContent* node = *(mOne.node);
     270               0 :       aBuilder->FlushPendingAppendNotifications();
     271               0 :       nsCOMPtr<nsIContent> parent = node->GetParent();
     272               0 :       if (parent) {
     273               0 :         nsHtml5OtherDocUpdate update(parent->OwnerDoc(),
     274               0 :                                      aBuilder->GetDocument());
     275               0 :         PRUint32 pos = parent->IndexOf(node);
     276                 :         NS_ASSERTION((pos >= 0), "Element not found as child of its parent");
     277               0 :         rv = parent->RemoveChildAt(pos, true);
     278               0 :         NS_ENSURE_SUCCESS(rv, rv);
     279                 :       }
     280               0 :       return rv;
     281                 :     }
     282                 :     case eTreeOpAppendChildrenToNewParent: {
     283               0 :       nsCOMPtr<nsIContent> node = *(mOne.node);
     284               0 :       nsIContent* parent = *(mTwo.node);
     285               0 :       aBuilder->FlushPendingAppendNotifications();
     286                 : 
     287                 :       nsHtml5OtherDocUpdate update(parent->OwnerDoc(),
     288               0 :                                    aBuilder->GetDocument());
     289                 : 
     290               0 :       PRUint32 childCount = parent->GetChildCount();
     291               0 :       bool didAppend = false;
     292               0 :       while (node->HasChildren()) {
     293               0 :         nsCOMPtr<nsIContent> child = node->GetFirstChild();
     294               0 :         rv = node->RemoveChildAt(0, true);
     295               0 :         NS_ENSURE_SUCCESS(rv, rv);
     296               0 :         rv = parent->AppendChildTo(child, false);
     297               0 :         NS_ENSURE_SUCCESS(rv, rv);
     298               0 :         didAppend = true;
     299                 :       }
     300               0 :       if (didAppend) {
     301               0 :         nsNodeUtils::ContentAppended(parent, parent->GetChildAt(childCount),
     302               0 :                                      childCount);
     303                 :       }
     304               0 :       return rv;
     305                 :     }
     306                 :     case eTreeOpFosterParent: {
     307               0 :       nsIContent* node = *(mOne.node);
     308               0 :       nsIContent* parent = *(mTwo.node);
     309               0 :       nsIContent* table = *(mThree.node);
     310               0 :       nsIContent* foster = table->GetParent();
     311                 : 
     312               0 :       if (foster && foster->IsElement()) {
     313               0 :         aBuilder->FlushPendingAppendNotifications();
     314                 : 
     315                 :         nsHtml5OtherDocUpdate update(foster->OwnerDoc(),
     316               0 :                                      aBuilder->GetDocument());
     317                 : 
     318               0 :         PRUint32 pos = foster->IndexOf(table);
     319               0 :         rv = foster->InsertChildAt(node, pos, false);
     320               0 :         NS_ENSURE_SUCCESS(rv, rv);
     321               0 :         nsNodeUtils::ContentInserted(foster, node, pos);
     322               0 :         return rv;
     323                 :       }
     324                 : 
     325               0 :       return Append(node, parent, aBuilder);
     326                 :     }
     327                 :     case eTreeOpAppendToDocument: {
     328             234 :       nsIContent* node = *(mOne.node);
     329             234 :       return AppendToDocument(node, aBuilder);
     330                 :     }
     331                 :     case eTreeOpAddAttributes: {
     332               0 :       dom::Element* node = (*(mOne.node))->AsElement();
     333               0 :       nsHtml5HtmlAttributes* attributes = mTwo.attributes;
     334                 : 
     335                 :       nsHtml5OtherDocUpdate update(node->OwnerDoc(),
     336               0 :                                    aBuilder->GetDocument());
     337                 : 
     338               0 :       PRInt32 len = attributes->getLength();
     339               0 :       for (PRInt32 i = len; i > 0;) {
     340               0 :         --i;
     341                 :         // prefix doesn't need regetting. it is always null or a static atom
     342                 :         // local name is never null
     343               0 :         nsCOMPtr<nsIAtom> localName = Reget(attributes->getLocalName(i));
     344               0 :         PRInt32 nsuri = attributes->getURI(i);
     345               0 :         if (!node->HasAttr(nsuri, localName)) {
     346                 :           // prefix doesn't need regetting. it is always null or a static atom
     347                 :           // local name is never null
     348               0 :           node->SetAttr(nsuri, localName, attributes->getPrefix(i), *(attributes->getValue(i)), true);
     349                 :           // XXX what to do with nsresult?
     350                 :         }
     351                 :       }
     352                 :       
     353               0 :       return rv;
     354                 :     }
     355                 :     case eTreeOpCreateElementNetwork:
     356                 :     case eTreeOpCreateElementNotNetwork: {
     357             780 :       nsIContent** target = mOne.node;
     358             780 :       PRInt32 ns = mFour.integer;
     359            1560 :       nsCOMPtr<nsIAtom> name = Reget(mTwo.atom);
     360             780 :       nsHtml5HtmlAttributes* attributes = mThree.attributes;
     361                 :       
     362             780 :       bool isKeygen = (name == nsHtml5Atoms::keygen && ns == kNameSpaceID_XHTML);
     363             780 :       if (NS_UNLIKELY(isKeygen)) {
     364               0 :         name = nsHtml5Atoms::select;
     365                 :       }
     366                 :       
     367            1560 :       nsCOMPtr<nsIContent> newContent;
     368                 :       nsCOMPtr<nsINodeInfo> nodeInfo = aBuilder->GetNodeInfoManager()->
     369            1560 :         GetNodeInfo(name, nsnull, ns, nsIDOMNode::ELEMENT_NODE);
     370             780 :       NS_ASSERTION(nodeInfo, "Got null nodeinfo.");
     371             780 :       NS_NewElement(getter_AddRefs(newContent),
     372                 :                     nodeInfo.forget(),
     373                 :                     (mOpCode == eTreeOpCreateElementNetwork ?
     374                 :                      dom::FROM_PARSER_NETWORK
     375             780 :                      : (aBuilder->BelongsToStringParser() ?
     376                 :                         dom::FROM_PARSER_FRAGMENT :
     377            1560 :                         dom::FROM_PARSER_DOCUMENT_WRITE)));
     378             780 :       NS_ASSERTION(newContent, "Element creation created null pointer.");
     379                 : 
     380             780 :       aBuilder->HoldElement(*target = newContent);      
     381                 : 
     382             780 :       if (NS_UNLIKELY(name == nsHtml5Atoms::style || name == nsHtml5Atoms::link)) {
     383               0 :         nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(newContent));
     384               0 :         if (ssle) {
     385               0 :           ssle->InitStyleLinkElement(false);
     386               0 :           ssle->SetEnableUpdates(false);
     387                 :         }
     388             780 :       } else if (NS_UNLIKELY(isKeygen)) {
     389                 :         // Adapted from CNavDTD
     390                 :         nsCOMPtr<nsIFormProcessor> theFormProcessor =
     391               0 :           do_GetService(kFormProcessorCID, &rv);
     392               0 :         NS_ENSURE_SUCCESS(rv, rv);
     393                 :         
     394               0 :         nsTArray<nsString> theContent;
     395               0 :         nsAutoString theAttribute;
     396                 :          
     397               0 :         (void) theFormProcessor->ProvideContent(NS_LITERAL_STRING("select"),
     398                 :                                                 theContent,
     399               0 :                                                 theAttribute);
     400                 : 
     401               0 :         newContent->SetAttr(kNameSpaceID_None, 
     402                 :                             nsGkAtoms::moztype, 
     403                 :                             nsnull, 
     404                 :                             theAttribute,
     405               0 :                             false);
     406                 : 
     407                 :         nsCOMPtr<nsINodeInfo> optionNodeInfo = 
     408                 :           aBuilder->GetNodeInfoManager()->GetNodeInfo(nsHtml5Atoms::option, 
     409                 :                                                       nsnull, 
     410                 :                                                       kNameSpaceID_XHTML,
     411               0 :                                                       nsIDOMNode::ELEMENT_NODE);
     412                 :                                                       
     413               0 :         for (PRUint32 i = 0; i < theContent.Length(); ++i) {
     414               0 :           nsCOMPtr<nsIContent> optionElt;
     415               0 :           nsCOMPtr<nsINodeInfo> ni = optionNodeInfo;
     416               0 :           NS_NewElement(getter_AddRefs(optionElt), 
     417                 :                         ni.forget(),
     418                 :                         (mOpCode == eTreeOpCreateElementNetwork ?
     419                 :                          dom::FROM_PARSER_NETWORK
     420               0 :                          : (aBuilder->BelongsToStringParser() ?
     421                 :                             dom::FROM_PARSER_FRAGMENT :
     422               0 :                             dom::FROM_PARSER_DOCUMENT_WRITE)));
     423               0 :           nsCOMPtr<nsIContent> optionText;
     424               0 :           NS_NewTextNode(getter_AddRefs(optionText), 
     425               0 :                          aBuilder->GetNodeInfoManager());
     426               0 :           (void) optionText->SetText(theContent[i], false);
     427               0 :           optionElt->AppendChildTo(optionText, false);
     428               0 :           newContent->AppendChildTo(optionElt, false);
     429               0 :           newContent->DoneAddingChildren(false);
     430                 :         }
     431             780 :       } else if (name == nsHtml5Atoms::frameset && ns == kNameSpaceID_XHTML) {
     432               0 :         nsIDocument* doc = aBuilder->GetDocument();
     433               0 :         nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(doc);
     434               0 :         if (htmlDocument) {
     435                 :           // It seems harmless to call this multiple times, since this 
     436                 :           // is a simple field setter
     437               0 :           htmlDocument->SetIsFrameset(true);
     438                 :         }
     439                 :       }
     440                 : 
     441             780 :       if (!attributes) {
     442             780 :         return rv;
     443                 :       }
     444                 : 
     445               0 :       PRInt32 len = attributes->getLength();
     446               0 :       for (PRInt32 i = len; i > 0;) {
     447               0 :         --i;
     448                 :         // prefix doesn't need regetting. it is always null or a static atom
     449                 :         // local name is never null
     450               0 :         nsCOMPtr<nsIAtom> localName = Reget(attributes->getLocalName(i));
     451               0 :         if (ns == kNameSpaceID_XHTML &&
     452               0 :             nsHtml5Atoms::a == name &&
     453               0 :             nsHtml5Atoms::name == localName) {
     454                 :           // This is an HTML5-incompliant Geckoism.
     455                 :           // Remove when fixing bug 582361
     456               0 :           NS_ConvertUTF16toUTF8 cname(*(attributes->getValue(i)));
     457               0 :           NS_ConvertUTF8toUTF16 uv(nsUnescape(cname.BeginWriting()));
     458               0 :           newContent->SetAttr(attributes->getURI(i), localName,
     459               0 :               attributes->getPrefix(i), uv, false);
     460                 :         } else {
     461               0 :           newContent->SetAttr(attributes->getURI(i), localName,
     462               0 :               attributes->getPrefix(i), *(attributes->getValue(i)), false);
     463                 :         }
     464                 :       }
     465                 : 
     466               0 :       return rv;
     467                 :     }
     468                 :     case eTreeOpSetFormElement: {
     469               0 :       nsIContent* node = *(mOne.node);
     470               0 :       nsIContent* parent = *(mTwo.node);
     471               0 :       nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(node));
     472                 :       // NS_ASSERTION(formControl, "Form-associated element did not implement nsIFormControl.");
     473                 :       // TODO: uncomment the above line when <keygen> (bug 101019) is supported by Gecko
     474               0 :       nsCOMPtr<nsIDOMHTMLFormElement> formElement(do_QueryInterface(parent));
     475               0 :       NS_ASSERTION(formElement, "The form element doesn't implement nsIDOMHTMLFormElement.");
     476                 :       // avoid crashing on <keygen>
     477               0 :       if (formControl &&
     478               0 :           !node->HasAttr(kNameSpaceID_None, nsGkAtoms::form)) {
     479               0 :         formControl->SetForm(formElement);
     480                 :       }
     481               0 :       return rv;
     482                 :     }
     483                 :     case eTreeOpAppendText: {
     484             287 :       nsIContent* parent = *mOne.node;
     485             287 :       PRUnichar* buffer = mTwo.unicharPtr;
     486             287 :       PRUint32 length = mFour.integer;
     487             287 :       return AppendText(buffer, length, parent, aBuilder);
     488                 :     }
     489                 :     case eTreeOpAppendIsindexPrompt: {
     490               0 :       nsIContent* parent = *mOne.node;
     491               0 :       nsXPIDLString prompt;
     492                 :       nsresult rv =
     493                 :           nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
     494               0 :                                              "IsIndexPromptWithSpace", prompt);
     495               0 :       PRUint32 len = prompt.Length();
     496               0 :       if (NS_FAILED(rv)) {
     497               0 :         return rv;
     498                 :       }
     499               0 :       if (!len) {
     500                 :         // Don't bother appending a zero-length text node.
     501               0 :         return NS_OK;
     502                 :       }
     503               0 :       return AppendText(prompt.BeginReading(), len, parent, aBuilder);
     504                 :     }
     505                 :     case eTreeOpFosterParentText: {
     506               0 :       nsIContent* stackParent = *mOne.node;
     507               0 :       PRUnichar* buffer = mTwo.unicharPtr;
     508               0 :       PRUint32 length = mFour.integer;
     509               0 :       nsIContent* table = *mThree.node;
     510                 :       
     511               0 :       nsIContent* foster = table->GetParent();
     512                 : 
     513               0 :       if (foster && foster->IsElement()) {
     514               0 :         aBuilder->FlushPendingAppendNotifications();
     515                 : 
     516                 :         nsHtml5OtherDocUpdate update(foster->OwnerDoc(),
     517               0 :                                      aBuilder->GetDocument());
     518                 : 
     519               0 :         PRUint32 pos = foster->IndexOf(table);
     520                 : 
     521               0 :         nsIContent* previousSibling = table->GetPreviousSibling();
     522               0 :         if (previousSibling && previousSibling->IsNodeOfType(nsINode::eTEXT)) {
     523                 :           return AppendTextToTextNode(buffer, 
     524                 :                                       length, 
     525                 :                                       previousSibling, 
     526               0 :                                       aBuilder);
     527                 :         }
     528                 :         
     529               0 :         nsCOMPtr<nsIContent> text;
     530               0 :         NS_NewTextNode(getter_AddRefs(text), aBuilder->GetNodeInfoManager());
     531               0 :         NS_ASSERTION(text, "Infallible malloc failed?");
     532               0 :         rv = text->SetText(buffer, length, false);
     533               0 :         NS_ENSURE_SUCCESS(rv, rv);
     534                 :         
     535               0 :         rv = foster->InsertChildAt(text, pos, false);
     536               0 :         NS_ENSURE_SUCCESS(rv, rv);
     537               0 :         nsNodeUtils::ContentInserted(foster, text, pos);
     538               0 :         return rv;
     539                 :       }
     540                 :       
     541               0 :       return AppendText(buffer, length, stackParent, aBuilder);
     542                 :     }
     543                 :     case eTreeOpAppendComment: {
     544               0 :       nsIContent* parent = *mOne.node;
     545               0 :       PRUnichar* buffer = mTwo.unicharPtr;
     546               0 :       PRInt32 length = mFour.integer;
     547                 :       
     548               0 :       nsCOMPtr<nsIContent> comment;
     549               0 :       NS_NewCommentNode(getter_AddRefs(comment), aBuilder->GetNodeInfoManager());
     550               0 :       NS_ASSERTION(comment, "Infallible malloc failed?");
     551               0 :       rv = comment->SetText(buffer, length, false);
     552               0 :       NS_ENSURE_SUCCESS(rv, rv);
     553                 :       
     554               0 :       return Append(comment, parent, aBuilder);
     555                 :     }
     556                 :     case eTreeOpAppendCommentToDocument: {
     557               0 :       PRUnichar* buffer = mTwo.unicharPtr;
     558               0 :       PRInt32 length = mFour.integer;
     559                 :       
     560               0 :       nsCOMPtr<nsIContent> comment;
     561               0 :       NS_NewCommentNode(getter_AddRefs(comment), aBuilder->GetNodeInfoManager());
     562               0 :       NS_ASSERTION(comment, "Infallible malloc failed?");
     563               0 :       rv = comment->SetText(buffer, length, false);
     564               0 :       NS_ENSURE_SUCCESS(rv, rv);
     565                 :       
     566               0 :       return AppendToDocument(comment, aBuilder);
     567                 :     }
     568                 :     case eTreeOpAppendDoctypeToDocument: {
     569               0 :       nsCOMPtr<nsIAtom> name = Reget(mOne.atom);
     570               0 :       nsHtml5TreeOperationStringPair* pair = mTwo.stringPair;
     571               0 :       nsString publicId;
     572               0 :       nsString systemId;
     573               0 :       pair->Get(publicId, systemId);
     574                 :       
     575                 :       // Adapted from nsXMLContentSink
     576                 :       // Create a new doctype node
     577               0 :       nsCOMPtr<nsIDOMDocumentType> docType;
     578               0 :       nsAutoString voidString;
     579               0 :       voidString.SetIsVoid(true);
     580               0 :       NS_NewDOMDocumentType(getter_AddRefs(docType),
     581                 :                             aBuilder->GetNodeInfoManager(),
     582                 :                             name,
     583                 :                             publicId,
     584                 :                             systemId,
     585               0 :                             voidString);
     586               0 :       NS_ASSERTION(docType, "Doctype creation failed.");
     587               0 :       nsCOMPtr<nsIContent> asContent = do_QueryInterface(docType);
     588               0 :       return AppendToDocument(asContent, aBuilder);
     589                 :     }
     590                 :     case eTreeOpMarkAsBroken: {
     591               0 :       aBuilder->MarkAsBroken();
     592               0 :       return rv;
     593                 :     }
     594                 :     case eTreeOpRunScript: {
     595               0 :       nsIContent* node = *(mOne.node);
     596               0 :       nsAHtml5TreeBuilderState* snapshot = mTwo.state;
     597               0 :       if (snapshot) {
     598               0 :         aBuilder->InitializeDocWriteParserState(snapshot, mFour.integer);
     599                 :       }
     600               0 :       *aScriptElement = node;
     601               0 :       return rv;
     602                 :     }
     603                 :     case eTreeOpRunScriptAsyncDefer: {
     604               0 :       nsIContent* node = *(mOne.node);
     605               0 :       aBuilder->RunScript(node);
     606               0 :       return rv;
     607                 :     }
     608                 :     case eTreeOpDoneAddingChildren: {
     609               0 :       nsIContent* node = *(mOne.node);
     610               0 :       node->DoneAddingChildren(aBuilder->HaveNotified(node));
     611               0 :       return rv;
     612                 :     }
     613                 :     case eTreeOpDoneCreatingElement: {
     614               0 :       nsIContent* node = *(mOne.node);
     615               0 :       node->DoneCreatingElement();
     616               0 :       return rv;
     617                 :     }
     618                 :     case eTreeOpFlushPendingAppendNotifications: {
     619               0 :       aBuilder->FlushPendingAppendNotifications();
     620               0 :       return rv;
     621                 :     }
     622                 :     case eTreeOpSetDocumentCharset: {
     623               0 :       char* str = mOne.charPtr;
     624               0 :       PRInt32 charsetSource = mFour.integer;
     625               0 :       nsDependentCString dependentString(str);
     626               0 :       aBuilder->SetDocumentCharsetAndSource(dependentString, charsetSource);
     627               0 :       return rv;
     628                 :     }
     629                 :     case eTreeOpNeedsCharsetSwitchTo: {
     630               0 :       char* str = mOne.charPtr;
     631               0 :       PRInt32 charsetSource = mFour.integer;
     632               0 :       aBuilder->NeedsCharsetSwitchTo(str, charsetSource);
     633               0 :       return rv;    
     634                 :     }
     635                 :     case eTreeOpUpdateStyleSheet: {
     636               0 :       nsIContent* node = *(mOne.node);
     637               0 :       aBuilder->FlushPendingAppendNotifications();
     638               0 :       aBuilder->UpdateStyleSheet(node);
     639               0 :       return rv;
     640                 :     }
     641                 :     case eTreeOpProcessMeta: {
     642               0 :       nsIContent* node = *(mOne.node);
     643               0 :       rv = aBuilder->ProcessMETATag(node);
     644               0 :       return rv;
     645                 :     }
     646                 :     case eTreeOpProcessOfflineManifest: {
     647             234 :       PRUnichar* str = mOne.unicharPtr;
     648             468 :       nsDependentString dependentString(str);
     649             234 :       aBuilder->ProcessOfflineManifest(dependentString);
     650             234 :       return rv;
     651                 :     }
     652                 :     case eTreeOpMarkMalformedIfScript: {
     653             468 :       nsIContent* node = *(mOne.node);
     654             936 :       nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node);
     655             468 :       if (sele) {
     656                 :         // Make sure to serialize this script correctly, for nice round tripping.
     657               0 :         sele->SetIsMalformed();
     658                 :       }
     659             468 :       return rv;
     660                 :     }
     661                 :     case eTreeOpStreamEnded: {
     662             234 :       aBuilder->DidBuildModel(false); // this causes a notifications flush anyway
     663             234 :       return rv;
     664                 :     }
     665                 :     case eTreeOpStartLayout: {
     666             234 :       aBuilder->StartLayout(); // this causes a notification flush anyway
     667             234 :       return rv;
     668                 :     }
     669                 :     case eTreeOpDocumentMode: {
     670             234 :       aBuilder->SetDocumentMode(mOne.mode);
     671             234 :       return rv;
     672                 :     }
     673                 :     case eTreeOpSetStyleLineNumber: {
     674               0 :       nsIContent* node = *(mOne.node);
     675               0 :       nsCOMPtr<nsIStyleSheetLinkingElement> ssle = do_QueryInterface(node);
     676               0 :       NS_ASSERTION(ssle, "Node didn't QI to style.");
     677               0 :       ssle->SetLineNumber(mFour.integer);
     678               0 :       return rv;
     679                 :     }
     680                 :     case eTreeOpSetScriptLineNumberAndFreeze: {
     681               0 :       nsIContent* node = *(mOne.node);
     682               0 :       nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node);
     683               0 :       NS_ASSERTION(sele, "Node didn't QI to script.");
     684               0 :       sele->SetScriptLineNumber(mFour.integer);
     685               0 :       sele->FreezeUriAsyncDefer();
     686               0 :       return rv;
     687                 :     }
     688                 :     case eTreeOpSvgLoad: {
     689               0 :       nsIContent* node = *(mOne.node);
     690               0 :       nsCOMPtr<nsIRunnable> event = new nsHtml5SVGLoadDispatcher(node);
     691               0 :       if (NS_FAILED(NS_DispatchToMainThread(event))) {
     692               0 :         NS_WARNING("failed to dispatch svg load dispatcher");
     693                 :       }
     694               0 :       return rv;
     695                 :     }
     696                 :     case eTreeOpAddClass: {
     697               0 :       nsIContent* node = *(mOne.node);
     698               0 :       PRUnichar* str = mTwo.unicharPtr;
     699               0 :       nsDependentString depStr(str);
     700                 :       // See viewsource.css for the possible classes
     701               0 :       nsAutoString klass;
     702               0 :       node->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass);
     703               0 :       if (!klass.IsEmpty()) {
     704               0 :         klass.Append(' ');
     705               0 :         klass.Append(depStr);
     706               0 :         node->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass, true);
     707                 :       } else {
     708               0 :         node->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, depStr, true);
     709                 :       }
     710               0 :       return rv;
     711                 :     }
     712                 :     case eTreeOpAddLineNumberId: {
     713               0 :       nsIContent* node = *(mOne.node);
     714               0 :       PRInt32 lineNumber = mFour.integer;
     715               0 :       nsAutoString val(NS_LITERAL_STRING("line"));
     716               0 :       val.AppendInt(lineNumber);
     717               0 :       node->SetAttr(kNameSpaceID_None, nsGkAtoms::id, val, true);
     718               0 :       return rv;
     719                 :     }
     720                 :     case eTreeOpAddViewSourceHref: {
     721               0 :       nsIContent* node = *mOne.node;
     722               0 :       PRUnichar* buffer = mTwo.unicharPtr;
     723               0 :       PRInt32 length = mFour.integer;
     724                 : 
     725               0 :       nsDependentString relative(buffer, length);
     726                 : 
     727               0 :       nsIDocument* doc = aBuilder->GetDocument();
     728                 : 
     729               0 :       const nsCString& charset = doc->GetDocumentCharacterSet();
     730               0 :       nsCOMPtr<nsIURI> uri;
     731               0 :       rv = NS_NewURI(getter_AddRefs(uri),
     732                 :                      relative,
     733                 :                      charset.get(),
     734               0 :                      aBuilder->GetViewSourceBaseURI());
     735               0 :       NS_ENSURE_SUCCESS(rv, rv);
     736                 : 
     737                 :       // Reuse the fix for bug 467852
     738                 :       // URLs that execute script (e.g. "javascript:" URLs) should just be
     739                 :       // ignored.  There's nothing reasonable we can do with them, and allowing
     740                 :       // them to execute in the context of the view-source window presents a
     741                 :       // security risk.  Just return the empty string in this case.
     742               0 :       bool openingExecutesScript = false;
     743                 :       rv = NS_URIChainHasFlags(uri,
     744                 :                                nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT,
     745               0 :                                &openingExecutesScript);
     746               0 :       if (NS_FAILED(rv) || openingExecutesScript) {
     747               0 :         return NS_OK;
     748                 :       }
     749                 : 
     750               0 :       nsCAutoString viewSourceUrl;
     751                 : 
     752                 :       // URLs that return data (e.g. "http:" URLs) should be prefixed with
     753                 :       // "view-source:".  URLs that don't return data should just be returned
     754                 :       // undecorated.
     755               0 :       bool doesNotReturnData = false;
     756                 :       rv = NS_URIChainHasFlags(uri,
     757                 :                                nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA,
     758               0 :                                &doesNotReturnData);
     759               0 :       NS_ENSURE_SUCCESS(rv, NS_OK);
     760               0 :       if (!doesNotReturnData) {
     761               0 :         viewSourceUrl.AssignLiteral("view-source:");
     762                 :       }
     763                 : 
     764               0 :       nsCAutoString spec;
     765               0 :       uri->GetSpec(spec);
     766                 : 
     767               0 :       viewSourceUrl.Append(spec);
     768                 : 
     769               0 :       nsAutoString utf16;
     770               0 :       CopyUTF8toUTF16(viewSourceUrl, utf16);
     771                 : 
     772               0 :       node->SetAttr(kNameSpaceID_None, nsGkAtoms::href, utf16, true);
     773               0 :       return rv;
     774                 :     }
     775                 :     case eTreeOpAddError: {
     776               0 :       nsIContent* node = *(mOne.node);
     777               0 :       char* msgId = mTwo.charPtr;
     778               0 :       nsCOMPtr<nsIAtom> atom = Reget(mThree.atom);
     779               0 :       nsCOMPtr<nsIAtom> otherAtom = Reget(mFour.atom);
     780                 :       // See viewsource.css for the possible classes in addition to "error".
     781               0 :       nsAutoString klass;
     782               0 :       node->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass);
     783               0 :       if (!klass.IsEmpty()) {
     784               0 :         klass.Append(NS_LITERAL_STRING(" error"));
     785               0 :         node->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass, true);
     786                 :       } else {
     787                 :         node->SetAttr(kNameSpaceID_None,
     788                 :                       nsGkAtoms::_class,
     789               0 :                       NS_LITERAL_STRING("error"),
     790               0 :                       true);
     791                 :       }
     792                 : 
     793               0 :       nsXPIDLString message;
     794               0 :       if (otherAtom) {
     795               0 :         const PRUnichar* params[] = { atom->GetUTF16String(),
     796               0 :                                       otherAtom->GetUTF16String() };
     797                 :         rv = nsContentUtils::FormatLocalizedString(
     798               0 :           nsContentUtils::eHTMLPARSER_PROPERTIES, msgId, params, message);
     799               0 :         NS_ENSURE_SUCCESS(rv, rv);
     800               0 :       } else if (atom) {
     801               0 :         const PRUnichar* params[] = { atom->GetUTF16String() };
     802                 :         rv = nsContentUtils::FormatLocalizedString(
     803               0 :           nsContentUtils::eHTMLPARSER_PROPERTIES, msgId, params, message);
     804               0 :         NS_ENSURE_SUCCESS(rv, rv);
     805                 :       } else {
     806                 :         rv = nsContentUtils::GetLocalizedString(
     807               0 :           nsContentUtils::eHTMLPARSER_PROPERTIES, msgId, message);
     808               0 :         NS_ENSURE_SUCCESS(rv, rv);
     809                 :       }
     810                 : 
     811               0 :       nsAutoString title;
     812               0 :       node->GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
     813               0 :       if (!title.IsEmpty()) {
     814               0 :         title.Append('\n');
     815               0 :         title.Append(message);
     816               0 :         node->SetAttr(kNameSpaceID_None, nsGkAtoms::title, title, true);
     817                 :       } else {
     818               0 :         node->SetAttr(kNameSpaceID_None, nsGkAtoms::title, message, true);
     819                 :       }
     820               0 :       return rv;
     821                 :     }
     822                 :     default: {
     823               0 :       NS_NOTREACHED("Bogus tree op");
     824                 :     }
     825                 :   }
     826               0 :   return rv; // keep compiler happy
     827                 : }

Generated by: LCOV version 1.7