LCOV - app.info - content/xslt/src/xslt/txMozillaXMLOutput.cpp

LCOV - code coverage report
| Current view: | directory - content/xslt/src/xslt - txMozillaXMLOutput.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 488 | 0 | 0.0 %
| Date: | 2012-07-07 | Functions: | 38 | 0 | 0.0 %

           1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is TransforMiiX XSLT processor code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * Netscape Communications Corporation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 2001
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *   Peter Van der Beken <peterv@propagandism.org>
          24                 :  *
          25                 :  * Alternatively, the contents of this file may be used under the terms of
          26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          29                 :  * of those above. If you wish to allow use of your version of this file only
          30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          31                 :  * use your version of this file under the terms of the MPL, indicate your
          32                 :  * decision by deleting the provisions above and replace them with the notice
          33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          34                 :  * the provisions above, a recipient may use your version of this file under
          35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          36                 :  *
          37                 :  * ***** END LICENSE BLOCK ***** */
          38                 :
          39                 : #include "txMozillaXMLOutput.h"
          40                 :
          41                 : #include "nsIDocument.h"
          42                 : #include "nsIDocShell.h"
          43                 : #include "nsScriptLoader.h"
          44                 : #include "nsIDOMDocument.h"
          45                 : #include "nsIDOMDocumentType.h"
          46                 : #include "nsIScriptElement.h"
          47                 : #include "nsIParser.h"
          48                 : #include "nsIRefreshURI.h"
          49                 : #include "nsPIDOMWindow.h"
          50                 : #include "nsIContent.h"
          51                 : #include "nsContentCID.h"
          52                 : #include "nsNetUtil.h"
          53                 : #include "nsUnicharUtils.h"
          54                 : #include "nsGkAtoms.h"
          55                 : #include "txLog.h"
          56                 : #include "nsIConsoleService.h"
          57                 : #include "nsIDOMDocumentFragment.h"
          58                 : #include "nsINameSpaceManager.h"
          59                 : #include "nsCSSStyleSheet.h"
          60                 : #include "txStringUtils.h"
          61                 : #include "txURIUtils.h"
          62                 : #include "nsIHTMLDocument.h"
          63                 : #include "nsIStyleSheetLinkingElement.h"
          64                 : #include "nsIDocumentTransformer.h"
          65                 : #include "mozilla/css/Loader.h"
          66                 : #include "mozilla/dom/Element.h"
          67                 : #include "nsCharsetAlias.h"
          68                 : #include "nsIHTMLContentSink.h"
          69                 : #include "nsContentUtils.h"
          70                 : #include "txXMLUtils.h"
          71                 : #include "nsContentSink.h"
          72                 : #include "nsINode.h"
          73                 : #include "nsContentCreatorFunctions.h"
          74                 : #include "txError.h"
          75                 :
          76                 : using namespace mozilla::dom;
          77                 :
          78                 : #define TX_ENSURE_CURRENTNODE                           \
          79                 :     NS_ASSERTION(mCurrentNode, "mCurrentNode is NULL"); \
          80                 :     if (!mCurrentNode)                                  \
          81                 :         return NS_ERROR_UNEXPECTED
          82                 :
          83               0 : txMozillaXMLOutput::txMozillaXMLOutput(txOutputFormat* aFormat,
          84                 :                                        nsITransformObserver* aObserver)
          85                 :     : mTreeDepth(0),
          86                 :       mBadChildLevel(0),
          87                 :       mTableState(NORMAL),
          88                 :       mCreatingNewDocument(true),
          89                 :       mOpenedElementIsHTML(false),
          90                 :       mRootContentCreated(false),
          91               0 :       mNoFixup(false)
          92                 : {
          93               0 :     MOZ_COUNT_CTOR(txMozillaXMLOutput);
          94               0 :     if (aObserver) {
          95               0 :         mNotifier = new txTransformNotifier();
          96               0 :         if (mNotifier) {
          97               0 :             mNotifier->Init(aObserver);
          98                 :         }
          99                 :     }
         100                 :
         101               0 :     mOutputFormat.merge(*aFormat);
         102               0 :     mOutputFormat.setFromDefaults();
         103               0 : }
         104                 :
         105               0 : txMozillaXMLOutput::txMozillaXMLOutput(txOutputFormat* aFormat,
         106                 :                                        nsIDOMDocumentFragment* aFragment,
         107                 :                                        bool aNoFixup)
         108                 :     : mTreeDepth(0),
         109                 :       mBadChildLevel(0),
         110                 :       mTableState(NORMAL),
         111                 :       mCreatingNewDocument(false),
         112                 :       mOpenedElementIsHTML(false),
         113                 :       mRootContentCreated(false),
         114               0 :       mNoFixup(aNoFixup)
         115                 : {
         116               0 :     MOZ_COUNT_CTOR(txMozillaXMLOutput);
         117               0 :     mOutputFormat.merge(*aFormat);
         118               0 :     mOutputFormat.setFromDefaults();
         119                 :
         120               0 :     mCurrentNode = do_QueryInterface(aFragment);
         121               0 :     mDocument = mCurrentNode->OwnerDoc();
         122               0 :     mNodeInfoManager = mDocument->NodeInfoManager();
         123               0 : }
         124                 :
         125               0 : txMozillaXMLOutput::~txMozillaXMLOutput()
         126                 : {
         127               0 :     MOZ_COUNT_DTOR(txMozillaXMLOutput);
         128               0 : }
         129                 :
         130                 : nsresult
         131               0 : txMozillaXMLOutput::attribute(nsIAtom* aPrefix,
         132                 :                               nsIAtom* aLocalName,
         133                 :                               nsIAtom* aLowercaseLocalName,
         134                 :                               const PRInt32 aNsID,
         135                 :                               const nsString& aValue)
         136                 : {
         137               0 :     nsCOMPtr<nsIAtom> owner;
         138               0 :     if (mOpenedElementIsHTML && aNsID == kNameSpaceID_None) {
         139               0 :         if (aLowercaseLocalName) {
         140               0 :             aLocalName = aLowercaseLocalName;
         141                 :         }
         142                 :         else {
         143               0 :             owner = TX_ToLowerCaseAtom(aLocalName);
         144               0 :             NS_ENSURE_TRUE(owner, NS_ERROR_OUT_OF_MEMORY);
         145                 :
         146               0 :             aLocalName = owner;
         147                 :         }
         148                 :     }
         149                 :
         150               0 :     return attributeInternal(aPrefix, aLocalName, aNsID, aValue);
         151                 : }
         152                 :
         153                 : nsresult
         154               0 : txMozillaXMLOutput::attribute(nsIAtom* aPrefix,
         155                 :                               const nsSubstring& aLocalName,
         156                 :                               const PRInt32 aNsID,
         157                 :                               const nsString& aValue)
         158                 : {
         159               0 :     nsCOMPtr<nsIAtom> lname;
         160                 :
         161               0 :     if (mOpenedElementIsHTML && aNsID == kNameSpaceID_None) {
         162               0 :         nsAutoString lnameStr;
         163               0 :         nsContentUtils::ASCIIToLower(aLocalName, lnameStr);
         164               0 :         lname = do_GetAtom(lnameStr);
         165                 :     }
         166                 :     else {
         167               0 :         lname = do_GetAtom(aLocalName);
         168                 :     }
         169                 :
         170               0 :     NS_ENSURE_TRUE(lname, NS_ERROR_OUT_OF_MEMORY);
         171                 :
         172                 :     // Check that it's a valid name
         173               0 :     if (!nsContentUtils::IsValidNodeName(lname, aPrefix, aNsID)) {
         174                 :         // Try without prefix
         175               0 :         aPrefix = nsnull;
         176               0 :         if (!nsContentUtils::IsValidNodeName(lname, aPrefix, aNsID)) {
         177                 :             // Don't return error here since the callers don't deal
         178               0 :             return NS_OK;
         179                 :         }
         180                 :     }
         181                 :
         182               0 :     return attributeInternal(aPrefix, lname, aNsID, aValue);
         183                 : }
         184                 :
         185                 : nsresult
         186               0 : txMozillaXMLOutput::attributeInternal(nsIAtom* aPrefix,
         187                 :                                       nsIAtom* aLocalName,
         188                 :                                       PRInt32 aNsID,
         189                 :                                       const nsString& aValue)
         190                 : {
         191               0 :     if (!mOpenedElement) {
         192                 :         // XXX Signal this? (can't add attributes after element closed)
         193               0 :         return NS_OK;
         194                 :     }
         195                 :
         196               0 :     NS_ASSERTION(!mBadChildLevel, "mBadChildLevel set when element is opened");
         197                 :
         198               0 :     return mOpenedElement->SetAttr(aNsID, aLocalName, aPrefix, aValue,
         199               0 :                                    false);
         200                 : }
         201                 :
         202                 : nsresult
         203               0 : txMozillaXMLOutput::characters(const nsSubstring& aData, bool aDOE)
         204                 : {
         205               0 :     nsresult rv = closePrevious(false);
         206               0 :     NS_ENSURE_SUCCESS(rv, rv);
         207                 :
         208               0 :     if (!mBadChildLevel) {
         209               0 :         mText.Append(aData);
         210                 :     }
         211                 :
         212               0 :     return NS_OK;
         213                 : }
         214                 :
         215                 : nsresult
         216               0 : txMozillaXMLOutput::comment(const nsString& aData)
         217                 : {
         218               0 :     nsresult rv = closePrevious(true);
         219               0 :     NS_ENSURE_SUCCESS(rv, rv);
         220                 :
         221               0 :     if (mBadChildLevel) {
         222               0 :         return NS_OK;
         223                 :     }
         224                 :
         225               0 :     TX_ENSURE_CURRENTNODE;
         226                 :
         227               0 :     nsCOMPtr<nsIContent> comment;
         228               0 :     rv = NS_NewCommentNode(getter_AddRefs(comment), mNodeInfoManager);
         229               0 :     NS_ENSURE_SUCCESS(rv, rv);
         230                 :
         231               0 :     rv = comment->SetText(aData, false);
         232               0 :     NS_ENSURE_SUCCESS(rv, rv);
         233                 :
         234               0 :     return mCurrentNode->AppendChildTo(comment, true);
         235                 : }
         236                 :
         237                 : nsresult
         238               0 : txMozillaXMLOutput::endDocument(nsresult aResult)
         239                 : {
         240               0 :     TX_ENSURE_CURRENTNODE;
         241                 :
         242               0 :     if (NS_FAILED(aResult)) {
         243               0 :         if (mNotifier) {
         244               0 :             mNotifier->OnTransformEnd(aResult);
         245                 :         }
         246                 :
         247               0 :         return NS_OK;
         248                 :     }
         249                 :
         250               0 :     nsresult rv = closePrevious(true);
         251               0 :     if (NS_FAILED(rv)) {
         252               0 :         if (mNotifier) {
         253               0 :             mNotifier->OnTransformEnd(rv);
         254                 :         }
         255                 :
         256               0 :         return rv;
         257                 :     }
         258                 :
         259               0 :     if (mCreatingNewDocument) {
         260                 :         // This should really be handled by nsIDocument::EndLoad
         261               0 :         mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_INTERACTIVE);
         262               0 :         nsScriptLoader* loader = mDocument->ScriptLoader();
         263               0 :         if (loader) {
         264               0 :             loader->ParsingComplete(false);
         265                 :         }
         266                 :     }
         267                 :
         268               0 :     if (!mRefreshString.IsEmpty()) {
         269               0 :         nsPIDOMWindow *win = mDocument->GetWindow();
         270               0 :         if (win) {
         271                 :             nsCOMPtr<nsIRefreshURI> refURI =
         272               0 :                 do_QueryInterface(win->GetDocShell());
         273               0 :             if (refURI) {
         274               0 :                 refURI->SetupRefreshURIFromHeader(mDocument->GetDocBaseURI(),
         275               0 :                                                   mRefreshString);
         276                 :             }
         277                 :         }
         278                 :     }
         279                 :
         280               0 :     if (mNotifier) {
         281               0 :         mNotifier->OnTransformEnd();
         282                 :     }
         283                 :
         284               0 :     return NS_OK;
         285                 : }
         286                 :
         287                 : nsresult
         288               0 : txMozillaXMLOutput::endElement()
         289                 : {
         290               0 :     TX_ENSURE_CURRENTNODE;
         291                 :
         292               0 :     if (mBadChildLevel) {
         293               0 :         --mBadChildLevel;
         294               0 :         PR_LOG(txLog::xslt, PR_LOG_DEBUG,
         295                 :                ("endElement, mBadChildLevel = %d\n", mBadChildLevel));
         296               0 :         return NS_OK;
         297                 :     }
         298                 :
         299               0 :     --mTreeDepth;
         300                 :
         301               0 :     nsresult rv = closePrevious(true);
         302               0 :     NS_ENSURE_SUCCESS(rv, rv);
         303                 :
         304               0 :     NS_ASSERTION(mCurrentNode->IsElement(), "borked mCurrentNode");
         305               0 :     NS_ENSURE_TRUE(mCurrentNode->IsElement(), NS_ERROR_UNEXPECTED);
         306                 :
         307               0 :     Element* element = mCurrentNode->AsElement();
         308                 :
         309                 :     // Handle html-elements
         310               0 :     if (!mNoFixup) {
         311               0 :         if (element->IsHTML()) {
         312               0 :             rv = endHTMLElement(element);
         313               0 :             NS_ENSURE_SUCCESS(rv, rv);
         314                 :         }
         315                 :
         316                 :         // Handle elements that are different when parser-created
         317               0 :         PRInt32 ns = element->GetNameSpaceID();
         318               0 :         nsIAtom* localName = element->Tag();
         319                 :
         320               0 :         if ((ns == kNameSpaceID_XHTML && (localName == nsGkAtoms::title ||
         321                 :                                           localName == nsGkAtoms::object ||
         322                 :                                           localName == nsGkAtoms::applet ||
         323                 :                                           localName == nsGkAtoms::select ||
         324                 :                                           localName == nsGkAtoms::textarea)) ||
         325                 :             (ns == kNameSpaceID_SVG && localName == nsGkAtoms::title)) {
         326               0 :             element->DoneAddingChildren(true);
         327               0 :         } else if ((ns == kNameSpaceID_XHTML || ns == kNameSpaceID_SVG) &&
         328                 :                    localName == nsGkAtoms::script) {
         329               0 :             nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(element);
         330               0 :             NS_ABORT_IF_FALSE(sele, "script elements need to implement nsIScriptElement");
         331               0 :             bool block = sele->AttemptToExecute();
         332                 :             // If the act of insertion evaluated the script, we're fine.
         333                 :             // Else, add this script element to the array of loading scripts.
         334               0 :             if (block) {
         335               0 :                 rv = mNotifier->AddScriptElement(sele);
         336               0 :                 NS_ENSURE_SUCCESS(rv, rv);
         337               0 :             }
         338               0 :         } else if (ns == kNameSpaceID_XHTML &&
         339                 :                    (localName == nsGkAtoms::input ||
         340                 :                     localName == nsGkAtoms::button ||
         341                 :                     localName == nsGkAtoms::menuitem
         342                 : #ifdef MOZ_MEDIA
         343                 :                      ||
         344                 :                     localName == nsGkAtoms::audio ||
         345                 :                     localName == nsGkAtoms::video
         346                 : #endif
         347                 :                   )) {
         348               0 :           element->DoneCreatingElement();
         349                 :         }
         350                 :     }
         351                 :
         352               0 :     if (mCreatingNewDocument) {
         353                 :         // Handle all sorts of stylesheets
         354                 :         nsCOMPtr<nsIStyleSheetLinkingElement> ssle =
         355               0 :             do_QueryInterface(mCurrentNode);
         356               0 :         if (ssle) {
         357               0 :             ssle->SetEnableUpdates(true);
         358                 :             bool willNotify;
         359                 :             bool isAlternate;
         360               0 :             nsresult rv = ssle->UpdateStyleSheet(mNotifier, &willNotify,
         361               0 :                                                  &isAlternate);
         362               0 :             if (mNotifier && NS_SUCCEEDED(rv) && willNotify && !isAlternate) {
         363               0 :                 mNotifier->AddPendingStylesheet();
         364                 :             }
         365                 :         }
         366                 :     }
         367                 :
         368                 :     // Add the element to the tree if it wasn't added before and take one step
         369                 :     // up the tree
         370               0 :     PRUint32 last = mCurrentNodeStack.Count() - 1;
         371               0 :     NS_ASSERTION(last != (PRUint32)-1, "empty stack");
         372                 :
         373               0 :     nsCOMPtr<nsINode> parent = mCurrentNodeStack.SafeObjectAt(last);
         374               0 :     mCurrentNodeStack.RemoveObjectAt(last);
         375                 :
         376               0 :     if (mCurrentNode == mNonAddedNode) {
         377               0 :         if (parent == mDocument) {
         378               0 :             NS_ASSERTION(!mRootContentCreated,
         379                 :                          "Parent to add to shouldn't be a document if we "
         380                 :                          "have a root content");
         381               0 :             mRootContentCreated = true;
         382                 :         }
         383                 :
         384                 :         // Check to make sure that script hasn't inserted the node somewhere
         385                 :         // else in the tree
         386               0 :         if (!mCurrentNode->GetNodeParent()) {
         387               0 :             parent->AppendChildTo(mNonAddedNode, true);
         388                 :         }
         389               0 :         mNonAddedNode = nsnull;
         390                 :     }
         391                 :
         392               0 :     mCurrentNode = parent;
         393                 :
         394                 :     mTableState =
         395               0 :         static_cast<TableState>(NS_PTR_TO_INT32(mTableStateStack.pop()));
         396                 :
         397               0 :     return NS_OK;
         398                 : }
         399                 :
         400               0 : void txMozillaXMLOutput::getOutputDocument(nsIDOMDocument** aDocument)
         401                 : {
         402               0 :     CallQueryInterface(mDocument, aDocument);
         403               0 : }
         404                 :
         405                 : nsresult
         406               0 : txMozillaXMLOutput::processingInstruction(const nsString& aTarget, const nsString& aData)
         407                 : {
         408               0 :     nsresult rv = closePrevious(true);
         409               0 :     NS_ENSURE_SUCCESS(rv, rv);
         410                 :
         411               0 :     if (mOutputFormat.mMethod == eHTMLOutput)
         412               0 :         return NS_OK;
         413                 :
         414               0 :     TX_ENSURE_CURRENTNODE;
         415                 :
         416               0 :     rv = nsContentUtils::CheckQName(aTarget, false);
         417               0 :     NS_ENSURE_SUCCESS(rv, rv);
         418                 :
         419               0 :     nsCOMPtr<nsIContent> pi;
         420               0 :     rv = NS_NewXMLProcessingInstruction(getter_AddRefs(pi),
         421               0 :                                         mNodeInfoManager, aTarget, aData);
         422               0 :     NS_ENSURE_SUCCESS(rv, rv);
         423                 :
         424               0 :     nsCOMPtr<nsIStyleSheetLinkingElement> ssle;
         425               0 :     if (mCreatingNewDocument) {
         426               0 :         ssle = do_QueryInterface(pi);
         427               0 :         if (ssle) {
         428               0 :             ssle->InitStyleLinkElement(false);
         429               0 :             ssle->SetEnableUpdates(false);
         430                 :         }
         431                 :     }
         432                 :
         433               0 :     rv = mCurrentNode->AppendChildTo(pi, true);
         434               0 :     NS_ENSURE_SUCCESS(rv, rv);
         435                 :
         436               0 :     if (ssle) {
         437               0 :         ssle->SetEnableUpdates(true);
         438                 :         bool willNotify;
         439                 :         bool isAlternate;
         440               0 :         rv = ssle->UpdateStyleSheet(mNotifier, &willNotify, &isAlternate);
         441               0 :         if (mNotifier && NS_SUCCEEDED(rv) && willNotify && !isAlternate) {
         442               0 :             mNotifier->AddPendingStylesheet();
         443                 :         }
         444                 :     }
         445                 :
         446               0 :     return NS_OK;
         447                 : }
         448                 :
         449                 : nsresult
         450               0 : txMozillaXMLOutput::startDocument()
         451                 : {
         452               0 :     if (mNotifier) {
         453               0 :         mNotifier->OnTransformStart();
         454                 :     }
         455                 :
         456               0 :     if (mCreatingNewDocument) {
         457               0 :         nsScriptLoader* loader = mDocument->ScriptLoader();
         458               0 :         if (loader) {
         459               0 :             loader->BeginDeferringScripts();
         460                 :         }
         461                 :     }
         462                 :
         463               0 :     return NS_OK;
         464                 : }
         465                 :
         466                 : nsresult
         467               0 : txMozillaXMLOutput::startElement(nsIAtom* aPrefix, nsIAtom* aLocalName,
         468                 :                                  nsIAtom* aLowercaseLocalName,
         469                 :                                  const PRInt32 aNsID)
         470                 : {
         471               0 :     NS_PRECONDITION(aNsID != kNameSpaceID_None || !aPrefix,
         472                 :                     "Can't have prefix without namespace");
         473                 :
         474               0 :     if (mOutputFormat.mMethod == eHTMLOutput && aNsID == kNameSpaceID_None) {
         475               0 :         nsCOMPtr<nsIAtom> owner;
         476               0 :         if (!aLowercaseLocalName) {
         477               0 :             owner = TX_ToLowerCaseAtom(aLocalName);
         478               0 :             NS_ENSURE_TRUE(owner, NS_ERROR_OUT_OF_MEMORY);
         479                 :
         480               0 :             aLowercaseLocalName = owner;
         481                 :         }
         482                 :         return startElementInternal(nsnull,
         483                 :                                     aLowercaseLocalName,
         484               0 :                                     kNameSpaceID_XHTML);
         485                 :     }
         486                 :
         487               0 :     return startElementInternal(aPrefix, aLocalName, aNsID);
         488                 : }
         489                 :
         490                 : nsresult
         491               0 : txMozillaXMLOutput::startElement(nsIAtom* aPrefix,
         492                 :                                  const nsSubstring& aLocalName,
         493                 :                                  const PRInt32 aNsID)
         494                 : {
         495               0 :     PRInt32 nsId = aNsID;
         496               0 :     nsCOMPtr<nsIAtom> lname;
         497                 :
         498               0 :     if (mOutputFormat.mMethod == eHTMLOutput && aNsID == kNameSpaceID_None) {
         499               0 :         nsId = kNameSpaceID_XHTML;
         500                 :
         501               0 :         nsAutoString lnameStr;
         502               0 :         nsContentUtils::ASCIIToLower(aLocalName, lnameStr);
         503               0 :         lname = do_GetAtom(lnameStr);
         504                 :     }
         505                 :     else {
         506               0 :         lname = do_GetAtom(aLocalName);
         507                 :     }
         508                 :
         509                 :     // No biggie if we lose the prefix due to OOM
         510               0 :     NS_ENSURE_TRUE(lname, NS_ERROR_OUT_OF_MEMORY);
         511                 :
         512                 :     // Check that it's a valid name
         513               0 :     if (!nsContentUtils::IsValidNodeName(lname, aPrefix, nsId)) {
         514                 :         // Try without prefix
         515               0 :         aPrefix = nsnull;
         516               0 :         if (!nsContentUtils::IsValidNodeName(lname, aPrefix, nsId)) {
         517               0 :             return NS_ERROR_XSLT_BAD_NODE_NAME;
         518                 :         }
         519                 :     }
         520                 :
         521               0 :     return startElementInternal(aPrefix, lname, nsId);
         522                 : }
         523                 :
         524                 : nsresult
         525               0 : txMozillaXMLOutput::startElementInternal(nsIAtom* aPrefix,
         526                 :                                          nsIAtom* aLocalName,
         527                 :                                          PRInt32 aNsID)
         528                 : {
         529               0 :     TX_ENSURE_CURRENTNODE;
         530                 :
         531               0 :     if (mBadChildLevel) {
         532               0 :         ++mBadChildLevel;
         533               0 :         PR_LOG(txLog::xslt, PR_LOG_DEBUG,
         534                 :                ("startElement, mBadChildLevel = %d\n", mBadChildLevel));
         535               0 :         return NS_OK;
         536                 :     }
         537                 :
         538               0 :     nsresult rv = closePrevious(true);
         539               0 :     NS_ENSURE_SUCCESS(rv, rv);
         540                 :
         541                 :     // Push and init state
         542               0 :     if (mTreeDepth == MAX_REFLOW_DEPTH) {
         543                 :         // eCloseElement couldn't add the parent so we fail as well or we've
         544                 :         // reached the limit of the depth of the tree that we allow.
         545               0 :         ++mBadChildLevel;
         546               0 :         PR_LOG(txLog::xslt, PR_LOG_DEBUG,
         547                 :                ("startElement, mBadChildLevel = %d\n", mBadChildLevel));
         548               0 :         return NS_OK;
         549                 :     }
         550                 :
         551               0 :     ++mTreeDepth;
         552                 :
         553               0 :     rv = mTableStateStack.push(NS_INT32_TO_PTR(mTableState));
         554               0 :     NS_ENSURE_SUCCESS(rv, rv);
         555                 :
         556               0 :     if (!mCurrentNodeStack.AppendObject(mCurrentNode)) {
         557               0 :         return NS_ERROR_OUT_OF_MEMORY;
         558                 :     }
         559                 :
         560               0 :     mTableState = NORMAL;
         561               0 :     mOpenedElementIsHTML = false;
         562                 :
         563                 :     // Create the element
         564                 :     nsCOMPtr<nsINodeInfo> ni =
         565                 :         mNodeInfoManager->GetNodeInfo(aLocalName, aPrefix, aNsID,
         566               0 :                                       nsIDOMNode::ELEMENT_NODE);
         567               0 :     NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
         568                 :
         569               0 :     NS_NewElement(getter_AddRefs(mOpenedElement), ni.forget(),
         570                 :                   mCreatingNewDocument ?
         571               0 :                   FROM_PARSER_XSLT : FROM_PARSER_FRAGMENT);
         572                 :
         573                 :     // Set up the element and adjust state
         574               0 :     if (!mNoFixup) {
         575               0 :         if (aNsID == kNameSpaceID_XHTML) {
         576               0 :             mOpenedElementIsHTML = (mOutputFormat.mMethod == eHTMLOutput);
         577               0 :             rv = startHTMLElement(mOpenedElement, mOpenedElementIsHTML);
         578               0 :             NS_ENSURE_SUCCESS(rv, rv);
         579                 :
         580                 :         }
         581                 :     }
         582                 :
         583               0 :     if (mCreatingNewDocument) {
         584                 :         // Handle all sorts of stylesheets
         585                 :         nsCOMPtr<nsIStyleSheetLinkingElement> ssle =
         586               0 :             do_QueryInterface(mOpenedElement);
         587               0 :         if (ssle) {
         588               0 :             ssle->InitStyleLinkElement(false);
         589               0 :             ssle->SetEnableUpdates(false);
         590                 :         }
         591                 :     }
         592                 :
         593               0 :     return NS_OK;
         594                 : }
         595                 :
         596                 : nsresult
         597               0 : txMozillaXMLOutput::closePrevious(bool aFlushText)
         598                 : {
         599               0 :     TX_ENSURE_CURRENTNODE;
         600                 :
         601                 :     nsresult rv;
         602               0 :     if (mOpenedElement) {
         603               0 :         bool currentIsDoc = mCurrentNode == mDocument;
         604               0 :         if (currentIsDoc && mRootContentCreated) {
         605                 :             // We already have a document element, but the XSLT spec allows this.
         606                 :             // As a workaround, create a wrapper object and use that as the
         607                 :             // document element.
         608                 :
         609               0 :             rv = createTxWrapper();
         610               0 :             NS_ENSURE_SUCCESS(rv, rv);
         611                 :         }
         612                 :
         613               0 :         rv = mCurrentNode->AppendChildTo(mOpenedElement, true);
         614               0 :         NS_ENSURE_SUCCESS(rv, rv);
         615                 :
         616               0 :         if (currentIsDoc) {
         617               0 :             mRootContentCreated = true;
         618               0 :             nsContentSink::NotifyDocElementCreated(mDocument);
         619                 :         }
         620                 :
         621               0 :         mCurrentNode = mOpenedElement;
         622               0 :         mOpenedElement = nsnull;
         623                 :     }
         624               0 :     else if (aFlushText && !mText.IsEmpty()) {
         625                 :         // Text can't appear in the root of a document
         626               0 :         if (mDocument == mCurrentNode) {
         627               0 :             if (XMLUtils::isWhitespace(mText)) {
         628               0 :                 mText.Truncate();
         629                 :
         630               0 :                 return NS_OK;
         631                 :             }
         632                 :
         633               0 :             rv = createTxWrapper();
         634               0 :             NS_ENSURE_SUCCESS(rv, rv);
         635                 :         }
         636               0 :         nsCOMPtr<nsIContent> text;
         637               0 :         rv = NS_NewTextNode(getter_AddRefs(text), mNodeInfoManager);
         638               0 :         NS_ENSURE_SUCCESS(rv, rv);
         639                 :
         640               0 :         rv = text->SetText(mText, false);
         641               0 :         NS_ENSURE_SUCCESS(rv, rv);
         642                 :
         643               0 :         rv = mCurrentNode->AppendChildTo(text, true);
         644               0 :         NS_ENSURE_SUCCESS(rv, rv);
         645                 :
         646               0 :         mText.Truncate();
         647                 :     }
         648                 :
         649               0 :     return NS_OK;
         650                 : }
         651                 :
         652                 : nsresult
         653               0 : txMozillaXMLOutput::createTxWrapper()
         654                 : {
         655               0 :     NS_ASSERTION(mDocument == mCurrentNode,
         656                 :                  "creating wrapper when document isn't parent");
         657                 :
         658                 :     PRInt32 namespaceID;
         659               0 :     nsresult rv = nsContentUtils::NameSpaceManager()->
         660               0 :         RegisterNameSpace(NS_LITERAL_STRING(kTXNameSpaceURI), namespaceID);
         661               0 :     NS_ENSURE_SUCCESS(rv, rv);
         662                 :
         663               0 :     nsCOMPtr<nsIContent> wrapper;
         664               0 :     rv = mDocument->CreateElem(nsDependentAtomString(nsGkAtoms::result),
         665                 :                                nsGkAtoms::transformiix, namespaceID,
         666               0 :                                getter_AddRefs(wrapper));
         667               0 :     NS_ENSURE_SUCCESS(rv, rv);
         668                 :
         669               0 :     PRUint32 i, j, childCount = mDocument->GetChildCount();
         670                 : #ifdef DEBUG
         671                 :     // Keep track of the location of the current documentElement, if there is
         672                 :     // one, so we can verify later
         673               0 :     PRUint32 rootLocation = 0;
         674                 : #endif
         675               0 :     for (i = 0, j = 0; i < childCount; ++i) {
         676               0 :         nsCOMPtr<nsIContent> childContent = mDocument->GetChildAt(j);
         677                 :
         678                 : #ifdef DEBUG
         679               0 :         if (childContent->IsElement()) {
         680               0 :             rootLocation = j;
         681                 :         }
         682                 : #endif
         683                 :
         684               0 :         if (childContent->Tag() == nsGkAtoms::documentTypeNodeName) {
         685                 : #ifdef DEBUG
         686                 :             // The new documentElement should go after the document type.
         687                 :             // This is needed for cases when there is no existing
         688                 :             // documentElement in the document.
         689               0 :             rootLocation = NS_MAX(rootLocation, j + 1);
         690                 : #endif
         691               0 :             ++j;
         692                 :         }
         693                 :         else {
         694               0 :             rv = mDocument->RemoveChildAt(j, true);
         695               0 :             NS_ENSURE_SUCCESS(rv, rv);
         696                 :
         697               0 :             rv = wrapper->AppendChildTo(childContent, true);
         698               0 :             NS_ENSURE_SUCCESS(rv, rv);
         699                 :             break;
         700                 :         }
         701                 :     }
         702                 :
         703               0 :     if (!mCurrentNodeStack.AppendObject(wrapper)) {
         704               0 :         return NS_ERROR_OUT_OF_MEMORY;
         705                 :     }
         706               0 :     mCurrentNode = wrapper;
         707               0 :     mRootContentCreated = true;
         708               0 :     NS_ASSERTION(rootLocation == mDocument->GetChildCount(),
         709                 :                  "Incorrect root location");
         710               0 :     return mDocument->AppendChildTo(wrapper, true);
         711                 : }
         712                 :
         713                 : nsresult
         714               0 : txMozillaXMLOutput::startHTMLElement(nsIContent* aElement, bool aIsHTML)
         715                 : {
         716               0 :     nsresult rv = NS_OK;
         717               0 :     nsIAtom *atom = aElement->Tag();
         718                 :
         719               0 :     if ((atom != nsGkAtoms::tr || !aIsHTML) &&
         720               0 :         NS_PTR_TO_INT32(mTableStateStack.peek()) == ADDED_TBODY) {
         721               0 :         PRUint32 last = mCurrentNodeStack.Count() - 1;
         722               0 :         NS_ASSERTION(last != (PRUint32)-1, "empty stack");
         723                 :
         724               0 :         mCurrentNode = mCurrentNodeStack.SafeObjectAt(last);
         725               0 :         mCurrentNodeStack.RemoveObjectAt(last);
         726               0 :         mTableStateStack.pop();
         727                 :     }
         728                 :
         729               0 :     if (atom == nsGkAtoms::table && aIsHTML) {
         730               0 :         mTableState = TABLE;
         731                 :     }
         732               0 :     else if (atom == nsGkAtoms::tr && aIsHTML &&
         733               0 :              NS_PTR_TO_INT32(mTableStateStack.peek()) == TABLE) {
         734               0 :         nsCOMPtr<nsIContent> tbody;
         735               0 :         rv = createHTMLElement(nsGkAtoms::tbody, getter_AddRefs(tbody));
         736               0 :         NS_ENSURE_SUCCESS(rv, rv);
         737                 :
         738               0 :         rv = mCurrentNode->AppendChildTo(tbody, true);
         739               0 :         NS_ENSURE_SUCCESS(rv, rv);
         740                 :
         741               0 :         rv = mTableStateStack.push(NS_INT32_TO_PTR(ADDED_TBODY));
         742               0 :         NS_ENSURE_SUCCESS(rv, rv);
         743                 :
         744               0 :         if (!mCurrentNodeStack.AppendObject(tbody)) {
         745               0 :             return NS_ERROR_OUT_OF_MEMORY;
         746                 :         }
         747                 :
         748               0 :         mCurrentNode = tbody;
         749                 :     }
         750               0 :     else if (atom == nsGkAtoms::head &&
         751                 :              mOutputFormat.mMethod == eHTMLOutput) {
         752                 :         // Insert META tag, according to spec, 16.2, like
         753                 :         // <META http-equiv="Content-Type" content="text/html; charset=EUC-JP">
         754               0 :         nsCOMPtr<nsIContent> meta;
         755               0 :         rv = createHTMLElement(nsGkAtoms::meta, getter_AddRefs(meta));
         756               0 :         NS_ENSURE_SUCCESS(rv, rv);
         757                 :
         758                 :         rv = meta->SetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv,
         759               0 :                            NS_LITERAL_STRING("Content-Type"), false);
         760               0 :         NS_ENSURE_SUCCESS(rv, rv);
         761                 :
         762               0 :         nsAutoString metacontent;
         763               0 :         metacontent.Append(mOutputFormat.mMediaType);
         764               0 :         metacontent.AppendLiteral("; charset=");
         765               0 :         metacontent.Append(mOutputFormat.mEncoding);
         766                 :         rv = meta->SetAttr(kNameSpaceID_None, nsGkAtoms::content,
         767               0 :                            metacontent, false);
         768               0 :         NS_ENSURE_SUCCESS(rv, rv);
         769                 :
         770                 :         // No need to notify since aElement hasn't been inserted yet
         771               0 :         NS_ASSERTION(!aElement->IsInDoc(), "should not be in doc");
         772               0 :         rv = aElement->AppendChildTo(meta, false);
         773               0 :         NS_ENSURE_SUCCESS(rv, rv);
         774                 :     }
         775                 :
         776               0 :     return NS_OK;
         777                 : }
         778                 :
         779                 : nsresult
         780               0 : txMozillaXMLOutput::endHTMLElement(nsIContent* aElement)
         781                 : {
         782               0 :     nsIAtom *atom = aElement->Tag();
         783                 :
         784               0 :     if (mTableState == ADDED_TBODY) {
         785               0 :         NS_ASSERTION(atom == nsGkAtoms::tbody,
         786                 :                      "Element flagged as added tbody isn't a tbody");
         787               0 :         PRUint32 last = mCurrentNodeStack.Count() - 1;
         788               0 :         NS_ASSERTION(last != (PRUint32)-1, "empty stack");
         789                 :
         790               0 :         mCurrentNode = mCurrentNodeStack.SafeObjectAt(last);
         791               0 :         mCurrentNodeStack.RemoveObjectAt(last);
         792                 :         mTableState = static_cast<TableState>
         793               0 :                                  (NS_PTR_TO_INT32(mTableStateStack.pop()));
         794                 :
         795               0 :         return NS_OK;
         796                 :     }
         797               0 :     else if (mCreatingNewDocument && atom == nsGkAtoms::meta) {
         798                 :         // handle HTTP-EQUIV data
         799               0 :         nsAutoString httpEquiv;
         800               0 :         aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, httpEquiv);
         801               0 :         if (!httpEquiv.IsEmpty()) {
         802               0 :             nsAutoString value;
         803               0 :             aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::content, value);
         804               0 :             if (!value.IsEmpty()) {
         805               0 :                 nsContentUtils::ASCIIToLower(httpEquiv);
         806               0 :                 nsCOMPtr<nsIAtom> header = do_GetAtom(httpEquiv);
         807               0 :                 processHTTPEquiv(header, value);
         808                 :             }
         809                 :         }
         810                 :     }
         811                 :
         812               0 :     return NS_OK;
         813                 : }
         814                 :
         815               0 : void txMozillaXMLOutput::processHTTPEquiv(nsIAtom* aHeader, const nsString& aValue)
         816                 : {
         817                 :     // For now we only handle "refresh". There's a longer list in
         818                 :     // HTMLContentSink::ProcessHeaderData
         819               0 :     if (aHeader == nsGkAtoms::refresh)
         820               0 :         LossyCopyUTF16toASCII(aValue, mRefreshString);
         821               0 : }
         822                 :
         823                 : nsresult
         824               0 : txMozillaXMLOutput::createResultDocument(const nsSubstring& aName, PRInt32 aNsID,
         825                 :                                          nsIDOMDocument* aSourceDocument)
         826                 : {
         827                 :     nsresult rv;
         828                 :
         829                 :     // Create the document
         830               0 :     if (mOutputFormat.mMethod == eHTMLOutput) {
         831               0 :         rv = NS_NewHTMLDocument(getter_AddRefs(mDocument));
         832               0 :         NS_ENSURE_SUCCESS(rv, rv);
         833                 :     }
         834                 :     else {
         835                 :         // We should check the root name/namespace here and create the
         836                 :         // appropriate document
         837               0 :         rv = NS_NewXMLDocument(getter_AddRefs(mDocument));
         838               0 :         NS_ENSURE_SUCCESS(rv, rv);
         839                 :     }
         840                 :     // This should really be handled by nsIDocument::BeginLoad
         841               0 :     mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_LOADING);
         842               0 :     nsCOMPtr<nsIDocument> source = do_QueryInterface(aSourceDocument);
         843               0 :     NS_ENSURE_STATE(source);
         844               0 :     bool hasHadScriptObject = false;
         845                 :     nsIScriptGlobalObject* sgo =
         846               0 :       source->GetScriptHandlingObject(hasHadScriptObject);
         847               0 :     NS_ENSURE_STATE(sgo || !hasHadScriptObject);
         848               0 :     mDocument->SetScriptHandlingObject(sgo);
         849                 :
         850               0 :     mCurrentNode = mDocument;
         851               0 :     mNodeInfoManager = mDocument->NodeInfoManager();
         852                 :
         853                 :     // Reset and set up the document
         854               0 :     URIUtils::ResetWithSource(mDocument, aSourceDocument);
         855                 :
         856                 :     // Set the charset
         857               0 :     if (!mOutputFormat.mEncoding.IsEmpty()) {
         858               0 :         NS_LossyConvertUTF16toASCII charset(mOutputFormat.mEncoding);
         859               0 :         nsCAutoString canonicalCharset;
         860               0 :         if (NS_SUCCEEDED(nsCharsetAlias::GetPreferred(charset, canonicalCharset))) {
         861               0 :             mDocument->SetDocumentCharacterSetSource(kCharsetFromOtherComponent);
         862               0 :             mDocument->SetDocumentCharacterSet(canonicalCharset);
         863                 :         }
         864                 :     }
         865                 :
         866                 :     // Set the mime-type
         867               0 :     if (!mOutputFormat.mMediaType.IsEmpty()) {
         868               0 :         mDocument->SetContentType(mOutputFormat.mMediaType);
         869                 :     }
         870               0 :     else if (mOutputFormat.mMethod == eHTMLOutput) {
         871               0 :         mDocument->SetContentType(NS_LITERAL_STRING("text/html"));
         872                 :     }
         873                 :     else {
         874               0 :         mDocument->SetContentType(NS_LITERAL_STRING("application/xml"));
         875                 :     }
         876                 :
         877               0 :     if (mOutputFormat.mMethod == eXMLOutput &&
         878                 :         mOutputFormat.mOmitXMLDeclaration != eTrue) {
         879                 :         PRInt32 standalone;
         880               0 :         if (mOutputFormat.mStandalone == eNotSet) {
         881               0 :           standalone = -1;
         882                 :         }
         883               0 :         else if (mOutputFormat.mStandalone == eFalse) {
         884               0 :           standalone = 0;
         885                 :         }
         886                 :         else {
         887               0 :           standalone = 1;
         888                 :         }
         889                 :
         890                 :         // Could use mOutputFormat.mVersion.get() when we support
         891                 :         // versions > 1.0.
         892                 :         static const PRUnichar kOneDotZero[] = { '1', '.', '0', '\0' };
         893               0 :         mDocument->SetXMLDeclaration(kOneDotZero, mOutputFormat.mEncoding.get(),
         894               0 :                                      standalone);
         895                 :     }
         896                 :
         897                 :     // Set up script loader of the result document.
         898               0 :     nsScriptLoader *loader = mDocument->ScriptLoader();
         899               0 :     if (mNotifier) {
         900               0 :         loader->AddObserver(mNotifier);
         901                 :     }
         902                 :     else {
         903                 :         // Don't load scripts, we can't notify the caller when they're loaded.
         904               0 :         loader->SetEnabled(false);
         905                 :     }
         906                 :
         907               0 :     if (mNotifier) {
         908               0 :         rv = mNotifier->SetOutputDocument(mDocument);
         909               0 :         NS_ENSURE_SUCCESS(rv, rv);
         910                 :     }
         911                 :
         912                 :     // Do this after calling OnDocumentCreated to ensure that the
         913                 :     // PresShell/PresContext has been hooked up and get notified.
         914               0 :     nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
         915               0 :     if (htmlDoc) {
         916               0 :         htmlDoc->SetCompatibilityMode(eCompatibility_FullStandards);
         917                 :     }
         918                 :
         919                 :     // Add a doc-type if requested
         920               0 :     if (!mOutputFormat.mSystemId.IsEmpty()) {
         921               0 :         nsAutoString qName;
         922               0 :         if (mOutputFormat.mMethod == eHTMLOutput) {
         923               0 :             qName.AssignLiteral("html");
         924                 :         }
         925                 :         else {
         926               0 :             qName.Assign(aName);
         927                 :         }
         928                 :
         929               0 :         nsCOMPtr<nsIDOMDocumentType> documentType;
         930                 :
         931               0 :         nsresult rv = nsContentUtils::CheckQName(qName);
         932               0 :         if (NS_SUCCEEDED(rv)) {
         933               0 :             nsCOMPtr<nsIAtom> doctypeName = do_GetAtom(qName);
         934               0 :             if (!doctypeName) {
         935               0 :                 return NS_ERROR_OUT_OF_MEMORY;
         936                 :             }
         937                 :
         938                 :             // Indicate that there is no internal subset (not just an empty one)
         939               0 :             rv = NS_NewDOMDocumentType(getter_AddRefs(documentType),
         940                 :                                        mNodeInfoManager,
         941                 :                                        doctypeName,
         942                 :                                        mOutputFormat.mPublicId,
         943                 :                                        mOutputFormat.mSystemId,
         944               0 :                                        NullString());
         945               0 :             NS_ENSURE_SUCCESS(rv, rv);
         946                 :
         947               0 :             nsCOMPtr<nsIContent> docType = do_QueryInterface(documentType);
         948               0 :             rv = mDocument->AppendChildTo(docType, true);
         949               0 :             NS_ENSURE_SUCCESS(rv, rv);
         950                 :         }
         951                 :     }
         952                 :
         953               0 :     return NS_OK;
         954                 : }
         955                 :
         956                 : nsresult
         957               0 : txMozillaXMLOutput::createHTMLElement(nsIAtom* aName,
         958                 :                                       nsIContent** aResult)
         959                 : {
         960               0 :     NS_ASSERTION(mOutputFormat.mMethod == eHTMLOutput,
         961                 :                  "need to adjust createHTMLElement");
         962                 :
         963               0 :     *aResult = nsnull;
         964                 :
         965               0 :     nsCOMPtr<nsINodeInfo> ni;
         966                 :     ni = mNodeInfoManager->GetNodeInfo(aName, nsnull,
         967                 :                                        kNameSpaceID_XHTML,
         968               0 :                                        nsIDOMNode::ELEMENT_NODE);
         969               0 :     NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
         970                 :
         971                 :     return NS_NewHTMLElement(aResult, ni.forget(), mCreatingNewDocument ?
         972               0 :         FROM_PARSER_XSLT : FROM_PARSER_FRAGMENT);
         973                 :
         974                 : }
         975                 :
         976               0 : txTransformNotifier::txTransformNotifier()
         977                 :     : mPendingStylesheetCount(0),
         978               0 :       mInTransform(false)
         979                 : {
         980               0 : }
         981                 :
         982               0 : NS_IMPL_ISUPPORTS2(txTransformNotifier,
         983                 :                    nsIScriptLoaderObserver,
         984                 :                    nsICSSLoaderObserver)
         985                 :
         986                 : NS_IMETHODIMP
         987               0 : txTransformNotifier::ScriptAvailable(nsresult aResult,
         988                 :                                      nsIScriptElement *aElement,
         989                 :                                      bool aIsInline,
         990                 :                                      nsIURI *aURI,
         991                 :                                      PRInt32 aLineNo)
         992                 : {
         993               0 :     if (NS_FAILED(aResult) &&
         994               0 :         mScriptElements.RemoveObject(aElement)) {
         995               0 :         SignalTransformEnd();
         996                 :     }
         997                 :
         998               0 :     return NS_OK;
         999                 : }
        1000                 :
        1001                 : NS_IMETHODIMP
        1002               0 : txTransformNotifier::ScriptEvaluated(nsresult aResult,
        1003                 :                                      nsIScriptElement *aElement,
        1004                 :                                      bool aIsInline)
        1005                 : {
        1006               0 :     if (mScriptElements.RemoveObject(aElement)) {
        1007               0 :         SignalTransformEnd();
        1008                 :     }
        1009                 :
        1010               0 :     return NS_OK;
        1011                 : }
        1012                 :
        1013                 : NS_IMETHODIMP
        1014               0 : txTransformNotifier::StyleSheetLoaded(nsCSSStyleSheet* aSheet,
        1015                 :                                       bool aWasAlternate,
        1016                 :                                       nsresult aStatus)
        1017                 : {
        1018               0 :     if (mPendingStylesheetCount == 0) {
        1019                 :         // We weren't waiting on this stylesheet anyway.  This can happen if
        1020                 :         // SignalTransformEnd got called with an error aResult.  See
        1021                 :         // http://bugzilla.mozilla.org/show_bug.cgi?id=215465.
        1022               0 :         return NS_OK;
        1023                 :     }
        1024                 :
        1025                 :     // We're never waiting for alternate stylesheets
        1026               0 :     if (!aWasAlternate) {
        1027               0 :         --mPendingStylesheetCount;
        1028               0 :         SignalTransformEnd();
        1029                 :     }
        1030                 :
        1031               0 :     return NS_OK;
        1032                 : }
        1033                 :
        1034                 : void
        1035               0 : txTransformNotifier::Init(nsITransformObserver* aObserver)
        1036                 : {
        1037               0 :     mObserver = aObserver;
        1038               0 : }
        1039                 :
        1040                 : nsresult
        1041               0 : txTransformNotifier::AddScriptElement(nsIScriptElement* aElement)
        1042                 : {
        1043               0 :     return mScriptElements.AppendObject(aElement) ? NS_OK :
        1044               0 :                                                     NS_ERROR_OUT_OF_MEMORY;
        1045                 : }
        1046                 :
        1047                 : void
        1048               0 : txTransformNotifier::AddPendingStylesheet()
        1049                 : {
        1050               0 :     ++mPendingStylesheetCount;
        1051               0 : }
        1052                 :
        1053                 : void
        1054               0 : txTransformNotifier::OnTransformEnd(nsresult aResult)
        1055                 : {
        1056               0 :     mInTransform = false;
        1057               0 :     SignalTransformEnd(aResult);
        1058               0 : }
        1059                 :
        1060                 : void
        1061               0 : txTransformNotifier::OnTransformStart()
        1062                 : {
        1063               0 :     mInTransform = true;
        1064               0 : }
        1065                 :
        1066                 : nsresult
        1067               0 : txTransformNotifier::SetOutputDocument(nsIDocument* aDocument)
        1068                 : {
        1069               0 :     mDocument = aDocument;
        1070                 :
        1071                 :     // Notify the contentsink that the document is created
        1072               0 :     return mObserver->OnDocumentCreated(mDocument);
        1073                 : }
        1074                 :
        1075                 : void
        1076               0 : txTransformNotifier::SignalTransformEnd(nsresult aResult)
        1077                 : {
        1078               0 :     if (mInTransform ||
        1079               0 :         (NS_SUCCEEDED(aResult) &&
        1080               0 :          (mScriptElements.Count() > 0 || mPendingStylesheetCount > 0))) {
        1081               0 :         return;
        1082                 :     }
        1083                 :
        1084                 :     // mPendingStylesheetCount is nonzero at this point only if aResult is an
        1085                 :     // error.  Set it to 0 so we won't reenter this code when we stop the
        1086                 :     // CSSLoader.
        1087               0 :     mPendingStylesheetCount = 0;
        1088               0 :     mScriptElements.Clear();
        1089                 :
        1090                 :     // Make sure that we don't get deleted while this function is executed and
        1091                 :     // we remove ourselfs from the scriptloader
        1092               0 :     nsCOMPtr<nsIScriptLoaderObserver> kungFuDeathGrip(this);
        1093                 :
        1094               0 :     if (mDocument) {
        1095               0 :         mDocument->ScriptLoader()->RemoveObserver(this);
        1096                 :         // XXX Maybe we want to cancel script loads if NS_FAILED(rv)?
        1097                 :
        1098               0 :         if (NS_FAILED(aResult)) {
        1099               0 :             mDocument->CSSLoader()->Stop();
        1100                 :         }
        1101                 :     }
        1102                 :
        1103               0 :     if (NS_SUCCEEDED(aResult)) {
        1104               0 :         mObserver->OnTransformDone(aResult, mDocument);
        1105                 :     }
        1106                 : }

Generated by: LCOV version 1.7