michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsXMLContentSink_h__ michael@0: #define nsXMLContentSink_h__ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "nsContentSink.h" michael@0: #include "nsIXMLContentSink.h" michael@0: #include "nsIExpatSink.h" michael@0: #include "nsIDocumentTransformer.h" michael@0: #include "nsTArray.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsCRT.h" michael@0: #include "nsCycleCollectionParticipant.h" michael@0: #include "nsIDTD.h" michael@0: #include "mozilla/dom/FromParser.h" michael@0: michael@0: class nsIDocument; michael@0: class nsIURI; michael@0: class nsIContent; michael@0: class nsINodeInfo; michael@0: class nsIParser; michael@0: class nsViewManager; michael@0: michael@0: typedef enum { michael@0: eXMLContentSinkState_InProlog, michael@0: eXMLContentSinkState_InDocumentElement, michael@0: eXMLContentSinkState_InEpilog michael@0: } XMLContentSinkState; michael@0: michael@0: struct StackNode { michael@0: nsCOMPtr mContent; michael@0: uint32_t mNumFlushed; michael@0: }; michael@0: michael@0: class nsXMLContentSink : public nsContentSink, michael@0: public nsIXMLContentSink, michael@0: public nsITransformObserver, michael@0: public nsIExpatSink michael@0: { michael@0: public: michael@0: nsXMLContentSink(); michael@0: virtual ~nsXMLContentSink(); michael@0: michael@0: NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW michael@0: michael@0: nsresult Init(nsIDocument* aDoc, michael@0: nsIURI* aURL, michael@0: nsISupports* aContainer, michael@0: nsIChannel* aChannel); michael@0: michael@0: // nsISupports michael@0: NS_DECL_ISUPPORTS_INHERITED michael@0: michael@0: NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsXMLContentSink, michael@0: nsContentSink) michael@0: michael@0: NS_DECL_NSIEXPATSINK michael@0: michael@0: // nsIContentSink michael@0: NS_IMETHOD WillParse(void) MOZ_OVERRIDE; michael@0: NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode) MOZ_OVERRIDE; michael@0: NS_IMETHOD DidBuildModel(bool aTerminated) MOZ_OVERRIDE; michael@0: NS_IMETHOD WillInterrupt(void) MOZ_OVERRIDE; michael@0: NS_IMETHOD WillResume(void) MOZ_OVERRIDE; michael@0: NS_IMETHOD SetParser(nsParserBase* aParser) MOZ_OVERRIDE; michael@0: virtual void FlushPendingNotifications(mozFlushType aType) MOZ_OVERRIDE; michael@0: NS_IMETHOD SetDocumentCharset(nsACString& aCharset) MOZ_OVERRIDE; michael@0: virtual nsISupports *GetTarget() MOZ_OVERRIDE; michael@0: virtual bool IsScriptExecuting() MOZ_OVERRIDE; michael@0: virtual void ContinueInterruptedParsingAsync() MOZ_OVERRIDE; michael@0: michael@0: // nsITransformObserver michael@0: NS_IMETHOD OnDocumentCreated(nsIDocument *aResultDocument) MOZ_OVERRIDE; michael@0: NS_IMETHOD OnTransformDone(nsresult aResult, nsIDocument *aResultDocument) MOZ_OVERRIDE; michael@0: michael@0: // nsICSSLoaderObserver michael@0: NS_IMETHOD StyleSheetLoaded(nsCSSStyleSheet* aSheet, bool aWasAlternate, michael@0: nsresult aStatus) MOZ_OVERRIDE; michael@0: static bool ParsePIData(const nsString &aData, nsString &aHref, michael@0: nsString &aTitle, nsString &aMedia, michael@0: bool &aIsAlternate); michael@0: michael@0: protected: michael@0: michael@0: nsIParser* GetParser(); michael@0: michael@0: void ContinueInterruptedParsingIfEnabled(); michael@0: michael@0: // Start layout. If aIgnorePendingSheets is true, this will happen even if michael@0: // we still have stylesheet loads pending. Otherwise, we'll wait until the michael@0: // stylesheets are all done loading. michael@0: virtual void MaybeStartLayout(bool aIgnorePendingSheets); michael@0: michael@0: virtual nsresult AddAttributes(const char16_t** aNode, nsIContent* aContent); michael@0: nsresult AddText(const char16_t* aString, int32_t aLength); michael@0: michael@0: virtual bool OnOpenContainer(const char16_t **aAtts, michael@0: uint32_t aAttsCount, michael@0: int32_t aNameSpaceID, michael@0: nsIAtom* aTagName, michael@0: uint32_t aLineNumber) { return true; } michael@0: // Set the given content as the root element for the created document michael@0: // don't set if root element was already set. michael@0: // return TRUE if this call set the root element michael@0: virtual bool SetDocElement(int32_t aNameSpaceID, michael@0: nsIAtom *aTagName, michael@0: nsIContent *aContent); michael@0: virtual bool NotifyForDocElement() { return true; } michael@0: virtual nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount, michael@0: nsINodeInfo* aNodeInfo, uint32_t aLineNumber, michael@0: nsIContent** aResult, bool* aAppendContent, michael@0: mozilla::dom::FromParser aFromParser); michael@0: michael@0: // aParent is allowed to be null here if this is the root content michael@0: // being closed michael@0: virtual nsresult CloseElement(nsIContent* aContent); michael@0: michael@0: virtual nsresult FlushText(bool aReleaseTextNode = true); michael@0: michael@0: nsresult AddContentAsLeaf(nsIContent *aContent); michael@0: michael@0: nsIContent* GetCurrentContent(); michael@0: StackNode* GetCurrentStackNode(); michael@0: nsresult PushContent(nsIContent *aContent); michael@0: void PopContent(); michael@0: bool HaveNotifiedForCurrentContent() const; michael@0: michael@0: nsresult FlushTags() MOZ_OVERRIDE; michael@0: michael@0: void UpdateChildCounts() MOZ_OVERRIDE; michael@0: michael@0: void DidAddContent() michael@0: { michael@0: if (IsTimeToNotify()) { michael@0: FlushTags(); michael@0: } michael@0: } michael@0: michael@0: // nsContentSink override michael@0: virtual nsresult ProcessStyleLink(nsIContent* aElement, michael@0: const nsSubstring& aHref, michael@0: bool aAlternate, michael@0: const nsSubstring& aTitle, michael@0: const nsSubstring& aType, michael@0: const nsSubstring& aMedia) MOZ_OVERRIDE; michael@0: michael@0: nsresult LoadXSLStyleSheet(nsIURI* aUrl); michael@0: michael@0: bool CanStillPrettyPrint(); michael@0: michael@0: nsresult MaybePrettyPrint(); michael@0: michael@0: bool IsMonolithicContainer(nsINodeInfo* aNodeInfo); michael@0: michael@0: nsresult HandleStartElement(const char16_t *aName, const char16_t **aAtts, michael@0: uint32_t aAttsCount, int32_t aIndex, michael@0: uint32_t aLineNumber, michael@0: bool aInterruptable); michael@0: nsresult HandleEndElement(const char16_t *aName, bool aInterruptable); michael@0: nsresult HandleCharacterData(const char16_t *aData, uint32_t aLength, michael@0: bool aInterruptable); michael@0: michael@0: nsCOMPtr mDocElement; michael@0: nsCOMPtr mCurrentHead; // When set, we're in an XHTML michael@0: char16_t* mText; michael@0: michael@0: XMLContentSinkState mState; michael@0: michael@0: int32_t mTextLength; michael@0: int32_t mTextSize; michael@0: michael@0: int32_t mNotifyLevel; michael@0: nsCOMPtr mLastTextNode; michael@0: int32_t mLastTextNodeSize; michael@0: michael@0: uint8_t mConstrainSize : 1; michael@0: uint8_t mPrettyPrintXML : 1; michael@0: uint8_t mPrettyPrintHasSpecialRoot : 1; michael@0: uint8_t mPrettyPrintHasFactoredElements : 1; michael@0: uint8_t mPrettyPrinting : 1; // True if we called PrettyPrint() and it michael@0: // decided we should in fact prettyprint. michael@0: // True to call prevent script execution in the fragment mode. michael@0: uint8_t mPreventScriptExecution : 1; michael@0: michael@0: nsTArray mContentStack; michael@0: michael@0: nsCOMPtr mXSLTProcessor; michael@0: }; michael@0: michael@0: #endif // nsXMLContentSink_h__