LCOV - code coverage report
Current view: directory - content/xml/document/src - nsXMLContentSink.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 762 461 60.5 %
Date: 2012-06-02 Functions: 62 49 79.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 "nsCOMPtr.h"
      42                 : #include "nsXMLContentSink.h"
      43                 : #include "nsIParser.h"
      44                 : #include "nsIDocument.h"
      45                 : #include "nsIDOMDocument.h"
      46                 : #include "nsIDOMDocumentType.h"
      47                 : #include "nsIDOMDOMImplementation.h"
      48                 : #include "nsIContent.h"
      49                 : #include "nsIURI.h"
      50                 : #include "nsNetUtil.h"
      51                 : #include "nsIDocShell.h"
      52                 : #include "nsIDocShellTreeItem.h"
      53                 : #include "nsIStyleSheetLinkingElement.h"
      54                 : #include "nsIDOMComment.h"
      55                 : #include "nsIDOMCDATASection.h"
      56                 : #include "nsDOMDocumentType.h"
      57                 : #include "nsHTMLParts.h"
      58                 : #include "nsCRT.h"
      59                 : #include "nsCSSStyleSheet.h"
      60                 : #include "mozilla/css/Loader.h"
      61                 : #include "nsGkAtoms.h"
      62                 : #include "nsContentUtils.h"
      63                 : #include "nsIScriptContext.h"
      64                 : #include "nsINameSpaceManager.h"
      65                 : #include "nsIServiceManager.h"
      66                 : #include "nsIScriptSecurityManager.h"
      67                 : #include "nsIContentViewer.h"
      68                 : #include "prtime.h"
      69                 : #include "prlog.h"
      70                 : #include "prmem.h"
      71                 : #include "nsRect.h"
      72                 : #include "nsGenericElement.h"
      73                 : #include "nsIWebNavigation.h"
      74                 : #include "nsIScriptElement.h"
      75                 : #include "nsScriptLoader.h"
      76                 : #include "nsStyleLinkElement.h"
      77                 : #include "nsIImageLoadingContent.h"
      78                 : #include "nsReadableUtils.h"
      79                 : #include "nsUnicharUtils.h"
      80                 : #include "nsICookieService.h"
      81                 : #include "nsIPrompt.h"
      82                 : #include "nsIChannel.h"
      83                 : #include "nsIPrincipal.h"
      84                 : #include "nsXMLPrettyPrinter.h"
      85                 : #include "nsNodeInfoManager.h"
      86                 : #include "nsContentCreatorFunctions.h"
      87                 : #include "nsIContentPolicy.h"
      88                 : #include "nsIContentViewer.h"
      89                 : #include "nsContentPolicyUtils.h"
      90                 : #include "nsContentErrors.h"
      91                 : #include "nsIDOMProcessingInstruction.h"
      92                 : #include "nsNodeUtils.h"
      93                 : #include "nsIScriptGlobalObject.h"
      94                 : #include "nsIHTMLDocument.h"
      95                 : #include "mozAutoDocUpdate.h"
      96                 : #include "nsMimeTypes.h"
      97                 : #include "nsHtml5SVGLoadDispatcher.h"
      98                 : 
      99                 : using namespace mozilla::dom;
     100                 : 
     101                 : // XXX Open Issues:
     102                 : // 1) what's not allowed - We need to figure out which HTML tags
     103                 : //    (prefixed with a HTML namespace qualifier) are explicitly not
     104                 : //    allowed (if any).
     105                 : // 2) factoring code with nsHTMLContentSink - There's some amount of
     106                 : //    common code between this and the HTML content sink. This will
     107                 : //    increase as we support more and more HTML elements. How can code
     108                 : //    from the code be factored?
     109                 : 
     110                 : nsresult
     111            1038 : NS_NewXMLContentSink(nsIXMLContentSink** aResult,
     112                 :                      nsIDocument* aDoc,
     113                 :                      nsIURI* aURI,
     114                 :                      nsISupports* aContainer,
     115                 :                      nsIChannel* aChannel)
     116                 : {
     117            1038 :   NS_PRECONDITION(nsnull != aResult, "null ptr");
     118            1038 :   if (nsnull == aResult) {
     119               0 :     return NS_ERROR_NULL_POINTER;
     120                 :   }
     121            1038 :   nsXMLContentSink* it = new nsXMLContentSink();
     122            1038 :   if (nsnull == it) {
     123               0 :     return NS_ERROR_OUT_OF_MEMORY;
     124                 :   }
     125                 :   
     126            2076 :   nsCOMPtr<nsIXMLContentSink> kungFuDeathGrip = it;
     127            1038 :   nsresult rv = it->Init(aDoc, aURI, aContainer, aChannel);
     128            1038 :   NS_ENSURE_SUCCESS(rv, rv);
     129                 :   
     130            1038 :   return CallQueryInterface(it, aResult);
     131                 : }
     132                 : 
     133            1039 : nsXMLContentSink::nsXMLContentSink()
     134                 :   : mConstrainSize(true),
     135            1039 :     mPrettyPrintXML(true)
     136                 : {
     137            1039 : }
     138                 : 
     139            3116 : nsXMLContentSink::~nsXMLContentSink()
     140                 : {
     141            1039 :   NS_IF_RELEASE(mDocElement);
     142            1039 :   if (mText) {
     143             769 :     PR_Free(mText);  //  Doesn't null out, unlike PR_FREEIF
     144                 :   }
     145            2077 : }
     146                 : 
     147                 : nsresult
     148            1038 : nsXMLContentSink::Init(nsIDocument* aDoc,
     149                 :                        nsIURI* aURI,
     150                 :                        nsISupports* aContainer,
     151                 :                        nsIChannel* aChannel)
     152                 : {
     153            1038 :   nsresult rv = nsContentSink::Init(aDoc, aURI, aContainer, aChannel);
     154            1038 :   NS_ENSURE_SUCCESS(rv, rv);
     155                 : 
     156            1038 :   aDoc->AddObserver(this);
     157            1038 :   mIsDocumentObserver = true;
     158                 : 
     159            1038 :   if (!mDocShell) {
     160            1038 :     mPrettyPrintXML = false;
     161                 :   }
     162                 :   
     163            1038 :   mState = eXMLContentSinkState_InProlog;
     164            1038 :   mDocElement = nsnull;
     165                 : 
     166            1038 :   return NS_OK;
     167                 : }
     168                 : 
     169           34518 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXMLContentSink)
     170           18382 :   NS_INTERFACE_MAP_ENTRY(nsIContentSink)
     171           16303 :   NS_INTERFACE_MAP_ENTRY(nsIXMLContentSink)
     172           13189 :   NS_INTERFACE_MAP_ENTRY(nsIExpatSink)
     173           12142 :   NS_INTERFACE_MAP_ENTRY(nsITransformObserver)
     174           12142 : NS_INTERFACE_MAP_END_INHERITING(nsContentSink)
     175                 : 
     176           29424 : NS_IMPL_ADDREF_INHERITED(nsXMLContentSink, nsContentSink)
     177           29424 : NS_IMPL_RELEASE_INHERITED(nsXMLContentSink, nsContentSink)
     178                 : 
     179            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLContentSink)
     180                 : 
     181               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLContentSink,
     182                 :                                                   nsContentSink)
     183               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCurrentHead)
     184               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDocElement)
     185               0 :   for (PRUint32 i = 0, count = tmp->mContentStack.Length(); i < count; i++) {
     186               0 :     const StackNode& node = tmp->mContentStack.ElementAt(i);
     187               0 :     cb.NoteXPCOMChild(node.mContent);
     188                 :   }
     189               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     190                 : 
     191                 : // nsIContentSink
     192                 : NS_IMETHODIMP
     193            2153 : nsXMLContentSink::WillParse(void)
     194                 : {
     195            2153 :   return WillParseImpl();
     196                 : }
     197                 : 
     198                 : NS_IMETHODIMP
     199            1038 : nsXMLContentSink::WillBuildModel(nsDTDMode aDTDMode)
     200                 : {
     201            1038 :   WillBuildModelImpl();
     202                 : 
     203                 :   // Notify document that the load is beginning
     204            1038 :   mDocument->BeginLoad();
     205                 : 
     206                 :   // Check for correct load-command for maybe prettyprinting
     207            1038 :   if (mPrettyPrintXML) {
     208               0 :     nsCAutoString command;
     209               0 :     GetParser()->GetCommand(command);
     210               0 :     if (!command.EqualsLiteral("view")) {
     211               0 :       mPrettyPrintXML = false;
     212                 :     }
     213                 :   }
     214                 :   
     215            1038 :   return NS_OK;
     216                 : }
     217                 : 
     218                 : bool
     219            2076 : nsXMLContentSink::CanStillPrettyPrint()
     220                 : {
     221                 :   return mPrettyPrintXML &&
     222            2076 :          (!mPrettyPrintHasFactoredElements || mPrettyPrintHasSpecialRoot);
     223                 : }
     224                 : 
     225                 : nsresult
     226            1038 : nsXMLContentSink::MaybePrettyPrint()
     227                 : {
     228            1038 :   if (!CanStillPrettyPrint()) {
     229            1038 :     mPrettyPrintXML = false;
     230                 : 
     231            1038 :     return NS_OK;
     232                 :   }
     233                 : 
     234                 :   // stop observing in order to avoid crashing when replacing content
     235               0 :   mDocument->RemoveObserver(this);
     236               0 :   mIsDocumentObserver = false;
     237                 : 
     238                 :   // Reenable the CSSLoader so that the prettyprinting stylesheets can load
     239               0 :   if (mCSSLoader) {
     240               0 :     mCSSLoader->SetEnabled(true);
     241                 :   }
     242                 :   
     243               0 :   nsCOMPtr<nsXMLPrettyPrinter> printer;
     244               0 :   nsresult rv = NS_NewXMLPrettyPrinter(getter_AddRefs(printer));
     245               0 :   NS_ENSURE_SUCCESS(rv, rv);
     246                 : 
     247                 :   bool isPrettyPrinting;
     248               0 :   rv = printer->PrettyPrint(mDocument, &isPrettyPrinting);
     249               0 :   NS_ENSURE_SUCCESS(rv, rv);
     250                 : 
     251               0 :   mPrettyPrinting = isPrettyPrinting;
     252               0 :   return NS_OK;
     253                 : }
     254                 : 
     255                 : static void
     256               0 : CheckXSLTParamPI(nsIDOMProcessingInstruction* aPi,
     257                 :                  nsIDocumentTransformer* aProcessor,
     258                 :                  nsIDocument* aDocument)
     259                 : {
     260               0 :   nsAutoString target, data;
     261               0 :   aPi->GetTarget(target);
     262                 : 
     263                 :   // Check for namespace declarations
     264               0 :   if (target.EqualsLiteral("xslt-param-namespace")) {
     265               0 :     aPi->GetData(data);
     266               0 :     nsAutoString prefix, namespaceAttr;
     267                 :     nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::prefix,
     268               0 :                                             prefix);
     269               0 :     if (!prefix.IsEmpty() &&
     270                 :         nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::_namespace,
     271               0 :                                                 namespaceAttr)) {
     272               0 :       aProcessor->AddXSLTParamNamespace(prefix, namespaceAttr);
     273                 :     }
     274                 :   }
     275                 : 
     276                 :   // Check for actual parameters
     277               0 :   else if (target.EqualsLiteral("xslt-param")) {
     278               0 :     aPi->GetData(data);
     279               0 :     nsAutoString name, namespaceAttr, select, value;
     280                 :     nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::name,
     281               0 :                                             name);
     282                 :     nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::_namespace,
     283               0 :                                             namespaceAttr);
     284               0 :     if (!nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::select, select)) {
     285               0 :       select.SetIsVoid(true);
     286                 :     }
     287               0 :     if (!nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::value, value)) {
     288               0 :       value.SetIsVoid(true);
     289                 :     }
     290               0 :     if (!name.IsEmpty()) {
     291               0 :       nsCOMPtr<nsIDOMNode> doc = do_QueryInterface(aDocument);
     292               0 :       aProcessor->AddXSLTParam(name, namespaceAttr, select, value, doc);
     293                 :     }
     294                 :   }
     295               0 : }
     296                 : 
     297                 : NS_IMETHODIMP
     298            1038 : nsXMLContentSink::DidBuildModel(bool aTerminated)
     299                 : {
     300            1038 :   DidBuildModelImpl(aTerminated);
     301                 : 
     302            1038 :   if (mXSLTProcessor) {
     303                 :     // stop observing in order to avoid crashing when replacing content
     304               0 :     mDocument->RemoveObserver(this);
     305               0 :     mIsDocumentObserver = false;
     306                 : 
     307                 :     // Check for xslt-param and xslt-param-namespace PIs
     308               0 :     for (nsIContent* child = mDocument->GetFirstChild();
     309                 :          child;
     310               0 :          child = child->GetNextSibling()) {
     311               0 :       if (child->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
     312               0 :         nsCOMPtr<nsIDOMProcessingInstruction> pi = do_QueryInterface(child);
     313               0 :         CheckXSLTParamPI(pi, mXSLTProcessor, mDocument);
     314                 :       }
     315               0 :       else if (child->IsElement()) {
     316                 :         // Only honor PIs in the prolog
     317               0 :         break;
     318                 :       }
     319                 :     }
     320                 : 
     321               0 :     nsCOMPtr<nsIDOMDocument> currentDOMDoc(do_QueryInterface(mDocument));
     322               0 :     mXSLTProcessor->SetSourceContentModel(currentDOMDoc);
     323                 :     // Since the processor now holds a reference to us we drop our reference
     324                 :     // to it to avoid owning cycles
     325               0 :     mXSLTProcessor = nsnull;
     326                 :   }
     327                 :   else {
     328                 :     // Kick off layout for non-XSLT transformed documents.
     329                 : 
     330                 :     // Check if we want to prettyprint
     331            1038 :     MaybePrettyPrint();
     332                 : 
     333            1038 :     bool startLayout = true;
     334                 :     
     335            1038 :     if (mPrettyPrinting) {
     336               0 :       NS_ASSERTION(!mPendingSheetCount, "Shouldn't have pending sheets here!");
     337                 :       
     338                 :       // We're pretty-printing now.  See whether we should wait up on
     339                 :       // stylesheet loads
     340               0 :       if (mDocument->CSSLoader()->HasPendingLoads() &&
     341               0 :           NS_SUCCEEDED(mDocument->CSSLoader()->AddObserver(this))) {
     342                 :         // wait for those sheets to load
     343               0 :         startLayout = false;
     344                 :       }
     345                 :     }
     346                 :     
     347            1038 :     if (startLayout) {
     348            1038 :       StartLayout(false);
     349                 : 
     350            1038 :       ScrollToRef();
     351                 :     }
     352                 : 
     353            1038 :     mDocument->RemoveObserver(this);
     354            1038 :     mIsDocumentObserver = false;
     355                 : 
     356            1038 :     mDocument->EndLoad();
     357                 :   }
     358                 : 
     359            1038 :   DropParserAndPerfHint();
     360                 : 
     361            1038 :   return NS_OK;
     362                 : }
     363                 : 
     364                 : NS_IMETHODIMP
     365               0 : nsXMLContentSink::OnDocumentCreated(nsIDocument* aResultDocument)
     366                 : {
     367               0 :   NS_ENSURE_ARG(aResultDocument);
     368                 : 
     369               0 :   nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(aResultDocument);
     370               0 :   if (htmlDoc) {
     371               0 :     htmlDoc->SetDocWriteDisabled(true);
     372                 :   }
     373                 : 
     374               0 :   nsCOMPtr<nsIContentViewer> contentViewer;
     375               0 :   mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
     376               0 :   if (contentViewer) {
     377               0 :     return contentViewer->SetDocumentInternal(aResultDocument, true);
     378                 :   }
     379               0 :   return NS_OK;
     380                 : }
     381                 : 
     382                 : NS_IMETHODIMP
     383               0 : nsXMLContentSink::OnTransformDone(nsresult aResult,
     384                 :                                   nsIDocument* aResultDocument)
     385                 : {
     386               0 :   NS_ASSERTION(NS_FAILED(aResult) || aResultDocument,
     387                 :                "Don't notify about transform success without a document.");
     388                 : 
     389               0 :   nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aResultDocument);
     390                 : 
     391               0 :   nsCOMPtr<nsIContentViewer> contentViewer;
     392               0 :   mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
     393                 : 
     394               0 :   if (NS_FAILED(aResult) && contentViewer) {
     395                 :     // Transform failed.
     396               0 :     if (domDoc) {
     397               0 :       aResultDocument->SetMayStartLayout(false);
     398                 :       // We have an error document.
     399               0 :       contentViewer->SetDOMDocument(domDoc);
     400                 :     }
     401                 :     else {
     402                 :       // We don't have an error document, display the
     403                 :       // untransformed source document.
     404               0 :       nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(mDocument);
     405               0 :       contentViewer->SetDOMDocument(document);
     406                 :     }
     407                 :   }
     408                 : 
     409               0 :   nsCOMPtr<nsIDocument> originalDocument = mDocument;
     410               0 :   if (NS_SUCCEEDED(aResult) || aResultDocument) {
     411                 :     // Transform succeeded or it failed and we have an error
     412                 :     // document to display.
     413               0 :     mDocument = aResultDocument;
     414               0 :     nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
     415               0 :     if (htmlDoc) {
     416               0 :       htmlDoc->SetDocWriteDisabled(false);
     417                 :     }
     418                 :   }
     419                 : 
     420                 :   // Notify document observers that all the content has been stuck
     421                 :   // into the document.  
     422                 :   // XXX do we need to notify for things like PIs?  Or just the
     423                 :   // documentElement?
     424               0 :   nsIContent *rootElement = mDocument->GetRootElement();
     425               0 :   if (rootElement) {
     426               0 :     NS_ASSERTION(mDocument->IndexOf(rootElement) != -1,
     427                 :                  "rootElement not in doc?");
     428               0 :     mDocument->BeginUpdate(UPDATE_CONTENT_MODEL);
     429                 :     nsNodeUtils::ContentInserted(mDocument, rootElement,
     430               0 :                                  mDocument->IndexOf(rootElement));
     431               0 :     mDocument->EndUpdate(UPDATE_CONTENT_MODEL);
     432                 :   }
     433                 : 
     434                 :   // Start the layout process
     435               0 :   StartLayout(false);
     436                 : 
     437               0 :   ScrollToRef();
     438                 : 
     439               0 :   originalDocument->EndLoad();
     440                 : 
     441               0 :   return NS_OK;
     442                 : }
     443                 : 
     444                 : NS_IMETHODIMP
     445               0 : nsXMLContentSink::StyleSheetLoaded(nsCSSStyleSheet* aSheet,
     446                 :                                    bool aWasAlternate,
     447                 :                                    nsresult aStatus)
     448                 : {
     449               0 :   if (!mPrettyPrinting) {
     450               0 :     return nsContentSink::StyleSheetLoaded(aSheet, aWasAlternate, aStatus);
     451                 :   }
     452                 : 
     453               0 :   if (!mDocument->CSSLoader()->HasPendingLoads()) {
     454               0 :     mDocument->CSSLoader()->RemoveObserver(this);
     455               0 :     StartLayout(false);
     456               0 :     ScrollToRef();
     457                 :   }
     458                 : 
     459               0 :   return NS_OK;
     460                 : }
     461                 : 
     462                 : NS_IMETHODIMP
     463            1117 : nsXMLContentSink::WillInterrupt(void)
     464                 : {
     465            1117 :   return WillInterruptImpl();
     466                 : }
     467                 : 
     468                 : NS_IMETHODIMP
     469            2156 : nsXMLContentSink::WillResume(void)
     470                 : {
     471            2156 :   return WillResumeImpl();
     472                 : }
     473                 : 
     474                 : NS_IMETHODIMP
     475            1039 : nsXMLContentSink::SetParser(nsParserBase* aParser)
     476                 : {
     477            1039 :   NS_PRECONDITION(aParser, "Should have a parser here!");
     478            1039 :   mParser = aParser;
     479            1039 :   return NS_OK;
     480                 : }
     481                 : 
     482                 : nsresult
     483           36753 : nsXMLContentSink::CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount,
     484                 :                                 nsINodeInfo* aNodeInfo, PRUint32 aLineNumber,
     485                 :                                 nsIContent** aResult, bool* aAppendContent,
     486                 :                                 FromParser aFromParser)
     487                 : {
     488           36753 :   NS_ASSERTION(aNodeInfo, "can't create element without nodeinfo");
     489                 : 
     490           36753 :   *aResult = nsnull;
     491           36753 :   *aAppendContent = true;
     492           36753 :   nsresult rv = NS_OK;
     493                 : 
     494           73506 :   nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
     495           73506 :   nsCOMPtr<nsIContent> content;
     496           36753 :   rv = NS_NewElement(getter_AddRefs(content), ni.forget(), aFromParser);
     497           36753 :   NS_ENSURE_SUCCESS(rv, rv);
     498                 : 
     499           73506 :   if (aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML)
     500           36753 :       || aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_SVG)
     501                 :     ) {
     502               0 :     nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(content);
     503               0 :     sele->SetScriptLineNumber(aLineNumber);
     504               0 :     sele->SetCreatorParser(GetParser());
     505               0 :     mConstrainSize = false;
     506                 :   }
     507                 : 
     508                 :   // XHTML needs some special attention
     509           36753 :   if (aNodeInfo->NamespaceEquals(kNameSpaceID_XHTML)) {
     510              11 :     mPrettyPrintHasFactoredElements = true;
     511                 :   }
     512                 :   else {
     513                 :     // If we care, find out if we just used a special factory.
     514           36742 :     if (!mPrettyPrintHasFactoredElements && !mPrettyPrintHasSpecialRoot &&
     515                 :         mPrettyPrintXML) {
     516                 :       mPrettyPrintHasFactoredElements =
     517               0 :         nsContentUtils::NameSpaceManager()->
     518               0 :           HasElementCreator(aNodeInfo->NamespaceID());
     519                 :     }
     520                 : 
     521           36742 :     if (!aNodeInfo->NamespaceEquals(kNameSpaceID_SVG)) {
     522           36742 :       content.swap(*aResult);
     523                 : 
     524           36742 :       return NS_OK;
     525                 :     }
     526                 :   }
     527                 : 
     528              33 :   if (aNodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML) ||
     529              11 :       aNodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_XHTML) ||
     530              11 :       aNodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_SVG)) {
     531               0 :     nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(content));
     532               0 :     if (ssle) {
     533               0 :       ssle->InitStyleLinkElement(false);
     534               0 :       if (aFromParser) {
     535               0 :         ssle->SetEnableUpdates(false);
     536                 :       }
     537               0 :       if (!aNodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML)) {
     538               0 :         ssle->SetLineNumber(aFromParser ? aLineNumber : 0);
     539                 :       }
     540                 :     }
     541                 :   } 
     542                 : 
     543              11 :   content.swap(*aResult);
     544                 : 
     545              11 :   return NS_OK;
     546                 : }
     547                 : 
     548                 : 
     549                 : nsresult
     550           36741 : nsXMLContentSink::CloseElement(nsIContent* aContent)
     551                 : {
     552           36741 :   NS_ASSERTION(aContent, "missing element to close");
     553                 : 
     554           36741 :   nsINodeInfo *nodeInfo = aContent->NodeInfo();
     555                 : 
     556                 :   // Some HTML nodes need DoneAddingChildren() called to initialize
     557                 :   // properly (eg form state restoration).
     558           90906 :   if ((nodeInfo->NamespaceID() == kNameSpaceID_XHTML &&
     559               9 :        (nodeInfo->NameAtom() == nsGkAtoms::select ||
     560               9 :         nodeInfo->NameAtom() == nsGkAtoms::textarea ||
     561                 : #ifdef MOZ_MEDIA
     562               9 :         nodeInfo->NameAtom() == nsGkAtoms::video ||
     563               9 :         nodeInfo->NameAtom() == nsGkAtoms::audio ||
     564                 : #endif
     565               9 :         nodeInfo->NameAtom() == nsGkAtoms::object ||
     566               9 :         nodeInfo->NameAtom() == nsGkAtoms::applet))
     567                 : #ifdef MOZ_XTF
     568           36741 :       || nodeInfo->NamespaceID() > kNameSpaceID_LastBuiltin
     569                 : #endif
     570           17370 :       || nodeInfo->NameAtom() == nsGkAtoms::title
     571                 :       ) {
     572           19421 :     aContent->DoneAddingChildren(HaveNotifiedForCurrentContent());
     573                 :   }
     574                 :   
     575           36741 :   if (IsMonolithicContainer(nodeInfo)) {
     576               0 :     mInMonolithicContainer--;
     577                 :   }
     578                 : 
     579           73473 :   if (!nodeInfo->NamespaceEquals(kNameSpaceID_XHTML) &&
     580           36732 :       !nodeInfo->NamespaceEquals(kNameSpaceID_SVG)) {
     581           36732 :     return NS_OK;
     582                 :   }
     583                 : 
     584              18 :   if (nodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML)
     585               9 :       || nodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_SVG)
     586                 :     ) {
     587               0 :     mConstrainSize = true; 
     588               0 :     nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aContent);
     589                 : 
     590               0 :     if (mPreventScriptExecution) {
     591               0 :       sele->PreventExecution();
     592               0 :       return NS_OK;
     593                 :     }
     594                 : 
     595                 :     // Always check the clock in nsContentSink right after a script
     596               0 :     StopDeflecting();
     597                 : 
     598                 :     // Now tell the script that it's ready to go. This may execute the script
     599                 :     // or return true, or neither if the script doesn't need executing.
     600               0 :     bool block = sele->AttemptToExecute();
     601                 : 
     602                 :     // If the parser got blocked, make sure to return the appropriate rv.
     603                 :     // I'm not sure if this is actually needed or not.
     604               0 :     if (mParser && !mParser->IsParserEnabled()) {
     605                 :       // XXX The HTML sink doesn't call BlockParser here, why do we?
     606               0 :       GetParser()->BlockParser();
     607               0 :       block = true;
     608                 :     }
     609                 : 
     610               0 :     return block ? NS_ERROR_HTMLPARSER_BLOCK : NS_OK;
     611                 :   }
     612                 :   
     613               9 :   nsresult rv = NS_OK;
     614               9 :   if (nodeInfo->Equals(nsGkAtoms::meta, kNameSpaceID_XHTML) &&
     615                 :            // Need to check here to make sure this meta tag does not set
     616                 :            // mPrettyPrintXML to false when we have a special root!
     617               0 :            (!mPrettyPrintXML || !mPrettyPrintHasSpecialRoot)) {
     618               0 :     rv = ProcessMETATag(aContent);
     619                 :   }
     620              27 :   else if (nodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML) ||
     621               9 :            nodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_XHTML) ||
     622               9 :            nodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_SVG)) {
     623               0 :     nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(aContent));
     624               0 :     if (ssle) {
     625               0 :       ssle->SetEnableUpdates(true);
     626                 :       bool willNotify;
     627                 :       bool isAlternate;
     628               0 :       rv = ssle->UpdateStyleSheet(mRunsToCompletion ? nsnull : this,
     629                 :                                   &willNotify,
     630               0 :                                   &isAlternate);
     631               0 :       if (NS_SUCCEEDED(rv) && willNotify && !isAlternate && !mRunsToCompletion) {
     632               0 :         ++mPendingSheetCount;
     633               0 :         mScriptLoader->AddExecuteBlocker();
     634                 :       }
     635                 :     }
     636                 :     // Look for <link rel="dns-prefetch" href="hostname">
     637                 :     // and look for <link rel="next" href="hostname"> like in HTML sink
     638               0 :     if (nodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML)) {
     639               0 :       nsAutoString relVal;
     640               0 :       aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, relVal);
     641               0 :       if (!relVal.IsEmpty()) {
     642               0 :         PRUint32 linkTypes = nsStyleLinkElement::ParseLinkTypes(relVal);
     643               0 :         bool hasPrefetch = linkTypes & PREFETCH;
     644               0 :         if (hasPrefetch || (linkTypes & NEXT)) {
     645               0 :           nsAutoString hrefVal;
     646               0 :           aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
     647               0 :           if (!hrefVal.IsEmpty()) {
     648               0 :             PrefetchHref(hrefVal, aContent, hasPrefetch);
     649                 :           }
     650                 :         }
     651               0 :         if (linkTypes & DNS_PREFETCH) {
     652               0 :           nsAutoString hrefVal;
     653               0 :           aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
     654               0 :           if (!hrefVal.IsEmpty()) {
     655               0 :             PrefetchDNS(hrefVal);
     656                 :           }
     657                 :         }
     658                 :       }
     659                 :     }
     660                 :   }
     661                 : 
     662               9 :   return rv;
     663                 : }  
     664                 : 
     665                 : nsresult
     666           73125 : nsXMLContentSink::AddContentAsLeaf(nsIContent *aContent)
     667                 : {
     668           73125 :   nsresult result = NS_OK;
     669                 : 
     670           73125 :   if ((eXMLContentSinkState_InProlog == mState) ||
     671                 :       (eXMLContentSinkState_InEpilog == mState)) {
     672              71 :     NS_ASSERTION(mDocument, "Fragments have no prolog or epilog");
     673              71 :     mDocument->AppendChildTo(aContent, false);
     674                 :   }
     675                 :   else {
     676          146108 :     nsCOMPtr<nsIContent> parent = GetCurrentContent();
     677                 : 
     678           73054 :     if (parent) {
     679           73054 :       result = parent->AppendChildTo(aContent, false);
     680                 :     }
     681                 :   }
     682           73125 :   return result;
     683                 : }
     684                 : 
     685                 : // Create an XML parser and an XSL content sink and start parsing
     686                 : // the XSL stylesheet located at the given URI.
     687                 : nsresult
     688               0 : nsXMLContentSink::LoadXSLStyleSheet(nsIURI* aUrl)
     689                 : {
     690                 :   nsCOMPtr<nsIDocumentTransformer> processor =
     691               0 :     do_CreateInstance("@mozilla.org/document-transformer;1?type=xslt");
     692               0 :   if (!processor) {
     693                 :     // No XSLT processor available, continue normal document loading
     694               0 :     return NS_OK;
     695                 :   }
     696                 : 
     697               0 :   processor->Init(mDocument->NodePrincipal());
     698               0 :   processor->SetTransformObserver(this);
     699                 : 
     700               0 :   nsCOMPtr<nsILoadGroup> loadGroup = mDocument->GetDocumentLoadGroup();
     701               0 :   if (!loadGroup) {
     702               0 :     return NS_ERROR_FAILURE;
     703                 :   }
     704                 : 
     705               0 :   if (NS_SUCCEEDED(processor->LoadStyleSheet(aUrl, loadGroup))) {
     706               0 :     mXSLTProcessor.swap(processor);
     707                 :   }
     708                 : 
     709                 :   // Intentionally ignore errors here, we should continue loading the
     710                 :   // XML document whether we're able to load the XSLT stylesheet or
     711                 :   // not.
     712                 : 
     713               0 :   return NS_OK;
     714                 : }
     715                 : 
     716                 : nsresult
     717               0 : nsXMLContentSink::ProcessStyleLink(nsIContent* aElement,
     718                 :                                    const nsSubstring& aHref,
     719                 :                                    bool aAlternate,
     720                 :                                    const nsSubstring& aTitle,
     721                 :                                    const nsSubstring& aType,
     722                 :                                    const nsSubstring& aMedia)
     723                 : {
     724               0 :   nsresult rv = NS_OK;
     725               0 :   mPrettyPrintXML = false;
     726                 : 
     727               0 :   nsCAutoString cmd;
     728               0 :   if (mParser)
     729               0 :     GetParser()->GetCommand(cmd);
     730               0 :   if (cmd.EqualsASCII(kLoadAsData))
     731               0 :     return NS_OK; // Do not load stylesheets when loading as data
     732                 : 
     733               0 :   NS_ConvertUTF16toUTF8 type(aType);
     734               0 :   if (type.EqualsIgnoreCase(TEXT_XSL) ||
     735               0 :       type.EqualsIgnoreCase(APPLICATION_XSLT_XML) ||
     736               0 :       type.EqualsIgnoreCase(TEXT_XML) ||
     737               0 :       type.EqualsIgnoreCase(APPLICATION_XML)) {
     738               0 :     if (aAlternate) {
     739                 :       // don't load alternate XSLT
     740               0 :       return NS_OK;
     741                 :     }
     742                 :     // LoadXSLStyleSheet needs a mDocShell.
     743               0 :     if (!mDocShell)
     744               0 :       return NS_OK;
     745                 : 
     746               0 :     nsCOMPtr<nsIURI> url;
     747               0 :     rv = NS_NewURI(getter_AddRefs(url), aHref, nsnull,
     748               0 :                    mDocument->GetDocBaseURI());
     749               0 :     NS_ENSURE_SUCCESS(rv, rv);
     750                 : 
     751                 :     // Do security check
     752               0 :     nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
     753                 :     rv = secMan->
     754               0 :       CheckLoadURIWithPrincipal(mDocument->NodePrincipal(), url,
     755               0 :                                 nsIScriptSecurityManager::ALLOW_CHROME);
     756               0 :     NS_ENSURE_SUCCESS(rv, NS_OK);
     757                 : 
     758                 :     // Do content policy check
     759               0 :     PRInt16 decision = nsIContentPolicy::ACCEPT;
     760                 :     rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET,
     761                 :                                    url,
     762               0 :                                    mDocument->NodePrincipal(),
     763                 :                                    aElement,
     764                 :                                    type,
     765                 :                                    nsnull,
     766                 :                                    &decision,
     767                 :                                    nsContentUtils::GetContentPolicy(),
     768               0 :                                    nsContentUtils::GetSecurityManager());
     769                 : 
     770               0 :     NS_ENSURE_SUCCESS(rv, rv);
     771                 : 
     772               0 :     if (NS_CP_REJECTED(decision)) {
     773               0 :       return NS_OK;
     774                 :     }
     775                 : 
     776               0 :     return LoadXSLStyleSheet(url);
     777                 :   }
     778                 : 
     779                 :   // Let nsContentSink deal with css.
     780                 :   rv = nsContentSink::ProcessStyleLink(aElement, aHref, aAlternate,
     781               0 :                                        aTitle, aType, aMedia);
     782                 : 
     783                 :   // nsContentSink::ProcessStyleLink handles the bookkeeping here wrt
     784                 :   // pending sheets.
     785                 :   
     786               0 :   return rv;
     787                 : }
     788                 : 
     789                 : NS_IMETHODIMP 
     790             373 : nsXMLContentSink::SetDocumentCharset(nsACString& aCharset)
     791                 : {
     792             373 :   if (mDocument) {
     793             373 :     mDocument->SetDocumentCharacterSet(aCharset);
     794                 :   }
     795                 :   
     796             373 :   return NS_OK;
     797                 : }
     798                 : 
     799                 : nsISupports *
     800            1046 : nsXMLContentSink::GetTarget()
     801                 : {
     802            1046 :   return mDocument;
     803                 : }
     804                 : 
     805                 : bool
     806            2154 : nsXMLContentSink::IsScriptExecuting()
     807                 : {
     808            2154 :   return IsScriptExecutingImpl();
     809                 : }
     810                 : 
     811                 : nsresult
     812           77408 : nsXMLContentSink::FlushText(bool aReleaseTextNode)
     813                 : {
     814           77408 :   nsresult rv = NS_OK;
     815                 : 
     816           77408 :   if (mTextLength != 0) {
     817           71334 :     if (mLastTextNode) {
     818               0 :       if ((mLastTextNodeSize + mTextLength) > mTextSize && !mXSLTProcessor) {
     819               0 :         mLastTextNodeSize = 0;
     820               0 :         mLastTextNode = nsnull;
     821               0 :         FlushText(aReleaseTextNode);
     822                 :       } else {
     823               0 :         bool notify = HaveNotifiedForCurrentContent();
     824                 :         // We could probably always increase mInNotification here since
     825                 :         // if AppendText doesn't notify it shouldn't trigger evil code.
     826                 :         // But just in case it does, we don't want to mask any notifications.
     827               0 :         if (notify) {
     828               0 :           ++mInNotification;
     829                 :         }
     830               0 :         rv = mLastTextNode->AppendText(mText, mTextLength, notify);
     831               0 :         if (notify) {
     832               0 :           --mInNotification;
     833                 :         }
     834                 : 
     835               0 :         mLastTextNodeSize += mTextLength;
     836               0 :         mTextLength = 0;
     837                 :       }
     838                 :     } else {
     839          142668 :       nsCOMPtr<nsIContent> textContent;
     840           71334 :       rv = NS_NewTextNode(getter_AddRefs(textContent),
     841           71334 :                           mNodeInfoManager);
     842           71334 :       NS_ENSURE_SUCCESS(rv, rv);
     843                 : 
     844           71334 :       mLastTextNode = textContent;
     845                 :       
     846                 :       // Set the text in the text node
     847           71334 :       textContent->SetText(mText, mTextLength, false);
     848           71334 :       mLastTextNodeSize += mTextLength;
     849           71334 :       mTextLength = 0;
     850                 : 
     851                 :       // Add text to its parent
     852          142668 :       rv = AddContentAsLeaf(textContent);
     853                 :     }
     854                 :   }
     855                 : 
     856           77408 :   if (aReleaseTextNode) {
     857           75319 :     mLastTextNodeSize = 0;
     858           75319 :     mLastTextNode = nsnull;
     859                 :   }
     860                 :   
     861           77408 :   return rv;
     862                 : }
     863                 : 
     864                 : nsIContent*
     865          109807 : nsXMLContentSink::GetCurrentContent()
     866                 : {
     867          109807 :   if (mContentStack.Length() == 0) {
     868            1049 :     return nsnull;
     869                 :   }
     870          108758 :   return GetCurrentStackNode()->mContent;
     871                 : }
     872                 : 
     873                 : StackNode*
     874          145501 : nsXMLContentSink::GetCurrentStackNode()
     875                 : {
     876          145501 :   PRInt32 count = mContentStack.Length();
     877          145501 :   return count != 0 ? &mContentStack[count-1] : nsnull;
     878                 : }
     879                 : 
     880                 : 
     881                 : nsresult
     882           36754 : nsXMLContentSink::PushContent(nsIContent *aContent)
     883                 : {
     884           36754 :   NS_PRECONDITION(aContent, "Null content being pushed!");
     885           36754 :   StackNode *sn = mContentStack.AppendElement();
     886           36754 :   NS_ENSURE_TRUE(sn, NS_ERROR_OUT_OF_MEMORY);
     887                 : 
     888           36754 :   sn->mContent = aContent;
     889           36754 :   sn->mNumFlushed = 0;
     890           36754 :   return NS_OK;
     891                 : }
     892                 : 
     893                 : void
     894           36744 : nsXMLContentSink::PopContent()
     895                 : {
     896           36744 :   PRInt32 count = mContentStack.Length();
     897                 : 
     898           36744 :   if (count == 0) {
     899               0 :     NS_WARNING("Popping empty stack");
     900               0 :     return;
     901                 :   }
     902                 : 
     903           36744 :   mContentStack.RemoveElementAt(count - 1);
     904                 : }
     905                 : 
     906                 : bool
     907           19421 : nsXMLContentSink::HaveNotifiedForCurrentContent() const
     908                 : {
     909           19421 :   PRUint32 stackLength = mContentStack.Length();
     910           19421 :   if (stackLength) {
     911           18815 :     const StackNode& stackNode = mContentStack[stackLength - 1];
     912           18815 :     nsIContent* parent = stackNode.mContent;
     913           18815 :     return stackNode.mNumFlushed == parent->GetChildCount();
     914                 :   }
     915             606 :   return true;
     916                 : }
     917                 : 
     918                 : void
     919           36741 : nsXMLContentSink::MaybeStartLayout(bool aIgnorePendingSheets)
     920                 : {
     921                 :   // XXXbz if aIgnorePendingSheets is true, what should we do when
     922                 :   // mXSLTProcessor or CanStillPrettyPrint()?
     923           36741 :   if (mLayoutStarted || mXSLTProcessor || CanStillPrettyPrint()) {
     924           35703 :     return;
     925                 :   }
     926            1038 :   StartLayout(aIgnorePendingSheets);
     927                 : }
     928                 : 
     929                 : ////////////////////////////////////////////////////////////////////////
     930                 : 
     931                 : bool
     932           36751 : nsXMLContentSink::SetDocElement(PRInt32 aNameSpaceID,
     933                 :                                 nsIAtom* aTagName,
     934                 :                                 nsIContent *aContent)
     935                 : {
     936           36751 :   if (mDocElement)
     937           35703 :     return false;
     938                 : 
     939                 :   // check for root elements that needs special handling for
     940                 :   // prettyprinting
     941            1048 :   if ((aNameSpaceID == kNameSpaceID_XBL &&
     942                 :        aTagName == nsGkAtoms::bindings) ||
     943                 :       (aNameSpaceID == kNameSpaceID_XSLT &&
     944                 :        (aTagName == nsGkAtoms::stylesheet ||
     945                 :         aTagName == nsGkAtoms::transform))) {
     946               0 :     mPrettyPrintHasSpecialRoot = true;
     947               0 :     if (mPrettyPrintXML) {
     948                 :       // In this case, disable script execution, stylesheet
     949                 :       // loading, and auto XLinks since we plan to prettyprint.
     950               0 :       mDocument->ScriptLoader()->SetEnabled(false);
     951               0 :       if (mCSSLoader) {
     952               0 :         mCSSLoader->SetEnabled(false);
     953                 :       }
     954                 :     }        
     955                 :   }
     956                 : 
     957            1048 :   mDocElement = aContent;
     958            1048 :   NS_ADDREF(mDocElement);
     959            1048 :   nsresult rv = mDocument->AppendChildTo(mDocElement, NotifyForDocElement());
     960            1048 :   if (NS_FAILED(rv)) {
     961                 :     // If we return false here, the caller will bail out because it won't
     962                 :     // find a parent content node to append to, which is fine.
     963               0 :     return false;
     964                 :   }
     965                 : 
     966            1048 :   if (aTagName == nsGkAtoms::html &&
     967                 :       aNameSpaceID == kNameSpaceID_XHTML) {
     968               1 :     ProcessOfflineManifest(aContent);
     969                 :   }
     970                 : 
     971            1048 :   return true;
     972                 : }
     973                 : 
     974                 : NS_IMETHODIMP
     975           36629 : nsXMLContentSink::HandleStartElement(const PRUnichar *aName,
     976                 :                                      const PRUnichar **aAtts,
     977                 :                                      PRUint32 aAttsCount,
     978                 :                                      PRInt32 aIndex,
     979                 :                                      PRUint32 aLineNumber)
     980                 : {
     981                 :   return HandleStartElement(aName, aAtts, aAttsCount, aIndex, aLineNumber,
     982           36629 :                             true);
     983                 : }
     984                 : 
     985                 : nsresult
     986           36753 : nsXMLContentSink::HandleStartElement(const PRUnichar *aName,
     987                 :                                      const PRUnichar **aAtts,
     988                 :                                      PRUint32 aAttsCount,
     989                 :                                      PRInt32 aIndex,
     990                 :                                      PRUint32 aLineNumber,
     991                 :                                      bool aInterruptable)
     992                 : {
     993           36753 :   NS_PRECONDITION(aIndex >= -1, "Bogus aIndex");
     994           36753 :   NS_PRECONDITION(aAttsCount % 2 == 0, "incorrect aAttsCount");
     995                 :   // Adjust aAttsCount so it's the actual number of attributes
     996           36753 :   aAttsCount /= 2;
     997                 : 
     998           36753 :   nsresult result = NS_OK;
     999           36753 :   bool appendContent = true;
    1000           73506 :   nsCOMPtr<nsIContent> content;
    1001                 : 
    1002                 :   // XXX Hopefully the parser will flag this before we get
    1003                 :   // here. If we're in the epilog, there should be no
    1004                 :   // new elements
    1005           36753 :   PR_ASSERT(eXMLContentSinkState_InEpilog != mState);
    1006                 : 
    1007           36753 :   FlushText();
    1008           36753 :   DidAddContent();
    1009                 : 
    1010           36753 :   mState = eXMLContentSinkState_InDocumentElement;
    1011                 : 
    1012                 :   PRInt32 nameSpaceID;
    1013           73506 :   nsCOMPtr<nsIAtom> prefix, localName;
    1014           36753 :   nsContentUtils::SplitExpatName(aName, getter_AddRefs(prefix),
    1015           73506 :                                  getter_AddRefs(localName), &nameSpaceID);
    1016                 : 
    1017           36753 :   if (!OnOpenContainer(aAtts, aAttsCount, nameSpaceID, localName, aLineNumber)) {
    1018               0 :     return NS_OK;
    1019                 :   }
    1020                 :   
    1021           73506 :   nsCOMPtr<nsINodeInfo> nodeInfo;
    1022                 :   nodeInfo = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID,
    1023           36753 :                                            nsIDOMNode::ELEMENT_NODE);
    1024           36753 :   NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
    1025                 : 
    1026                 :   result = CreateElement(aAtts, aAttsCount, nodeInfo, aLineNumber,
    1027           36753 :                          getter_AddRefs(content), &appendContent,
    1028           36753 :                          FROM_PARSER_NETWORK);
    1029           36753 :   NS_ENSURE_SUCCESS(result, result);
    1030                 : 
    1031                 :   // Have to do this before we push the new content on the stack... and have to
    1032                 :   // do that before we set attributes, call BindToTree, etc.  Ideally we'd push
    1033                 :   // on the stack inside CreateElement (which is effectively what the HTML sink
    1034                 :   // does), but that's hard with all the subclass overrides going on.
    1035           73506 :   nsCOMPtr<nsIContent> parent = GetCurrentContent();
    1036                 :   
    1037           36753 :   result = PushContent(content);
    1038           36753 :   NS_ENSURE_SUCCESS(result, result);
    1039                 : 
    1040                 :   // Set the ID attribute atom on the node info object for this node
    1041                 :   // This must occur before the attributes are added so the name
    1042                 :   // of the id attribute is known.
    1043           36753 :   if (aIndex != -1 && NS_SUCCEEDED(result)) {
    1044             224 :     nsCOMPtr<nsIAtom> IDAttr = do_GetAtom(aAtts[aIndex]);
    1045                 : 
    1046             112 :     if (IDAttr) {
    1047             112 :       nodeInfo->SetIDAttributeAtom(IDAttr);
    1048                 :     }
    1049                 :   }
    1050                 :   
    1051                 : #ifdef MOZ_XTF
    1052           36753 :   if (nameSpaceID > kNameSpaceID_LastBuiltin)
    1053           19371 :     content->BeginAddingChildren();
    1054                 : #endif
    1055                 : 
    1056                 :   // Set the attributes on the new content element
    1057           36753 :   result = AddAttributes(aAtts, content);
    1058                 : 
    1059           36753 :   if (NS_OK == result) {
    1060                 :     // Store the element 
    1061           36753 :     if (!SetDocElement(nameSpaceID, localName, content) && appendContent) {
    1062           35704 :       NS_ENSURE_TRUE(parent, NS_ERROR_UNEXPECTED);
    1063                 : 
    1064           35704 :       parent->AppendChildTo(content, false);
    1065                 :     }
    1066                 :   }
    1067                 : 
    1068                 :   // Some HTML nodes need DoneCreatingElement() called to initialize
    1069                 :   // properly (eg form state restoration).
    1070           36753 :   if (nodeInfo->NamespaceID() == kNameSpaceID_XHTML) {
    1071              51 :     if (nodeInfo->NameAtom() == nsGkAtoms::input ||
    1072              10 :         nodeInfo->NameAtom() == nsGkAtoms::button ||
    1073              10 :         nodeInfo->NameAtom() == nsGkAtoms::menuitem
    1074                 : #ifdef MOZ_MEDIA
    1075                 :         ||
    1076              10 :         nodeInfo->NameAtom() == nsGkAtoms::audio ||
    1077              10 :         nodeInfo->NameAtom() == nsGkAtoms::video
    1078                 : #endif
    1079                 :         ) {
    1080               1 :       content->DoneCreatingElement();
    1081              10 :     } else if (nodeInfo->NameAtom() == nsGkAtoms::head && !mCurrentHead) {
    1082               0 :       mCurrentHead = content;
    1083                 :     }
    1084                 :   }
    1085                 : 
    1086           36753 :   if (IsMonolithicContainer(nodeInfo)) {
    1087               0 :     mInMonolithicContainer++;
    1088                 :   }
    1089                 : 
    1090           36753 :   if (content != mDocElement && !mCurrentHead) {
    1091                 :     // This isn't the root and we're not inside an XHTML <head>.
    1092                 :     // Might need to start layout
    1093           35705 :     MaybeStartLayout(false);
    1094                 :   }
    1095                 : 
    1096           36753 :   if (content == mDocElement) {
    1097            1048 :     NotifyDocElementCreated(mDocument);
    1098                 :   }
    1099                 : 
    1100           73258 :   return aInterruptable && NS_SUCCEEDED(result) ? DidProcessATokenImpl() :
    1101          110011 :                                                   result;
    1102                 : }
    1103                 : 
    1104                 : NS_IMETHODIMP
    1105           36619 : nsXMLContentSink::HandleEndElement(const PRUnichar *aName)
    1106                 : {
    1107           36619 :   return HandleEndElement(aName, true);
    1108                 : }
    1109                 : 
    1110                 : nsresult
    1111           36743 : nsXMLContentSink::HandleEndElement(const PRUnichar *aName,
    1112                 :                                    bool aInterruptable)
    1113                 : {
    1114           36743 :   nsresult result = NS_OK;
    1115                 : 
    1116                 :   // XXX Hopefully the parser will flag this before we get
    1117                 :   // here. If we're in the prolog or epilog, there should be
    1118                 :   // no close tags for elements.
    1119           36743 :   PR_ASSERT(eXMLContentSinkState_InDocumentElement == mState);
    1120                 : 
    1121           36743 :   FlushText();
    1122                 : 
    1123           36743 :   StackNode* sn = GetCurrentStackNode();
    1124           36743 :   if (!sn) {
    1125               0 :     return NS_ERROR_UNEXPECTED;
    1126                 :   }
    1127                 : 
    1128           73486 :   nsCOMPtr<nsIContent> content;
    1129           36743 :   sn->mContent.swap(content);
    1130           36743 :   PRUint32 numFlushed = sn->mNumFlushed;
    1131                 : 
    1132           36743 :   PopContent();
    1133           36743 :   NS_ASSERTION(content, "failed to pop content");
    1134                 : #ifdef DEBUG
    1135                 :   // Check that we're closing the right thing
    1136           73486 :   nsCOMPtr<nsIAtom> debugNameSpacePrefix, debugTagAtom;
    1137                 :   PRInt32 debugNameSpaceID;
    1138           36743 :   nsContentUtils::SplitExpatName(aName, getter_AddRefs(debugNameSpacePrefix),
    1139           36743 :                                  getter_AddRefs(debugTagAtom),
    1140           36743 :                                  &debugNameSpaceID);
    1141           36743 :   NS_ASSERTION(content->NodeInfo()->Equals(debugTagAtom, debugNameSpaceID),
    1142                 :                "Wrong element being closed");
    1143                 : #endif  
    1144                 : 
    1145           36743 :   result = CloseElement(content);
    1146                 : 
    1147           36743 :   if (mCurrentHead == content) {
    1148               0 :     mCurrentHead = nsnull;
    1149                 :   }
    1150                 :   
    1151           36743 :   if (mDocElement == content) {
    1152                 :     // XXXbz for roots that don't want to be appended on open, we
    1153                 :     // probably need to deal here.... (and stop appending them on open).
    1154            1038 :     mState = eXMLContentSinkState_InEpilog;
    1155                 : 
    1156                 :     // We might have had no occasion to start layout yet.  Do so now.
    1157            1038 :     MaybeStartLayout(false);
    1158                 :   }
    1159                 : 
    1160           36743 :   PRInt32 stackLen = mContentStack.Length();
    1161           36743 :   if (mNotifyLevel >= stackLen) {
    1162            1227 :     if (numFlushed < content->GetChildCount()) {
    1163            1097 :           NotifyAppend(content, numFlushed);
    1164                 :     }
    1165            1227 :     mNotifyLevel = stackLen - 1;
    1166                 :   }
    1167           36743 :   DidAddContent();
    1168                 : 
    1169           36743 :   if (content->IsSVG(nsGkAtoms::svg)) {
    1170               0 :     FlushTags();
    1171               0 :     nsCOMPtr<nsIRunnable> event = new nsHtml5SVGLoadDispatcher(content);
    1172               0 :     if (NS_FAILED(NS_DispatchToMainThread(event))) {
    1173               0 :       NS_WARNING("failed to dispatch svg load dispatcher");
    1174                 :     }
    1175                 :   }
    1176                 : 
    1177           73238 :   return aInterruptable && NS_SUCCEEDED(result) ? DidProcessATokenImpl() :
    1178          109981 :                                                   result;
    1179                 : }
    1180                 : 
    1181                 : NS_IMETHODIMP 
    1182            1637 : nsXMLContentSink::HandleComment(const PRUnichar *aName)
    1183                 : {
    1184            1637 :   FlushText();
    1185                 : 
    1186            3274 :   nsCOMPtr<nsIContent> comment;
    1187            1637 :   nsresult rv = NS_NewCommentNode(getter_AddRefs(comment), mNodeInfoManager);
    1188            1637 :   if (comment) {
    1189            1637 :     comment->SetText(nsDependentString(aName), false);
    1190            1637 :     rv = AddContentAsLeaf(comment);
    1191            1637 :     DidAddContent();
    1192                 :   }
    1193                 : 
    1194            1637 :   return NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv;
    1195                 : }
    1196                 : 
    1197                 : NS_IMETHODIMP 
    1198              42 : nsXMLContentSink::HandleCDataSection(const PRUnichar *aData, 
    1199                 :                                      PRUint32 aLength)
    1200                 : {
    1201                 :   // XSLT doesn't differentiate between text and cdata and wants adjacent
    1202                 :   // textnodes merged, so add as text.
    1203              42 :   if (mXSLTProcessor) {
    1204               0 :     return AddText(aData, aLength);
    1205                 :   }
    1206                 : 
    1207              42 :   FlushText();
    1208                 :   
    1209              84 :   nsCOMPtr<nsIContent> cdata;
    1210              42 :   nsresult rv = NS_NewXMLCDATASection(getter_AddRefs(cdata), mNodeInfoManager);
    1211              42 :   if (cdata) {
    1212              42 :     cdata->SetText(aData, aLength, false);
    1213              42 :     rv = AddContentAsLeaf(cdata);
    1214              42 :     DidAddContent();
    1215                 :   }
    1216                 : 
    1217              42 :   return NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv;
    1218                 : }
    1219                 : 
    1220                 : NS_IMETHODIMP
    1221              31 : nsXMLContentSink::HandleDoctypeDecl(const nsAString & aSubset, 
    1222                 :                                     const nsAString & aName, 
    1223                 :                                     const nsAString & aSystemId, 
    1224                 :                                     const nsAString & aPublicId,
    1225                 :                                     nsISupports* aCatalogData)
    1226                 : {
    1227              31 :   FlushText();
    1228                 : 
    1229              31 :   nsresult rv = NS_OK;
    1230                 : 
    1231              31 :   NS_ASSERTION(mDocument, "Shouldn't get here from a document fragment");
    1232                 : 
    1233              62 :   nsCOMPtr<nsIAtom> name = do_GetAtom(aName);
    1234              31 :   NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY);
    1235                 : 
    1236                 :   // Create a new doctype node
    1237              62 :   nsCOMPtr<nsIDOMDocumentType> docType;
    1238              31 :   rv = NS_NewDOMDocumentType(getter_AddRefs(docType), mNodeInfoManager,
    1239              31 :                              name, aPublicId, aSystemId, aSubset);
    1240              31 :   if (NS_FAILED(rv) || !docType) {
    1241               0 :     return rv;
    1242                 :   }
    1243                 : 
    1244              31 :   if (aCatalogData && mCSSLoader && mDocument) {
    1245                 :     // bug 124570 - we only expect additional agent sheets for now -- ignore
    1246                 :     // exit codes, error are not fatal here, just that the stylesheet won't apply
    1247               0 :     nsCOMPtr<nsIURI> uri(do_QueryInterface(aCatalogData));
    1248               0 :     if (uri) {
    1249               0 :       nsRefPtr<nsCSSStyleSheet> sheet;
    1250               0 :       mCSSLoader->LoadSheetSync(uri, true, true, getter_AddRefs(sheet));
    1251                 : 
    1252                 : #ifdef NS_DEBUG
    1253               0 :       nsCAutoString uriStr;
    1254               0 :       uri->GetSpec(uriStr);
    1255               0 :       printf("Loading catalog stylesheet: %s ... %s\n", uriStr.get(), sheet.get() ? "Done" : "Failed");
    1256                 : #endif
    1257               0 :       if (sheet) {
    1258               0 :         mDocument->BeginUpdate(UPDATE_STYLE);
    1259               0 :         mDocument->AddCatalogStyleSheet(sheet);
    1260               0 :         mDocument->EndUpdate(UPDATE_STYLE);
    1261                 :       }
    1262                 :     }
    1263                 :   }
    1264                 : 
    1265              62 :   nsCOMPtr<nsIContent> content = do_QueryInterface(docType);
    1266              31 :   NS_ASSERTION(content, "doctype isn't content?");
    1267                 : 
    1268              31 :   rv = mDocument->AppendChildTo(content, false);
    1269              31 :   DidAddContent();
    1270              31 :   return NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv;
    1271                 : }
    1272                 : 
    1273                 : NS_IMETHODIMP
    1274          131699 : nsXMLContentSink::HandleCharacterData(const PRUnichar *aData, 
    1275                 :                                       PRUint32 aLength)
    1276                 : {
    1277          131699 :   return HandleCharacterData(aData, aLength, true);
    1278                 : }
    1279                 : 
    1280                 : nsresult
    1281          131823 : nsXMLContentSink::HandleCharacterData(const PRUnichar *aData, PRUint32 aLength,
    1282                 :                                       bool aInterruptable)
    1283                 : {
    1284          131823 :   nsresult rv = NS_OK;
    1285          131823 :   if (aData && mState != eXMLContentSinkState_InProlog &&
    1286                 :       mState != eXMLContentSinkState_InEpilog) {
    1287          130074 :     rv = AddText(aData, aLength);
    1288                 :   }
    1289          131823 :   return aInterruptable && NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv;
    1290                 : }
    1291                 : 
    1292                 : NS_IMETHODIMP
    1293             112 : nsXMLContentSink::HandleProcessingInstruction(const PRUnichar *aTarget, 
    1294                 :                                               const PRUnichar *aData)
    1295                 : {
    1296             112 :   FlushText();
    1297                 : 
    1298             224 :   const nsDependentString target(aTarget);
    1299             224 :   const nsDependentString data(aData);
    1300                 : 
    1301             224 :   nsCOMPtr<nsIContent> node;
    1302                 : 
    1303             112 :   nsresult rv = NS_NewXMLProcessingInstruction(getter_AddRefs(node),
    1304             112 :                                                mNodeInfoManager, target, data);
    1305             112 :   NS_ENSURE_SUCCESS(rv, rv);
    1306                 : 
    1307             224 :   nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(node));
    1308             112 :   if (ssle) {
    1309              62 :     ssle->InitStyleLinkElement(false);
    1310              62 :     ssle->SetEnableUpdates(false);
    1311              62 :     mPrettyPrintXML = false;
    1312                 :   }
    1313                 : 
    1314             112 :   rv = AddContentAsLeaf(node);
    1315             112 :   NS_ENSURE_SUCCESS(rv, rv);
    1316             112 :   DidAddContent();
    1317                 : 
    1318             112 :   if (ssle) {
    1319                 :     // This is an xml-stylesheet processing instruction... but it might not be
    1320                 :     // a CSS one if the type is set to something else.
    1321              62 :     ssle->SetEnableUpdates(true);
    1322                 :     bool willNotify;
    1323                 :     bool isAlternate;
    1324              62 :     rv = ssle->UpdateStyleSheet(mRunsToCompletion ? nsnull : this,
    1325                 :                                 &willNotify,
    1326              62 :                                 &isAlternate);
    1327              62 :     NS_ENSURE_SUCCESS(rv, rv);
    1328                 :     
    1329              62 :     if (willNotify) {
    1330                 :       // Successfully started a stylesheet load
    1331               0 :       if (!isAlternate && !mRunsToCompletion) {
    1332               0 :         ++mPendingSheetCount;
    1333               0 :         mScriptLoader->AddExecuteBlocker();
    1334                 :       }
    1335                 : 
    1336               0 :       return NS_OK;
    1337                 :     }
    1338                 :   }
    1339                 : 
    1340                 :   // If it's not a CSS stylesheet PI...
    1341             224 :   nsAutoString type;
    1342             112 :   nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::type, type);
    1343                 : 
    1344             300 :   if (mState != eXMLContentSinkState_InProlog ||
    1345              64 :       !target.EqualsLiteral("xml-stylesheet") ||
    1346              62 :       type.IsEmpty()                          ||
    1347              62 :       type.LowerCaseEqualsLiteral("text/css")) {
    1348             112 :     return DidProcessATokenImpl();
    1349                 :   }
    1350                 : 
    1351               0 :   nsAutoString href, title, media;
    1352               0 :   bool isAlternate = false;
    1353                 : 
    1354                 :   // If there was no href, we can't do anything with this PI
    1355               0 :   if (!ParsePIData(data, href, title, media, isAlternate)) {
    1356               0 :       return DidProcessATokenImpl();
    1357                 :   }
    1358                 : 
    1359               0 :   rv = ProcessStyleLink(node, href, isAlternate, title, type, media);
    1360               0 :   return NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv;
    1361                 : }
    1362                 : 
    1363                 : /* static */
    1364                 : bool
    1365               0 : nsXMLContentSink::ParsePIData(const nsString &aData, nsString &aHref,
    1366                 :                               nsString &aTitle, nsString &aMedia,
    1367                 :                               bool &aIsAlternate)
    1368                 : {
    1369                 :   // If there was no href, we can't do anything with this PI
    1370               0 :   if (!nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::href, aHref)) {
    1371               0 :     return false;
    1372                 :   }
    1373                 : 
    1374               0 :   nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::title, aTitle);
    1375                 : 
    1376               0 :   nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::media, aMedia);
    1377                 : 
    1378               0 :   nsAutoString alternate;
    1379                 :   nsContentUtils::GetPseudoAttributeValue(aData,
    1380                 :                                           nsGkAtoms::alternate,
    1381               0 :                                           alternate);
    1382                 : 
    1383               0 :   aIsAlternate = alternate.EqualsLiteral("yes");
    1384                 : 
    1385               0 :   return true;
    1386                 : }
    1387                 : 
    1388                 : NS_IMETHODIMP
    1389             825 : nsXMLContentSink::HandleXMLDeclaration(const PRUnichar *aVersion,
    1390                 :                                        const PRUnichar *aEncoding,
    1391                 :                                        PRInt32 aStandalone)
    1392                 : {
    1393             825 :   mDocument->SetXMLDeclaration(aVersion, aEncoding, aStandalone);
    1394                 : 
    1395             825 :   return DidProcessATokenImpl();
    1396                 : }
    1397                 : 
    1398                 : NS_IMETHODIMP
    1399              62 : nsXMLContentSink::ReportError(const PRUnichar* aErrorText, 
    1400                 :                               const PRUnichar* aSourceText,
    1401                 :                               nsIScriptError *aError,
    1402                 :                               bool *_retval)
    1403                 : {
    1404              62 :   NS_PRECONDITION(aError && aSourceText && aErrorText, "Check arguments!!!");
    1405              62 :   nsresult rv = NS_OK;
    1406                 : 
    1407                 :   // The expat driver should report the error.  We're just cleaning up the mess.
    1408              62 :   *_retval = true;
    1409                 :   
    1410              62 :   mPrettyPrintXML = false;
    1411                 : 
    1412              62 :   mState = eXMLContentSinkState_InProlog;
    1413                 : 
    1414                 :   // XXX need to stop scripts here -- hsivonen
    1415                 : 
    1416                 :   // stop observing in order to avoid crashing when removing content
    1417              62 :   mDocument->RemoveObserver(this);
    1418              62 :   mIsDocumentObserver = false;
    1419                 : 
    1420                 :   // Clear the current content and
    1421                 :   // prepare to set <parsererror> as the document root
    1422             124 :   nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mDocument));
    1423              62 :   if (node) {
    1424              10 :     for (;;) {
    1425             216 :       nsCOMPtr<nsIDOMNode> child, dummy;
    1426              72 :       node->GetLastChild(getter_AddRefs(child));
    1427              72 :       if (!child)
    1428                 :         break;
    1429              82 :       node->RemoveChild(child, getter_AddRefs(dummy));
    1430                 :     }
    1431                 :   }
    1432              62 :   NS_IF_RELEASE(mDocElement); 
    1433                 : 
    1434                 :   // Clear any buffered-up text we have.  It's enough to set the length to 0.
    1435                 :   // The buffer itself is allocated when we're created and deleted in our
    1436                 :   // destructor, so don't mess with it.
    1437              62 :   mTextLength = 0;
    1438                 : 
    1439              62 :   if (mXSLTProcessor) {
    1440                 :     // Get rid of the XSLT processor.
    1441               0 :     mXSLTProcessor->CancelLoads();
    1442               0 :     mXSLTProcessor = nsnull;
    1443                 :   }
    1444                 : 
    1445                 :   // release the nodes on stack
    1446              62 :   mContentStack.Clear();
    1447              62 :   mNotifyLevel = 0;
    1448                 : 
    1449              62 :   rv = HandleProcessingInstruction(NS_LITERAL_STRING("xml-stylesheet").get(),
    1450             124 :                                    NS_LITERAL_STRING("href=\"chrome://global/locale/intl.css\" type=\"text/css\"").get());
    1451              62 :   NS_ENSURE_SUCCESS(rv, rv);
    1452                 : 
    1453              62 :   const PRUnichar* noAtts[] = { 0, 0 };
    1454                 : 
    1455             124 :   NS_NAMED_LITERAL_STRING(errorNs,
    1456                 :                           "http://www.mozilla.org/newlayout/xml/parsererror.xml");
    1457                 : 
    1458             124 :   nsAutoString parsererror(errorNs);
    1459              62 :   parsererror.Append((PRUnichar)0xFFFF);
    1460              62 :   parsererror.AppendLiteral("parsererror");
    1461                 :   
    1462                 :   rv = HandleStartElement(parsererror.get(), noAtts, 0, -1, (PRUint32)-1,
    1463              62 :                           false);
    1464              62 :   NS_ENSURE_SUCCESS(rv, rv);
    1465                 : 
    1466              62 :   rv = HandleCharacterData(aErrorText, nsCRT::strlen(aErrorText), false);
    1467              62 :   NS_ENSURE_SUCCESS(rv, rv);  
    1468                 :   
    1469             124 :   nsAutoString sourcetext(errorNs);
    1470              62 :   sourcetext.Append((PRUnichar)0xFFFF);
    1471              62 :   sourcetext.AppendLiteral("sourcetext");
    1472                 : 
    1473                 :   rv = HandleStartElement(sourcetext.get(), noAtts, 0, -1, (PRUint32)-1,
    1474              62 :                           false);
    1475              62 :   NS_ENSURE_SUCCESS(rv, rv);
    1476                 :   
    1477              62 :   rv = HandleCharacterData(aSourceText, nsCRT::strlen(aSourceText), false);
    1478              62 :   NS_ENSURE_SUCCESS(rv, rv);
    1479                 :   
    1480              62 :   rv = HandleEndElement(sourcetext.get(), false);
    1481              62 :   NS_ENSURE_SUCCESS(rv, rv); 
    1482                 :   
    1483              62 :   rv = HandleEndElement(parsererror.get(), false);
    1484              62 :   NS_ENSURE_SUCCESS(rv, rv);
    1485                 : 
    1486              62 :   FlushTags();
    1487                 : 
    1488              62 :   return NS_OK;
    1489                 : }
    1490                 : 
    1491                 : nsresult
    1492           36753 : nsXMLContentSink::AddAttributes(const PRUnichar** aAtts,
    1493                 :                                 nsIContent* aContent)
    1494                 : {
    1495                 :   // Add tag attributes to the content attributes
    1496           73506 :   nsCOMPtr<nsIAtom> prefix, localName;
    1497           82919 :   while (*aAtts) {
    1498                 :     PRInt32 nameSpaceID;
    1499            9413 :     nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
    1500           18826 :                                    getter_AddRefs(localName), &nameSpaceID);
    1501                 : 
    1502                 :     // Add attribute to content
    1503                 :     aContent->SetAttr(nameSpaceID, localName, prefix,
    1504            9413 :                       nsDependentString(aAtts[1]), false);
    1505            9413 :     aAtts += 2;
    1506                 :   }
    1507                 : 
    1508           36753 :   return NS_OK;
    1509                 : }
    1510                 : 
    1511                 : #define NS_ACCUMULATION_BUFFER_SIZE 4096
    1512                 : 
    1513                 : nsresult
    1514          130074 : nsXMLContentSink::AddText(const PRUnichar* aText, 
    1515                 :                           PRInt32 aLength)
    1516                 : {
    1517                 :   // Create buffer when we first need it
    1518          130074 :   if (0 == mTextSize) {
    1519             769 :     mText = (PRUnichar *) PR_MALLOC(sizeof(PRUnichar) * NS_ACCUMULATION_BUFFER_SIZE);
    1520             769 :     if (nsnull == mText) {
    1521               0 :       return NS_ERROR_OUT_OF_MEMORY;
    1522                 :     }
    1523             769 :     mTextSize = NS_ACCUMULATION_BUFFER_SIZE;
    1524                 :   }
    1525                 : 
    1526                 :   // Copy data from string into our buffer; flush buffer when it fills up
    1527          130074 :   PRInt32 offset = 0;
    1528          390222 :   while (0 != aLength) {
    1529          130074 :     PRInt32 amount = mTextSize - mTextLength;
    1530          130074 :     if (0 == amount) {
    1531                 :       // XSLT wants adjacent textnodes merged.
    1532               0 :       if (mConstrainSize && !mXSLTProcessor) {
    1533               0 :         nsresult rv = FlushText();
    1534               0 :         if (NS_OK != rv) {
    1535               0 :           return rv;
    1536                 :         }
    1537                 : 
    1538               0 :         amount = mTextSize - mTextLength;
    1539                 :       }
    1540                 :       else {
    1541               0 :         mTextSize += aLength;
    1542               0 :         mText = (PRUnichar *) PR_REALLOC(mText, sizeof(PRUnichar) * mTextSize);
    1543               0 :         if (nsnull == mText) {
    1544               0 :           mTextSize = 0;
    1545                 : 
    1546               0 :           return NS_ERROR_OUT_OF_MEMORY;
    1547                 :         }
    1548                 : 
    1549               0 :         amount = aLength;
    1550                 :       }
    1551                 :     }
    1552          130074 :     if (amount > aLength) {
    1553          130074 :       amount = aLength;
    1554                 :     }
    1555          130074 :     memcpy(&mText[mTextLength], &aText[offset], sizeof(PRUnichar) * amount);
    1556          130074 :     mTextLength += amount;
    1557          130074 :     offset += amount;
    1558          130074 :     aLength -= amount;
    1559                 :   }
    1560                 : 
    1561          130074 :   return NS_OK;
    1562                 : }
    1563                 : 
    1564                 : void
    1565               0 : nsXMLContentSink::FlushPendingNotifications(mozFlushType aType)
    1566                 : {
    1567                 :   // Only flush tags if we're not doing the notification ourselves
    1568                 :   // (since we aren't reentrant)
    1569               0 :   if (!mInNotification) {
    1570               0 :     if (mIsDocumentObserver) {
    1571                 :       // Only flush if we're still a document observer (so that our child
    1572                 :       // counts should be correct).
    1573               0 :       if (aType >= Flush_ContentAndNotify) {
    1574               0 :         FlushTags();
    1575                 :       }
    1576                 :       else {
    1577               0 :         FlushText(false);
    1578                 :       }
    1579                 :     }
    1580               0 :     if (aType >= Flush_InterruptibleLayout) {
    1581                 :       // Make sure that layout has started so that the reflow flush
    1582                 :       // will actually happen.
    1583               0 :       MaybeStartLayout(true);
    1584                 :     }
    1585                 :   }
    1586               0 : }
    1587                 : 
    1588                 : /**
    1589                 :  * NOTE!! Forked from SinkContext. Please keep in sync.
    1590                 :  *
    1591                 :  * Flush all elements that have been seen so far such that
    1592                 :  * they are visible in the tree. Specifically, make sure
    1593                 :  * that they are all added to their respective parents.
    1594                 :  * Also, do notification at the top for all content that
    1595                 :  * has been newly added so that the frame tree is complete.
    1596                 :  */
    1597                 : nsresult
    1598            2089 : nsXMLContentSink::FlushTags()
    1599                 : {
    1600            2089 :   mDeferredFlushTags = false;
    1601            2089 :   bool oldBeganUpdate = mBeganUpdate;
    1602            2089 :   PRUint32 oldUpdates = mUpdatesInNotification;
    1603                 : 
    1604            2089 :   mUpdatesInNotification = 0;
    1605            2089 :   ++mInNotification;
    1606                 :   {
    1607                 :     // Scope so we call EndUpdate before we decrease mInNotification
    1608            4178 :     mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, true);
    1609            2089 :     mBeganUpdate = true;
    1610                 : 
    1611                 :     // Don't release last text node in case we need to add to it again
    1612            2089 :     FlushText(false);
    1613                 : 
    1614                 :     // Start from the base of the stack (growing downward) and do
    1615                 :     // a notification from the node that is closest to the root of
    1616                 :     // tree for any content that has been added.
    1617                 : 
    1618                 :     PRInt32 stackPos;
    1619            2089 :     PRInt32 stackLen = mContentStack.Length();
    1620            2089 :     bool flushed = false;
    1621                 :     PRUint32 childCount;
    1622                 :     nsIContent* content;
    1623                 : 
    1624            4304 :     for (stackPos = 0; stackPos < stackLen; ++stackPos) {
    1625            2215 :       content = mContentStack[stackPos].mContent;
    1626            2215 :       childCount = content->GetChildCount();
    1627                 : 
    1628            2215 :       if (!flushed && (mContentStack[stackPos].mNumFlushed < childCount)) {
    1629             614 :         NotifyAppend(content, mContentStack[stackPos].mNumFlushed);
    1630             614 :         flushed = true;
    1631                 :       }
    1632                 : 
    1633            2215 :       mContentStack[stackPos].mNumFlushed = childCount;
    1634                 :     }
    1635            2089 :     mNotifyLevel = stackLen - 1;
    1636                 :   }
    1637            2089 :   --mInNotification;
    1638                 : 
    1639            2089 :   if (mUpdatesInNotification > 1) {
    1640               0 :     UpdateChildCounts();
    1641                 :   }
    1642                 : 
    1643            2089 :   mUpdatesInNotification = oldUpdates;
    1644            2089 :   mBeganUpdate = oldBeganUpdate;
    1645                 :   
    1646            2089 :   return NS_OK;
    1647                 : }
    1648                 : 
    1649                 : /**
    1650                 :  * NOTE!! Forked from SinkContext. Please keep in sync.
    1651                 :  */
    1652                 : void
    1653             986 : nsXMLContentSink::UpdateChildCounts()
    1654                 : {
    1655                 :   // Start from the top of the stack (growing upwards) and see if any
    1656                 :   // new content has been appended. If so, we recognize that reflows
    1657                 :   // have been generated for it and we should make sure that no
    1658                 :   // further reflows occur.  Note that we have to include stackPos == 0
    1659                 :   // to properly notify on kids of <html>.
    1660             986 :   PRInt32 stackLen = mContentStack.Length();
    1661             986 :   PRInt32 stackPos = stackLen - 1;
    1662            2958 :   while (stackPos >= 0) {
    1663             986 :     StackNode & node = mContentStack[stackPos];
    1664             986 :     node.mNumFlushed = node.mContent->GetChildCount();
    1665                 : 
    1666             986 :     stackPos--;
    1667                 :   }
    1668             986 :   mNotifyLevel = stackLen - 1;
    1669             986 : }
    1670                 : 
    1671                 : bool
    1672           73494 : nsXMLContentSink::IsMonolithicContainer(nsINodeInfo* aNodeInfo)
    1673                 : {
    1674           73494 :   return ((aNodeInfo->NamespaceID() == kNameSpaceID_XHTML &&
    1675              20 :           (aNodeInfo->NameAtom() == nsGkAtoms::tr ||
    1676              20 :            aNodeInfo->NameAtom() == nsGkAtoms::select ||
    1677              20 :            aNodeInfo->NameAtom() == nsGkAtoms::object ||
    1678              20 :            aNodeInfo->NameAtom() == nsGkAtoms::applet)) ||
    1679           73494 :           (aNodeInfo->NamespaceID() == kNameSpaceID_MathML &&
    1680               0 :           (aNodeInfo->NameAtom() == nsGkAtoms::math))
    1681          147068 :           );
    1682                 : }
    1683                 : 
    1684                 : void
    1685               0 : nsXMLContentSink::ContinueInterruptedParsingIfEnabled()
    1686                 : {
    1687               0 :   if (mParser && mParser->IsParserEnabled()) {
    1688               0 :     GetParser()->ContinueInterruptedParsing();
    1689                 :   }
    1690               0 : }
    1691                 : 
    1692                 : void
    1693               0 : nsXMLContentSink::ContinueInterruptedParsingAsync()
    1694                 : {
    1695                 :   nsCOMPtr<nsIRunnable> ev = NS_NewRunnableMethod(this,
    1696               0 :     &nsXMLContentSink::ContinueInterruptedParsingIfEnabled);
    1697                 : 
    1698               0 :   NS_DispatchToCurrentThread(ev);
    1699               0 : }
    1700                 : 
    1701                 : nsIParser*
    1702               0 : nsXMLContentSink::GetParser()
    1703                 : {
    1704               0 :   return static_cast<nsIParser*>(mParser.get());
    1705            4392 : }

Generated by: LCOV version 1.7