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