1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
9 * This class does two primary jobs:
10 * 1) It iterates the tokens provided during the
11 * tokenization process, identifing where elements
12 * begin and end (doing validation and normalization).
13 * 2) It controls and coordinates with an instance of
14 * the IContentSink interface, to coordinate the
15 * the production of the content model.
17 * The basic operation of this class assumes that an HTML
18 * document is non-normalized. Therefore, we don't process
19 * the document in a normalized way. Don't bother to look
20 * for methods like: doHead() or doBody().
22 * Instead, in order to be backward compatible, we must
23 * scan the set of tokens and perform this basic set of
25 * 1) Determine the token type (easy, since the tokens know)
26 * 2) Determine the appropriate section of the HTML document
27 * each token belongs in (HTML,HEAD,BODY,FRAMESET).
28 * 3) Insert content into our document (via the sink) into
29 * the correct section.
30 * 4) In the case of tags that belong in the BODY, we must
31 * ensure that our underlying document state reflects
32 * the appropriate context for our tag.
34 * For example,if we see a <TR>, we must ensure our
35 * document contains a table into which the row can
36 * be placed. This may result in "implicit containers"
37 * created to ensure a well-formed document.
44 #include "nsIParser.h"
46 #include "CParserContext.h"
47 #include "nsHTMLTags.h"
48 #include "nsIContentSink.h"
49 #include "nsCOMArray.h"
50 #include "nsCycleCollectionParticipant.h"
51 #include "nsWeakReference.h"
52 #include "mozilla/Maybe.h"
53 #include "mozilla/UniquePtr.h"
59 # pragma warning(disable : 4275)
62 class nsParser final
: public nsIParser
,
63 public nsIStreamListener
,
64 public nsSupportsWeakReference
{
73 * Called on module init
75 static nsresult
Init();
78 * Called on module shutdown
80 static void Shutdown();
82 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
83 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsParser
, nsIParser
)
92 * Select given content sink into parser for parser output
94 * @param aSink is the new sink to be used by parser
95 * @return old sink, or nullptr
97 NS_IMETHOD_(void) SetContentSink(nsIContentSink
* aSink
) override
;
100 * retrive the sink set into the parser
101 * @update gess5/11/98
102 * @param aSink is the new sink to be used by parser
103 * @return old sink, or nullptr
105 NS_IMETHOD_(nsIContentSink
*) GetContentSink(void) override
;
108 * Call this method once you've created a parser, and want to instruct it
109 * about the command which caused the parser to be constructed. For example,
110 * this allows us to select a DTD which can do, say, view-source.
112 * @update gess 3/25/98
113 * @param aCommand -- ptrs to string that contains command
116 NS_IMETHOD_(void) GetCommand(nsCString
& aCommand
) override
;
117 NS_IMETHOD_(void) SetCommand(const char* aCommand
) override
;
118 NS_IMETHOD_(void) SetCommand(eParserCommands aParserCommand
) override
;
121 * Call this method once you've created a parser, and want to instruct it
122 * about what charset to load
124 * @update ftang 4/23/99
125 * @param aCharset- the charset of a document
126 * @param aCharsetSource- the source of the charset
127 * @param aChannelHadCharset- ignored
130 virtual void SetDocumentCharset(NotNull
<const Encoding
*> aCharset
,
132 bool aForceAutoDetection
) override
;
134 NotNull
<const Encoding
*> GetDocumentCharset(int32_t& aSource
) {
135 aSource
= mCharsetSource
;
140 * Cause parser to parse input from given URL
142 NS_IMETHOD
Parse(nsIURI
* aURL
) override
;
145 * This method gets called when you want to parse a fragment of XML surrounded
146 * by the context |aTagStack|. It requires that the parser have been given a
147 * fragment content sink.
149 * @param aSourceBuffer The XML that hasn't been parsed yet.
150 * @param aTagStack The context of the source buffer.
152 nsresult
ParseFragment(const nsAString
& aSourceBuffer
,
153 nsTArray
<nsString
>& aTagStack
);
155 NS_IMETHOD
ContinueInterruptedParsing() override
;
156 NS_IMETHOD_(void) BlockParser() override
;
157 NS_IMETHOD_(void) UnblockParser() override
;
158 NS_IMETHOD_(void) ContinueInterruptedParsingAsync() override
;
159 NS_IMETHOD
Terminate(void) override
;
162 * Call this to query whether the parser is enabled or not.
164 * @update vidur 4/12/99
165 * @return current state
167 NS_IMETHOD_(bool) IsParserEnabled() override
;
170 * Call this to query whether the parser thinks it's done with parsing.
172 * @update rickg 5/12/01
173 * @return complete state
175 NS_IMETHOD_(bool) IsComplete() override
;
178 * This method gets called (automatically) during incremental parsing
179 * @update gess5/11/98
180 * @return TRUE if all went well, otherwise FALSE
182 virtual nsresult
ResumeParse(bool allowIteration
= true,
183 bool aIsFinalChunk
= false,
184 bool aCanInterrupt
= true);
186 //*********************************************
187 // These methods are callback methods used by
188 // net lib to let us know about our inputstream.
189 //*********************************************
190 // nsIRequestObserver methods:
191 NS_DECL_NSIREQUESTOBSERVER
193 // nsIStreamListener methods:
194 NS_DECL_NSISTREAMLISTENER
197 * Get the nsIStreamListener for this parser
199 virtual nsIStreamListener
* GetStreamListener() override
;
201 void SetSinkCharset(NotNull
<const Encoding
*> aCharset
);
206 virtual bool IsInsertionPointDefined() override
;
211 void IncrementScriptNestingLevel() final
;
216 void DecrementScriptNestingLevel() final
;
218 bool HasNonzeroScriptNestingLevel() const final
;
223 virtual bool IsScriptCreated() override
;
226 * This is called when the final chunk has been
227 * passed to the parser and the content sink has
228 * interrupted token processing. It schedules
229 * a ParserContinue PL_Event which will ask the parser
230 * to HandleParserContinueEvent when it is handled.
231 * @update kmcclusk6/1/2001
233 nsresult
PostContinueEvent();
236 * Fired when the continue parse event is triggered.
237 * @update kmcclusk 5/18/98
239 void HandleParserContinueEvent(class nsParserContinueEvent
*);
243 mUnusedInput
.Truncate();
247 bool IsScriptExecuting() { return mSink
&& mSink
->IsScriptExecuting(); }
249 bool IsOkToProcessNetworkData() {
250 return !IsScriptExecuting() && !mProcessingNetworkData
;
253 // Returns Nothing() if we haven't determined yet what the parser is being
254 // used for. Else returns whether this parser is used for parsing XML.
255 mozilla::Maybe
<bool> IsForParsingXML() {
256 if (!mParserContext
|| mParserContext
->mDTDMode
== eDTDMode_autodetect
) {
257 return mozilla::Nothing();
260 return mozilla::Some(mParserContext
->mDocType
== eXML
);
269 * @update gess5/18/98
273 nsresult
WillBuildModel();
276 * Called when parsing is done.
278 void DidBuildModel();
282 * Pushes XML fragment parsing data to expat without an input stream.
284 nsresult
Parse(const nsAString
& aSourceBuffer
, bool aLastCall
);
287 //*********************************************
288 // And now, some data members...
289 //*********************************************
291 mozilla::UniquePtr
<CParserContext
> mParserContext
;
292 nsCOMPtr
<nsIDTD
> mDTD
;
293 nsCOMPtr
<nsIContentSink
> mSink
;
294 nsIRunnable
* mContinueEvent
; // weak ref
296 eParserCommands mCommand
;
297 nsresult mInternalState
;
298 nsresult mStreamStatus
;
299 int32_t mCharsetSource
;
304 nsString mUnusedInput
;
305 NotNull
<const Encoding
*> mCharset
;
306 nsCString mCommandStr
;
308 bool mProcessingNetworkData
;