nsXMLContentSink.h (8308B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef nsXMLContentSink_h__ 8 #define nsXMLContentSink_h__ 9 10 #include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin 11 #include "mozilla/dom/FromParser.h" 12 #include "nsCOMPtr.h" 13 #include "nsCRT.h" 14 #include "nsContentSink.h" 15 #include "nsCycleCollectionParticipant.h" 16 #include "nsIDocumentTransformer.h" 17 #include "nsIExpatSink.h" 18 #include "nsIXMLContentSink.h" 19 #include "nsTArray.h" 20 21 class nsIURI; 22 class nsIContent; 23 class nsIParser; 24 class nsTextNode; 25 26 namespace mozilla::dom { 27 class NodeInfo; 28 class ProcessingInstruction; 29 } // namespace mozilla::dom 30 31 enum XMLContentSinkState { 32 eXMLContentSinkState_InProlog, 33 eXMLContentSinkState_InDocumentElement, 34 eXMLContentSinkState_InEpilog 35 }; 36 37 class nsXMLContentSink : public nsContentSink, 38 public nsIXMLContentSink, 39 public nsITransformObserver, 40 public nsIExpatSink { 41 public: 42 struct StackNode { 43 nsCOMPtr<nsIContent> mContent; 44 uint32_t mNumFlushed; 45 }; 46 47 nsXMLContentSink(); 48 49 nsresult Init(mozilla::dom::Document* aDoc, nsIURI* aURL, 50 nsISupports* aContainer, nsIChannel* aChannel); 51 52 // nsISupports 53 NS_DECL_ISUPPORTS_INHERITED 54 55 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXMLContentSink, nsContentSink) 56 57 NS_DECL_NSIEXPATSINK 58 59 // nsIContentSink 60 NS_IMETHOD WillParse(void) override; 61 NS_IMETHOD WillBuildModel() override; 62 NS_IMETHOD DidBuildModel(bool aTerminated) override; 63 NS_IMETHOD WillInterrupt(void) override; 64 void WillResume() override; 65 NS_IMETHOD SetParser(nsParserBase* aParser) override; 66 virtual void InitialTranslationCompleted() override; 67 virtual void FlushPendingNotifications(mozilla::FlushType aType) override; 68 virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding) override; 69 virtual nsISupports* GetTarget() override; 70 bool IsScriptExecuting() override { return IsScriptExecutingImpl(); } 71 void ContinueParsingDocumentAfterCurrentScript() override { 72 ContinueParsingDocumentAfterCurrentScriptImpl(); 73 } 74 virtual void ContinueInterruptedParsingAsync() override; 75 bool IsPrettyPrintXML() const override { return mPrettyPrintXML; } 76 bool IsPrettyPrintHasSpecialRoot() const override { 77 return mPrettyPrintHasSpecialRoot; 78 } 79 80 // nsITransformObserver 81 nsresult OnDocumentCreated(mozilla::dom::Document* aSourceDocument, 82 mozilla::dom::Document* aResultDocument) override; 83 nsresult OnTransformDone(mozilla::dom::Document* aSourceDocument, 84 nsresult aResult, 85 mozilla::dom::Document* aResultDocument) override; 86 87 // nsICSSLoaderObserver 88 NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheet* aSheet, bool aWasDeferred, 89 nsresult aStatus) override; 90 static bool ParsePIData(const nsString& aData, nsString& aHref, 91 nsString& aTitle, nsString& aMedia, 92 bool& aIsAlternate); 93 94 protected: 95 virtual ~nsXMLContentSink(); 96 97 nsIParser* GetParser(); 98 99 void ContinueInterruptedParsingIfEnabled(); 100 101 // Start layout. If aIgnorePendingSheets is true, this will happen even if 102 // we still have stylesheet loads pending. Otherwise, we'll wait until the 103 // stylesheets are all done loading. 104 virtual void MaybeStartLayout(bool aIgnorePendingSheets); 105 106 virtual nsresult AddAttributes(const char16_t** aNode, 107 mozilla::dom::Element* aElement); 108 nsresult AddText(const char16_t* aString, int32_t aLength); 109 110 virtual bool OnOpenContainer(const char16_t** aAtts, uint32_t aAttsCount, 111 int32_t aNameSpaceID, nsAtom* aTagName, 112 uint32_t aLineNumber) { 113 return true; 114 } 115 // Set the given content as the root element for the created document 116 // don't set if root element was already set. 117 // return TRUE if this call set the root element 118 virtual bool SetDocElement(int32_t aNameSpaceID, nsAtom* aTagName, 119 nsIContent* aContent); 120 virtual bool NotifyForDocElement() { return true; } 121 virtual nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount, 122 mozilla::dom::NodeInfo* aNodeInfo, 123 uint32_t aLineNumber, uint32_t aColumnNumber, 124 nsIContent** aResult, bool* aAppendContent, 125 mozilla::dom::FromParser aFromParser); 126 127 // aParent is allowed to be null here if this is the root content 128 // being closed 129 virtual nsresult CloseElement(nsIContent* aContent); 130 131 virtual nsresult FlushText(bool aReleaseTextNode = true); 132 133 nsresult AddContentAsLeaf(nsIContent* aContent); 134 135 nsIContent* GetCurrentContent(); 136 StackNode* GetCurrentStackNode(); 137 nsresult PushContent(nsIContent* aContent); 138 void PopContent(); 139 bool HaveNotifiedForCurrentContent() const; 140 141 nsresult FlushTags() override; 142 143 void UpdateChildCounts() override; 144 145 void DidAddContent() { 146 if (!mXSLTProcessor && IsTimeToNotify()) { 147 FlushTags(); 148 } 149 } 150 151 // nsContentSink override 152 virtual nsresult ProcessStyleLinkFromHeader( 153 const nsAString& aHref, bool aAlternate, const nsAString& aTitle, 154 const nsAString& aIntegrity, const nsAString& aType, 155 const nsAString& aMedia, const nsAString& aReferrerPolicy, 156 const nsAString& aFetchPriority) override; 157 158 // Try to handle an XSLT style link. If NS_OK is returned and aWasXSLT is not 159 // null, *aWasXSLT will be set to whether we processed this link as XSLT. 160 // 161 // aProcessingInstruction can be null if this information comes from a Link 162 // header; otherwise it will be the xml-styleshset XML PI that the loading 163 // information comes from. 164 virtual nsresult MaybeProcessXSLTLink( 165 mozilla::dom::ProcessingInstruction* aProcessingInstruction, 166 const nsAString& aHref, bool aAlternate, const nsAString& aTitle, 167 const nsAString& aType, const nsAString& aMedia, 168 const nsAString& aReferrerPolicy, bool* aWasXSLT = nullptr); 169 170 nsresult LoadXSLStyleSheet(nsIURI* aUrl); 171 172 bool CanStillPrettyPrint(); 173 174 nsresult MaybePrettyPrint(); 175 176 bool IsMonolithicContainer(mozilla::dom::NodeInfo* aNodeInfo); 177 178 nsresult HandleStartElement(const char16_t* aName, const char16_t** aAtts, 179 uint32_t aAttsCount, uint32_t aLineNumber, 180 uint32_t aColumnNumber, bool aInterruptable); 181 nsresult HandleEndElement(const char16_t* aName, bool aInterruptable); 182 nsresult HandleCharacterData(const char16_t* aData, uint32_t aLength, 183 bool aInterruptable); 184 185 nsCOMPtr<nsIContent> mDocElement; 186 nsCOMPtr<nsIContent> mCurrentHead; // When set, we're in an XHTML <haed> 187 188 XMLContentSinkState mState; 189 190 // The length of the valid data in mText. 191 int32_t mTextLength; 192 193 int32_t mNotifyLevel; 194 RefPtr<nsTextNode> mLastTextNode; 195 196 uint8_t mPrettyPrintXML : 1; 197 uint8_t mPrettyPrintHasSpecialRoot : 1; 198 uint8_t mPrettyPrintHasFactoredElements : 1; 199 uint8_t mPrettyPrinting : 1; // True if we called PrettyPrint() and it 200 // decided we should in fact prettyprint. 201 // True to call prevent script execution in the fragment mode. 202 uint8_t mPreventScriptExecution : 1; 203 204 nsTArray<StackNode> mContentStack; 205 206 nsCOMPtr<nsIDocumentTransformer> mXSLTProcessor; 207 208 // Holds the children in the prolog until the root element is added, after 209 // which they're inserted in the document. However, if we're doing an XSLT 210 // transform this will actually hold all the children of the source document, 211 // until the transform is finished. After the transform is finished we'll just 212 // discard the children. 213 nsTArray<nsCOMPtr<nsIContent>> mDocumentChildren; 214 215 static const int NS_ACCUMULATION_BUFFER_SIZE = 4096; 216 // Our currently accumulated text that we have not flushed to a textnode yet. 217 char16_t mText[NS_ACCUMULATION_BUFFER_SIZE]; 218 }; 219 220 #endif // nsXMLContentSink_h__