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/. */
7 #ifndef nsXMLContentSink_h__
8 #define nsXMLContentSink_h__
10 #include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin
11 #include "mozilla/Attributes.h"
12 #include "nsContentSink.h"
13 #include "nsIXMLContentSink.h"
14 #include "nsIExpatSink.h"
15 #include "nsIDocumentTransformer.h"
19 #include "nsCycleCollectionParticipant.h"
21 #include "mozilla/dom/FromParser.h"
28 namespace mozilla::dom
{
30 class ProcessingInstruction
;
31 } // namespace mozilla::dom
33 enum XMLContentSinkState
{
34 eXMLContentSinkState_InProlog
,
35 eXMLContentSinkState_InDocumentElement
,
36 eXMLContentSinkState_InEpilog
39 class nsXMLContentSink
: public nsContentSink
,
40 public nsIXMLContentSink
,
41 public nsITransformObserver
,
45 nsCOMPtr
<nsIContent
> mContent
;
51 nsresult
Init(mozilla::dom::Document
* aDoc
, nsIURI
* aURL
,
52 nsISupports
* aContainer
, nsIChannel
* aChannel
);
55 NS_DECL_ISUPPORTS_INHERITED
57 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXMLContentSink
, nsContentSink
)
62 NS_IMETHOD
WillParse(void) override
;
63 NS_IMETHOD
WillBuildModel(nsDTDMode aDTDMode
) override
;
64 NS_IMETHOD
DidBuildModel(bool aTerminated
) override
;
65 NS_IMETHOD
WillInterrupt(void) override
;
66 void WillResume() override
;
67 NS_IMETHOD
SetParser(nsParserBase
* aParser
) override
;
68 virtual void InitialTranslationCompleted() override
;
69 virtual void FlushPendingNotifications(mozilla::FlushType aType
) override
;
70 virtual void SetDocumentCharset(NotNull
<const Encoding
*> aEncoding
) override
;
71 virtual nsISupports
* GetTarget() override
;
72 virtual bool IsScriptExecuting() override
;
73 virtual void ContinueInterruptedParsingAsync() override
;
74 bool IsPrettyPrintXML() const override
{ return mPrettyPrintXML
; }
75 bool IsPrettyPrintHasSpecialRoot() const override
{
76 return mPrettyPrintHasSpecialRoot
;
79 // nsITransformObserver
80 nsresult
OnDocumentCreated(mozilla::dom::Document
* aSourceDocument
,
81 mozilla::dom::Document
* aResultDocument
) override
;
82 nsresult
OnTransformDone(mozilla::dom::Document
* aSourceDocument
,
84 mozilla::dom::Document
* aResultDocument
) override
;
86 // nsICSSLoaderObserver
87 NS_IMETHOD
StyleSheetLoaded(mozilla::StyleSheet
* aSheet
, bool aWasDeferred
,
88 nsresult aStatus
) override
;
89 static bool ParsePIData(const nsString
& aData
, nsString
& aHref
,
90 nsString
& aTitle
, nsString
& aMedia
,
94 virtual ~nsXMLContentSink();
96 nsIParser
* GetParser();
98 void ContinueInterruptedParsingIfEnabled();
100 // Start layout. If aIgnorePendingSheets is true, this will happen even if
101 // we still have stylesheet loads pending. Otherwise, we'll wait until the
102 // stylesheets are all done loading.
103 virtual void MaybeStartLayout(bool aIgnorePendingSheets
);
105 virtual nsresult
AddAttributes(const char16_t
** aNode
,
106 mozilla::dom::Element
* aElement
);
107 nsresult
AddText(const char16_t
* aString
, int32_t aLength
);
109 virtual bool OnOpenContainer(const char16_t
** aAtts
, uint32_t aAttsCount
,
110 int32_t aNameSpaceID
, nsAtom
* aTagName
,
111 uint32_t aLineNumber
) {
114 // Set the given content as the root element for the created document
115 // don't set if root element was already set.
116 // return TRUE if this call set the root element
117 virtual bool SetDocElement(int32_t aNameSpaceID
, nsAtom
* aTagName
,
118 nsIContent
* aContent
);
119 virtual bool NotifyForDocElement() { return true; }
120 virtual nsresult
CreateElement(const char16_t
** aAtts
, uint32_t aAttsCount
,
121 mozilla::dom::NodeInfo
* aNodeInfo
,
122 uint32_t aLineNumber
, uint32_t aColumnNumber
,
123 nsIContent
** aResult
, bool* aAppendContent
,
124 mozilla::dom::FromParser aFromParser
);
126 // aParent is allowed to be null here if this is the root content
128 virtual nsresult
CloseElement(nsIContent
* aContent
);
130 virtual nsresult
FlushText(bool aReleaseTextNode
= true);
132 nsresult
AddContentAsLeaf(nsIContent
* aContent
);
134 nsIContent
* GetCurrentContent();
135 StackNode
* GetCurrentStackNode();
136 nsresult
PushContent(nsIContent
* aContent
);
138 bool HaveNotifiedForCurrentContent() const;
140 nsresult
FlushTags() override
;
142 void UpdateChildCounts() override
;
144 void DidAddContent() {
145 if (!mXSLTProcessor
&& IsTimeToNotify()) {
150 // nsContentSink override
151 virtual nsresult
ProcessStyleLinkFromHeader(
152 const nsAString
& aHref
, bool aAlternate
, const nsAString
& aTitle
,
153 const nsAString
& aIntegrity
, const nsAString
& aType
,
154 const nsAString
& aMedia
, const nsAString
& aReferrerPolicy
,
155 const nsAString
& aFetchPriority
) override
;
157 // Try to handle an XSLT style link. If NS_OK is returned and aWasXSLT is not
158 // null, *aWasXSLT will be set to whether we processed this link as XSLT.
160 // aProcessingInstruction can be null if this information comes from a Link
161 // header; otherwise it will be the xml-styleshset XML PI that the loading
162 // information comes from.
163 virtual nsresult
MaybeProcessXSLTLink(
164 mozilla::dom::ProcessingInstruction
* aProcessingInstruction
,
165 const nsAString
& aHref
, bool aAlternate
, const nsAString
& aTitle
,
166 const nsAString
& aType
, const nsAString
& aMedia
,
167 const nsAString
& aReferrerPolicy
, bool* aWasXSLT
= nullptr);
169 nsresult
LoadXSLStyleSheet(nsIURI
* aUrl
);
171 bool CanStillPrettyPrint();
173 nsresult
MaybePrettyPrint();
175 bool IsMonolithicContainer(mozilla::dom::NodeInfo
* aNodeInfo
);
177 nsresult
HandleStartElement(const char16_t
* aName
, const char16_t
** aAtts
,
178 uint32_t aAttsCount
, uint32_t aLineNumber
,
179 uint32_t aColumnNumber
, bool aInterruptable
);
180 nsresult
HandleEndElement(const char16_t
* aName
, bool aInterruptable
);
181 nsresult
HandleCharacterData(const char16_t
* aData
, uint32_t aLength
,
182 bool aInterruptable
);
184 nsCOMPtr
<nsIContent
> mDocElement
;
185 nsCOMPtr
<nsIContent
> mCurrentHead
; // When set, we're in an XHTML <haed>
187 XMLContentSinkState mState
;
189 // The length of the valid data in mText.
192 int32_t mNotifyLevel
;
193 RefPtr
<nsTextNode
> mLastTextNode
;
195 uint8_t mPrettyPrintXML
: 1;
196 uint8_t mPrettyPrintHasSpecialRoot
: 1;
197 uint8_t mPrettyPrintHasFactoredElements
: 1;
198 uint8_t mPrettyPrinting
: 1; // True if we called PrettyPrint() and it
199 // decided we should in fact prettyprint.
200 // True to call prevent script execution in the fragment mode.
201 uint8_t mPreventScriptExecution
: 1;
203 nsTArray
<StackNode
> mContentStack
;
205 nsCOMPtr
<nsIDocumentTransformer
> mXSLTProcessor
;
207 // Holds the children in the prolog until the root element is added, after
208 // which they're inserted in the document. However, if we're doing an XSLT
209 // transform this will actually hold all the children of the source document,
210 // until the transform is finished. After the transform is finished we'll just
211 // discard the children.
212 nsTArray
<nsCOMPtr
<nsIContent
>> mDocumentChildren
;
214 static const int NS_ACCUMULATION_BUFFER_SIZE
= 4096;
215 // Our currently accumulated text that we have not flushed to a textnode yet.
216 char16_t mText
[NS_ACCUMULATION_BUFFER_SIZE
];
219 #endif // nsXMLContentSink_h__